From e28d9923d727d70d26b456c5271e8641cbb93042 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Thu, 6 Mar 2025 21:32:37 -0500 Subject: [PATCH 01/61] Add DensityShift check to prepare() --- .../jedk1/jedcore/ability/earthbending/EarthKick.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java index 505e17b..b85ad0d 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -8,13 +8,12 @@ import com.jedk1.jedcore.util.BlockUtil; import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.*; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -95,10 +94,15 @@ public void setFields() { private boolean prepare() { block = player.getTargetBlock(getTransparentMaterialSet(), sourceRange); - if (!isEarthbendable(player, block)){ + + if (!isEarthbendable(player, block) && !isBendableEarthTempBlock(block)) { return false; } + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + if (block != null && !isMetal(block)) { materialData = block.getBlockData().clone(); location.setX(block.getX() + 0.5); From c9813b6ea29520547702465c9fa7ed6c26f09694 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sat, 15 Mar 2025 23:16:16 -0400 Subject: [PATCH 02/61] Completely removes the integrated BendingBoard --- src/com/jedk1/jedcore/JCMethods.java | 6 - src/com/jedk1/jedcore/JedCore.java | 5 +- .../jedk1/jedcore/command/BoardCommand.java | 28 -- src/com/jedk1/jedcore/command/Commands.java | 5 - .../jedcore/configuration/JedCoreConfig.java | 33 --- .../jedk1/jedcore/event/PKCommandEvent.java | 3 +- .../jedcore/listener/CommandListener.java | 7 - .../jedk1/jedcore/listener/JCListener.java | 65 ---- .../jedcore/scoreboard/BendingBoard.java | 279 ------------------ .../jedcore/scoreboard/SimpleScoreboard.java | 237 --------------- src/plugin.yml | 1 - 11 files changed, 2 insertions(+), 667 deletions(-) delete mode 100644 src/com/jedk1/jedcore/command/BoardCommand.java delete mode 100644 src/com/jedk1/jedcore/scoreboard/BendingBoard.java delete mode 100644 src/com/jedk1/jedcore/scoreboard/SimpleScoreboard.java diff --git a/src/com/jedk1/jedcore/JCMethods.java b/src/com/jedk1/jedcore/JCMethods.java index 27d4ddb..f039c83 100644 --- a/src/com/jedk1/jedcore/JCMethods.java +++ b/src/com/jedk1/jedcore/JCMethods.java @@ -16,7 +16,6 @@ import org.bukkit.util.Vector; import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.scoreboard.BendingBoard; import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ability.CoreAbility; @@ -341,16 +340,11 @@ public static void reload() { JedCore.log.info("JedCore Reloaded."); JedCore.plugin.reloadConfig(); JedCore.logDebug = JedCoreConfig.getConfig((World)null).getBoolean("Properties.LogDebug"); - JedCoreConfig.board.reloadConfig(); CoreAbility.registerPluginAbilities(JedCore.plugin, "com.jedk1.jedcore.ability"); registerDisabledWorlds(); registerCombos(); RegenTempBlock.revertAll(); - BendingBoard.setFields(); - BendingBoard.updateOnline(); JedCore.plugin.initializeCollisions(); FireTick.loadMethod(); - - BendingBoard.loadOtherCooldowns(); } } diff --git a/src/com/jedk1/jedcore/JedCore.java b/src/com/jedk1/jedcore/JedCore.java index b29466e..9dc2ca2 100644 --- a/src/com/jedk1/jedcore/JedCore.java +++ b/src/com/jedk1/jedcore/JedCore.java @@ -17,7 +17,6 @@ import com.jedk1.jedcore.listener.AbilityListener; import com.jedk1.jedcore.listener.CommandListener; import com.jedk1.jedcore.listener.JCListener; -import com.jedk1.jedcore.scoreboard.BendingBoard; import com.projectkorra.projectkorra.ability.CoreAbility; import org.bukkit.scheduler.BukkitRunnable; @@ -50,8 +49,7 @@ public void onEnable() { getServer().getPluginManager().registerEvents(new JCListener(this), this); getServer().getPluginManager().registerEvents(new ChiRestrictor(), this); getServer().getScheduler().scheduleSyncRepeatingTask(this, new JCManager(this), 0, 1); - - BendingBoard.updateOnline(); + new Commands(); FireTick.loadMethod(); @@ -66,7 +64,6 @@ public void onEnable() { @Override public void run() { JCMethods.registerCombos(); - BendingBoard.loadOtherCooldowns(); initializeCollisions(); } }.runTaskLater(this, 1); diff --git a/src/com/jedk1/jedcore/command/BoardCommand.java b/src/com/jedk1/jedcore/command/BoardCommand.java deleted file mode 100644 index 993c08a..0000000 --- a/src/com/jedk1/jedcore/command/BoardCommand.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.jedk1.jedcore.command; - -import com.jedk1.jedcore.scoreboard.BendingBoard; -import com.projectkorra.projectkorra.command.PKCommand; - -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.List; - -public class BoardCommand extends PKCommand { - - public BoardCommand() { - super("board", "/bending board", "Toggles the visibility of the BendingBoard.", new String[] { "board", "bendingboard", "bb" }); - } - - @Override - public void execute(CommandSender sender, List args) { - if (!isPlayer(sender) || !correctLength(sender, args.size(), 0, 0) || !hasPermission(sender)) { - return; - } - if (args.size() == 0) { - BendingBoard.toggle((Player) sender); - } else { - help(sender, false); - } - } -} diff --git a/src/com/jedk1/jedcore/command/Commands.java b/src/com/jedk1/jedcore/command/Commands.java index 0ac6876..1c23a38 100644 --- a/src/com/jedk1/jedcore/command/Commands.java +++ b/src/com/jedk1/jedcore/command/Commands.java @@ -1,14 +1,9 @@ package com.jedk1.jedcore.command; -import com.jedk1.jedcore.scoreboard.BendingBoard; - public class Commands { public Commands() { - if (BendingBoard.enabled) { - new BoardCommand(); - } new JedCoreCommand(); } } diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 4acc321..f67929f 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -16,48 +16,15 @@ public class JedCoreConfig { - public static Config board; static JedCore plugin; public JedCoreConfig(JedCore plugin) { JedCoreConfig.plugin = plugin; - board = new Config(new File("board.yml")); - loadConfigBoard(); loadConfigCore(); addDeathMessages(); setupElementSphereNames(); } - private void loadConfigBoard() { - FileConfiguration config; - config = board.getConfig(); - - config.addDefault("Settings.Enabled", true); - config.addDefault("Settings.Title", "&lSlots"); - config.addDefault("Settings.Pointer", "> "); - config.addDefault("Settings.EmptySlot", "&8&o-- Slot % --"); - config.addDefault("Settings.Combos", "&fCombos:"); - config.addDefault("Settings.Toggle.Off", "&7You have hidden the bending board."); - config.addDefault("Settings.Toggle.On", "&7You have toggled the bending board on."); - config.addDefault("Settings.Display.DisabledWorlds", true); - - config.addDefault("Settings.OtherCooldowns.WallRun.Color", "GOLD"); - config.addDefault("Settings.OtherCooldowns.WallRun.Enabled", true); - config.addDefault("Settings.OtherCooldowns.TorrentWave.Color", "AQUA"); - config.addDefault("Settings.OtherCooldowns.TorrentWave.Enabled", true); - config.addDefault("Settings.OtherCooldowns.SurgeWave.Color", "AQUA"); - config.addDefault("Settings.OtherCooldowns.SurgeWave.Enabled", true); - config.addDefault("Settings.OtherCooldowns.SurgeWall.Color", "AQUA"); - config.addDefault("Settings.OtherCooldowns.SurgeWall.Enabled", true); - config.addDefault("Settings.OtherCooldowns.RaiseEarthPillar.Color", "GREEN"); - config.addDefault("Settings.OtherCooldowns.RaiseEarthPillar.Enabled", true); - config.addDefault("Settings.OtherCooldowns.RaiseEarthWall.Color", "GREEN"); - config.addDefault("Settings.OtherCooldowns.RaiseEarthWall.Enabled", true); - - config.options().copyDefaults(true); - board.saveConfig(); - } - private void loadConfigCore() { FileConfiguration config; config = JedCore.plugin.getConfig(); diff --git a/src/com/jedk1/jedcore/event/PKCommandEvent.java b/src/com/jedk1/jedcore/event/PKCommandEvent.java index 76af79e..3886951 100644 --- a/src/com/jedk1/jedcore/event/PKCommandEvent.java +++ b/src/com/jedk1/jedcore/event/PKCommandEvent.java @@ -24,8 +24,7 @@ public enum CommandType { TOGGLE, VERSION, WHO, - JEDCORE, - SCOREBOARD; + JEDCORE; public static CommandType getType(String string) { for (CommandType element : CommandType.values()) { diff --git a/src/com/jedk1/jedcore/listener/CommandListener.java b/src/com/jedk1/jedcore/listener/CommandListener.java index a5d879d..3e3f803 100644 --- a/src/com/jedk1/jedcore/listener/CommandListener.java +++ b/src/com/jedk1/jedcore/listener/CommandListener.java @@ -4,12 +4,10 @@ import com.jedk1.jedcore.command.JedCoreCommand; import com.jedk1.jedcore.event.PKCommandEvent; import com.jedk1.jedcore.event.PKCommandEvent.CommandType; -import com.jedk1.jedcore.scoreboard.BendingBoard; import com.projectkorra.projectkorra.command.PKCommand; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -56,11 +54,6 @@ public void onPKCommand(final PKCommandEvent event) { new BukkitRunnable() { public void run() { if (event.getType() != null) { - if (Arrays.asList(types).contains(event.getType())) { - Player player = event.getSender(); - if (BendingBoard.isDisabled(player)) return; - BendingBoard.get(player).update(); - } if (event.getType().equals(CommandType.WHO) && event.getSender().hasPermission("bending.command.who")) { if (event.getArgs().length == 3) { if (Bukkit.getPlayer(event.getArgs()[2]) != null) { diff --git a/src/com/jedk1/jedcore/listener/JCListener.java b/src/com/jedk1/jedcore/listener/JCListener.java index 8eea29f..7a865ff 100644 --- a/src/com/jedk1/jedcore/listener/JCListener.java +++ b/src/com/jedk1/jedcore/listener/JCListener.java @@ -11,7 +11,6 @@ import com.jedk1.jedcore.ability.firebending.FireSki; import com.jedk1.jedcore.ability.waterbending.IceClaws; import com.jedk1.jedcore.ability.waterbending.IceWall; -import com.jedk1.jedcore.scoreboard.BendingBoard; import com.jedk1.jedcore.util.LightManager; import com.jedk1.jedcore.util.RegenTempBlock; import com.projectkorra.projectkorra.ProjectKorra; @@ -49,29 +48,6 @@ public JCListener(JedCore plugin) { this.plugin = plugin; } - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerJoin(PlayerJoinEvent event) { - if (BendingBoard.isDisabled(event.getPlayer())) { - return; - } - BendingBoard bb = BendingBoard.get(event.getPlayer()); - if (bb != null) { - new BukkitRunnable() { - public void run() { - bb.update(); - } - }.runTaskLater(JedCore.plugin, 50); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerQuit(PlayerQuitEvent event){ - BendingBoard bb = BendingBoard.get(event.getPlayer()); - if (bb != null) { - bb.remove(); - } - } - @EventHandler public void onAbilityStart(AbilityStartEvent event) { if (event.isCancelled()) return; @@ -236,47 +212,6 @@ public void run() { } }.runTaskLater(JedCore.plugin, 1); } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerItemHoldEvent(PlayerItemHeldEvent event) { - BendingBoard.update(event.getPlayer(), event.getNewSlot()); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onCooldownChange(PlayerCooldownChangeEvent event) { - if (event.getPlayer() == null) return; - - // Fix a bug in ProjectKorra 1.8.4 that keeps IceWave around forever. - // It will continuously add a cooldown to WaterWave, which makes this spam tasks / scoreboard updates. - // It also happens with FastSwim when the player is a waterbender. - if (BendingBoard.shouldIgnoreAbility(event.getAbility())) { - return; - } - new BukkitRunnable() { - public void run() { - BendingBoard.update(event.getPlayer()); - } - }.runTaskLater(JedCore.plugin, 1); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onWorldChange(PlayerChangedWorldEvent event){ - new BukkitRunnable() { - public void run() { - BendingBoard.update(event.getPlayer()); - } - }.runTaskLater(JedCore.plugin, 1); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onElementChange(PlayerChangeElementEvent event){ - if (event.getTarget() == null) return; - new BukkitRunnable() { - public void run() { - BendingBoard.update(event.getTarget()); - } - }.runTaskLater(JedCore.plugin, 1); - } @EventHandler(priority = EventPriority.NORMAL) public void onChat(AsyncPlayerChatEvent event){ diff --git a/src/com/jedk1/jedcore/scoreboard/BendingBoard.java b/src/com/jedk1/jedcore/scoreboard/BendingBoard.java deleted file mode 100644 index 3485d45..0000000 --- a/src/com/jedk1/jedcore/scoreboard/BendingBoard.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.jedk1.jedcore.scoreboard; - -import java.io.File; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -import com.projectkorra.projectkorra.util.ChatUtil; -import net.md_5.bungee.api.ChatColor; -import org.bukkit.Bukkit; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.configuration.Config; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; - -public class BendingBoard { - private static final List IGNORE_ABILITIES = Arrays.asList("WaterWave", "FastSwim"); - private static final String OTHER = "Other:"; - public static Map otherAbilities = new HashMap<>(); - public static ConcurrentHashMap boards = new ConcurrentHashMap<>(); - public static List disabled = new ArrayList<>(); - public static boolean enabled; - public static String title; - public static String pointer; - public static String empty; - public static String toggleOn; - public static String toggleOff; - public static String combo; - public static Config toggled; - public static boolean disabledworlds; - - static { - toggled = new Config(new File("/board/players.yml")); - - List uuids = toggled.getConfig().getStringList("Players"); - if (!uuids.isEmpty()) { - if (!uuids.get(0).matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}")) { - toggled.getConfig().set("Players", new ArrayList()); - toggled.saveConfig(); - } else { - for (String s : uuids) { - disabled.add(UUID.fromString(s)); - } - } - } - setFields(); - } - - private Player player; - private SimpleScoreboard scoreboard; - - public BendingBoard(Player player) { - this.player = player; - this.scoreboard = new SimpleScoreboard(title); - boards.put(player, this); - } - - public static void setFields() { - enabled = JedCoreConfig.board.getConfig().getBoolean("Settings.Enabled"); - title = ChatUtil.color(JedCoreConfig.board.getConfig().getString("Settings.Title")); - pointer = ChatUtil.color(JedCoreConfig.board.getConfig().getString("Settings.Pointer")); - empty = ChatUtil.color(JedCoreConfig.board.getConfig().getString("Settings.EmptySlot")); - combo = ChatUtil.color(JedCoreConfig.board.getConfig().getString("Settings.Combos")); - toggleOn = ChatUtil.color(JedCoreConfig.board.getConfig().getString("Settings.Toggle.On")); - toggleOff = ChatUtil.color(JedCoreConfig.board.getConfig().getString("Settings.Toggle.Off")); - disabledworlds = JedCoreConfig.board.getConfig().getBoolean("Settings.Display.DisabledWorlds"); - } - - public static boolean shouldIgnoreAbility(String abilityName) { - if (abilityName == null) return false; - - return IGNORE_ABILITIES.contains(abilityName); - } - - public static void loadOtherCooldowns() { - ConfigurationSection section = JedCoreConfig.board.getConfig().getConfigurationSection("Settings.OtherCooldowns"); - - otherAbilities.clear(); - - for (String ability : section.getKeys(false)) { - ConfigurationSection abilitySection = section.getConfigurationSection(ability); - if (abilitySection == null) continue; - - boolean enabled = abilitySection.getBoolean("Enabled", true); - if (!enabled) continue; - - String colorString = abilitySection.getString("Color"); - ChatColor color = null; - - if (colorString != null) { - color = ChatColor.of(colorString); - } - - otherAbilities.put(ability, color); - } - } - - public static void updateOnline() { - if (!enabled) return; - for (Player player : Bukkit.getOnlinePlayers()) { - if (disabled.contains(player.getUniqueId())) continue; - if (!disabledworlds && JCMethods.getDisabledWorlds().contains(player.getWorld().getName())) continue; - BendingBoard.get(player).update(); - } - } - - public static void toggle(Player player) { - if (!enabled) return; - List uuids = new ArrayList<>(toggled.getConfig().getStringList("Players")); - if (uuids.contains(player.getUniqueId().toString())) { - uuids.remove(player.getUniqueId().toString()); - disabled.remove(player.getUniqueId()); - get(player).update(); - player.sendMessage(toggleOn); - } else { - uuids.add(player.getUniqueId().toString()); - disabled.add(player.getUniqueId()); - get(player).remove(); - player.sendMessage(toggleOff); - } - toggled.getConfig().set("Players", uuids); - toggled.saveConfig(); - } - - public static void update(Player player) { - update(player, -1); - } - - public static void update(Player player, int slot) { - if (!enabled) { - if (disabled.contains(player.getUniqueId())) return; - if (!boards.containsKey(player)) return; - get(player).remove(); - return; - } - if (disabled.contains(player.getUniqueId())) return; - if (!disabledworlds && JCMethods.getDisabledWorlds().contains(player.getWorld().getName())) { - if (boards.containsKey(player)) { - get(player).remove(); - } - return; - } - get(player).update(slot); - } - - public static BendingBoard get(Player player) { - if (!enabled) return null; - if (boards.containsKey(player)) { - return boards.get(player); - } else { - return new BendingBoard(player); - } - } - - public static boolean isDisabled(Player player) { - return !enabled || disabled.contains(player.getUniqueId()); - } - - public void remove() { - scoreboard.reset(); - boards.remove(player); - player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); - } - - public void update() { - update(-1); - } - - public void update(final int slot) { - if (!enabled) return; - - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null) return; - - // Check if the player removed their bending board. It's possible for the board to update after hidden. - if (boards.get(player) == null) { - player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); - return; - } - - HashMap abilities = bPlayer.getAbilities(); - - int currentSlot = slot; - if (currentSlot < 0) { - currentSlot = player.getInventory().getHeldItemSlot(); - } - - List formatted = new ArrayList<>(); - - for (int slotIndex = 1; slotIndex < 10; slotIndex++) { - CoreAbility currentAbility = CoreAbility.getAbility(abilities.get(slotIndex)); - String currentAbilityName = abilities.get(slotIndex); - StringBuilder sb = new StringBuilder(); - - if (currentSlot == (slotIndex - 1)) { - sb.append(pointer); - } - - if (abilities.containsKey(slotIndex) && currentAbility != null) { - for (String str : formatted) { - String stripped = ChatColor.stripColor(str).replace(pointer, ""); - - if (stripped.equalsIgnoreCase(currentAbilityName)) { - // Add a unique chat color to the beginning, so the ability doesn't override other slots in the map. - sb.append(ChatColor.getByChar((char) slotIndex)); - break; - } - } - - sb.append(currentAbility.getElement().getColor()); - - if (bPlayer.isOnCooldown(currentAbilityName)) { - sb.append(ChatColor.STRIKETHROUGH); - } - - sb.append(currentAbilityName); - } else { - if (abilities.containsKey(slotIndex) && MultiAbilityManager.hasMultiAbilityBound(player)) { - sb.append(abilities.get(slotIndex)); - } else { - sb.append(empty.replace("%", String.valueOf(slotIndex))); - } - } - formatted.add(sb.toString()); - } - boolean combo = false; - for (String ability : bPlayer.getCooldowns().keySet()) { - if (JCMethods.getCombos().contains(ability)) { - if (!combo) { - formatted.add(BendingBoard.combo); - } - - combo = true; - formatted.add("" + CoreAbility.getAbility(ability).getElement().getColor() + ChatColor.STRIKETHROUGH + ability); - } - } - - if (!otherAbilities.isEmpty()) { - boolean other = false; - for (String ability : bPlayer.getCooldowns().keySet()) { - if (!otherAbilities.containsKey(ability)) continue; - ChatColor color = otherAbilities.get(ability); - - if (!other) { - formatted.add(OTHER); - other = true; - } - - if (color == null) - color = getColor(ability); - formatted.add("" + color + ChatColor.STRIKETHROUGH + ability); - } - } - - if (scoreboard.get(-10, "") != null) { - for (int i = -9; i > -22; i--) { - scoreboard.remove(i, ""); - } - } - - for (String s : formatted) { - scoreboard.add(s, -(formatted.indexOf(s) + 1)); - } - - scoreboard.update(); - scoreboard.send(player); - } - - private ChatColor getColor(String abilityName) { - CoreAbility ability = CoreAbility.getAbility(abilityName); - if (ability != null) - return ability.getElement().getColor(); - return ChatColor.WHITE; - } -} diff --git a/src/com/jedk1/jedcore/scoreboard/SimpleScoreboard.java b/src/com/jedk1/jedcore/scoreboard/SimpleScoreboard.java deleted file mode 100644 index 40162fb..0000000 --- a/src/com/jedk1/jedcore/scoreboard/SimpleScoreboard.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.jedk1.jedcore.scoreboard; - -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.scoreboard.DisplaySlot; -import org.bukkit.scoreboard.Objective; -import org.bukkit.scoreboard.Score; -import org.bukkit.scoreboard.Scoreboard; -import org.bukkit.scoreboard.Team; - -import java.util.AbstractMap; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class SimpleScoreboard { - - private static Map cache = new HashMap<>(); - - private Scoreboard scoreboard; - private String title; - private Map scores; - private Objective obj; - private List teams; - private List removed; - private Set updated; - - public SimpleScoreboard(String title) { - this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); - this.title = ChatColor.translateAlternateColorCodes('&', title); - this.scores = new ConcurrentHashMap<>(); - this.teams = Collections.synchronizedList(Lists.newArrayList()); - this.removed = Lists.newArrayList(); - this.updated = Collections.synchronizedSet(new HashSet<>()); - } - - public void add(String text, Integer score) { - text = ChatColor.translateAlternateColorCodes('&', text); - String stripped = ChatColor.stripColor(text); - - // Use the first 16 real characters. - if (stripped.length() > 16) { - int formatCounts = 0; - for (int i = 0; i < text.length(); ++i) { - if (text.charAt(i) == ChatColor.COLOR_CHAR) { - ++formatCounts; - } - } - - text = text.substring(0, Math.min(15 + formatCounts * 2, text.length())); - } - - if (remove(score, text, false) || !scores.containsValue(score)) { - updated.add(text); - } - - scores.put(text, score); - } - - public boolean remove(Integer score, String text) { - return remove(score, text, true); - } - - public boolean remove(Integer score, String n, boolean b) { - String toRemove = get(score, n); - - if (toRemove == null) - return false; - - scores.remove(toRemove); - - if(b) - removed.add(score); - - return true; - } - - public String get(int score, String n) { - String str = null; - - for (Map.Entry entry : scores.entrySet()) { - if (entry.getValue().equals(score) && - !entry.getKey().equals(n)) { - str = entry.getKey(); - } - } - - return str; - } - - private Map.Entry createTeam(String text, int pos) { - Team team; - ChatColor color = ChatColor.values()[(pos < 0) ? -pos : pos]; - String result; - - if (!cache.containsKey(color.toString())) - cache.put(color.toString(), color.toString()); - - result = cache.get(color.toString()); - - try { - team = scoreboard.registerNewTeam("text-" + (teams.size() + 1)); - } catch (IllegalArgumentException e) { - team = scoreboard.getTeam("text-" + (teams.size())); - } - - applyText(team, text, result); - - teams.add(team); - return new AbstractMap.SimpleEntry<>(team, result); - } - - private void applyText(Team team, String text, String result) { - Iterator iterator = Splitter.fixedLength(16).split(text).iterator(); - String prefix = iterator.next(); - - team.setPrefix(prefix); - - if(!team.hasEntry(result)) - team.addEntry(result); - - if (text.length() > 16) { - String prefixColor = ChatColor.getLastColors(prefix); - String suffix = iterator.next(); - - if (prefix.endsWith(String.valueOf(ChatColor.COLOR_CHAR))) { - prefix = prefix.substring(0, prefix.length() - 1); - team.setPrefix(prefix); - prefixColor = ChatColor.getByChar(suffix.charAt(0)).toString(); - suffix = suffix.substring(1); - } - - if (prefixColor == null) - prefixColor = ""; - - if (suffix.length() > 16) { - suffix = suffix.substring(0, (13 - prefixColor.length())); // cut off suffix, done if text is over 30 characters - } - - team.setSuffix((prefixColor.equals("") ? ChatColor.RESET : prefixColor) + suffix); - } - } - - public void update() { - if (updated.isEmpty()) { - return; - } - - if (obj == null) { - obj = scoreboard.registerNewObjective((title.length() > 16 ? title.substring(0, 15) : title), "dummy", (title.length() > 16 ? title.substring(0, 15) : title)); - obj.setDisplayName(title); - obj.setDisplaySlot(DisplaySlot.SIDEBAR); - } - - for (Integer aRemoved : removed) { - for (String s : scoreboard.getEntries()) { - Score score = obj.getScore(s); - - if (score == null) - continue; - - if (score.getScore() != aRemoved) - continue; - - scoreboard.resetScores(s); - } - } - - removed.clear(); - - int index = scores.size(); - - for (Map.Entry text : scores.entrySet()) { - Team t = scoreboard.getTeam(ChatColor.values()[(text.getValue() < 0) ? -text.getValue() : text.getValue()].toString()); - Map.Entry team; - - if(!updated.contains(text.getKey())) { - continue; - } - - if(t != null) { - String color = ChatColor.values()[(text.getValue() < 0) ? -text.getValue() : text.getValue()].toString(); - - if (!cache.containsKey(color)) { - cache.put(color, color); - } - - team = new AbstractMap.SimpleEntry<>(t, cache.get(color)); - applyText(team.getKey(), text.getKey(), team.getValue()); - index -= 1; - - continue; - } else { - team = createTeam(text.getKey(), text.getValue()); - } - - Integer score = text.getValue() != null ? text.getValue() : index; - - obj.getScore(team.getValue()).setScore(score); - index -= 1; - } - - updated.clear(); - } - - public void setTitle(String title) { - this.title = ChatColor.translateAlternateColorCodes('&', title); - - if(obj != null) - obj.setDisplayName(title); - } - - public void reset() { - for (Team t : teams) - t.unregister(); - teams.clear(); - scores.clear(); - } - - public Scoreboard getScoreboard() { - return scoreboard; - } - - public void send(Player... players) { - for (Player p : players) - p.setScoreboard(scoreboard); - } -} \ No newline at end of file diff --git a/src/plugin.yml b/src/plugin.yml index 119cd14..eab00e3 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -31,7 +31,6 @@ permissions: description: Access to player commands. children: bending.command.jedcore: true - bending.command.board: true jedcore.passive: default: true description: Access to passive abilities. From 56d6b9384f591759571dce5d1fc9c6fb8493a5d3 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 00:17:57 -0400 Subject: [PATCH 03/61] Fix WakeFishing server crash on MC 1.21.4 --- src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java b/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java index 6f4bf55..26ada5f 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java +++ b/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java @@ -70,10 +70,9 @@ private void applyModifiers() { } } - @SuppressWarnings("deprecation") private boolean prepare() { Block block = BlockSource.getWaterSourceBlock(player, range, ClickType.SHIFT_DOWN, true, false, false); - if (isWater(block) && block.getData() == 0) { + if (isWater(block)) { focusedBlock = block; location = focusedBlock.getLocation(); return true; From 4e7c49471f544f0e2715fa5034d0c0808677040a Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 00:18:23 -0400 Subject: [PATCH 04/61] Fix EarthLine sourcing for good --- src/com/jedk1/jedcore/ability/earthbending/EarthLine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java index 90e0ba4..d2631fe 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java @@ -100,7 +100,7 @@ public void setFields() { } public boolean prepare() { - final Block block = BlockSource.getEarthSourceBlock(this.player, this.range, ClickType.SHIFT_DOWN); + final Block block = getEarthSourceBlock(this.range); if (block == null || !this.isEarthbendable(block)) { return false; } else if (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block)) { From 9b5147d4b23b114cb0bfa84a0ec7e2995a0a620c Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 00:18:51 -0400 Subject: [PATCH 05/61] Balance Discharge and LightningBurst audio --- src/com/jedk1/jedcore/ability/firebending/Discharge.java | 8 ++++---- .../jedk1/jedcore/ability/firebending/LightningBurst.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/firebending/Discharge.java b/src/com/jedk1/jedcore/ability/firebending/Discharge.java index 705eeb2..4b74d44 100644 --- a/src/com/jedk1/jedcore/ability/firebending/Discharge.java +++ b/src/com/jedk1/jedcore/ability/firebending/Discharge.java @@ -138,8 +138,8 @@ private void advanceLocation() { playLightningbendingParticle(l.clone(), 0f, 0f, 0f); JCMethods.emitLight(l.clone()); - if (rand.nextInt(3) == 0) { - player.getWorld().playSound(l, Sound.ENTITY_CREEPER_PRIMED, 1, 0); + if (rand.nextInt(6) == 0) { + player.getWorld().playSound(l, Sound.ENTITY_BEE_HURT, 0.6f, 0.2f); } Vector vec = l.toVector(); @@ -158,8 +158,8 @@ private void advanceLocation() { JCMethods.emitLight(entity.getLocation()); } - entity.getWorld().playSound(entity.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1, 0); - player.getWorld().playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 1, 0); + entity.getWorld().playSound(entity.getLocation(), Sound.ENTITY_BEE_HURT, 0.8f, 0.2f); + player.getWorld().playSound(player.getLocation(), Sound.ENTITY_BEE_HURT, 0.8f, 0.2f); return true; }); diff --git a/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java b/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java index 8a20c8c..bad83a6 100644 --- a/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java +++ b/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java @@ -310,8 +310,8 @@ private void progress() { break; } - if (rand.nextInt(3) == 0) { - location.getWorld().playSound(location, Sound.ENTITY_CREEPER_PRIMED, 1, 0); + if (rand.nextInt(5) == 0) { + location.getWorld().playSound(location, Sound.ENTITY_BEE_HURT, 0.7f, 0.2f); } for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { From 449a485e48ab3561ad1afc83be02a98b31ca8c04 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 00:36:23 -0400 Subject: [PATCH 06/61] Fix SandBlast sourcing --- src/com/jedk1/jedcore/ability/earthbending/SandBlast.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java b/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java index cef279e..a8ab2d0 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java +++ b/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java @@ -90,7 +90,7 @@ public void setFields() { } private boolean prepare() { - source = BlockSource.getEarthSourceBlock(player, sourceRange, ClickType.SHIFT_DOWN); + source = getEarthSourceBlock(sourceRange); if (source != null) { if (isSand(source) && ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType())) { From 95a59b3eb1f1a254a7880ae32149fb4c28d177aa Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 00:40:20 -0400 Subject: [PATCH 07/61] Allow EarthKick to source metal blocks --- src/com/jedk1/jedcore/ability/earthbending/EarthKick.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java index b85ad0d..c29b7f1 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -103,7 +103,7 @@ private boolean prepare() { DensityShift.revertSand(block); } - if (block != null && !isMetal(block)) { + if (block != null) { materialData = block.getBlockData().clone(); location.setX(block.getX() + 0.5); location.setY(block.getY()); From 77a6628de5240403ddba3b4513450ff35685ecf3 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 00:46:14 -0400 Subject: [PATCH 08/61] Add EarthKick "AllowMetal" configuration --- src/com/jedk1/jedcore/ability/earthbending/EarthKick.java | 4 +++- src/com/jedk1/jedcore/configuration/JedCoreConfig.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java index c29b7f1..d941438 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -53,6 +53,7 @@ public class EarthKick extends EarthAbility implements AddonAbility { private int sourceRange; private int spread; private double velocity; + private boolean allowMetal; private Set hitEntities = new HashSet<>(); @@ -86,6 +87,7 @@ public void setFields() { sourceRange = config.getInt("Abilities.Earth.EarthKick.SourceRange"); spread = config.getInt("Abilities.Earth.EarthKick.Spread"); velocity = config.getDouble("Abilities.Earth.EarthKick.Velocity"); + allowMetal = config.getBoolean("Abilities.Earth.EarthKick.AllowMetal"); if (entityCollisionRadius < 1.0) { entityCollisionRadius = 1.0; @@ -103,7 +105,7 @@ private boolean prepare() { DensityShift.revertSand(block); } - if (block != null) { + if (block != null && (allowMetal || !isMetal(block))) { materialData = block.getBlockData().clone(); location.setX(block.getX() + 0.5); location.setY(block.getY()); diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index f67929f..77295c6 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -241,6 +241,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Earth.EarthKick.SourceRange", 2.0); config.addDefault("Abilities.Earth.EarthKick.Spread", 20); config.addDefault("Abilities.Earth.EarthKick.Velocity", 0.7); + config.addDefault("Abilities.Earth.EarthKick.AllowMetal", true); config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.Enabled", true); config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveFirst", false); config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveSecond", true); From a61590ed3a4f7dcc647956aa3680b57f171946a0 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 01:44:10 -0400 Subject: [PATCH 09/61] Fix EarthLine dupe glitch --- .../ability/earthbending/EarthLine.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java index d2631fe..b0991dd 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java @@ -35,6 +35,7 @@ public class EarthLine extends EarthAbility implements AddonAbility { private Location location; private Location endLocation; private Block sourceBlock; + private TempBlock sourceTempBlock; private Material sourceType; private boolean progressing; private boolean hitted; @@ -133,37 +134,39 @@ private void focusBlock() { if (DensityShift.isPassiveSand(this.sourceBlock)) { DensityShift.revertSand(this.sourceBlock); } + if (this.sourceBlock.getType() == Material.SAND) { this.sourceType = Material.SAND; - this.sourceBlock.setType(Material.SANDSTONE); + sourceTempBlock = new TempBlock(sourceBlock, Material.SANDSTONE.createBlockData()); + //this.sourceBlock.setType(Material.SANDSTONE); } else if (this.sourceBlock.getType() == Material.RED_SAND) { this.sourceType = Material.RED_SAND; - this.sourceBlock.setType(Material.RED_SANDSTONE); + sourceTempBlock = new TempBlock(sourceBlock, Material.RED_SANDSTONE.createBlockData()); + //this.sourceBlock.setType(Material.RED_SANDSTONE); } else if (this.sourceBlock.getType() == Material.STONE) { - this.sourceBlock.setType(Material.COBBLESTONE); + //this.sourceBlock.setType(Material.COBBLESTONE); this.sourceType = Material.STONE; + sourceTempBlock = new TempBlock(sourceBlock, Material.COBBLESTONE.createBlockData()); } else { this.sourceType = this.sourceBlock.getType(); - this.sourceBlock.setType(Material.STONE); + //this.sourceBlock.setType(Material.STONE); + sourceTempBlock = new TempBlock(sourceBlock, Material.STONE.createBlockData()); } this.location = this.sourceBlock.getLocation(); } private void unfocusBlock() { - sourceBlock.setType(sourceType); - } - - private void breakSourceBlock() { - sourceBlock.setType(sourceType); - new RegenTempBlock(sourceBlock, Material.AIR, Material.AIR.createBlockData(), 5000L); + //sourceBlock.setType(sourceType); + sourceTempBlock.revertBlock(); } @Override public void remove() { - if (sourceBlock != null && sourceBlock.getType() != Material.AIR) { - sourceBlock.setType(sourceType); // Ensure no duplication of the source block - } +// if (sourceBlock != null && sourceBlock.getType() != Material.AIR) { +// sourceBlock.setType(sourceType); // Ensure no duplication of the source block +// } + sourceTempBlock.revertBlock(); super.remove(); } @@ -185,7 +188,6 @@ public void shootLine(Location endLocation) { if (maxDuration > 0) removalTime = System.currentTimeMillis() + maxDuration; this.endLocation = endLocation; progressing = true; - breakSourceBlock(); sourceBlock.getWorld().playEffect(sourceBlock.getLocation(), Effect.GHAST_SHOOT, 0, 10); } @@ -253,7 +255,8 @@ public void progress() { playEarthbendingSound(location); if (isEarthbendable(location.getBlock())) { - new RegenTempBlock(location.getBlock(), Material.AIR, Material.AIR.createBlockData(), 700L); + //new RegenTempBlock(location.getBlock(), Material.AIR, Material.AIR.createBlockData(), 700L); + new TempBlock(location.getBlock(), Material.AIR.createBlockData(), 700L); new TempFallingBlock(locationYUP, cloneType.createBlockData(), new Vector(0.0, 0.35, 0.0), this); } From 6bbefe42c905d06dbbc78001df80b7c1552d71dc Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 02:02:04 -0400 Subject: [PATCH 10/61] EarthShard source launches entities up --- .../jedk1/jedcore/ability/earthbending/EarthShard.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java index 96c34e1..5576980 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java @@ -17,6 +17,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -109,7 +110,6 @@ public void raiseEarthBlock(Block block) { Vector blockVector = block.getLocation().toVector().toBlockVector().setY(0); - // Don't select from locations that already have an EarthShard block. for (TempBlock tempBlock : tblockTracker) { if (tempBlock.getLocation().getWorld() != block.getWorld()) { continue; @@ -146,6 +146,14 @@ public void raiseEarthBlock(Block block) { new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); tblockTracker.add(tb); + + for (Entity entity : block.getWorld().getNearbyEntities(block.getLocation(), 1.5, 1.5, 1.5)) { + Location entityLoc = entity.getLocation(); + if (entityLoc.getY() >= block.getY()) { + Vector velocity = new Vector(0, 1, 0); + entity.setVelocity(entity.getVelocity().add(velocity)); + } + } } } From 3e6aa6a11594e3f279522941b594e68f37f084c4 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 02:18:32 -0400 Subject: [PATCH 11/61] Adds EarthKick normal and metal damage config --- .../ability/earthbending/EarthKick.java | 18 +++++++++++++++--- .../jedcore/configuration/JedCoreConfig.java | 10 +++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java index d941438..6020481 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -45,6 +45,8 @@ public class EarthKick extends EarthAbility implements AddonAbility { private int earthBlocks; @Attribute(Attribute.DAMAGE) private double damage; + @Attribute(Attribute.DAMAGE) + private double metalDmg; @Attribute("CollisionRadius") private double entityCollisionRadius; private Block block; @@ -80,7 +82,8 @@ public void setFields() { cooldown = config.getLong("Abilities.Earth.EarthKick.Cooldown"); earthBlocks = config.getInt("Abilities.Earth.EarthKick.EarthBlocks"); - damage = config.getDouble("Abilities.Earth.EarthKick.Damage"); + damage = config.getDouble("Abilities.Earth.EarthKick.Damage.Normal"); + metalDmg = config.getDouble("Abilities.Earth.EarthKick.Damage.Metal"); entityCollisionRadius = config.getDouble("Abilities.Earth.EarthKick.EntityCollisionRadius"); multipleHits = config.getBoolean("Abilities.Earth.EarthKick.MultipleHits"); @@ -97,7 +100,8 @@ public void setFields() { private boolean prepare() { block = player.getTargetBlock(getTransparentMaterialSet(), sourceRange); - if (!isEarthbendable(player, block) && !isBendableEarthTempBlock(block)) { + //if (!isEarthbendable(player, block) && !isBendableEarthTempBlock(block)) { + if (!isEarthbendable(player, block)) { return false; } @@ -192,7 +196,7 @@ public void track() { CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { UUID uuid = entity.getUniqueId(); if (this.multipleHits || hitEntities.add(uuid)) { - DamageHandler.damageEntity(entity, damage, this); + DamageHandler.damageEntity(entity, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : damage, this); } return false; }); @@ -290,6 +294,14 @@ public void setDamage(double damage) { this.damage = damage; } + public double getMetalDmg() { + return metalDmg; + } + + public void setMetalDmg(double metalDmg) { + this.metalDmg = metalDmg; + } + public double getEntityCollisionRadius() { return entityCollisionRadius; } diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 77295c6..076aef3 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -234,7 +234,15 @@ private void loadConfigCore() { + "your foe!"); config.addDefault("Abilities.Earth.EarthKick.Cooldown", 2000); config.addDefault("Abilities.Earth.EarthKick.EarthBlocks", 10); - config.addDefault("Abilities.Earth.EarthKick.Damage", 2.0); + + double oldDamage = 0.0; + if (config.contains("Abilities.Earth.EarthKick.Damage")) { + oldDamage = config.getDouble("Abilities.Earth.EarthKick.Damage"); + config.set("Abilities.Earth.EarthKick.Damage", null); + } + + config.addDefault("Abilities.Earth.EarthKick.Damage.Normal", oldDamage > 0.0 ? oldDamage : 2.0); + config.addDefault("Abilities.Earth.EarthKick.Damage.Metal", 3.0); config.addDefault("Abilities.Earth.EarthKick.EntityCollisionRadius", 1.5); config.addDefault("Abilities.Earth.EarthKick.AbilityCollisionRadius", 1.5); config.addDefault("Abilities.Earth.EarthKick.MultipleHits", true); From 02e97836b3fd162fece7375a0a99e7cf47c5585c Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 02:43:41 -0400 Subject: [PATCH 12/61] Adds Discharge and LightningBurst volume and interval config --- .../jedcore/ability/firebending/Discharge.java | 14 ++++++++++---- .../ability/firebending/LightningBurst.java | 10 ++++++++-- .../jedk1/jedcore/configuration/JedCoreConfig.java | 4 ++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/firebending/Discharge.java b/src/com/jedk1/jedcore/ability/firebending/Discharge.java index 4b74d44..49e62dc 100644 --- a/src/com/jedk1/jedcore/ability/firebending/Discharge.java +++ b/src/com/jedk1/jedcore/ability/firebending/Discharge.java @@ -44,6 +44,9 @@ public class Discharge extends LightningAbility implements AddonAbility { @Attribute("CollisionRadius") private double entityCollisionRadius; + private float soundVolume; + private int soundInterval; + public Discharge(Player player) { super(player); @@ -74,6 +77,9 @@ public void setFields() { duration = config.getLong("Abilities.Fire.Discharge.Duration"); slotSwapping = config.getBoolean("Abilities.Fire.Discharge.SlotSwapping"); entityCollisionRadius = config.getDouble("Abilities.Fire.Discharge.EntityCollisionRadius"); + + soundVolume = (float) config.getDouble("Abilities.Fire.Discharge.Sound.Volume"); + soundInterval = config.getInt("Abilities.Fire.Discharge.Sound.Interval"); branchSpace = 0.2; } @@ -138,8 +144,8 @@ private void advanceLocation() { playLightningbendingParticle(l.clone(), 0f, 0f, 0f); JCMethods.emitLight(l.clone()); - if (rand.nextInt(6) == 0) { - player.getWorld().playSound(l, Sound.ENTITY_BEE_HURT, 0.6f, 0.2f); + if (rand.nextInt(soundInterval) == 0) { + player.getWorld().playSound(l, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); } Vector vec = l.toVector(); @@ -158,8 +164,8 @@ private void advanceLocation() { JCMethods.emitLight(entity.getLocation()); } - entity.getWorld().playSound(entity.getLocation(), Sound.ENTITY_BEE_HURT, 0.8f, 0.2f); - player.getWorld().playSound(player.getLocation(), Sound.ENTITY_BEE_HURT, 0.8f, 0.2f); + entity.getWorld().playSound(entity.getLocation(), Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); + player.getWorld().playSound(player.getLocation(), Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); return true; }); diff --git a/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java b/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java index bad83a6..2227761 100644 --- a/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java +++ b/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java @@ -38,6 +38,9 @@ public class LightningBurst extends LightningAbility implements AddonAbility { private boolean charged; private static int ID = Integer.MIN_VALUE; + private float soundVolume; + private int soundInterval; + public LightningBurst(Player player) { super(player); if (!bPlayer.canBend(this) || hasAbility(player, LightningBurst.class)) { @@ -62,6 +65,9 @@ public void setFields() { avatarChargeup = config.getLong("Abilities.Fire.LightningBurst.AvatarChargeUp"); damage = config.getDouble("Abilities.Fire.LightningBurst.Damage"); radius = config.getDouble("Abilities.Fire.LightningBurst.Radius"); + + soundVolume = (float) config.getDouble("Abilities.Fire.LightningBurst.Sound.Volume"); + soundInterval = config.getInt("Abilities.Fire.LightningBurst.Sound.Interval"); } @Override @@ -310,8 +316,8 @@ private void progress() { break; } - if (rand.nextInt(5) == 0) { - location.getWorld().playSound(location, Sound.ENTITY_BEE_HURT, 0.7f, 0.2f); + if (rand.nextInt(soundInterval) == 0) { + location.getWorld().playSound(location, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); } for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 076aef3..8fae33f 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -597,6 +597,8 @@ private void loadConfigCore() { config.addDefault("Abilities.Fire.Discharge.SlotSwapping", false); config.addDefault("Abilities.Fire.Discharge.EntityCollisionRadius", 1.0); config.addDefault("Abilities.Fire.Discharge.AbilityCollisionRadius", 1.0); + config.addDefault("Abilities.Fire.Discharge.Sound.Volume", 0.6); + config.addDefault("Abilities.Fire.Discharge.Sound.Interval", 6); config.addDefault("Abilities.Fire.FireBall.Enabled", true); config.addDefault("Abilities.Fire.FireBall.Description", "To use, simply Left-Click to shoot a fireball at your target!"); @@ -700,6 +702,8 @@ private void loadConfigCore() { config.addDefault("Abilities.Fire.LightningBurst.AvatarChargeUp", 1000); config.addDefault("Abilities.Fire.LightningBurst.Radius", 12); config.addDefault("Abilities.Fire.LightningBurst.Damage", 9.0); + config.addDefault("Abilities.Fire.LightningBurst.Sound.Volume", 0.6); + config.addDefault("Abilities.Fire.LightningBurst.Sound.Interval", 6); config.addDefault("Abilities.Water.Bloodbending.Enabled", true); config.addDefault("Abilities.Water.Bloodbending.Description", "This ability allows a skilled waterbender " From c3bf28b3a8d20d7a8443d3eda38917e539d31b59 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 02:52:55 -0400 Subject: [PATCH 13/61] EarthKick will revert TempBlocks before activating --- src/com/jedk1/jedcore/ability/earthbending/EarthKick.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java index 6020481..c687a0b 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -100,11 +100,14 @@ public void setFields() { private boolean prepare() { block = player.getTargetBlock(getTransparentMaterialSet(), sourceRange); - //if (!isEarthbendable(player, block) && !isBendableEarthTempBlock(block)) { if (!isEarthbendable(player, block)) { return false; } + if (TempBlock.isTempBlock(block)) { + TempBlock.get(block).revertBlock(); + } + if (DensityShift.isPassiveSand(block)) { DensityShift.revertSand(block); } From a305ab67dd3d86d6aa764439c8cb457b63b011a7 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sun, 16 Mar 2025 03:22:17 -0400 Subject: [PATCH 14/61] Add EarthShard KnockUp toggle and velocity config --- .../jedk1/jedcore/ability/earthbending/EarthShard.java | 9 ++++++++- src/com/jedk1/jedcore/configuration/JedCoreConfig.java | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java index 5576980..ee392d3 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java @@ -55,6 +55,9 @@ public class EarthShard extends EarthAbility implements AddonAbility { private final List readyBlocksTracker = new ArrayList<>(); private final List fallingBlocks = new ArrayList<>(); + private boolean allowKnockup; + private double knockupVelocity; + public EarthShard(Player player) { super(player); @@ -93,6 +96,8 @@ public void setFields() { cooldown = config.getLong("Abilities.Earth.EarthShard.Cooldown"); abilityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); entityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); + allowKnockup = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Allow"); + knockupVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Velocity"); } public void select() { @@ -147,10 +152,12 @@ public void raiseEarthBlock(Block block) { TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); tblockTracker.add(tb); + if (!allowKnockup) return; for (Entity entity : block.getWorld().getNearbyEntities(block.getLocation(), 1.5, 1.5, 1.5)) { + if (entity instanceof FallingBlock) continue; Location entityLoc = entity.getLocation(); if (entityLoc.getY() >= block.getY()) { - Vector velocity = new Vector(0, 1, 0); + Vector velocity = new Vector(0, knockupVelocity, 0); entity.setVelocity(entity.getVelocity().add(velocity)); } } diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 8fae33f..734a9c0 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -312,6 +312,8 @@ private void loadConfigCore() { config.addDefault("Abilities.Earth.EarthShard.PrepareRange", 5); config.addDefault("Abilities.Earth.EarthShard.AbilityRange", 30); config.addDefault("Abilities.Earth.EarthShard.MaxShards", 3); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Allow", true); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Velocity", 1.0); config.addDefault("Abilities.Earth.EarthShard.AbilityCollisionRadius", 2.0); config.addDefault("Abilities.Earth.EarthShard.EntityCollisionRadius", 1.4); From 83bc10804eeee696a82b59d9135448abbb417ba9 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 25 Mar 2025 11:51:36 -0400 Subject: [PATCH 15/61] IceClaws and FirePunch now respect dominant hand too --- .../ability/firebending/FirePunch.java | 29 +++++++++++++++---- .../ability/waterbending/IceClaws.java | 24 ++++++++++++--- .../jedcore/listener/AbilityListener.java | 5 ++++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/firebending/FirePunch.java b/src/com/jedk1/jedcore/ability/firebending/FirePunch.java index 1d954b9..8dfc35c 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FirePunch.java +++ b/src/com/jedk1/jedcore/ability/firebending/FirePunch.java @@ -18,6 +18,7 @@ import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.inventory.MainHand; public class FirePunch extends FireAbility implements AddonAbility { @@ -28,6 +29,8 @@ public class FirePunch extends FireAbility implements AddonAbility { @Attribute(Attribute.FIRE_TICK) private int fireTicks; + private Boolean flameInMainHand = null; + private Location location; public FirePunch(Player player) { @@ -70,12 +73,26 @@ public void progress() { return; } - location = GeneralMethods.getRightSide(player.getLocation(), 0.55) - .add(0, 1.2, 0) - .add(player.getLocation().getDirection().multiply(0.8)); - playFirebendingParticles(location, 3, 0, 0, 0); - ParticleEffect.SMOKE_NORMAL.display(location, 1); - JCMethods.emitLight(location); + Location hand = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); + + playFirebendingParticles(hand, 3, 0, 0, 0); + ParticleEffect.SMOKE_NORMAL.display(hand, 1); + JCMethods.emitLight(hand); + } + + public static void swapHands(Player player) { + FirePunch fp = getAbility(player, FirePunch.class); + if (fp == null) + return; + if (fp.flameInMainHand == null) + fp.flameInMainHand = true; + else fp.flameInMainHand = !fp.flameInMainHand; + } + + public Location getRightHandPos() { + return (player.getMainHand() == MainHand.RIGHT == ((flameInMainHand == null) || flameInMainHand) ? + GeneralMethods.getRightSide(player.getLocation(), .55) : + GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); } public void punch(LivingEntity target) { diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java b/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java index 5594a0c..e211317 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java @@ -1,6 +1,7 @@ package com.jedk1.jedcore.ability.waterbending; import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.ability.firebending.FirePunch; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.AddonAbility; @@ -15,6 +16,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.inventory.MainHand; import org.bukkit.potion.PotionEffectType; public class IceClaws extends IceAbility implements AddonAbility { @@ -34,6 +36,8 @@ public class IceClaws extends IceAbility implements AddonAbility { private Location origin; private boolean launched; + private Boolean iceInMainHand = null; + public IceClaws(Player player) { super(player); if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { @@ -96,6 +100,22 @@ public void progress() { } } + + public static void swapHands(Player player) { + IceClaws ic = getAbility(player, IceClaws.class); + if (ic == null) + return; + if (ic.iceInMainHand == null) + ic.iceInMainHand = true; + else ic.iceInMainHand = !ic.iceInMainHand; + } + + public Location getRightHandPos() { + return (player.getMainHand() == MainHand.RIGHT == ((iceInMainHand == null) || iceInMainHand) ? + GeneralMethods.getRightSide(player.getLocation(), .55) : + GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); + } + public boolean shoot() { for (double i = 0; i < 1; i+=.5) { head.add(origin.clone().getDirection().multiply(.5)); @@ -126,10 +146,6 @@ public static void throwClaws(Player player) { } } - public Location getRightHandPos() { - return GeneralMethods.getRightSide(player.getLocation(), .55).add(0, 1.2, 0); - } - private void displayClaws() { Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); GeneralMethods.displayColoredParticle("66FFFF", location); diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java index 2f04468..99f4b2d 100644 --- a/src/com/jedk1/jedcore/listener/AbilityListener.java +++ b/src/com/jedk1/jedcore/listener/AbilityListener.java @@ -393,6 +393,10 @@ public void onPlayerSneak(PlayerToggleSneakEvent event) { if (abilClass.equals(FireShots.class)) { FireShots.swapHands(player); } + + if (abilClass.equals(FirePunch.class)) { + FirePunch.swapHands(player); + } } } @@ -504,6 +508,7 @@ public void onPlayerSneak(PlayerToggleSneakEvent event) { } if (abilClass.equals(IceClaws.class)) { new IceClaws(player); + IceClaws.swapHands(player); } if (abilClass.equals(IceWall.class)) { new IceWall(player); From 5fa0c59b43f745ddbbebfdfc25e0504c9bf1738d Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 25 Mar 2025 12:00:26 -0400 Subject: [PATCH 16/61] (re)fix DaggerThrow damage config --- src/com/jedk1/jedcore/listener/AbilityListener.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java index 99f4b2d..6114022 100644 --- a/src/com/jedk1/jedcore/listener/AbilityListener.java +++ b/src/com/jedk1/jedcore/listener/AbilityListener.java @@ -533,9 +533,10 @@ public void onPlayerSneak(PlayerToggleSneakEvent event) { public void onArrowHit(EntityDamageByEntityEvent event) { if (event.getDamager().getType() == EntityType.ARROW) { Arrow arrow = (Arrow) event.getDamager(); - if (arrow.getShooter() instanceof Player && arrow.hasMetadata("daggerthrow")){ + if (arrow.getShooter() instanceof Player && arrow.hasMetadata("daggerthrow")) { Player player = (Player) arrow.getShooter(); - player.playSound(player.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1f, 1); + event.setDamage(0.0D); + player.playSound(player.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 1.0f); } } } From 6675ae3844741f85c98a0795acb089d25b561107 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 25 Mar 2025 15:48:30 -0400 Subject: [PATCH 17/61] Add material skip list to Combustion --- .../ability/firebending/Combustion.java | 53 +++++++++++++++++-- .../jedcore/configuration/JedCoreConfig.java | 13 ++++- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/firebending/Combustion.java b/src/com/jedk1/jedcore/ability/firebending/Combustion.java index d4cefcc..1e4edff 100644 --- a/src/com/jedk1/jedcore/ability/firebending/Combustion.java +++ b/src/com/jedk1/jedcore/ability/firebending/Combustion.java @@ -7,7 +7,10 @@ import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.policies.removal.*; import com.jedk1.jedcore.util.FireTick; -import com.jedk1.jedcore.util.LightManager; + +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.Tag; import com.jedk1.jedcore.util.MaterialUtil; import com.jedk1.jedcore.util.RegenTempBlock; import com.projectkorra.projectkorra.GeneralMethods; @@ -33,9 +36,11 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; +import java.util.stream.Collectors; public class Combustion extends CombustionAbility implements AddonAbility { @@ -45,6 +50,8 @@ public class Combustion extends CombustionAbility implements AddonAbility { private long cooldown; private CompositeRemovalPolicy removalPolicy; + private ArrayList skipMaterials; // use a configured list of blocks to skip through + public Combustion(Player player) { super(player); @@ -81,6 +88,8 @@ public void setFields() { ); this.removalPolicy.load(config, "Abilities.Fire.Combustion"); + + this.skipMaterials = loadSkipMaterials(); } @Override @@ -171,6 +180,35 @@ public boolean isEnabled() { return config.getBoolean("Abilities.Fire.Combustion.Enabled"); } + private ArrayList loadSkipMaterials() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + ArrayList skipList = new ArrayList<>(); + + if (config.contains("Abilities.Fire.Combustion.SkipMaterials")) { + List configuredSkipList = config.getStringList("Abilities.Fire.Combustion.SkipMaterials"); + + for (String entry : configuredSkipList) { + if (entry.startsWith("#")) { + String tagName = entry.substring(1).toLowerCase(); + + NamespacedKey tagKey = NamespacedKey.minecraft(tagName); + Tag materialTag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, tagKey, Material.class); + + if (materialTag != null) { + skipList.addAll(materialTag.getValues().stream() + .map(material -> material.name().toLowerCase()) + .collect(Collectors.toList())); + } + } else { + skipList.add(entry.toLowerCase()); + } + } + } + + return skipList; + } + private interface State { void update(); } @@ -328,8 +366,15 @@ private void travel() { } if (!MaterialUtil.isTransparent(location.getBlock()) || isWater(location.getBlock())) { - state = new CombustState(location); - return; + Material blockMaterial = location.getBlock().getType(); + String blockMaterialName = blockMaterial.name().toLowerCase(); + + boolean shouldSkip = skipMaterials.contains(blockMaterialName); + + if (!shouldSkip) { + state = new CombustState(location); + return; + } } direction = player.getEyeLocation().getDirection().normalize(); @@ -581,4 +626,4 @@ public boolean destroyBlock(Location l) { return false; } } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 734a9c0..a81e993 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -565,7 +565,15 @@ private void loadConfigCore() { config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources", 15); config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Combination", Arrays.asList("EarthBlast:SHIFT_DOWN", "LavaFlow:SHIFT_UP", "LavaFlow:SHIFT_DOWN", "LavaFlow:RIGHT_CLICK_BLOCK")); config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Instructions", "EarthBlast (Hold sneak) > LavaFlow (Release sneak) > LavaFlow (Hold sneak) > LavaFlow (Right-click a block) > LavaFlow (Left-click multiple times)"); - + + ArrayList combustionSkipMaterials = new ArrayList<>(); + combustionSkipMaterials.add("#bee_growables"); + combustionSkipMaterials.add("#cave_vines"); + combustionSkipMaterials.add("#crops"); + combustionSkipMaterials.add("#flowers"); + combustionSkipMaterials.add("vine"); + combustionSkipMaterials.add("pale_hanging_moss"); + config.addDefault("Abilities.Fire.Combustion.Enabled", true); config.addDefault("Abilities.Fire.Combustion.Description", "Hold Shift to focus large amounts of energy into your body, " + "Release Shift to fire Combustion. Move your mouse to " @@ -588,7 +596,8 @@ private void loadConfigCore() { config.addDefault("Abilities.Fire.Combustion.InstantExplodeIfHit", true); config.addDefault("Abilities.Fire.Combustion.ExplodeOnDeath", true); config.addDefault("Abilities.Fire.Combustion.RemovalPolicy.SwappedSlots.Enabled", false); - + config.addDefault("Abilities.Fire.Combustion.SkipMaterials", combustionSkipMaterials); + config.addDefault("Abilities.Fire.Discharge.Enabled", true); config.addDefault("Abilities.Fire.Discharge.Description", "Left-Click to shoot bolts of electricity out " + "of your fingertips zapping what ever it hits!"); From fb6a8e66ee253af4e561ae79c8f4d5bc054d8ac2 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 25 Mar 2025 16:11:57 -0400 Subject: [PATCH 18/61] Fix BendingGUI support with a config stub. Note: enabling the JedCore bendingboard will still do nothing, it doesn't exist. --- .../jedk1/jedcore/configuration/JedCoreConfig.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index a81e993..195d9d8 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -17,13 +17,24 @@ public class JedCoreConfig { static JedCore plugin; + public static Config board; public JedCoreConfig(JedCore plugin) { JedCoreConfig.plugin = plugin; + board = new Config(new File("board.yml")); + loadConfigBoard(); loadConfigCore(); addDeathMessages(); setupElementSphereNames(); } + + private void loadConfigBoard() { + FileConfiguration config; + config = board.getConfig(); + config.addDefault("Settings.Enabled", false); + config.options().copyDefaults(true); + board.saveConfig(); + } private void loadConfigCore() { FileConfiguration config; From 32c9d29bc88805fd1cfb745ae139b1a68ee087c9 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 25 Mar 2025 16:57:59 -0400 Subject: [PATCH 19/61] Add `bending.ability.IceSkate` permission. Allow toggling IceSkate using only /b toggle waterpassives specifically. --- .../ability/waterbending/IcePassive.java | 23 ++++++++++++------- src/plugin.yml | 1 + 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java index 9477a8c..37478f0 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java @@ -12,6 +12,7 @@ import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; +import org.bukkit.permissions.Permission; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -20,7 +21,6 @@ public class IcePassive { - @SuppressWarnings("deprecation") public static void handleSkating() { Map> resultCache = new HashMap<>(); @@ -40,15 +40,22 @@ public static void handleSkating() { int speedFactor = result.second; if (!enabled) continue; + if (JCMethods.isDisabledWorld(player.getWorld())) continue; + if (!player.isOnGround()) continue; + if (!player.isSprinting()) continue; + if (!IceAbility.isIce(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) continue; BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer != null && bPlayer.canIcebend() && bPlayer.isElementToggled(Element.WATER) && bPlayer.hasElement(Element.WATER) && !JCMethods.isDisabledWorld(player.getWorld())) { - if (player.isSprinting() && IceAbility.isIce(player.getLocation().getBlock().getRelative(BlockFace.DOWN)) && player.isOnGround()) { - ParticleEffect.SNOW_SHOVEL.display(player.getLocation().clone().add(0, 0.2, 0), 15, Math.random()/2, Math.random()/2, Math.random()/2, 0); - player.removePotionEffect(PotionEffectType.SPEED); - player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 60, speedFactor)); - } - } + + if (bPlayer == null) continue; + if (!bPlayer.canIcebend()) continue; + if (!bPlayer.isPassiveToggled(Element.WATER)) continue; + + if (!player.hasPermission("bending.ability.IceSkate")) continue; + + ParticleEffect.SNOW_SHOVEL.display(player.getLocation().clone().add(0, 0.2, 0), 15, Math.random()/2, Math.random()/2, Math.random()/2, 0); + player.removePotionEffect(PotionEffectType.SPEED); + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 60, speedFactor)); } } diff --git a/src/plugin.yml b/src/plugin.yml index eab00e3..acae96d 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -53,6 +53,7 @@ permissions: children: bending.ability.FrostBreath: true bending.ability.IceClaws: true + bending.ability.IceSkate: true bending.ability.IceWall: true bending.ability.Drain: true bending.ability.WakeFishing: true From a131623ff3e9b6b21f7ab4b2eeda1c49cb10fb54 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 25 Mar 2025 22:48:10 -0400 Subject: [PATCH 20/61] Fix for WaterFlow replacing grass blocks --- src/com/jedk1/jedcore/JCMethods.java | 10 ++++++++-- src/com/jedk1/jedcore/util/MaterialUtil.java | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/com/jedk1/jedcore/JCMethods.java b/src/com/jedk1/jedcore/JCMethods.java index f039c83..d1a802f 100644 --- a/src/com/jedk1/jedcore/JCMethods.java +++ b/src/com/jedk1/jedcore/JCMethods.java @@ -4,6 +4,7 @@ import com.jedk1.jedcore.util.*; import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; import com.projectkorra.projectkorra.region.RegionProtection; import org.bukkit.*; import org.bukkit.block.Block; @@ -23,8 +24,10 @@ import com.projectkorra.projectkorra.util.TempBlock; public class JCMethods { + + // todo: either use PKs isPlant or the registry/tags (with config) private static final ArrayList SMALL_PLANTS = new ArrayList(){{ - addAll(Arrays.asList(Material.GRASS_BLOCK, Material.FERN, Material.POPPY, Material.DANDELION, Material.OAK_SAPLING, + addAll(Arrays.asList(Material.GRASS, Material.FERN, Material.POPPY, Material.DANDELION, Material.OAK_SAPLING, Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING, Material.ALLIUM, Material.ORANGE_TULIP, Material.PINK_TULIP, Material.RED_TULIP, Material.WHITE_TULIP, Material.ROSE_BUSH, Material.BLUE_ORCHID, Material.LILAC, Material.OXEYE_DAISY, @@ -32,6 +35,7 @@ public class JCMethods { Material.BROWN_MUSHROOM, Material.PUMPKIN_STEM, Material.MELON_STEM, Material.WHEAT, Material.TALL_GRASS, Material.BEETROOTS, Material.CARROTS, Material.POTATOES, Material.CRIMSON_FUNGUS, Material.WARPED_FUNGUS, Material.BAMBOO, Material.BAMBOO_SAPLING)); + int serverVersion = GeneralMethods.getMCVersion(); if (serverVersion >= 1170) { add(Material.getMaterial("AZALEA")); @@ -305,6 +309,7 @@ public static boolean isLunarEclipse(World world) { return false; } + // todo: see SMALL_PLANTS public static boolean isDoublePlant(Material material) { return material == Material.SUNFLOWER || material == Material.LILAC || material == Material.TALL_GRASS || material == Material.LARGE_FERN || material == Material.ROSE_BUSH || material == Material.PEONY; @@ -315,7 +320,8 @@ public static boolean isSmallPlant(Block block) { } public static boolean isSmallPlant(Material material) { - return SMALL_PLANTS.contains(material); + return WaterAbility.isPlant(material); + //return SMALL_PLANTS.contains(material); } public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra) { diff --git a/src/com/jedk1/jedcore/util/MaterialUtil.java b/src/com/jedk1/jedcore/util/MaterialUtil.java index b3c60bd..25d74c7 100644 --- a/src/com/jedk1/jedcore/util/MaterialUtil.java +++ b/src/com/jedk1/jedcore/util/MaterialUtil.java @@ -11,11 +11,13 @@ import java.util.List; public class MaterialUtil { + + // todo: use the registry/tags (with config) or grab directly from PKs config maybe? private static final List TRANSPARENT_MATERIALS = new ArrayList(){{ addAll(Arrays.asList( Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.OAK_SAPLING, Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING, Material.WATER, - Material.LAVA, Material.COBWEB, Material.TALL_GRASS, Material.GRASS_BLOCK, Material.FERN, Material.DEAD_BUSH, + Material.LAVA, Material.COBWEB, Material.TALL_GRASS, Material.GRASS, Material.FERN, Material.DEAD_BUSH, Material.DANDELION, Material.POPPY, Material.BLUE_ORCHID, Material.ALLIUM, Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, Material.OXEYE_DAISY, Material.BROWN_MUSHROOM, Material.RED_MUSHROOM, Material.TORCH, Material.FIRE, From f270ea5f9b2643354a97a30d4ec50479ffe27346 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 26 Mar 2025 01:25:56 -0400 Subject: [PATCH 21/61] LavaThrow SourceGrabRange fix and various improvements --- .../ability/earthbending/LavaThrow.java | 130 ++++++++---------- .../jedcore/listener/AbilityListener.java | 8 +- 2 files changed, 63 insertions(+), 75 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java index 4fac307..9501679 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java @@ -12,8 +12,12 @@ import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.Levelled; @@ -21,11 +25,9 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; import java.util.concurrent.ConcurrentHashMap; public class LavaThrow extends LavaAbility implements AddonAbility { @@ -45,17 +47,14 @@ public class LavaThrow extends LavaAbility implements AddonAbility { private Location location; private int shots; + private Block selectedSource; + private boolean isInitialState = true; private final ConcurrentHashMap blasts = new ConcurrentHashMap<>(); public LavaThrow(Player player) { super(player); - if (hasAbility(player, LavaThrow.class)) { - LavaThrow.createBlast(player); - return; - } - if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { return; } @@ -64,21 +63,16 @@ public LavaThrow(Player player) { location = player.getLocation(); location.setPitch(0); - location = location.toVector().add(location.getDirection().multiply(sourceRange)).toLocation(location.getWorld()); - - sourceRange = Math.round(sourceRange / 2F); if (prepare()) { + player.getWorld().playSound(selectedSource.getLocation(), Sound.ITEM_BUCKET_FILL_LAVA, 1.0f, 1.0f); start(); - if (!isRemoved()) { - createBlast(); - } } } public void setFields() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); - + cooldown = config.getLong("Abilities.Earth.LavaThrow.Cooldown"); range = config.getInt("Abilities.Earth.LavaThrow.Range"); damage = config.getDouble("Abilities.Earth.LavaThrow.Damage"); @@ -95,44 +89,67 @@ public void progress() { return; } - if (player.getWorld() != location.getWorld()) { - bPlayer.addCooldown(this); + if (!bPlayer.getBoundAbilityName().equalsIgnoreCase("LAVATHROW")) { remove(); return; } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - bPlayer.addCooldown(this); + if (player.getLocation().distance(selectedSource.getLocation()) >= sourceRange) { remove(); return; } - if (shots >= shotMax) { - bPlayer.addCooldown(this); + if (blasts.isEmpty() && shots >= shotMax && !isInitialState) { + remove(); + return; } + selectedSource.getWorld().spawnParticle(Particle.FLAME, selectedSource.getLocation(), 2, 0.3, 1.0, 0.3, 0.05); + selectedSource.getWorld().spawnParticle(Particle.LAVA, selectedSource.getLocation(), 2, 0.2, 0.2, 0.2, 0); + handleBlasts(); + } - if (blasts.isEmpty()) { - bPlayer.addCooldown(this); - remove(); + private boolean prepare() { + Block targetBlock = getTargetLavaBlock(sourceRange); + + if (targetBlock != null) { + selectedSource = targetBlock; } + + return selectedSource != null; } - private boolean prepare() { - Block block = getRandomSourceBlock(location, 3); + public Block getTargetLavaBlock(int maxDistance) { + Location eyeLocation = player.getEyeLocation(); + Vector direction = eyeLocation.getDirection(); + World world = player.getWorld(); + + RayTraceResult result = world.rayTraceBlocks( + eyeLocation, direction, maxDistance, + FluidCollisionMode.ALWAYS, true + ); - return block != null; + if (result != null) { + Block hitBlock = result.getHitBlock(); + if (LavaAbility.isLava(hitBlock)) { + return hitBlock; + } + } + return null; } public void createBlast() { - // TODO: This is just the worst. Fix it so it's not hidden distance selection. - Block source = getRandomSourceBlock(location, 3); - - if (source != null) { + if (selectedSource != null && shots < shotMax) { + isInitialState = false; shots++; - Location origin = source.getLocation().clone().add(0, 2, 0); + if (shots >= shotMax) { + bPlayer.addCooldown(this); + } + + Location origin = selectedSource.getLocation().clone().add(0, 2, 0); + player.getWorld().playSound(origin, Sound.ITEM_BUCKET_EMPTY_LAVA, 1.0f, 1.0f); double viewRange = range + origin.distance(player.getEyeLocation()); Location viewTarget = GeneralMethods.getTargetedLocation(player, viewRange, Material.WATER, Material.LAVA); Vector direction = viewTarget.clone().subtract(origin).toVector().normalize(); @@ -141,8 +158,9 @@ public void createBlast() { head.setDirection(direction); blasts.put(head, origin); - new RegenTempBlock(source.getRelative(BlockFace.UP), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); - new RegenTempBlock(source, Material.AIR, Material.AIR.createBlockData(), sourceRegen, false); + new RegenTempBlock(selectedSource.getRelative(BlockFace.UP), Material.LAVA, + Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); + new RegenTempBlock(selectedSource, Material.AIR, Material.AIR.createBlockData(), sourceRegen, false); } } @@ -156,12 +174,12 @@ public void handleBlasts() { continue; } - if(RegionProtection.isRegionProtected(this, l)){ + if (RegionProtection.isRegionProtected(this, l)) { blasts.remove(l); continue; } - if(GeneralMethods.isSolid(l.getBlock())){ + if (GeneralMethods.isSolid(l.getBlock())) { blasts.remove(l); continue; } @@ -172,8 +190,8 @@ public void handleBlasts() { boolean hit = false; - for(Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 2.0D)){ - if(entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))){ + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 2.0D)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { DamageHandler.damageEntity(entity, damage, this); blasts.remove(l); @@ -189,42 +207,6 @@ public void handleBlasts() { } } - public static Block getRandomSourceBlock(Location location, int radius) { - Random rand = new Random(); - List checked = new ArrayList<>(); - List blocks = GeneralMethods.getBlocksAroundPoint(location, radius); - - for (int i = 0; i < blocks.size(); i++) { - int index = rand.nextInt(blocks.size()); - - while (checked.contains(index)) { - index = rand.nextInt(blocks.size()); - } - - checked.add(index); - - Block block = blocks.get(index); - - if (!LavaAbility.isLava(block)) { - continue; - } - - return block; - } - - return null; - } - - public static void createBlast(Player player) { - if (hasAbility(player, LavaThrow.class)) { - LavaThrow lt = getAbility(player, LavaThrow.class); - - if (lt.shots < lt.shotMax) { - lt.createBlast(); - } - } - } - @Override public long getCooldown() { return cooldown; diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java index 6114022..eef43a0 100644 --- a/src/com/jedk1/jedcore/listener/AbilityListener.java +++ b/src/com/jedk1/jedcore/listener/AbilityListener.java @@ -262,7 +262,10 @@ public void onPlayerSwing(PlayerInteractEvent event) { new LavaFlux(player); } if (abilClass.equals(LavaThrow.class)) { - new LavaThrow(player); + LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); + if (lt != null) { + lt.createBlast(); + } } if (abilClass.equals(MetalFragments.class)) { MetalFragments.shootFragment(player); @@ -459,6 +462,9 @@ public void onPlayerSneak(PlayerToggleSneakEvent event) { if (abilClass.equals(Crevice.class)) { Crevice.closeCrevice(player); } + if (abilClass.equals(LavaThrow.class)) { + new LavaThrow(player); + } } if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { From 07a25e9d058057d5a48161f6c7aad8a2af3b970f Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 26 Mar 2025 02:41:27 -0400 Subject: [PATCH 22/61] Fix LavaThrow cooldowns --- src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java | 3 +++ src/com/jedk1/jedcore/listener/AbilityListener.java | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java index 9501679..5f33d74 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java @@ -91,16 +91,19 @@ public void progress() { if (!bPlayer.getBoundAbilityName().equalsIgnoreCase("LAVATHROW")) { remove(); + if (shots > 0) bPlayer.addCooldown(this); return; } if (player.getLocation().distance(selectedSource.getLocation()) >= sourceRange) { remove(); + if (shots > 0) bPlayer.addCooldown(this); return; } if (blasts.isEmpty() && shots >= shotMax && !isInitialState) { remove(); + bPlayer.addCooldown(this); return; } diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java index eef43a0..ea734a0 100644 --- a/src/com/jedk1/jedcore/listener/AbilityListener.java +++ b/src/com/jedk1/jedcore/listener/AbilityListener.java @@ -463,7 +463,10 @@ public void onPlayerSneak(PlayerToggleSneakEvent event) { Crevice.closeCrevice(player); } if (abilClass.equals(LavaThrow.class)) { - new LavaThrow(player); + LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); + if (lt == null) { + new LavaThrow(player); + } } } From 8abafc1c097ade0c68fc66ebebbb229b694e7060 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 26 Mar 2025 14:29:08 -0400 Subject: [PATCH 23/61] Add `CurveFactor` config for LavaThrow --- .../ability/earthbending/LavaThrow.java | 23 ++++++++++++++----- .../jedcore/configuration/JedCoreConfig.java | 1 + 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java index 5f33d74..07bd010 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java @@ -44,6 +44,8 @@ public class LavaThrow extends LavaAbility implements AddonAbility { private int shotMax; @Attribute(Attribute.FIRE_TICK) private int fireTicks; + @Attribute("CurveFactor") + private double curveFactor; private Location location; private int shots; @@ -80,6 +82,7 @@ public void setFields() { sourceRegen = config.getLong("Abilities.Earth.LavaThrow.SourceRegenDelay"); shotMax = config.getInt("Abilities.Earth.LavaThrow.MaxShots"); fireTicks = config.getInt("Abilities.Earth.LavaThrow.FireTicks"); + curveFactor = config.getDouble("Abilities.Earth.LavaThrow.CurveFactor"); } @Override @@ -177,17 +180,25 @@ public void handleBlasts() { continue; } - if (RegionProtection.isRegionProtected(this, l)) { - blasts.remove(l); - continue; - } - if (GeneralMethods.isSolid(l.getBlock())) { blasts.remove(l); continue; } - head = head.add(head.getDirection().multiply(1)); + Vector currentDirection = head.getDirection(); + Vector playerLookDirection = player.getEyeLocation().getDirection(); + + Vector curveVector = playerLookDirection.clone() + .subtract(currentDirection) + .multiply(curveFactor); + + Vector newDirection = currentDirection.clone() + .add(curveVector) + .normalize(); + + head.setDirection(newDirection); + head = head.add(newDirection.multiply(1)); + new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); ParticleEffect.LAVA.display(head, 1, Math.random(), Math.random(), Math.random(), 0); diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 195d9d8..77d8d88 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -413,6 +413,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Earth.LavaThrow.SourceGrabRange", 4); config.addDefault("Abilities.Earth.LavaThrow.SourceRegenDelay", 10000); config.addDefault("Abilities.Earth.LavaThrow.FireTicks", 80); + config.addDefault("Abilities.Earth.LavaThrow.CurveFactor", 0.5); config.addDefault("Abilities.Earth.MagnetShield.Enabled", true); config.addDefault("Abilities.Earth.MagnetShield.Description", "Repel any metal projectiles using a strong magnetic shield. " From 06373a20ec59fd46be880047018108047450f101 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Fri, 28 Mar 2025 12:08:21 -0400 Subject: [PATCH 24/61] Simplify MagmaBlast collisions for consistency --- .../earthbending/combo/MagmaBlast.java | 87 +++++++++++-------- .../jedcore/listener/AbilityListener.java | 9 ++ 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java b/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java index 55426ba..9b1f9d7 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java +++ b/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java @@ -1,6 +1,5 @@ package com.jedk1.jedcore.ability.earthbending.combo; -import com.jedk1.jedcore.collision.AABB; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.MaterialUtil; import com.projectkorra.projectkorra.ability.ElementalAbility; @@ -14,7 +13,6 @@ import com.projectkorra.projectkorra.ability.ComboAbility; import com.projectkorra.projectkorra.ability.LavaAbility; import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.TempBlock; @@ -27,8 +25,10 @@ import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.util.Vector; import java.util.*; @@ -113,7 +113,8 @@ private boolean raiseSources() { for (Block newSource : potentialBlocks) { if (!isValidSource(newSource)) continue; - sources.add(new TempFallingBlock(newSource.getLocation().add(0, 1, 0), Material.NETHERRACK.createBlockData(), new Vector(0, 0.9, 0), this)); + newSource.getWorld().playSound(newSource.getLocation(), Sound.ENTITY_GHAST_SHOOT, 0.8f, 0.3f); + sources.add(new TempFallingBlock(newSource.getLocation().add(0, 1, 0), Material.MAGMA_BLOCK.createBlockData(), new Vector(0, 0.9, 0), this)); if (sources.size() >= maxSources) { break; @@ -204,7 +205,7 @@ private void handleSources() { TempFallingBlock tfb = iter.next(); if (tfb.getLocation().getBlockY() >= (origin.getBlockY() + RAISE_HEIGHT)) { - blocks.add(new TempBlock(tfb.getLocation().getBlock(), Material.NETHERRACK.createBlockData())); + blocks.add(new TempBlock(tfb.getLocation().getBlock(), Material.MAGMA_BLOCK.createBlockData())); iter.remove(); tfb.remove(); } @@ -235,8 +236,10 @@ private void displayAnimation() { } private void doPlayerCollisions() { - for (Iterator iterator = firedBlocks.iterator(); iterator.hasNext();) { - TempFallingBlock tfb = iterator.next(); + List blocksCopy = new ArrayList<>(firedBlocks); + + for (TempFallingBlock tfb : blocksCopy) { + if (!firedBlocks.contains(tfb)) continue; boolean didExplode = false; @@ -250,8 +253,7 @@ private void doPlayerCollisions() { } if (didExplode) { - tfb.remove(); - iterator.remove(); + firedBlocks.remove(tfb); } } } @@ -299,7 +301,7 @@ private void performAction() { } if (target == null) { - target = GeneralMethods.getTargetedLocation(player, selectRange, Material.NETHERRACK); + target = GeneralMethods.getTargetedLocation(player, selectRange, Material.MAGMA_BLOCK); } TempBlock tb = getClosestSource(target); @@ -314,7 +316,19 @@ private void performAction() { tb.revertBlock(); - firedBlocks.add(new TempFallingBlock(tb.getLocation(), Material.NETHERRACK.createBlockData(), direction.multiply(fireSpeed), this, true)); + FallingBlock fallingBlock = tb.getLocation().getWorld().spawnFallingBlock( + tb.getLocation().clone().add(0.5, 0.5, 0.5), + Material.MAGMA_BLOCK.createBlockData() + ); + + fallingBlock.setTicksLived(Integer.MAX_VALUE); + fallingBlock.setMetadata("magmablast", new FixedMetadataValue(JedCore.plugin, "1")); + fallingBlock.setDropItem(false); + fallingBlock.setCancelDrop(true); + + TempFallingBlock tfb = new TempFallingBlock(tb.getLocation(), Material.MAGMA_BLOCK.createBlockData(), direction.multiply(fireSpeed), this, true); + firedBlocks.add(tfb); + lastShot = time; } @@ -343,45 +357,50 @@ public static boolean blast(TempFallingBlock tfb, boolean entityCollision) { MagmaBlast mb = (MagmaBlast) tfb.getAbility(); Location location = tfb.getLocation().clone().add(0.5, 0.5, 0.5); - float radius = mb.explosionRadius; + Block hitBlock = location.getBlock(); + if (hitBlock.getType().isSolid()) { + blastEffects(location, mb); + tfb.remove(); + mb.firedBlocks.remove(tfb); + return true; + } + float radius = mb.explosionRadius; boolean didHit = false; for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, radius)) { if (!(entity instanceof LivingEntity)) continue; + if (entity == mb.player) continue; - if (entity instanceof Player) { - AABB entityBounds = AABB.PlayerBounds.at(entity.getLocation().toVector()); - AABB blockBounds = AABB.BlockBounds.at(tfb.getLocation().toVector()); - - if (entityBounds.intersects(blockBounds)) { - DamageHandler.damageEntity(entity, mb.getDamage(), mb); - didHit = true; - } - } else { - DamageHandler.damageEntity(entity, mb.getDamage(), mb); - didHit = true; - } + DamageHandler.damageEntity(entity, mb.getDamage(), mb); + ((LivingEntity) entity).setNoDamageTicks(0); + didHit = true; } - if (entityCollision && !didHit) { - return false; + if (didHit || entityCollision) { + blastEffects(location, mb); + tfb.remove(); + mb.firedBlocks.remove(tfb); + return true; } + return false; + } + + private static void blastEffects(Location location, MagmaBlast mb) { + float radius = mb.explosionRadius; float speed = 0.1f; + ParticleEffect.FLAME.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); ParticleEffect.SMOKE_LARGE.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); ParticleEffect.FIREWORKS_SPARK.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - ParticleEffect.SMOKE_LARGE.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - location.getWorld().playSound(location, (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 1f, 1f); - location.getWorld().playSound(location, (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, 1f, 1f); - - if (!entityCollision) { - mb.firedBlocks.remove(tfb); - } - - return true; + location.getWorld().playSound(location, + (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, + 1f, 1f); + location.getWorld().playSound(location, + (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, + 1f, 1f); } // Generates a random number between -max and max. diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java index ea734a0..31c033a 100644 --- a/src/com/jedk1/jedcore/listener/AbilityListener.java +++ b/src/com/jedk1/jedcore/listener/AbilityListener.java @@ -69,11 +69,13 @@ import org.bukkit.Sound; import org.bukkit.entity.Arrow; import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; @@ -556,4 +558,11 @@ public void onPlayerInteraction(PlayerInteractEvent event) { MetalFragments.shootFragment(event.getPlayer()); } } + + @EventHandler + public void onChange(EntityChangeBlockEvent event) { + if (event.getEntity() instanceof FallingBlock) { + if (event.getEntity().hasMetadata("magmablast")) event.setCancelled(true); + } + } } From 51f5ff2a6fa66a3c4cdc60d5088f5aa31b13efaf Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Fri, 28 Mar 2025 12:44:45 -0400 Subject: [PATCH 25/61] DaggerThrow: New config `RequireArrows` and `AllowPickup` --- .../ability/chiblocking/DaggerThrow.java | 59 +++++++++++-------- .../jedcore/configuration/JedCoreConfig.java | 2 + .../jedk1/jedcore/listener/JCListener.java | 6 +- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java index 0d94826..7bbfc7d 100644 --- a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java +++ b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java @@ -30,15 +30,22 @@ public class DaggerThrow extends ChiAbility implements AddonAbility { private static final List INTERACTIONS = new ArrayList<>(); private static boolean particles; + private static double damage; - private long endTime; - private int shots = 1; @Attribute(Attribute.COOLDOWN) private long cooldown; private boolean limitEnabled; @Attribute("MaxShots") private int maxShots; + + private boolean requireArrows; + // require arrows (takes arrows from inv) + private boolean allowPickup; + // allow arrow pickup (disables pickup and removes the arrow entities) + + private long endTime; + private int shots = 1; private int hits = 0; private final List arrows = new ArrayList<>(); @@ -79,6 +86,8 @@ public void setFields() { maxShots = config.getInt("Abilities.Chi.DaggerThrow.MaxDaggers.Amount"); particles = config.getBoolean("Abilities.Chi.DaggerThrow.ParticleTrail"); damage = config.getDouble("Abilities.Chi.DaggerThrow.Damage"); + requireArrows = config.getBoolean("Abilities.Chi.DaggerThrow.RequireArrows"); + allowPickup = config.getBoolean("Abilities.Chi.DaggerThrow.AllowPickup"); loadInteractions(); } @@ -113,30 +122,30 @@ public void progress() { } private void shootArrow() { - if (JCMethods.removeItemFromInventory(player, Material.ARROW, 1)) { - shots++; - Location location = player.getEyeLocation(); - - Vector vector = location.toVector(). - add(location.getDirection().multiply(2.5)). - toLocation(location.getWorld()).toVector(). - subtract(player.getEyeLocation().toVector()); - - Arrow arrow = player.launchProjectile(Arrow.class); - arrow.setVelocity(vector); - arrow.getLocation().setDirection(vector); - arrow.setKnockbackStrength(0); - arrow.setBounce(false); - arrow.setMetadata("daggerthrow", new FixedMetadataValue(JedCore.plugin, "1")); - - if (particles) { - arrow.setCritical(true); - } - - arrows.add(arrow); - endTime = System.currentTimeMillis() + 500; - bPlayer.addCooldown("DaggerThrowShot", 100); + shots++; + Location location = player.getEyeLocation(); + + Vector vector = location.toVector(). + add(location.getDirection().multiply(2.5)). + toLocation(location.getWorld()).toVector(). + subtract(player.getEyeLocation().toVector()); + + if (requireArrows) JCMethods.removeItemFromInventory(player, Material.ARROW, 1); + Arrow arrow = player.launchProjectile(Arrow.class); + arrow.setVelocity(vector); + arrow.getLocation().setDirection(vector); + arrow.setKnockbackStrength(0); + arrow.setBounce(false); + arrow.setMetadata("daggerthrow", new FixedMetadataValue(JedCore.plugin, "1")); + if (!allowPickup) arrow.setPickupStatus(Arrow.PickupStatus.DISALLOWED); + + if (particles) { + arrow.setCritical(true); } + + arrows.add(arrow); + endTime = System.currentTimeMillis() + 500; + bPlayer.addCooldown("DaggerThrowShot", 100); } public static void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 77d8d88..7aa4131 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -953,6 +953,8 @@ private void loadConfigCore() { config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Amount", 6); config.addDefault("Abilities.Chi.DaggerThrow.Damage", 1.0); config.addDefault("Abilities.Chi.DaggerThrow.ParticleTrail", true); + config.addDefault("Abilities.Chi.DaggerThrow.RequireArrows", false); + config.addDefault("Abilities.Chi.DaggerThrow.AllowPickup", false); config.addDefault("Abilities.Chi.DaggerThrow.AbilityCollisionRadius", 0.5); config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Enabled", true); config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Cooldown", 1000); diff --git a/src/com/jedk1/jedcore/listener/JCListener.java b/src/com/jedk1/jedcore/listener/JCListener.java index 7a865ff..06395ac 100644 --- a/src/com/jedk1/jedcore/listener/JCListener.java +++ b/src/com/jedk1/jedcore/listener/JCListener.java @@ -11,6 +11,7 @@ import com.jedk1.jedcore.ability.firebending.FireSki; import com.jedk1.jedcore.ability.waterbending.IceClaws; import com.jedk1.jedcore.ability.waterbending.IceWall; +import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.LightManager; import com.jedk1.jedcore.util.RegenTempBlock; import com.projectkorra.projectkorra.ProjectKorra; @@ -36,6 +37,7 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.inventory.InventoryPickupItemEvent; import org.bukkit.event.player.*; import org.bukkit.scheduler.BukkitRunnable; @@ -147,15 +149,15 @@ public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { } event.setDamage(0); event.setCancelled(true); - arrow.remove(); arrow.removeMetadata("daggerthrow", JedCore.plugin); + arrow.remove(); } if (arrow.hasMetadata("metalhook")) { - arrow.remove(); event.setDamage(0); event.setCancelled(true); arrow.removeMetadata("metalhook", JedCore.plugin); + arrow.remove(); } } } From 1b8e2f3a0a9163d0184bce21b21cc48f3bd7e4d5 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Fri, 28 Mar 2025 13:40:53 -0400 Subject: [PATCH 26/61] DaggerThrow: we really dont need DamageAbility --- .../ability/chiblocking/DaggerThrow.java | 102 +++++++----------- .../jedk1/jedcore/listener/JCListener.java | 28 ++--- 2 files changed, 52 insertions(+), 78 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java index 7bbfc7d..27110f1 100644 --- a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java +++ b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java @@ -29,9 +29,10 @@ public class DaggerThrow extends ChiAbility implements AddonAbility { private static final List INTERACTIONS = new ArrayList<>(); - private static boolean particles; + private boolean particles; - private static double damage; + @Attribute(Attribute.DAMAGE) + private double damage; @Attribute(Attribute.COOLDOWN) private long cooldown; @@ -52,10 +53,6 @@ public class DaggerThrow extends ChiAbility implements AddonAbility { public DaggerThrow(Player player) { super(player); - if (this instanceof DamageAbility) { - return; - } - if (!bPlayer.canBend(this)) { return; } @@ -148,48 +145,63 @@ private void shootArrow() { bPlayer.addCooldown("DaggerThrowShot", 100); } - public static void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { - if (RegionProtection.isRegionProtected((Player) arrow.getShooter(), arrow.getLocation(), "DaggerThrow")) { + public void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { + if (!(arrow.getShooter() instanceof Player shooter)) { + return; + } + + System.out.println("Shooter: " + shooter.getName()); + System.out.println("Static Damage Value: " + damage); + System.out.println("Entity: " + entity.getName()); + System.out.println("Entity Health Before: " + entity.getHealth()); + + if (RegionProtection.isRegionProtected(shooter, arrow.getLocation(), "DaggerThrow")) { + System.out.println("Region Protected"); return; } arrow.setVelocity(new Vector(0, 0, 0)); entity.setNoDamageTicks(0); + double prevHealth = entity.getHealth(); - Player shooter = (Player) arrow.getShooter(); - DamageAbility da = new DamageAbility(shooter); - DamageHandler.damageEntity(entity, damage, da); - da.remove(); + + System.out.println("Attempting to damage with: " + damage); + DamageHandler.damageEntity(entity, damage, this); + System.out.println("Entity Health After: " + entity.getHealth()); + if (prevHealth > entity.getHealth()) { arrow.remove(); } - if (!(entity instanceof Player)) { + if (!(entity instanceof Player target)) { return; } - DaggerThrow dt = CoreAbility.getAbility(shooter, DaggerThrow.class); - if (dt == null) { + DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); + if (daggerThrow == null) { return; } - ++dt.hits; - - Player target = (Player)entity; - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(target); + daggerThrow.hits++; + BendingPlayer targetBPlayer = BendingPlayer.getBendingPlayer(target); for (AbilityInteraction interaction : INTERACTIONS) { - if (!interaction.enabled) continue; - if (dt.hits < interaction.hitRequirement) continue; + if (!interaction.enabled || daggerThrow.hits < interaction.hitRequirement) { + continue; + } CoreAbility abilityDefinition = AbilitySelector.getAbility(interaction.name); - if (abilityDefinition == null) continue; + if (abilityDefinition == null) { + continue; + } CoreAbility ability = CoreAbility.getAbility(target, abilityDefinition.getClass()); - if (ability == null) continue; + if (ability == null) { + continue; + } ability.remove(); - bPlayer.addCooldown(ability, interaction.cooldown); + targetBPlayer.addCooldown(ability, interaction.cooldown); } } @@ -259,11 +271,11 @@ public String getDescription() { return "* JedCore Addon *\n" + config.getString("Abilities.Chi.DaggerThrow.Description"); } - public static boolean hasParticleTrail() { + public boolean hasParticleTrail() { return particles; } - public static double getDamage() { + public double getDamage() { return damage; } @@ -326,44 +338,6 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Chi.DaggerThrow.Enabled"); } - - public static class DamageAbility extends DaggerThrow { - - public DamageAbility(Player player) { - super(player); - start(); - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "DaggerThrow"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public void progress() { - remove(); - } - } private class AbilityInteraction { public boolean enabled; diff --git a/src/com/jedk1/jedcore/listener/JCListener.java b/src/com/jedk1/jedcore/listener/JCListener.java index 06395ac..4479168 100644 --- a/src/com/jedk1/jedcore/listener/JCListener.java +++ b/src/com/jedk1/jedcore/listener/JCListener.java @@ -14,8 +14,10 @@ import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.LightManager; import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.IceAbility; import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; import com.projectkorra.projectkorra.event.*; @@ -139,25 +141,23 @@ public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { } } - if (event.getDamager() instanceof Arrow) { - Arrow arrow = (Arrow) event.getDamager(); - - if (event.getEntity() instanceof LivingEntity) { - if (arrow.hasMetadata("daggerthrow") && arrow.getShooter() instanceof Player) { - if (event.getEntity().getEntityId() != ((Player) arrow.getShooter()).getEntityId()) { - DaggerThrow.damageEntityFromArrow(((LivingEntity) event.getEntity()), arrow); - } + if (event.getDamager() instanceof Arrow arrow) { + if (event.getEntity() instanceof LivingEntity) { + if (arrow.hasMetadata("daggerthrow")) { event.setDamage(0); - event.setCancelled(true); - arrow.removeMetadata("daggerthrow", JedCore.plugin); - arrow.remove(); + if (!(arrow.getShooter() instanceof Player shooter)) return; + if (!CoreAbility.hasAbility(shooter, DaggerThrow.class)) return; + DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); + if (daggerThrow != null) { + daggerThrow.damageEntityFromArrow(((LivingEntity) event.getEntity()), arrow); + arrow.remove(); + event.setCancelled(true); + } } - if (arrow.hasMetadata("metalhook")) { event.setDamage(0); - event.setCancelled(true); - arrow.removeMetadata("metalhook", JedCore.plugin); arrow.remove(); + event.setCancelled(true); } } } From 9760150c68a0c3996daa59bfac2c11271dbe9847 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Fri, 28 Mar 2025 13:43:18 -0400 Subject: [PATCH 27/61] remove debugging --- .../jedcore/ability/chiblocking/DaggerThrow.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java index 27110f1..677e70a 100644 --- a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java +++ b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java @@ -146,28 +146,16 @@ private void shootArrow() { } public void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { - if (!(arrow.getShooter() instanceof Player shooter)) { - return; - } - - System.out.println("Shooter: " + shooter.getName()); - System.out.println("Static Damage Value: " + damage); - System.out.println("Entity: " + entity.getName()); - System.out.println("Entity Health Before: " + entity.getHealth()); + if (!(arrow.getShooter() instanceof Player shooter)) return; - if (RegionProtection.isRegionProtected(shooter, arrow.getLocation(), "DaggerThrow")) { - System.out.println("Region Protected"); - return; - } + if (RegionProtection.isRegionProtected(shooter, arrow.getLocation(), "DaggerThrow")) return; arrow.setVelocity(new Vector(0, 0, 0)); entity.setNoDamageTicks(0); double prevHealth = entity.getHealth(); - System.out.println("Attempting to damage with: " + damage); DamageHandler.damageEntity(entity, damage, this); - System.out.println("Entity Health After: " + entity.getHealth()); if (prevHealth > entity.getHealth()) { arrow.remove(); From 9c9164dffe58439da61b7a8cc52796ad8ac6ad38 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Sat, 29 Mar 2025 00:51:48 -0400 Subject: [PATCH 28/61] Refactor Air and Avatar --- .../jedcore/ability/airbending/AirBlade.java | 89 +++-- .../jedcore/ability/airbending/AirBreath.java | 156 ++++---- .../jedcore/ability/airbending/AirGlide.java | 19 +- .../jedcore/ability/airbending/AirPunch.java | 94 +++-- .../jedcore/ability/airbending/Meditate.java | 22 +- .../ability/airbending/SonicBlast.java | 63 ++-- .../ability/airbending/combo/AirSlam.java | 19 +- .../ability/airbending/combo/SwiftStream.java | 20 +- .../jedcore/ability/avatar/SpiritBeam.java | 97 +++-- .../ability/avatar/elementsphere/ESAir.java | 23 +- .../ability/avatar/elementsphere/ESEarth.java | 29 +- .../ability/avatar/elementsphere/ESFire.java | 92 +++-- .../avatar/elementsphere/ESStream.java | 240 +++++++----- .../ability/avatar/elementsphere/ESWater.java | 108 ++++-- .../avatar/elementsphere/ElementSphere.java | 356 +++++++++++------- .../jedcore/configuration/JedCoreConfig.java | 24 +- 16 files changed, 898 insertions(+), 553 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java index 08b814b..f0a6d9b 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java @@ -9,7 +9,6 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; @@ -77,58 +76,67 @@ public void progress() { private void progressBlade() { for (int j = 0; j < 2; j++) { - location = location.add(direction.multiply(1)); - playAirbendingSound(location); - travelled++; - growth += 0.125; - if (travelled >= range) { - remove(); - return; - } - - if (!isTransparent(location.getBlock())) { - remove(); - return; - } - - if (RegionProtection.isRegionProtected(player, player.getLocation(), this)) { - remove(); + if (!moveAndCheckCollision()) { return; } double pitch = -location.getPitch(); Location lastLoc = location.clone(); + for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { - Location tempLoc = location.clone(); - tempLoc.setPitch(0); - Vector tempDir = tempLoc.getDirection().clone(); - tempDir.setY(0); - Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(i))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(i)))); + Location tempLoc = calculateParticleLocation(i); playAirbendingParticles(tempLoc, 1, (float) Math.random() / 2, (float) Math.random() / 2, (float) Math.random() / 2); - if (j == 0) { - // Only check collisions for each block. - if (!lastLoc.getBlock().getLocation().equals(tempLoc.getBlock().getLocation())) { - lastLoc = tempLoc; - - boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), (entity) -> { - DamageHandler.damageEntity(entity, damage, this); - remove(); - return true; - }); - - if (hit) { - remove(); - return; - } + if (j == 0 && !lastLoc.getBlock().getLocation().equals(tempLoc.getBlock().getLocation())) { + if (handleEntityCollision(tempLoc)) { + return; } + lastLoc = tempLoc; } } } } + private boolean moveAndCheckCollision() { + location = location.add(direction.multiply(1)); + playAirbendingSound(location); + travelled++; + growth += 0.125; + + if (travelled >= range || + !isTransparent(location.getBlock()) || + RegionProtection.isRegionProtected(player, player.getLocation(), this)) { + remove(); + return false; + } + return true; + } + + private Location calculateParticleLocation(double angle) { + Location tempLoc = location.clone(); + tempLoc.setPitch(0); + Vector tempDir = tempLoc.getDirection().clone(); + tempDir.setY(0); + Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(angle))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(angle)))); + return tempLoc; + } + + private boolean handleEntityCollision(Location tempLoc) { + boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), entity -> { + DamageHandler.damageEntity(entity, damage, this); + remove(); + return true; + }); + if (hit) { + remove(); + return true; + } + return false; + } + + @Override public Player getPlayer() { return player; } @@ -143,11 +151,14 @@ public List getLocations() { List locations = new ArrayList<>(); double pitch = -location.getPitch(); + for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { Location tempLoc = location.clone(); tempLoc.setPitch(0); + Vector tempDir = tempLoc.getDirection().clone(); tempDir.setY(0); + Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(i))); tempLoc.add(newDir); tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(i)))); diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBreath.java b/src/com/jedk1/jedcore/ability/airbending/AirBreath.java index d563d70..497af20 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirBreath.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirBreath.java @@ -11,10 +11,7 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - -import org.bukkit.Color; import org.bukkit.Location; -import org.bukkit.Particle; import org.bukkit.block.Block; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.ArmorStand; @@ -27,37 +24,30 @@ public class AirBreath extends AirAbility implements AddonAbility { - private boolean isAvatar; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; private int particles; - private boolean coolLava; private boolean extinguishFire; private boolean extinguishMobs; - private boolean damageEnabled; + private double launch; + private boolean regenOxygen; + private boolean avatarAmplify; + private int avatarRange; + private double avatarKnockback; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; @Attribute(Attribute.DAMAGE) private double playerDamage; @Attribute(Attribute.DAMAGE) private double mobDamage; - @Attribute(Attribute.KNOCKBACK) private double knockback; @Attribute(Attribute.RANGE) private int range; - private double launch; - - private boolean regenOxygen; - - private boolean avatarAmplify; - private int avatarRange; - private double avatarKnockback; - public AirBreath(Player player) { super(player); if (!bPlayer.canBend(this)) { @@ -65,8 +55,8 @@ public AirBreath(Player player) { } setFields(); - isAvatar = bPlayer.isAvatarState(); - if (isAvatar && avatarAmplify) { + + if (bPlayer.isAvatarState() && avatarAmplify) { range = avatarRange; knockback = avatarKnockback; } @@ -100,16 +90,19 @@ public void progress() { remove(); return; } + if (!(bPlayer.getBoundAbility() instanceof AirBreath)) { bPlayer.addCooldown(this); remove(); return; } + if (!player.isSneaking()) { bPlayer.addCooldown(this); remove(); return; } + if (System.currentTimeMillis() < getStartTime() + duration) { playAirbendingSound(player.getLocation()); createBeam(); @@ -121,9 +114,11 @@ public void progress() { private boolean isLocationSafe(Location loc) { Block block = loc.getBlock(); + if (RegionProtection.isRegionProtected(player, loc, this)) { return false; } + return isTransparent(block); } @@ -139,62 +134,91 @@ private void createBeam() { size += 0.005; damageregion += 0.01; - if (!isLocationSafe(loc)) { - if (!isTransparent(loc.getBlock())) { - if (player.getLocation().getPitch() > 30) { - GeneralMethods.setVelocity(this, player, player.getLocation().getDirection().multiply(-launch)); - } - } + if (!handleLocationSafety(loc)) { return; } - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageregion)) { - if (entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { - if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))){ - continue; - } - if (entity instanceof LivingEntity) { - if (damageEnabled) { - if (entity instanceof Player) - DamageHandler.damageEntity(entity, playerDamage, this); - else - DamageHandler.damageEntity(entity, mobDamage, this); - } - - if (regenOxygen && isWater(entity.getLocation().getBlock())) { - if (!((LivingEntity) entity).hasPotionEffect(PotionEffectType.WATER_BREATHING)) - ((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 100, 2)); - } - - if (extinguishMobs) - entity.setFireTicks(0); - } - - dir.multiply(knockback); - GeneralMethods.setVelocity(this, entity, dir); - } + handleEntityCollisions(loc, dir, damageregion); + displayBeamParticles(loc, size); + handleBlockEffects(); + } + } + + private boolean handleLocationSafety(Location loc) { + if (!isLocationSafe(loc)) { + if (!isTransparent(loc.getBlock()) && player.getLocation().getPitch() > 30) { + GeneralMethods.setVelocity(this, player, player.getLocation().getDirection().multiply(-launch)); } + return false; + } + return true; + } - if (isWater(loc.getBlock())) { - ParticleEffect.WATER_BUBBLE.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + private void handleEntityCollisions(Location loc, Vector dir, double damageregion) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageregion)) { + if (isValidTarget(entity)) { + if (isEntityProtected(entity)) { + continue; + } + applyEntityEffects(entity, dir); } + } + } - JCMethods.extinguishBlocks(player, "AirBreath", range, 2, extinguishFire, coolLava); + private boolean isValidTarget(Entity entity) { + return entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand); + } - if (getAirbendingParticles() == ParticleEffect.CLOUD) { - ParticleEffect.CLOUD.display(loc, particles, Math.random(), Math.random(), Math.random(), size); - JCMethods.displayColoredParticles("#FFFFFF", loc, particles, Math.random(), Math.random(), Math.random(), 0f); - JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particles, Math.random(), Math.random(), Math.random(), size, 50); + private boolean isEntityProtected(Entity entity) { + return RegionProtection.isRegionProtected(this, entity.getLocation()) || (entity instanceof Player && Commands.invincible.contains(entity.getName())); + } + + private void applyEntityEffects(Entity entity, Vector dir) { + if (entity instanceof LivingEntity livingEntity) { + applyDamage(livingEntity); + applyOxygenRegen(livingEntity); + if (extinguishMobs) { + livingEntity.setFireTicks(0); + } + } + dir.multiply(knockback); + GeneralMethods.setVelocity(this, entity, dir); + } + + private void applyDamage(LivingEntity entity) { + if (damageEnabled) { + if (entity instanceof Player) { + DamageHandler.damageEntity(entity, playerDamage, this); } else { - getAirbendingParticles().display(loc, particles, Math.random(), Math.random(), Math.random(), size); + DamageHandler.damageEntity(entity, mobDamage, this); } } } - /* - * @Override public void remove() { if (player.isOnline()) { - * bPlayer.addCooldown("AirBreath", cooldown); } super.remove(); } - */ + private void applyOxygenRegen(LivingEntity entity) { + if (regenOxygen && isWater(entity.getLocation().getBlock()) && !entity.hasPotionEffect(PotionEffectType.WATER_BREATHING)) { + entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 100, 2)); + } + } + + private void displayBeamParticles(Location loc, double size) { + if (isWater(loc.getBlock())) { + ParticleEffect.WATER_BUBBLE.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + } + + ParticleEffect mainParticle = getAirbendingParticles(); + if (mainParticle == ParticleEffect.CLOUD) { + ParticleEffect.CLOUD.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + JCMethods.displayColoredParticles("#FFFFFF", loc, particles, Math.random(), Math.random(), Math.random(), 0f); + JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particles, Math.random(), Math.random(), Math.random(), size, 50); + } else if (mainParticle != null) { + mainParticle.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + } + } + + private void handleBlockEffects() { + JCMethods.extinguishBlocks(player, "AirBreath", range, 2, extinguishFire, coolLava); + } @Override public long getCooldown() { @@ -368,4 +392,4 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Air.AirBreath.Enabled"); } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/ability/airbending/AirGlide.java b/src/com/jedk1/jedcore/ability/airbending/AirGlide.java index 054af57..77c0b1d 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirGlide.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirGlide.java @@ -7,7 +7,6 @@ import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.AirAbility; import com.projectkorra.projectkorra.airbending.AirSpout; - import com.projectkorra.projectkorra.attribute.Attribute; import org.bukkit.Location; import org.bukkit.block.BlockFace; @@ -17,19 +16,20 @@ public class AirGlide extends AirAbility implements AddonAbility { + private double fallSpeed; + private int particles; + private boolean airspout; + private long lastCooldown; + private boolean progressing; // The player must touch the ground for the cooldown to start if this is true. private boolean requireGround; + @Attribute(Attribute.SPEED) private double speed; - private double fallSpeed; - private int particles; - private boolean airspout; @Attribute(Attribute.COOLDOWN) private long cooldown; @Attribute(Attribute.DURATION) private long duration; - private long lastCooldown; - private boolean progressing; public AirGlide(Player player) { super(player); @@ -76,13 +76,10 @@ public void progress() { } if (CollisionDetector.isOnGround(this.player)) { - // Flip this so remove() actually removes the instance. this.requireGround = false; remove(); } else { - // Limit how frequently addCooldown is called so bending board isn't spammed with updates. if (time > lastCooldown + cooldown / 2) { - // Keep resetting the cooldown until the player touches the ground. bPlayer.addCooldown(this); lastCooldown = time; } @@ -90,6 +87,7 @@ public void progress() { } } + @SuppressWarnings("deprecation") private void update(long time) { if (this.duration > 0 && time >= this.getStartTime() + this.duration) { remove(); @@ -113,12 +111,15 @@ private void update(long time) { if (!player.isOnGround()) { Location firstLocation = player.getEyeLocation(); + Vector directionVector = firstLocation.getDirection().normalize(); double distanceFromPlayer = speed; + Vector shootFromPlayer = new Vector(directionVector.getX() * distanceFromPlayer, -fallSpeed, directionVector.getZ() * distanceFromPlayer); firstLocation.add(shootFromPlayer.getX(), shootFromPlayer.getY(), shootFromPlayer.getZ()); GeneralMethods.setVelocity(this, player, shootFromPlayer); + playAirbendingParticles(player.getLocation(), particles); } else if (!isTransparent(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) { remove(); diff --git a/src/com/jedk1/jedcore/ability/airbending/AirPunch.java b/src/com/jedk1/jedcore/ability/airbending/AirPunch.java index d776d46..eac83b2 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirPunch.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirPunch.java @@ -11,12 +11,12 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -25,6 +25,9 @@ public class AirPunch extends AirAbility implements AddonAbility { private final Map locations = new ConcurrentHashMap<>(); + private int shots; + private long lastShotTime; + @Attribute(Attribute.COOLDOWN) private long cooldown; private long threshold; @@ -35,9 +38,6 @@ public class AirPunch extends AirAbility implements AddonAbility { @Attribute("CollisionRadius") private double entityCollisionRadius; - private int shots; - private long lastShotTime; - public AirPunch(Player player) { super(player); @@ -54,8 +54,8 @@ public AirPunch(Player player) { setFields(); start(); - if (!isRemoved()) - createShot(); + + if (!isRemoved()) createShot(); } public void setFields() { @@ -107,38 +107,70 @@ private void createShot() { } private void progressShots() { - for (Location l : locations.keySet()) { - Location loc = l.clone(); - double dist = locations.get(l); - boolean cancel = false; - for (int i = 0; i < 3; i++) { - dist++; - if (cancel || dist >= range) { - cancel = true; - break; - } - loc = loc.add(loc.getDirection().clone().multiply(1)); - if (GeneralMethods.isSolid(loc.getBlock()) || isWater(loc.getBlock()) || RegionProtection.isRegionProtected(player, loc, this)) { - cancel = true; - break; - } + Iterator> iterator = locations.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + Location originalLoc = entry.getKey(); + double dist = entry.getValue(); + ShotResult result = simulateShotProgression(originalLoc, dist); - getAirbendingParticles().display(loc, 2, Math.random() / 5, Math.random() / 5, Math.random() / 5, 0.0); - playAirbendingSound(loc); + iterator.remove(); - cancel = CollisionDetector.checkEntityCollisions(player, new Sphere(loc.toVector(), entityCollisionRadius), (entity) -> { - DamageHandler.damageEntity(entity, damage, this); - return true; - }); + if (result.moved) { + locations.put(result.newLoc, result.newDist); } + } + } - if (cancel) { - locations.remove(l); + private record ShotResult(Location newLoc, double newDist, boolean moved) {} + + private ShotResult simulateShotProgression(Location startLoc, double startDist) { + Location loc = startLoc.clone(); + double dist = startDist; + boolean shouldRemove = false; + boolean moved = false; + + for (int i = 0; i < 3 && !shouldRemove; i++) { + dist++; + if (dist >= range) { + shouldRemove = true; } else { - locations.remove(l); - locations.put(loc, dist); + Location nextLoc = calculateNextLocation(loc); + if (isPathBlocked(nextLoc)) { + shouldRemove = true; + } else { + applyShotEffects(nextLoc); + if (checkAndHandleCollision(nextLoc)) { + shouldRemove = true; + } else { + loc = nextLoc; + moved = true; + } + } } } + + return new ShotResult(loc, dist, moved); + } + + private Location calculateNextLocation(Location currentLocation) { + return currentLocation.add(currentLocation.getDirection().clone().multiply(1)); + } + + private boolean isPathBlocked(Location location) { + return GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock()) || RegionProtection.isRegionProtected(player, location, this); + } + + private void applyShotEffects(Location location) { + getAirbendingParticles().display(location, 2, Math.random() / 5, Math.random() / 5, Math.random() / 5, 0.0); + playAirbendingSound(location); + } + + private boolean checkAndHandleCollision(Location location) { + return CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), entityCollisionRadius), entity -> { + DamageHandler.damageEntity(entity, damage, this); + return true; + }); } @Override diff --git a/src/com/jedk1/jedcore/ability/airbending/Meditate.java b/src/com/jedk1/jedcore/ability/airbending/Meditate.java index 8f40caa..c240829 100644 --- a/src/com/jedk1/jedcore/ability/airbending/Meditate.java +++ b/src/com/jedk1/jedcore/ability/airbending/Meditate.java @@ -7,7 +7,6 @@ import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.SpiritualAbility; import com.projectkorra.projectkorra.attribute.Attribute; - import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.configuration.ConfigurationSection; @@ -18,19 +17,19 @@ public class Meditate extends SpiritualAbility implements AddonAbility { private double startHealth; - private String unfocusMsg; private long warmup; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private int boostDuration; private int particleDensity; private boolean lossFocusMessage; private int absorptionBoost; private int speedBoost; private int jumpBoost; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private int boostDuration; + public Meditate(Player player) { super(player); if (!bPlayer.canBend(this)) { @@ -63,20 +62,23 @@ public void progress() { remove(); return; } + if (!bPlayer.canBendIgnoreCooldowns(this)) { remove(); return; } + if (player.getHealth() < startHealth) { - if (lossFocusMessage) { - player.sendMessage(Element.SPIRITUAL.getColor() + unfocusMsg); - } + if (lossFocusMessage) player.sendMessage(Element.SPIRITUAL.getColor() + unfocusMsg); remove(); return; } + if (System.currentTimeMillis() > getStartTime() + warmup) { player.spawnParticle(Particle.ELECTRIC_SPARK, player.getLocation(), 3, 0.5, 0.5, 0.5, 0.003F); + JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particleDensity, Math.random(), Math.random(), Math.random(), 0f); + if (!player.isSneaking()) { bPlayer.addCooldown(this); givePlayerBuffs(); @@ -93,6 +95,7 @@ private void givePlayerBuffs() { if (player.hasPotionEffect(PotionEffectType.SPEED)) { player.removePotionEffect(PotionEffectType.SPEED); } + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, boostDuration/50, speedBoost - 1)); JedCore.plugin.getPotionEffectAdapter().applyJumpBoost(player, boostDuration, jumpBoost); @@ -100,6 +103,7 @@ private void givePlayerBuffs() { if (player.hasPotionEffect(PotionEffectType.ABSORPTION)) { player.removePotionEffect(PotionEffectType.ABSORPTION); } + player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, boostDuration/50, absorptionBoost - 1)); } diff --git a/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java b/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java index 0edeb08..5ae22f2 100644 --- a/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java +++ b/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java @@ -10,7 +10,6 @@ import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.configuration.ConfigurationSection; @@ -26,6 +25,9 @@ public class SonicBlast extends AirAbility implements AddonAbility { private Vector direction; private boolean isCharged; private int travelled; + private int nauseaDur; + private int blindDur; + private boolean chargeSwapping; @Attribute(Attribute.DAMAGE) private double damage; @@ -37,9 +39,6 @@ public class SonicBlast extends AirAbility implements AddonAbility { private long cooldown; @Attribute("WarmUp") private long warmup; - private int nauseaDur; - private int blindDur; - private boolean chargeSwapping; public SonicBlast(Player player) { super(player); @@ -67,40 +66,52 @@ public void setFields() { @Override public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); + if (!checkPlayerState()) { return; } - CoreAbility boundAbility = bPlayer.getBoundAbility(); - - if (!this.chargeSwapping && this.travelled == 0 && !(boundAbility instanceof SonicBlast)) { + if (!canStartAbility()) { remove(); return; } if (player.isSneaking() && travelled == 0) { - direction = player.getEyeLocation().getDirection().normalize(); + handleCharging(); + } else { + handleProgression(); + } + } + + private boolean checkPlayerState() { + return !player.isDead() && player.isOnline(); + } + + private boolean canStartAbility() { + CoreAbility boundAbility = bPlayer.getBoundAbility(); + return chargeSwapping || travelled > 0 || boundAbility instanceof SonicBlast; + } - if (isCharged) { - playAirbendingParticles(player.getLocation().add(0, 1, 0), 5, (float) Math.random(), (float) Math.random(), (float) Math.random()); - } else if (System.currentTimeMillis() > getStartTime() + warmup) { - isCharged = true; + private void handleCharging() { + direction = player.getEyeLocation().getDirection().normalize(); + if (isCharged) { + playAirbendingParticles(player.getLocation().add(0, 1, 0), 5, (float) Math.random(), (float) Math.random(), (float) Math.random()); + } else if (System.currentTimeMillis() > getStartTime() + warmup) { + isCharged = true; + } + } + + private void handleProgression() { + if (isCharged) { + if (!bPlayer.isOnCooldown(this)) { + bPlayer.addCooldown(this); } - } else { - if (isCharged) { - if (!bPlayer.isOnCooldown(this)) { - bPlayer.addCooldown(this); - } - - if (travelled < range && isLocationSafe()) { - advanceLocation(); - } else { - remove(); - } + if (travelled < range && isLocationSafe()) { + advanceLocation(); } else { remove(); } + } else { + remove(); } } @@ -129,7 +140,7 @@ private void advanceLocation() { playAirbendingParticles(temp, 1, 0, 0, 0); } - boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), entityCollisionRadius), (entity) -> { + boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), entityCollisionRadius), entity -> { DamageHandler.damageEntity(entity, damage, this); LivingEntity lE = (LivingEntity) entity; diff --git a/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java b/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java index de6bbf3..f2f99b3 100644 --- a/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java +++ b/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java @@ -13,8 +13,6 @@ import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ClickType; - import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -44,14 +42,16 @@ public AirSlam(Player player) { setFields(); - Entity target = GeneralMethods.getTargetedEntity(player, range, new ArrayList<>()); - if (!(target instanceof LivingEntity) - || RegionProtection.isRegionProtected(this, target.getLocation()) - || ((target instanceof Player) && Commands.invincible.contains(target.getName()))) + Entity targetEntity = GeneralMethods.getTargetedEntity(player, range, new ArrayList<>()); + if (!(targetEntity instanceof LivingEntity) + || RegionProtection.isRegionProtected(this, targetEntity.getLocation()) + || ((targetEntity instanceof Player) && Commands.invincible.contains(targetEntity.getName()))) return; - this.target = (LivingEntity) target; + + this.target = (LivingEntity) targetEntity; start(); + if (!isRemoved()) { bPlayer.addCooldown(this); GeneralMethods.setVelocity(this, target, new Vector(0, 2, 0)); @@ -72,6 +72,7 @@ public void progress() { remove(); return; } + if (System.currentTimeMillis() > getStartTime() + 50) { Vector dir = player.getLocation().getDirection(); GeneralMethods.setVelocity(this, target, new Vector(dir.getX(), 0.05, dir.getZ()).multiply(power)); @@ -79,10 +80,12 @@ public void progress() { new ThrownEntityTracker(this, target, player, 0L); target.setFallDistance(0); } + if (System.currentTimeMillis() > getStartTime() + 400) { remove(); return; } + playAirbendingParticles(target.getLocation(), 10); } @@ -182,4 +185,4 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Air.AirCombo.AirSlam.Enabled"); } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java b/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java index f5ce42c..0b2929c 100644 --- a/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java +++ b/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java @@ -10,8 +10,6 @@ import com.projectkorra.projectkorra.ability.util.ComboUtil; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; -import com.projectkorra.projectkorra.util.ClickType; - import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -24,22 +22,25 @@ public class SwiftStream extends FlightAbility implements AddonAbility, ComboAbility { + private final List affectedEntities = new ArrayList<>(); + @Attribute(Attribute.COOLDOWN) public long cooldown; + @Attribute("DragFactor") public double dragFactor; @Attribute(Attribute.DURATION) public long duration; - private final List affectedEntities = new ArrayList<>(); - public SwiftStream(Player player) { super(player); + if (!bPlayer.canBendIgnoreBinds(this) || !bPlayer.canUseFlight()) { return; } setFields(); start(); + if (!isRemoved()) { launch(); bPlayer.addCooldown(this); @@ -65,17 +66,16 @@ public void launch() { public void affectNearby() { for (Entity e : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), 2.5)) { - if (e instanceof LivingEntity && !affectedEntities.contains(e) && e.getEntityId() != player.getEntityId()) { + if (e instanceof LivingEntity livingEntity && !affectedEntities.contains(e) && e.getEntityId() != player.getEntityId()) { Vector v = player.getVelocity().clone(); - v = v.multiply(dragFactor); - v = v.setY(player.getVelocity().getY()); - v = v.add(new Vector(0, 0.15, 0)); GeneralMethods.setVelocity(this, e, v); - affectedEntities.add((LivingEntity) e); + + affectedEntities.add(livingEntity); + new HorizontalVelocityTracker(e, player, 200, this); } } @@ -194,4 +194,4 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Air.AirCombo.SwiftStream.Enabled"); } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java b/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java index 923b772..689a3b5 100644 --- a/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java +++ b/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java @@ -11,13 +11,9 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - -import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.Particle; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -25,33 +21,31 @@ public class SpiritBeam extends AvatarAbility implements AddonAbility { - private Location location; + private Location location; private Vector direction; + private boolean damagesBlocks; + private long regen; + private boolean avatarOnly; + @Attribute(Attribute.DURATION) private long duration; @Attribute(Attribute.COOLDOWN) private long cooldown; @Attribute(Attribute.RANGE) private double range; - private boolean avatarOnly; @Attribute(Attribute.DAMAGE) private double damage; - private boolean damagesBlocks; - private long regen; @Attribute(Attribute.RADIUS) private double radius; public SpiritBeam(Player player) { super(player); - if (bPlayer.isOnCooldown(this)) { - return; - } + + if (bPlayer.isOnCooldown(this)) return; setFields(); - if (avatarOnly && !bPlayer.isAvatarState()) { - return; - } + if (avatarOnly && !bPlayer.isAvatarState()) return; start(); } @@ -75,64 +69,93 @@ public void progress() { remove(); return; } + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { bPlayer.addCooldown(this); remove(); return; } + if (System.currentTimeMillis() > getStartTime() + duration) { bPlayer.addCooldown(this); remove(); return; } + if (!player.isSneaking()) { bPlayer.addCooldown(this); remove(); return; } + if (avatarOnly && !bPlayer.isAvatarState()) { bPlayer.addCooldown(this); remove(); return; } + createBeam(); } private void createBeam() { location = player.getLocation().add(0, 1.2, 0); - direction = location.getDirection(); + Vector beamDirection = location.getDirection().normalize().multiply(0.5); + for (double i = 0; i < range; i += 0.5) { - location = location.add(direction.multiply(0.5).normalize()); + location = location.add(beamDirection); - if (RegionProtection.isRegionProtected(player, location, this)) { + if (isBeamObstructed(location)) { return; } - JCMethods.displayColoredParticles("#A020F0", location, 1, 0f, 0f, 0f, 0f); - JCMethods.displayColoredParticles("#A020F0", location, 1, (float) Math.random() / 3, (float) Math.random() / 3, (float) Math.random() / 3, 0f); + displayBeamParticles(location, beamDirection); + JCMethods.emitLight(location); + damageNearbyEntities(location); + + if (handleBlockCollision(location)) { + return; + } + } + } - ParticleEffect.BLOCK_CRACK.display(location, 1,(float) Math.random() / 3, (float) Math.random() / 3, (float) Math.random() / 3, 0.1F, Material.NETHER_PORTAL.createBlockData()); - ParticleEffect.BLOCK_CRACK.display(location, 1, direction.getX(), direction.getY(), direction.getZ(), 0.1F, Material.NETHER_PORTAL.createBlockData()); + private boolean isBeamObstructed(Location location) { + return RegionProtection.isRegionProtected(player, location, this); + } - JCMethods.emitLight(location); + private void displayBeamParticles(Location location, Vector direction) { + String purple = "#A020F0"; + JCMethods.displayColoredParticles(purple, location, 1, 0f, 0f, 0f, 0f); + JCMethods.displayColoredParticles(purple, location, 1, (float) Math.random() / 3, (float) Math.random() / 3, (float) Math.random() / 3, 0f); - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { - entity.setFireTicks(100); - DamageHandler.damageEntity(entity, damage, this); - } + float randomOffset = (float) Math.random() / 3; + ParticleEffect.BLOCK_CRACK.display(location, 1, randomOffset, randomOffset, randomOffset, 0.1F, Material.NETHER_PORTAL.createBlockData()); + ParticleEffect.BLOCK_CRACK.display(location, 1, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), 0.1F, Material.NETHER_PORTAL.createBlockData()); + } + + private void damageNearbyEntities(Location location) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { + if (entity instanceof LivingEntity livingEntity && livingEntity.getEntityId() != player.getEntityId()) { + livingEntity.setFireTicks(100); + DamageHandler.damageEntity(livingEntity, damage, this); } + } + } - if (location.getBlock().getType().isSolid()) { - location.getWorld().createExplosion(location, 0F); - if (damagesBlocks) { - //new TempExplosion(player, location.getBlock(), "SpiritBeam", radius, regen, damage, false); - for (Location loc : GeneralMethods.getCircle(location, (int) radius, 0, false, true, 0)) { - if (JCMethods.isUnbreakable(loc.getBlock())) continue; - new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); - } - } - return; + private boolean handleBlockCollision(Location location) { + if (location.getBlock().getType().isSolid()) { + location.getWorld().createExplosion(location, 0F); + if (damagesBlocks) { + damageBlocksInRadius(location); + } + return true; + } + return false; + } + + private void damageBlocksInRadius(Location center) { + for (Location loc : GeneralMethods.getCircle(center, (int) radius, 0, false, true, 0)) { + if (!JCMethods.isUnbreakable(loc.getBlock())) { + new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); } } } diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java index bff4481..a7e0820 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java @@ -10,7 +10,6 @@ import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.ArmorStand; @@ -36,22 +35,30 @@ public class ESAir extends AvatarAbility implements AddonAbility { public ESAir(Player player) { super(player); + if (!hasAbility(player, ElementSphere.class)) { return; } + ElementSphere currES = getAbility(player, ElementSphere.class); if (currES.getAirUses() == 0) { return; } + if (bPlayer.isOnCooldown("ESAir")) { return; } + setFields(); + if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), (int) range).getLocation())) { return; } + location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); + start(); + if (!isRemoved()) { bPlayer.addCooldown("ESAir", getCooldown()); currES.setAirUses(currES.getAirUses() - 1); @@ -74,23 +81,27 @@ public void progress() { remove(); return; } + if (travelled >= range) { remove(); return; } + advanceAttack(); } private void advanceAttack() { for (int i = 0; i < speed; i++) { travelled++; - if (travelled >= range) - return; + if (travelled >= range) return; + location = location.add(location.getDirection().clone().multiply(1)); + if (RegionProtection.isRegionProtected(this, location)) { travelled = range; return; } + if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { travelled = range; return; @@ -100,7 +111,11 @@ private void advanceAttack() { AirAbility.playAirbendingSound(location); for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand) && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() + && !(entity instanceof ArmorStand) + && !RegionProtection.isRegionProtected(this, entity.getLocation()) + && !((entity instanceof Player targetPlayer) + && Commands.invincible.contains((targetPlayer).getName()))) { DamageHandler.damageEntity(entity, damage, this); GeneralMethods.setVelocity(this, entity, location.getDirection().multiply(knockback)); travelled = range; diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java index 9113ecf..c4517b8 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java @@ -13,7 +13,6 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; @@ -28,20 +27,22 @@ import org.bukkit.entity.Player; import java.util.Arrays; -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; public class ESEarth extends AvatarAbility implements AddonAbility { + static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, Material.NETHER_PORTAL, Material.END_PORTAL, + Material.END_PORTAL_FRAME, Material.ENDER_CHEST, Material.CHEST, Material.TRAPPED_CHEST }; + + private TempFallingBlock tfb; private long revertDelay; + @Attribute(Attribute.DAMAGE) private double damage; @Attribute("Size") private int impactSize; @Attribute(Attribute.COOLDOWN) private long cooldown; - private TempFallingBlock tfb; - - static Random rand = new Random(); public ESEarth(Player player) { super(player); @@ -95,13 +96,13 @@ public void progress() { EarthAbility.playEarthbendingSound(tfb.getLocation()); for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), 2.5)) { - if (entity instanceof LivingEntity && !(entity instanceof ArmorStand) && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { - //explodeEarth(fb); + if (entity instanceof LivingEntity && !(entity instanceof ArmorStand) && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player targetPlayer) && Commands.invincible.contains(targetPlayer.getName()))) { DamageHandler.damageEntity(entity, damage, this); } } } + // Unused public static void explodeEarth(TempFallingBlock tempfallingblock) { FallingBlock fb = tempfallingblock.getFallingBlock(); ESEarth es = (ESEarth) tempfallingblock.getAbility(); @@ -110,29 +111,23 @@ public static void explodeEarth(TempFallingBlock tempfallingblock) { ParticleEffect.SMOKE_LARGE.display(fb.getLocation(), 0, 0, 0, 0.3F, 25); fb.getWorld().playSound(fb.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 2f, 0.5f); + ThreadLocalRandom rand = ThreadLocalRandom.current(); + for (Location l : GeneralMethods.getCircle(fb.getLocation(), es.impactSize, 1, false, true, 0)) { - //if (TempBlock.isTempBlock(l.getBlock())) { - // TempBlock.revertBlock(l.getBlock(), Material.AIR); - // TempBlock.removeBlock(l.getBlock()); - //} if (isBreakable(l.getBlock()) && !RegionProtection.isRegionProtected(player, l, "ElementSphere") && EarthAbility.isEarthbendable(player, l.getBlock())) { ParticleEffect.SMOKE_LARGE.display(l, 0, 0, 0, 0.1F, 2); - //new RegenTempBlock(l.getBlock(), Material.AIR, (byte) 0, (long) rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000)); - new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), (long) rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000), false); + new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000), false); } if (GeneralMethods.isSolid(l.getBlock().getRelative(BlockFace.DOWN)) && isBreakable(l.getBlock()) && ElementalAbility.isAir(l.getBlock().getType()) && rand.nextInt(20) == 0 && EarthAbility.isEarthbendable(player, l.getBlock().getRelative(BlockFace.DOWN))) { Material type = l.getBlock().getRelative(BlockFace.DOWN).getType(); - new RegenTempBlock(l.getBlock(), type, type.createBlockData(), (long) rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000)); + new RegenTempBlock(l.getBlock(), type, type.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000)); } } tempfallingblock.remove(); } - static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, Material.NETHER_PORTAL, Material.END_PORTAL, - Material.END_PORTAL_FRAME, Material.ENDER_CHEST, Material.CHEST, Material.TRAPPED_CHEST }; - public static boolean isBreakable(Block block) { return !Arrays.asList(unbreakables).contains(block.getType()); } diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java index a377d39..32ec393 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java @@ -4,8 +4,8 @@ import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.AvatarAbility; import com.projectkorra.projectkorra.ability.BlueFireAbility; @@ -16,7 +16,6 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.BlockFace; @@ -32,6 +31,7 @@ public class ESFire extends AvatarAbility implements AddonAbility { private Location location; private Vector direction; private double travelled; + private boolean controllable; @Attribute(Attribute.COOLDOWN) private long cooldown; @@ -43,22 +43,26 @@ public class ESFire extends AvatarAbility implements AddonAbility { private long burnTime; @Attribute(Attribute.SPEED) private int speed; - private boolean controllable; public ESFire(Player player) { super(player); + if (!hasAbility(player, ElementSphere.class)) { return; } + ElementSphere currES = getAbility(player, ElementSphere.class); if (currES.getFireUses() == 0) { return; } + if (bPlayer.isOnCooldown("ESFire")) { return; } + setFields(); start(); + if (!isRemoved()) { bPlayer.addCooldown("ESFire", getCooldown()); currES.setFireUses(currES.getFireUses() - 1); @@ -82,7 +86,7 @@ public void setFields() { private void applyModifiers() { if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); + cooldown *= (long) BlueFireAbility.getCooldownFactor(); range *= BlueFireAbility.getRangeFactor(); damage *= BlueFireAbility.getDamageFactor(); } @@ -94,51 +98,85 @@ public void progress() { remove(); return; } + if (travelled >= range) { remove(); return; } + advanceAttack(); } private void advanceAttack() { for (int i = 0; i < speed; i++) { - travelled++; - if (travelled >= range) + if (!incrementTravelledAndCheckRange()) { return; + } - if (!player.isDead() && controllable) - direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); + updateDirectionIfControllable(); - location = location.add(direction.clone().multiply(1)); - if (RegionProtection.isRegionProtected(this, location)) { - travelled = range; - return; - } - if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { - travelled = range; + location.add(direction.clone().multiply(1)); + + if (checkEnvironmentCollision()) { return; } - ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; - flame.display(location, 5, Math.random(), Math.random(), Math.random(), 0.02); - ParticleEffect.SMOKE_LARGE.display(location, 2, Math.random(), Math.random(), Math.random(), 0.01); - FireAbility.playFirebendingSound(location); + displayAttackParticles(); + playAttackSoundsAndLight(); + placeFire(); + handleEntityCollisions(); + } + } - JCMethods.emitLight(location); + private boolean incrementTravelledAndCheckRange() { + travelled++; + return travelled < range; + } - placeFire(); + private void updateDirectionIfControllable() { + if (!player.isDead() && controllable) { + direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); + } + } + + private boolean checkEnvironmentCollision() { + if (RegionProtection.isRegionProtected(this, location) || GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { + travelled = range; + return true; + } + return false; + } + + private void displayAttackParticles() { + ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; + flame.display(location, 5, Math.random(), Math.random(), Math.random(), 0.02); + ParticleEffect.SMOKE_LARGE.display(location, 2, Math.random(), Math.random(), Math.random(), 0.01); + } + + private void playAttackSoundsAndLight() { + FireAbility.playFirebendingSound(location); + JCMethods.emitLight(location); + } - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand) && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { - DamageHandler.damageEntity(entity, damage, this); - entity.setFireTicks(Math.round(burnTime / 50F)); - travelled = range; - } + private void handleEntityCollisions() { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (isAttackableEntity(entity)) { + DamageHandler.damageEntity(entity, damage, this); + entity.setFireTicks(Math.round(burnTime / 50F)); + travelled = range; + return; } } } + private boolean isAttackableEntity(Entity entity) { + return entity instanceof LivingEntity && + entity.getEntityId() != player.getEntityId() && + !(entity instanceof ArmorStand) && + !RegionProtection.isRegionProtected(this, entity.getLocation()) && + !((entity instanceof Player targetPlayer) && Commands.invincible.contains((targetPlayer).getName())); + } + private void placeFire() { if (GeneralMethods.isSolid(location.getBlock().getRelative(BlockFace.DOWN))) { location.getBlock().setType(Material.FIRE); diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java index 41b16c7..efc8577 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java @@ -13,9 +13,10 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.*; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.block.BlockState; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -25,7 +26,7 @@ import java.util.ArrayList; import java.util.List; -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; /** * @author jedk1 @@ -33,6 +34,14 @@ */ public class ESStream extends AvatarAbility implements AddonAbility { + private boolean cancelAbility; + private int requiredUses; + private long regen; + private Location stream; + private Location origin; + private Vector dir; + private int angle; + @Attribute(Attribute.COOLDOWN) private long cooldown; @Attribute(Attribute.KNOCKBACK) @@ -41,29 +50,22 @@ public class ESStream extends AvatarAbility implements AddonAbility { private double range; @Attribute(Attribute.DAMAGE) private double damage; - private boolean cancelAbility; - private int requiredUses; - @Attribute(Attribute.RADIUS) private double radius; - private long regen; - - private Location stream; - private Location origin; - private Vector dir; - - private int an; - Random rand = new Random(); public ESStream(Player player) { super(player); + if (!hasAbility(player, ElementSphere.class)) { return; } + ElementSphere currES = getAbility(player, ElementSphere.class); + if (bPlayer.isOnCooldown("ESStream")) { return; } + setFields(); if (currES.getAirUses() < requiredUses @@ -89,9 +91,10 @@ public ESStream(Player player) { stream = player.getEyeLocation(); origin = player.getEyeLocation(); dir = player.getEyeLocation().getDirection(); - an = 0; + angle = 0; start(); + if (!isRemoved()) { bPlayer.addCooldown("ESStream", getCooldown()); } @@ -112,118 +115,163 @@ public void setFields() { @Override public void progress() { - if (player == null || !player.isOnline()) { - remove(); + if (!checkStreamValidity()) { return; } - if (origin.distance(stream) >= range) { - remove(); + if (checkStreamRangeAndProtection()) { return; } - if (RegionProtection.isRegionProtected(player, stream, this)) { - remove(); + handleNearbyEntities(); + + updateStreamDirection(); + + stream.add(dir); + + if (handleBlockCollision()) { return; } + playStreamParticles(); + } + + private boolean checkStreamValidity() { + return player != null && player.isOnline(); + } + + private boolean checkStreamRangeAndProtection() { + if (origin.distance(stream) >= range || RegionProtection.isRegionProtected(player, stream, this)) { + remove(); + return true; + } + return false; + } + + private void handleNearbyEntities() { for (Entity e : GeneralMethods.getEntitiesAroundPoint(stream, 1.5)) { if (e instanceof Player && e == player) { continue; } - GeneralMethods.setVelocity(this, e, dir.normalize().multiply(knockback)); - if (e instanceof LivingEntity) { - DamageHandler.damageEntity(e, damage, this); - } + applyStreamEffects(e); } + } + + private void applyStreamEffects(Entity entity) { + GeneralMethods.setVelocity(this, entity, dir.normalize().multiply(knockback)); + if (entity instanceof LivingEntity) { + DamageHandler.damageEntity(entity, damage, this); + } + } + private void updateStreamDirection() { if (!player.isDead() && hasAbility(player, ElementSphere.class)) { Location loc = stream.clone(); dir = GeneralMethods.getDirection(loc, player.getTargetBlock(null, (int) range).getLocation()).normalize().multiply(1.2); } + } - stream.add(dir); - + private boolean handleBlockCollision() { if (!isTransparent(stream.getBlock())) { - List blocks = new ArrayList<>(); - for (Location loc : GeneralMethods.getCircle(stream, (int) radius, 0, false, true, 0)) { - if (JCMethods.isUnbreakable(loc.getBlock())) continue; - if (RegionProtection.isRegionProtected(this, loc)) continue; - blocks.add(loc.getBlock().getState()); - new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); - } - for (Entity e : GeneralMethods.getEntitiesAroundPoint(stream, radius)) { - if (e instanceof Player && e == player) { - continue; - } - if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(((Player) e).getName()))){ - continue; - } - GeneralMethods.setVelocity(this, e, dir.normalize().multiply(knockback)); - if (e instanceof LivingEntity) { - DamageHandler.damageEntity(e, damage, this); - } - } + triggerCollisionEffects(); + remove(); + return true; + } + return false; + } + + private void triggerCollisionEffects() { + ThreadLocalRandom rand = ThreadLocalRandom.current(); + List blocks = getAffectedBlocks(); + damageNearbyEntitiesOnCollision(); + displayCollisionParticles(); + playCollisionSounds(rand); + spawnFallingBlocks(rand, blocks); + } - ParticleEffect.FLAME.display(stream, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.SMOKE_LARGE.display(stream, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.FIREWORKS_SPARK.display(stream, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.SMOKE_LARGE.display(stream, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.EXPLOSION_HUGE.display(stream, 5, Math.random(), Math.random(), Math.random(), 0.5); + private List getAffectedBlocks() { + List blocks = new ArrayList<>(); + for (Location loc : GeneralMethods.getCircle(stream, (int) radius, 0, false, true, 0)) { + if (JCMethods.isUnbreakable(loc.getBlock()) || RegionProtection.isRegionProtected(this, loc)) continue; + blocks.add(loc.getBlock().getState()); + new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); + } + return blocks; + } - stream.getWorld().playSound(stream, (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 1f, 1f); - stream.getWorld().playSound(stream, (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, 1f, 1f); + private void damageNearbyEntitiesOnCollision() { + GeneralMethods.getEntitiesAroundPoint(stream, radius).stream().filter(e -> !(e instanceof Player) || e != player).filter(e -> !RegionProtection.isRegionProtected(this, e.getLocation()) && (!(e instanceof Player targetPlayer) || !Commands.invincible.contains((targetPlayer).getName()))).forEach(e -> { + GeneralMethods.setVelocity(this, e, dir.normalize().multiply(knockback)); + if (e instanceof LivingEntity) DamageHandler.damageEntity(e, damage, this); + }); + } - for (BlockState block : blocks) { - double x = rand.nextDouble() / 3; - double z = rand.nextDouble() / 3; + private void displayCollisionParticles() { + ParticleEffect.FLAME.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.SMOKE_LARGE.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.FIREWORKS_SPARK.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.SMOKE_LARGE.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.EXPLOSION_HUGE.display(stream, 5, 0.5F, 0.5F, 0.5F, 0.5F); + } - x = (rand.nextBoolean()) ? -x : x; - z = (rand.nextBoolean()) ? -z : z; + private void playCollisionSounds(ThreadLocalRandom rand) { + stream.getWorld().playSound(stream, rand.nextBoolean() ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 1f, 1f); + stream.getWorld().playSound(stream, rand.nextBoolean() ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, 1f, 1f); + } - new TempFallingBlock(block.getLocation().add(0, 1, 0), block.getBlockData(), dir.clone().add(new Vector(x, 0, z)).normalize().multiply(-1), this); - } - remove(); - return; + private void spawnFallingBlocks(ThreadLocalRandom rand, List blocks) { + for (BlockState block : blocks) { + double x = (rand.nextBoolean() ? -1 : 1) * rand.nextDouble() / 3; + double z = (rand.nextBoolean() ? -1 : 1) * rand.nextDouble() / 3; + new TempFallingBlock(block.getLocation().add(0, 1, 0), block.getBlockData(), dir.clone().add(new Vector(x, 0, z)).normalize().multiply(-1), this); } - - an += 20; - if (an > 360) { - an = 0; + } + + private void playStreamParticles() { + angle += 20; + if (angle > 360) { + angle = 0; } for (int i = 0; i < 4; i++) { - for (double d = -4; d <= 0; d += .1) { - if (origin.distance(stream) < d) { - continue; - } - Location l = stream.clone().add(dir.clone().normalize().multiply(d)); - double r = d * -1 / 5; - if (r > .75) { - r = .75; - } + playIndividualStreamParticles(i); + } + } - Vector ov = GeneralMethods.getOrthogonalVector(dir, an + (90 * i) + d, r); - Location pl = l.clone().add(ov.clone()); - switch (i) { - case 0: - ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; - flame.display(pl, 1, 0.05F, 0.05F, 0.05F, 0.005F); - break; - case 1: - if (rand.nextInt(30) == 0) { - JCMethods.displayColoredParticles("#FFFFFF", pl, 1, 0, 0, 0, 0.003f); - } else { - JCMethods.displayColoredParticles("#FFFFFF", pl, 1, 0.05, 0.05, 0.05, 0.005f, 50); - } - break; - case 2: - GeneralMethods.displayColoredParticle("06C1FF", pl); - break; - case 3: - GeneralMethods.displayColoredParticle("754719", pl); - break; + private void playIndividualStreamParticles(int particleIndex) { + for (double d = -4; d <= 0; d += 0.1) { + if (origin.distance(stream) < d) continue; + Location l = stream.clone().add(dir.clone().normalize().multiply(d)); + double r = Math.min(0.75, d * -1 / 5); + Vector ov = GeneralMethods.getOrthogonalVector(dir, angle + (90 * particleIndex) + d, r); + Location pl = l.clone().add(ov.clone()); + displayStreamParticle(pl, particleIndex); + } + } + + private void displayStreamParticle(Location location, int index) { + ThreadLocalRandom rand = ThreadLocalRandom.current(); + switch (index) { + case 0: + ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; + flame.display(location, 1, 0.05F, 0.05F, 0.05F, 0.005F); + break; + case 1: + String color = "#FFFFFF"; + float offset = 0.05F; + float speed = 0.005F; + int viewDistance = 50; + if (rand.nextInt(30) == 0) { + JCMethods.displayColoredParticles(color, location, 1, 0, 0, 0, speed); + } else { + JCMethods.displayColoredParticles(color, location, 1, offset, offset, offset, speed, viewDistance); } - } + break; + case 2: + GeneralMethods.displayColoredParticle("06C1FF", location); + break; + case 3: + GeneralMethods.displayColoredParticle("754719", location); + break; } } diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java index 76e92e0..4d0fbb3 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.data.Levelled; @@ -40,19 +39,26 @@ public class ESWater extends AvatarAbility implements AddonAbility { public ESWater(Player player) { super(player); + if (!hasAbility(player, ElementSphere.class)) { return; } + ElementSphere currES = getAbility(player, ElementSphere.class); if (currES.getWaterUses() == 0) { return; } + if (bPlayer.isOnCooldown("ESWater")) { return; } + setFields(); + location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); + start(); + if (!isRemoved()) { bPlayer.addCooldown("ESWater", getCooldown()); currES.setWaterUses(currES.getWaterUses() - 1); @@ -74,44 +80,82 @@ public void progress() { remove(); return; } + if (travelled >= range) { remove(); return; } + advanceAttack(); } - private void advanceAttack() { - for (int i = 0; i < speed; i++) { - travelled++; - if (travelled >= range) - return; - - if (!player.isDead()) - direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); - location = location.add(direction.clone().multiply(1)); - if (RegionProtection.isRegionProtected(this, location)){ - travelled = range; - return; - } - if (GeneralMethods.isSolid(location.getBlock()) || !isTransparent(location.getBlock())) { - travelled = range; - return; - } - - WaterAbility.playWaterbendingSound(location); - if (isWater(location.getBlock())) - ParticleEffect.WATER_BUBBLE.display(location, 3, 0.5, 0.5, 0.5); - new RegenTempBlock(location.getBlock(), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 100L); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand) && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { - DamageHandler.damageEntity(entity, damage, this); - travelled = range; - } - } - } - } + private void advanceAttack() { + for (int i = 0; i < speed; i++) { + if (!incrementTravelledAndCheckRange()) { + return; + } + + updateDirection(); + + location.add(direction.clone().multiply(1)); + + if (checkCollision()) { + return; + } + + playAttackEffects(); + handleBlockTransformation(); + handleEntityCollisions(); + } + } + + private boolean incrementTravelledAndCheckRange() { + travelled++; + return travelled < range; + } + + private void updateDirection() { + if (!player.isDead()) { + direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); + } + } + + private boolean checkCollision() { + if (RegionProtection.isRegionProtected(this, location) || GeneralMethods.isSolid(location.getBlock()) || !isTransparent(location.getBlock())) { + travelled = range; + return true; + } + return false; + } + + private void playAttackEffects() { + WaterAbility.playWaterbendingSound(location); + if (isWater(location.getBlock())) { + ParticleEffect.WATER_BUBBLE.display(location, 3, 0.5, 0.5, 0.5); + } + } + + private void handleBlockTransformation() { + new RegenTempBlock(location.getBlock(), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 100L); + } + + private void handleEntityCollisions() { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (isAttackableEntity(entity)) { + DamageHandler.damageEntity(entity, damage, this); + travelled = range; + return; + } + } + } + + private boolean isAttackableEntity(Entity entity) { + return entity instanceof LivingEntity && + entity.getEntityId() != player.getEntityId() && + !(entity instanceof ArmorStand) && + !RegionProtection.isRegionProtected(this, entity.getLocation()) && + !((entity instanceof Player targetPlayer) && Commands.invincible.contains((targetPlayer).getName())); + } @Override public long getCooldown() { diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java index 51e78de..ee6b1ca 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java @@ -13,8 +13,10 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.ParticleEffect; - -import org.bukkit.*; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; @@ -27,19 +29,34 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.Random; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ThreadLocalRandom; public class ElementSphere extends AvatarAbility implements AddonAbility, MultiAbility { - public static ConcurrentHashMap> abilities = new ConcurrentHashMap>(); + protected static final ConcurrentMap> abilities = new ConcurrentHashMap<>(); + private static final ArrayList multiAbilityInfo = new ArrayList<>(); - private World world; + static { + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AIR)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.EARTH)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.FIRE)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.WATER)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AVATAR)); + } - public int airUses; - public int fireUses; - public int waterUses; - public int earthUses; + private World world; + private int airUses; + private int fireUses; + private int waterUses; + private int earthUses; + private boolean setup; + private Location location; + private double yaw; + private int point; + private long endTime; + private long lastClickTime; @Attribute(Attribute.COOLDOWN) public long cooldown; @@ -50,87 +67,92 @@ public class ElementSphere extends AvatarAbility implements AddonAbility, MultiA @Attribute(Attribute.SPEED) private double speed; - private boolean setup; - private Location location; - private double yaw; - private int point; - private long endTime; + public ElementSphere(Player player) { + super(player); - private long lastClickTime; + ElementSphere oldES = getAbility(player, ElementSphere.class); - private static final ArrayList multiAbilityInfo = new ArrayList<>(); + if (handleExistingSphere(player, oldES)) { + return; + } - static { - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AIR)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.EARTH)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.FIRE)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.WATER)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AVATAR)); + if (canStartNewSphere()) { + initializeNewSphere(player); + } } - Random rand = new Random(); - - public ElementSphere(Player player) { - super(player); - ElementSphere oldES = getAbility(player, ElementSphere.class); + private boolean handleExistingSphere(Player player, ElementSphere oldES) { if (oldES != null) { if (player.isSneaking()) { oldES.prepareCancel(); } else { if (oldES.setup) { - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - return; - } - - switch (player.getInventory().getHeldItemSlot()) { - case 0: - if (player.hasPermission("bending.ability.ElementSphere.Air")) { - new ESAir(player); - } - break; - case 1: - if (player.hasPermission("bending.ability.ElementSphere.Earth")) { - new ESEarth(player); - } - break; - case 2: - if (player.hasPermission("bending.ability.ElementSphere.Fire")) { - new ESFire(player); - } - break; - case 3: - if (player.hasPermission("bending.ability.ElementSphere.Water")) { - new ESWater(player); - } - break; - case 4: - if (player.hasPermission("bending.ability.ElementSphere.Stream")) { - new ESStream(player); - } - break; - default: - break; - } + handleElementSwitch(player); } } + return true; + } + return false; + } + + private void handleElementSwitch(Player player) { + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { return; } + switch (player.getInventory().getHeldItemSlot()) { + case 0: + if (checkPermission(player, "Air")) new ESAir(player); + break; + case 1: + if (checkPermission(player, "Earth")) new ESEarth(player); + break; + case 2: + if (checkPermission(player, "Fire")) new ESFire(player); + break; + case 3: + if (checkPermission(player, "Water")) new ESWater(player); + break; + case 4: + if (checkPermission(player, "Stream")) new ESStream(player); + break; + } + } + + private boolean checkPermission(Player player, String element) { + return player.hasPermission("bending.ability.ElementSphere." + element); + } + + private boolean canStartNewSphere() { + return bPlayer.canBend(this); + } + + private void initializeNewSphere(Player player) { setFields(); location = player.getLocation().clone().subtract(0, 1, 0); + world = player.getWorld(); + endTime = System.currentTimeMillis() + duration; + start(); + + if (!isRemoved()) { + bindAndCooldown(player); + enableFlight(player); + checkBoundAbilityName(); + } + } - if (bPlayer.canBend(this)) { - world = player.getWorld(); - endTime = System.currentTimeMillis() + duration; - start(); - if (!isRemoved()) { - MultiAbilityManager.bindMultiAbility(player, "ElementSphere"); - bPlayer.addCooldown(this); - flightHandler.createInstance(player, this.getName()); - if (ChatColor.stripColor(bPlayer.getBoundAbilityName()) == null) { - remove(); - } - } + private void bindAndCooldown(Player player) { + MultiAbilityManager.bindMultiAbility(player, "ElementSphere"); + bPlayer.addCooldown(this); + } + + private void enableFlight(Player player) { + flightHandler.createInstance(player, this.getName()); + } + + private void checkBoundAbilityName() { + if (ChatColor.stripColor(bPlayer.getBoundAbilityName()) == null) { + remove(); } } @@ -149,34 +171,56 @@ public void setFields() { @Override public void progress() { - if (player.isDead() || !player.isOnline() || world != player.getWorld()) { - remove(); - return; - } - if (player.getGameMode().equals(GameMode.SPECTATOR)) { - remove(); - return; - } - if (!bPlayer.isToggled()) { - remove(); + if (!checkPlayerValidity()) { return; } - if (!MultiAbilityManager.hasMultiAbilityBound(player, "ElementSphere")) { - remove(); + + if (!checkAbilityPrerequisites()) { return; } - if (System.currentTimeMillis() > endTime && duration > 0) { + + if (isDurationOver()) { remove(); return; } - if (airUses == 0 && fireUses == 0 && waterUses == 0 && earthUses == 0) { + + if (!hasUsableElements()) { remove(); return; } + + handlePlayerMovement(); + handleFlight(); + handleEntityPush(); + updateLocationAndPlayParticles(); + + setup = true; + } + + private boolean checkPlayerValidity() { + return !player.isDead() && player.isOnline() && world == player.getWorld() && !player.getGameMode().equals(GameMode.SPECTATOR); + } + + private boolean checkAbilityPrerequisites() { + return bPlayer.isToggled() && MultiAbilityManager.hasMultiAbilityBound(player, "ElementSphere"); + } + + private boolean isDurationOver() { + return duration > 0 && System.currentTimeMillis() > endTime; + } + + private boolean hasUsableElements() { + return airUses > 0 || fireUses > 0 || waterUses > 0 || earthUses > 0; + } + + private void handlePlayerMovement() { player.setFallDistance(0); - if (player.isSneaking()) + if (player.isSneaking()) { player.setVelocity(player.getLocation().getDirection().multiply(speed)); + } + } + private void handleFlight() { Block block = getGround(); if (block != null) { double dy = player.getLocation().getY() - block.getY(); @@ -186,18 +230,26 @@ public void progress() { allowFlight(); } } + } + private void handleEntityPush() { for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (!RegionProtection.isRegionProtected(player, entity.getLocation(), this)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { - entity.setVelocity(entity.getLocation().toVector().subtract(player.getLocation().toVector()).multiply(1)); - } + if (isPushableEntity(entity)) { + entity.setVelocity(entity.getLocation().toVector().subtract(player.getLocation().toVector()).multiply(1)); } } + } + + private boolean isPushableEntity(Entity entity) { + return entity instanceof LivingEntity && + entity.getEntityId() != player.getEntityId() && + !(entity instanceof ArmorStand) && + !RegionProtection.isRegionProtected(player, entity.getLocation(), this); + } + private void updateLocationAndPlayParticles() { location = player.getLocation().clone().subtract(0, 1, 0); playParticles(); - setup = true; } private void allowFlight() { @@ -220,67 +272,113 @@ private void removeFlight() { private Block getGround() { Block standingblock = player.getLocation().getBlock(); + for (int i = 0; i <= height + 5; i++) { Block block = standingblock.getRelative(BlockFace.DOWN, i); if (GeneralMethods.isSolid(block) || block.isLiquid()) { return block; } } + return null; } private void playParticles() { - Location fakeLoc = location.clone(); - fakeLoc.setPitch(0); - fakeLoc.setYaw((float) (yaw += 40)); - Vector direction = fakeLoc.getDirection(); - if (airUses != 0) + playAirParticles(); + playFireParticles(); + playWaterEarthParticles(); + updatePointCounter(); + } + + private void playAirParticles() { + if (airUses != 0) { + double currentYaw = yaw + 40; + yaw = currentYaw; + Location fakeLoc = createRotatedLocation(location.clone(), 0, currentYaw); + Vector direction = fakeLoc.getDirection(); for (double j = -180; j <= 180; j += 45) { - Location tempLoc = fakeLoc.clone(); - Vector newDir = direction.clone().multiply(2 * Math.cos(Math.toRadians(j))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + 2 + (2 * Math.sin(Math.toRadians(j)))); - if (rand.nextInt(30) == 0) { - JCMethods.displayColoredParticles("#FFFFFF", tempLoc, 1, 0, 0, 0, 0.003f); - } else { - JCMethods.displayColoredParticles("#FFFFFF", tempLoc, 1, 0, 0, 0, 0.003f, 50); - } + Location tempLoc = calculateAirParticleLocation(fakeLoc, direction, j); + displayAirParticle(tempLoc); } + } + } + + private Location createRotatedLocation(Location baseLoc, double pitchOffset, double yawOffset) { + Location newLoc = baseLoc.clone(); + newLoc.setPitch((float) pitchOffset); + newLoc.setYaw((float) yawOffset); + return newLoc; + } + + private Location calculateAirParticleLocation(Location center, Vector direction, double angleDegrees) { + Location tempLoc = center.clone(); + double angleRadians = Math.toRadians(angleDegrees); + Vector newDir = direction.clone().multiply(2 * Math.cos(angleRadians)); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + 2 + (2 * Math.sin(angleRadians))); + return tempLoc; + } - point++; - if (fireUses != 0) + private void displayAirParticle(Location loc) { + String color = "#FFFFFF"; + int count = 1; + float offsetX = 0; + float offsetY = 0; + float offsetZ = 0; + float particleSpeed = 0.003f; + int viewDistance = 50; + + if (ThreadLocalRandom.current().nextInt(30) == 0) { + JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed); + } else { + JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed, viewDistance); + } + } + + private void playFireParticles() { + if (fireUses != 0) { + ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; for (int i = -180; i < 180; i += 40) { - double angle = (i * Math.PI / 180); - double x = 2 * Math.cos(angle + point); - double z = 2 * Math.sin(angle + point); - Location loc = location.clone(); - loc.add(x, 2, z); - ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; - flame.display(loc, 0, 0, 0, 0, 1); - JCMethods.emitLight(loc); + Location particleLoc = calculateCircularLocation(location, 2, i, 2); + flame.display(particleLoc, 0, 0, 0, 0, 1); + JCMethods.emitLight(particleLoc); } + } + } + + private Location calculateCircularLocation(Location center, double radius, double angleOffsetDegrees, double yOffset) { + double angleRadians = Math.toRadians(angleOffsetDegrees); + double x = radius * Math.cos(angleRadians + point); + double z = radius * Math.sin(angleRadians + point); + return center.clone().add(x, yOffset, z); + } + + private void playWaterEarthParticles() { + Location centerLoc = location.clone().add(0, 2, 0); + double xRotation = Math.PI * 2.1 / 3; + double yawRadians = -(centerLoc.getYaw() * Math.PI / 180 - 1.575); - point++; - Location location = this.location.clone().add(0, 2, 0); for (int i = -180; i < 180; i += 30) { - double angle = (i * Math.PI / 180); - double xRotation = 3.141592653589793D / 3 * 2.1; + double angle = Math.toRadians(i); Vector v = new Vector(Math.cos(angle + point), Math.sin(angle + point), 0.0D).multiply(2); Vector v1 = v.clone(); + rotateAroundAxisX(v, xRotation); - rotateAroundAxisY(v, -((location.getYaw() * Math.PI / 180) - 1.575)); + rotateAroundAxisY(v, yawRadians); rotateAroundAxisX(v1, -xRotation); - rotateAroundAxisY(v1, -((location.getYaw() * Math.PI / 180) - 1.575)); - - if (waterUses != 0) - GeneralMethods.displayColoredParticle("06C1FF", location.clone().add(v)); + rotateAroundAxisY(v1, yawRadians); - if (earthUses != 0) - GeneralMethods.displayColoredParticle("754719", location.clone().add(v1)); + if (waterUses != 0) { + GeneralMethods.displayColoredParticle("06C1FF", centerLoc.clone().add(v)); + } + if (earthUses != 0) { + GeneralMethods.displayColoredParticle("754719", centerLoc.clone().add(v1)); + } } + } - if (point == 360) - point = 0; + private void updatePointCounter() { + point = (point + 1) % 360; } private void rotateAroundAxisX(Vector v, double angle) { diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 7aa4131..168026d 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -1,8 +1,6 @@ package com.jedk1.jedcore.configuration; import com.jedk1.jedcore.JedCore; - -import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.configuration.ConfigManager; import org.bukkit.Material; import org.bukkit.World; @@ -60,7 +58,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Avatar.ElementSphere.Enabled", true); config.addDefault("Abilities.Avatar.ElementSphere.Description", "ElementSphere is a very all round ability, being " + "able to shoot attacks of each element, each with a " - + "different affect. To use, simply Left-Click. Once active, " + + "different effect. To use, simply Left-Click. Once active, " + "Sneak (Default: Shift) to fly around. Sneak and double " + "Left-Click to disable the ability! " + "To use each element, simply select hotbar slots 1-4 and Left-Click. " @@ -118,7 +116,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.AirBlade.Enabled", true); config.addDefault("Abilities.Air.AirBlade.Description", "With this ability bound, Left-Click to shoot " - + "a strong blade of air at your targets doing some damage!"); + + "a strong blade of air at your targets to deal some damage!"); config.addDefault("Abilities.Air.AirBlade.Cooldown", 3000); config.addDefault("Abilities.Air.AirBlade.Range", 30.0); config.addDefault("Abilities.Air.AirBlade.Damage", 4.0); @@ -133,7 +131,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.AirBreath.Enabled", true); config.addDefault("Abilities.Air.AirBreath.Description", "To use, hold Sneak (Default: Shift) to release " - + "a strong breath of wind knocking your opponents " + + "a strong breath of wind, knocking your opponents " + "back. This ability also has a longer range and " + "stronger knockback while in AvatarState!"); config.addDefault("Abilities.Air.AirBreath.Cooldown", 3000); @@ -155,7 +153,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.AirGlide.Enabled", true); config.addDefault("Abilities.Air.AirGlide.Description", "While falling, tap Sneak for a " - + "slow and steady descent, tap Sneak again to stop gliding."); + + "slow and steady descent. Tap Sneak again to stop gliding."); config.addDefault("Abilities.Air.AirGlide.Speed", 0.5); config.addDefault("Abilities.Air.AirGlide.FallSpeed", 0.1); config.addDefault("Abilities.Air.AirGlide.Particles", 4); @@ -166,7 +164,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.AirPunch.Enabled", true); config.addDefault("Abilities.Air.AirPunch.Description", "Left-Click in rapid succession to punch high desnity packets of air " - + "at enemies to do slight damage to them. A few punches can be thrown before the ability has a cooldown."); + + "at enemies to do slight damage. A few punches can be thrown before the ability goes on cooldown."); config.addDefault("Abilities.Air.AirPunch.Cooldown", 5000); config.addDefault("Abilities.Air.AirPunch.Threshold", 500); config.addDefault("Abilities.Air.AirPunch.Shots", 4); @@ -187,7 +185,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.Meditate.Enabled", true); config.addDefault("Abilities.Air.Meditate.Description", "Hold Sneak (Default: Shift) to start meditating. " + "After you have focused your energy, you will obtain several buffs."); - config.addDefault("Abilities.Air.Meditate.UnfocusMessage", "You have become unfocused from taking damage!"); + config.addDefault("Abilities.Air.Meditate.UnfocusMessage", "You have become unfocused due to taking damage!"); config.addDefault("Abilities.Air.Meditate.LossFocusMessage", true); config.addDefault("Abilities.Air.Meditate.ChargeTime", 5000); config.addDefault("Abilities.Air.Meditate.Cooldown", 60000); @@ -199,9 +197,9 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.SonicBlast.Enabled", true); config.addDefault("Abilities.Air.SonicBlast.Description", "SonicBlast is a soundbending ability, known by very few airbenders. " - + "It allows the airbender to stun and deafen an opponent by creating a sonic blast, " - + "this is achieved by creating two regions of high and low pressure and bringing them together. " - + "To use, hold Sneak (Default: Shift) in the direction of the target. Once particles start appearing " + + "It allows the airbender to stun and deafen an opponent by creating a sonic blast. " + + "This is achieved by creating two regions of high and low pressure and bringing them together. " + + "To use, hold Sneak (Default: Shift) in the direction of the target. Once particles appear " + "around you, let go of Sneak to shoot a SonicBlast at your target! The technique is very powerful, " + "even if it doesn't seem it, and comes with a short cooldown."); config.addDefault("Abilities.Air.SonicBlast.ChargeTime", 2000); @@ -1014,8 +1012,8 @@ private void addDeathMessages() { //Air lang.addDefault("Abilities.Air.AirBlade.DeathMessage", "{victim} was sliced in two by {attacker}'s {ability}"); - lang.addDefault("Abilities.Air.AirPunch.DeathMessage", "{victim} was exploded from {attacker}'s {ability}"); - lang.addDefault("Abilities.Air.SonicBlast.DeathMessage", "{victim}'s ears burst from {attacker}'s {ability}"); + lang.addDefault("Abilities.Air.AirPunch.DeathMessage", "{victim} was exploded by {attacker}'s {ability}"); + lang.addDefault("Abilities.Air.SonicBlast.DeathMessage", "{victim}'s ears burst after {attacker}'s {ability}"); //Chi lang.addDefault("Abilities.Chi.DaggerThrow.DeathMessage", "{victim} got stabbed too many times from {attacker}'s {ability}"); From ec913499586e9c65542507c94ace1bff6f730062 Mon Sep 17 00:00:00 2001 From: Manu585 Date: Sat, 24 May 2025 15:42:40 +0200 Subject: [PATCH 29/61] IceWall destroyable with other abilities again --- src/com/jedk1/jedcore/JCManager.java | 3 +- .../jedcore/ability/waterbending/IceWall.java | 372 ++++++++---------- 2 files changed, 161 insertions(+), 214 deletions(-) diff --git a/src/com/jedk1/jedcore/JCManager.java b/src/com/jedk1/jedcore/JCManager.java index 5fda987..d567eaa 100644 --- a/src/com/jedk1/jedcore/JCManager.java +++ b/src/com/jedk1/jedcore/JCManager.java @@ -1,5 +1,6 @@ package com.jedk1.jedcore; +import com.jedk1.jedcore.ability.waterbending.IceWall; import org.bukkit.Bukkit; import com.jedk1.jedcore.ability.firebending.LightningBurst; @@ -20,7 +21,7 @@ public void run() { HealingWaters.heal(Bukkit.getServer()); IcePassive.handleSkating(); -// IceWall.progressAll(); + IceWall.progressAll(); RegenTempBlock.manage(); } diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceWall.java b/src/com/jedk1/jedcore/ability/waterbending/IceWall.java index bc5471a..31ec8ff 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/IceWall.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IceWall.java @@ -3,16 +3,12 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.ListIterator; import java.util.Random; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.projectkorra.projectkorra.ability.*; import com.projectkorra.projectkorra.attribute.Attribute; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.World; +import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; @@ -23,7 +19,6 @@ import com.jedk1.jedcore.JedCore; import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.airbending.AirBlast; import com.projectkorra.projectkorra.earthbending.EarthSmash; import com.projectkorra.projectkorra.firebending.FireBlast; import com.projectkorra.projectkorra.firebending.FireBlastCharged; @@ -35,19 +30,25 @@ import com.projectkorra.projectkorra.waterbending.ice.IceBlast; public class IceWall extends IceAbility implements AddonAbility { - public static List instances = new ArrayList<>(); + @Attribute(Attribute.HEIGHT) private int maxHeight; private int minHeight; + + @Attribute(Attribute.WIDTH) private int width; + @Attribute(Attribute.RANGE) private int range; + @Attribute("Health") private int maxHealth; private int minHealth; + @Attribute(Attribute.DAMAGE) private double damage; + @Attribute(Attribute.COOLDOWN) private long cooldown; @@ -74,6 +75,7 @@ public class IceWall extends IceAbility implements AddonAbility { private long lifetime = 0; private int wallHealth; private int tankedDamage; + private final List lastBlocks = new ArrayList<>(); private final List tempBlocks = new ArrayList<>(); @@ -87,37 +89,29 @@ public IceWall(Player player) { setFields(); Block b = getSourceBlock(player, (int) (range * getNightFactor(player.getWorld()))); + if (b == null) return; - if (b == null) - return; - - else { - for (IceWall iw : instances) { - if (iw.affectedBlocks.contains(b)) { - iw.collapse(player, false); - return; - } + for (IceWall iw : instances) { + if (iw.affectedBlocks.contains(b)) { + iw.collapse(player, false); + return; } + } - if (isWaterbendable(b)) { - if (!bPlayer.canBend(this)) { - return; - } + if (!bPlayer.canBend(this) || !isWaterbendable(b)) return; - wallHealth = (int) (((rand.nextInt((maxHealth - minHealth) + 1)) + minHealth) * getNightFactor(player.getWorld())); - loadAffectedBlocks(player, b); - lifetime = System.currentTimeMillis() + lifetimeTime; - } - } + wallHealth = (int) (((rand.nextInt((maxHealth - minHealth) + 1)) + minHealth) * getNightFactor(player.getWorld())); + loadAffectedBlocks(player, b); + lifetime = System.currentTimeMillis() + lifetimeTime; start(); } public void setFields() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); - setMaxHeight(config.getInt("Abilities.Water.IceWall.MaxHeight")); - setMinHeight(config.getInt("Abilities.Water.IceWall.MinHeight")); - setWidth(config.getInt("Abilities.Water.IceWall.Width")); + maxHeight = (config.getInt("Abilities.Water.IceWall.MaxHeight")); + minHeight = (config.getInt("Abilities.Water.IceWall.MinHeight")); + width = (config.getInt("Abilities.Water.IceWall.Width")); range = config.getInt("Abilities.Water.IceWall.Range"); maxHealth = config.getInt("Abilities.Water.IceWall.MaxWallHealth"); minHealth = config.getInt("Abilities.Water.IceWall.MinWallHealth"); @@ -232,23 +226,21 @@ public void progress() { if (rising) { if (lastBlocks.isEmpty()) { rising = false; - return; - } - - List theseBlocks = new ArrayList<>(lastBlocks); - - lastBlocks.clear(); + } else { + List theseBlocks = new ArrayList<>(lastBlocks); + lastBlocks.clear(); - for (Block b : theseBlocks) { - TempBlock tb = new TempBlock(b, Material.ICE.createBlockData()); - tempBlocks.add(tb); + for (Block b : theseBlocks) { + TempBlock tb = new TempBlock(b, Material.ICE.createBlockData()); + tempBlocks.add(tb); - playIcebendingSound(b.getLocation()); + playIcebendingSound(b.getLocation()); - Block up = b.getRelative(BlockFace.UP); + Block up = b.getRelative(BlockFace.UP); - if (affectedBlocks.contains(up)) - lastBlocks.add(up); + if (affectedBlocks.contains(up)) + lastBlocks.add(up); + } } } @@ -264,67 +256,39 @@ public void damageWall(Player player, int damage) { lastDamageTime = System.currentTimeMillis(); tankedDamage += damage; + if (tankedDamage >= wallHealth) { collapse(player, true); } } public void collapse(Player player, boolean forceful) { - if (rising) - return; - - remove(player, forceful); - } + if (rising) return; - public void remove(Player player, boolean forceful) { for (TempBlock tb : tempBlocks) { - if (tb != null) { - tb.revertBlock(); - - ParticleEffect.BLOCK_CRACK.display(tb.getLocation(), 5, 0, 0, 0, 0, Material.PACKED_ICE.createBlockData()); - tb.getLocation().getWorld().playSound(tb.getLocation(), Sound.BLOCK_GLASS_BREAK, 5f, 5f); - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 2.5)) { - if (e.getEntityId() != player.getEntityId()) { - if (e instanceof LivingEntity) { - DamageHandler.damageEntity(e, damage * getNightFactor(player.getWorld()), this); - if (forceful) { - ((LivingEntity) e).setNoDamageTicks(0); - } - } + tb.revertBlock(); + tb.getLocation().getWorld().spawnParticle(Particle.BLOCK_CRACK, tb.getLocation(), 5, 0, 0, 0, 0, Material.PACKED_ICE.createBlockData()); + tb.getLocation().getWorld().playSound(tb.getLocation(), Sound.BLOCK_GLASS_BREAK, 5f, 5f); + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 2.5)) { + if (e.getEntityId() != player.getEntityId() && e instanceof LivingEntity) { + DamageHandler.damageEntity(e, damage * getNightFactor(player.getWorld()), this); + if (forceful) { + ((LivingEntity) e).setNoDamageTicks(0); } } } } tempBlocks.clear(); - isWallDoneFor = true; - remove(); } + @Override public void remove() { - for (TempBlock tb : tempBlocks) { - if (tb != null) { - tb.revertBlock(); - } - } - - tempBlocks.clear(); - - instances.remove(this); super.remove(); } - public static void removeDeadInstances() { - for (int i = 0; i < instances.size(); i++) { - IceWall iw = instances.get(i); - if (iw.isWallDoneFor) { - instances.remove(i); - } - } - } - public static void collisionDamage(Entity entity, double travelledDistance, Vector difference, Player instigator) { for (IceWall iw : IceWall.instances) { for (Block b : iw.affectedBlocks) { @@ -362,142 +326,124 @@ public static boolean isIceWallBlock(Block block) { return false; } - public static void removeAll() { - Iterator it = instances.iterator(); - while (it.hasNext()) { - it.next().remove(); - it.remove(); - } - } - public static void progressAll() { - /* - for (IceWall iw : IceWall.instances) { - iw.progress(); - } - */ - - ListIterator iwli = IceWall.instances.listIterator(); - - while (iwli.hasNext()) { - IceWall iw = iwli.next(); - for (Torrent t : getAbilities(Torrent.class)) { - if (t.getLocation() == null) continue; - for (int i = 0; i < t.getLaunchedBlocks().size(); i++) { - TempBlock tb = t.getLaunchedBlocks().get(i); - - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == tb.getLocation().getWorld() && ice.getLocation().distance(tb.getLocation()) <= 2) { - if (t.isFreeze()) - iw.damageWall(t.getPlayer(), (int) (iw.torrentFreezeDamage * getNightFactor(ice.getWorld()))); - else - iw.damageWall(t.getPlayer(), (int) (iw.torrentDamage * getNightFactor(ice.getWorld()))); - - if (!iw.isWallDoneFor) - t.setFreeze(false); - } - } - } - } - - for (IceBlast ib : getAbilities(IceBlast.class)) { - if (ib.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ib.source == null) - break; - - if (ice.getLocation().getWorld() == ib.source.getLocation().getWorld() && ice.getLocation().distance(ib.source.getLocation()) <= 2) { - iw.damageWall(ib.getPlayer(), (int) (iw.iceBlastDamage * getNightFactor(ice.getWorld()))); - - if (!iw.isWallDoneFor) - ib.remove(); - } - } - } - - for (FireBlastCharged fb : getAbilities(FireBlastCharged.class)) { - if (fb.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { - iw.damageWall(fb.getPlayer(), iw.fireBlastChargedDamage); - - if (!iw.isWallDoneFor) fb.remove(); - } - } - } - - for (FireBlast fb : getAbilities(FireBlast.class)) { - if (fb.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { - iw.damageWall(fb.getPlayer(), iw.fireBlastDamage); - - if (!iw.isWallDoneFor) fb.remove(); - } - } - } - - for (EarthSmash es : getAbilities(EarthSmash.class)) { - if (es.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (es.getState() == EarthSmash.State.SHOT) { - for (int j = 0; j < es.getBlocks().size(); j++) { - Block b = es.getBlocks().get(j); - if (ice.getLocation().getWorld() == b.getLocation().getWorld() && b.getLocation().distance(ice.getLocation()) <= 2) { - iw.damageWall(es.getPlayer(), iw.earthSmashDamage); - - if (!iw.isWallDoneFor) { - for (Block block : es.getBlocksIncludingInner()) { - if (block != null && !ElementalAbility.isAir(block.getType())) { - ParticleEffect.BLOCK_CRACK.display(block.getLocation(), 5, 0, 0, 0, 0, block.getBlockData().clone()); - } - } - es.remove(); - } - } - } - } - } - } + for (IceWall iw : new ArrayList<>(instances)) { + if (iw.isWallDoneFor) continue; // Skip already collapsed walls + for (Torrent t : getAbilities(Torrent.class)) { + if (t.getLocation() == null) continue; + for (int i = 0; i < t.getLaunchedBlocks().size(); i++) { + TempBlock tb = t.getLaunchedBlocks().get(i); + + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == tb.getLocation().getWorld() && ice.getLocation().distance(tb.getLocation()) <= 2) { + if (t.isFreeze()) + iw.damageWall(t.getPlayer(), (int) (iw.torrentFreezeDamage * getNightFactor(ice.getWorld()))); + else + iw.damageWall(t.getPlayer(), (int) (iw.torrentDamage * getNightFactor(ice.getWorld()))); + + if (!iw.isWallDoneFor) + t.setFreeze(false); + } + } + } + } + + for (IceBlast ib : getAbilities(IceBlast.class)) { + if (ib.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ib.source == null) + break; + + if (ice.getLocation().getWorld() == ib.source.getLocation().getWorld() && ice.getLocation().distance(ib.source.getLocation()) <= 2) { + iw.damageWall(ib.getPlayer(), (int) (iw.iceBlastDamage * getNightFactor(ice.getWorld()))); + + if (!iw.isWallDoneFor) + ib.remove(); + } + } + } + + for (FireBlastCharged fb : getAbilities(FireBlastCharged.class)) { + if (fb.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { + iw.damageWall(fb.getPlayer(), iw.fireBlastChargedDamage); + + if (!iw.isWallDoneFor) + fb.remove(); + } + } + } + + for (FireBlast fb : getAbilities(FireBlast.class)) { + if (fb.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { + iw.damageWall(fb.getPlayer(), iw.fireBlastDamage); + + if (!iw.isWallDoneFor) + fb.remove(); + } + } + } + + for (EarthSmash es : getAbilities(EarthSmash.class)) { + if (es.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (es.getState() == EarthSmash.State.SHOT) { + for (int j = 0; j < es.getBlocks().size(); j++) { + Block b = es.getBlocks().get(j); + if (ice.getLocation().getWorld() == b.getLocation().getWorld() && b.getLocation().distance(ice.getLocation()) <= 2) { + iw.damageWall(es.getPlayer(), iw.earthSmashDamage); + + if (!iw.isWallDoneFor) { + for (Block block : es.getBlocksIncludingInner()) { + if (block != null && !ElementalAbility.isAir(block.getType())) { + ParticleEffect.BLOCK_CRACK.display(block.getLocation(), 5, 0, 0, 0, 0, block.getBlockData().clone()); + } + } + es.remove(); + } + } + } + } + } + } + + for (Lightning l : getAbilities(Lightning.class)) { + for (Lightning.Arc arc : l.getArcs()) { + for (Block ice : iw.affectedBlocks) { + for (Location loc : arc.getPoints()) { + if (ice.getLocation().getWorld() == loc.getWorld() && loc.distance(ice.getLocation()) <= 1.5) { + iw.damageWall(l.getPlayer(), (int) (FireAbility.getDayFactor(iw.lightningDamage, ice.getWorld()))); + + if (!iw.isWallDoneFor) + l.remove(); + } + } + } + } + } + + for (CoreAbility ca : getAbilities(getAbility("Combustion").getClass())) { + if (ca.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == ca.getLocation().getWorld() && ca.getLocation().distance(ice.getLocation()) <= 1.5) { + iw.damageWall(ca.getPlayer(), iw.combustionDamage); + if (!iw.isWallDoneFor) ca.remove(); + } + } + } + } - for (Lightning l : getAbilities(Lightning.class)) { - for (Lightning.Arc arc : l.getArcs()) { - for (Block ice : iw.affectedBlocks) { - for (Location loc : arc.getPoints()) { - if (ice.getLocation().getWorld() == loc.getWorld() && loc.distance(ice.getLocation()) <= 1.5) { - iw.damageWall(l.getPlayer(), (int) (FireAbility.getDayFactor(iw.lightningDamage, ice.getWorld()))); - - if (!iw.isWallDoneFor) - l.remove(); - } - } - } - } - } - - for (AirBlast ab : getAbilities(AirBlast.class)) { - if (ab.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == ab.getLocation().getWorld() && ab.getLocation().distance(ice.getLocation()) <= 1.5) { - iw.damageWall(ab.getPlayer(), iw.airBlastDamage); - - if (!iw.isWallDoneFor) ab.remove(); - } - } - } - - for (CoreAbility ca : getAbilities(getAbility("Combustion").getClass())) { - if (ca.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == ca.getLocation().getWorld() && ca.getLocation().distance(ice.getLocation()) <= 1.5) { - iw.damageWall(ca.getPlayer(), iw.combustionDamage); - if (!iw.isWallDoneFor) ca.remove(); - } - } + Iterator it = instances.iterator(); + while (it.hasNext()) { + IceWall iw = it.next(); + if (iw.isWallDoneFor) { + iw.affectedBlocks.clear(); + it.remove(); } } - - IceWall.removeDeadInstances(); } @Override From d949f99293facedf05c90d9873db5b36885b4457 Mon Sep 17 00:00:00 2001 From: Manu585 Date: Wed, 11 Jun 2025 20:04:25 +0200 Subject: [PATCH 30/61] Differentiate between mob and player damage attribute --- src/com/jedk1/jedcore/ability/firebending/FireBreath.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java index 3e3e2c5..0082b9e 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java @@ -49,11 +49,11 @@ public class FireBreath extends FireAbility implements AddonAbility { @Attribute(Attribute.DURATION) private long duration; private int particles; - @Attribute(Attribute.DAMAGE) + @Attribute("Player" + Attribute.DAMAGE) private double playerDamage; @Attribute(Attribute.DAMAGE) private double mobDamage; - @Attribute(Attribute.DURATION) + @Attribute("Mob" + Attribute.DURATION) private int fireDuration; @Attribute(Attribute.RANGE) private int range; From e6f1d32e96aa621112a11ed4ea38e900b3ae18de Mon Sep 17 00:00:00 2001 From: Manu585 Date: Wed, 11 Jun 2025 21:10:42 +0200 Subject: [PATCH 31/61] Fixed mistake --- src/com/jedk1/jedcore/ability/firebending/FireBreath.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java index 0082b9e..8795627 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java @@ -51,9 +51,9 @@ public class FireBreath extends FireAbility implements AddonAbility { private int particles; @Attribute("Player" + Attribute.DAMAGE) private double playerDamage; - @Attribute(Attribute.DAMAGE) + @Attribute("Mob" + Attribute.DAMAGE) private double mobDamage; - @Attribute("Mob" + Attribute.DURATION) + @Attribute(Attribute.DURATION) private int fireDuration; @Attribute(Attribute.RANGE) private int range; From 754af3ab4ff7fd9e89e4a73958994bdcb10dc566 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 9 Jul 2025 18:42:19 -0400 Subject: [PATCH 32/61] Some more refactoring --- src/com/jedk1/jedcore/JCManager.java | 9 ++- .../ability/avatar/elementsphere/ESWater.java | 3 + .../avatar/elementsphere/ElementSphere.java | 4 +- .../jedcore/ability/chiblocking/Backstab.java | 11 ++-- .../ability/chiblocking/DaggerThrow.java | 28 +++++---- .../ability/earthbending/EarthKick.java | 32 +++++----- .../ability/earthbending/EarthLine.java | 46 +++++++------- .../ability/earthbending/EarthPillar.java | 1 - .../ability/earthbending/EarthShard.java | 20 +++---- .../ability/earthbending/EarthSurf.java | 5 +- .../ability/earthbending/LavaDisc.java | 33 +++++----- .../ability/earthbending/LavaFlux.java | 26 ++++---- .../ability/earthbending/LavaThrow.java | 1 - .../ability/earthbending/MagnetShield.java | 2 - .../ability/earthbending/MetalArmor.java | 1 - .../ability/earthbending/MetalFragments.java | 8 ++- .../ability/earthbending/MetalHook.java | 1 - .../ability/earthbending/MetalShred.java | 1 - .../ability/earthbending/MudSurge.java | 17 +++++- .../ability/earthbending/SandBlast.java | 3 - .../ability/earthbending/combo/Crevice.java | 39 ++++++------ .../earthbending/combo/MagmaBlast.java | 60 ++++++++++--------- .../ability/firebending/Combustion.java | 16 ++--- .../ability/firebending/Discharge.java | 1 - .../jedcore/ability/firebending/FireBall.java | 21 ++++--- .../ability/firebending/FireBreath.java | 35 ++++++----- .../ability/firebending/FireComet.java | 1 - .../ability/firebending/FirePunch.java | 9 ++- .../jedcore/ability/firebending/FireSki.java | 1 - .../jedcore/ability/passive/WallRun.java | 1 - .../ability/waterbending/BloodPuppet.java | 34 +++++++---- .../ability/waterbending/Bloodbending.java | 7 ++- .../jedcore/ability/waterbending/Drain.java | 1 - .../ability/waterbending/DrainBlast.java | 1 - .../ability/waterbending/HealingWaters.java | 5 +- .../ability/waterbending/IcePassive.java | 2 - .../ability/waterbending/WakeFishing.java | 1 - .../ability/waterbending/WaterBlast.java | 1 - .../ability/waterbending/combo/Maelstrom.java | 1 - .../ability/waterbending/combo/WaterFlow.java | 6 +- .../waterbending/combo/WaterGimbal.java | 3 +- .../jedcore/collision/CollisionDetector.java | 4 +- .../jedk1/jedcore/command/JedCoreCommand.java | 11 ++-- .../jedk1/jedcore/configuration/Config.java | 3 +- .../jedcore/listener/CommandListener.java | 1 - .../jedk1/jedcore/listener/JCListener.java | 22 ++++--- .../jedk1/jedcore/util/AbilitySelector.java | 24 ++++++-- src/com/jedk1/jedcore/util/LightManager.java | 15 ++++- src/com/jedk1/jedcore/util/MaterialUtil.java | 19 +++--- .../jedk1/jedcore/util/RegenTempBlock.java | 23 ++----- .../jedcore/util/ThrownEntityTracker.java | 21 ++++--- 51 files changed, 345 insertions(+), 296 deletions(-) diff --git a/src/com/jedk1/jedcore/JCManager.java b/src/com/jedk1/jedcore/JCManager.java index d567eaa..a1872aa 100644 --- a/src/com/jedk1/jedcore/JCManager.java +++ b/src/com/jedk1/jedcore/JCManager.java @@ -1,13 +1,12 @@ package com.jedk1.jedcore; import com.jedk1.jedcore.ability.waterbending.IceWall; +import com.jedk1.jedcore.ability.firebending.LightningBurst; +import com.jedk1.jedcore.ability.waterbending.HealingWaters; +import com.jedk1.jedcore.ability.waterbending.IcePassive; +import com.jedk1.jedcore.util.RegenTempBlock; import org.bukkit.Bukkit; - import com.jedk1.jedcore.ability.firebending.LightningBurst; - import com.jedk1.jedcore.ability.waterbending.HealingWaters; - import com.jedk1.jedcore.ability.waterbending.IcePassive; - import com.jedk1.jedcore.util.RegenTempBlock; - public class JCManager implements Runnable { public JedCore plugin; diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java index 4d0fbb3..8caf0da 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java @@ -14,6 +14,7 @@ import com.projectkorra.projectkorra.util.ParticleEffect; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Particle; import org.bukkit.block.data.Levelled; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.ArmorStand; @@ -132,6 +133,8 @@ private void playAttackEffects() { WaterAbility.playWaterbendingSound(location); if (isWater(location.getBlock())) { ParticleEffect.WATER_BUBBLE.display(location, 3, 0.5, 0.5, 0.5); + location.getWorld().spawnParticle(Particle.WATER_WAKE, location, 3, 0.0, 0.0, 0.0, 0.005F); + GeneralMethods.displayColoredParticle("06C1FF", location); } } diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java index ee6b1ca..aec8327 100644 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java @@ -12,10 +12,12 @@ import com.projectkorra.projectkorra.ability.util.MultiAbilityManager.MultiAbilityInfoSub; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.FlightHandler; import com.projectkorra.projectkorra.util.ParticleEffect; import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; +import org.bukkit.Particle; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -367,8 +369,8 @@ private void playWaterEarthParticles() { rotateAroundAxisY(v, yawRadians); rotateAroundAxisX(v1, -xRotation); rotateAroundAxisY(v1, yawRadians); - if (waterUses != 0) { + centerLoc.getWorld().spawnParticle(Particle.WATER_WAKE, centerLoc.clone().add(v), 3, 0.0, 0.0, 0.0, 0.005F); GeneralMethods.displayColoredParticle("06C1FF", centerLoc.clone().add(v)); } if (earthUses != 0) { diff --git a/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java b/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java index f6c87ec..701121a 100644 --- a/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java +++ b/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java @@ -1,18 +1,17 @@ package com.jedk1.jedcore.ability.chiblocking; +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.chiblocking.passive.ChiPassive; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.chiblocking.passive.ChiPassive; import org.bukkit.util.Vector; public class Backstab extends ChiAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java index 677e70a..d13d909 100644 --- a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java +++ b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -29,26 +28,23 @@ public class DaggerThrow extends ChiAbility implements AddonAbility { private static final List INTERACTIONS = new ArrayList<>(); - private boolean particles; - @Attribute(Attribute.DAMAGE) - private double damage; + private final List arrows = new ArrayList<>(); - @Attribute(Attribute.COOLDOWN) - private long cooldown; private boolean limitEnabled; - @Attribute("MaxShots") - private int maxShots; - private boolean requireArrows; - // require arrows (takes arrows from inv) private boolean allowPickup; - // allow arrow pickup (disables pickup and removes the arrow entities) - + private boolean particles; private long endTime; private int shots = 1; private int hits = 0; - private final List arrows = new ArrayList<>(); + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("MaxShots") + private int maxShots; public DaggerThrow(Player player) { super(player); @@ -70,6 +66,7 @@ public DaggerThrow(Player player) { setFields(); start(); + if (!isRemoved()) { shootArrow(); } @@ -96,6 +93,7 @@ private void loadInteractions() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); ConfigurationSection section = config.getConfigurationSection(path); + for (String abilityName : section.getKeys(false)) { INTERACTIONS.add(new AbilityInteraction(abilityName)); } @@ -107,11 +105,13 @@ public void progress() { remove(); return; } + if (System.currentTimeMillis() > endTime) { bPlayer.addCooldown(this); remove(); return; } + if (shots > maxShots && limitEnabled) { bPlayer.addCooldown(this); remove(); @@ -128,12 +128,14 @@ private void shootArrow() { subtract(player.getEyeLocation().toVector()); if (requireArrows) JCMethods.removeItemFromInventory(player, Material.ARROW, 1); + Arrow arrow = player.launchProjectile(Arrow.class); arrow.setVelocity(vector); arrow.getLocation().setDirection(vector); arrow.setKnockbackStrength(0); arrow.setBounce(false); arrow.setMetadata("daggerthrow", new FixedMetadataValue(JedCore.plugin, "1")); + if (!allowPickup) arrow.setPickupStatus(Arrow.PickupStatus.DISALLOWED); if (particles) { diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java index c687a0b..bac1840 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -12,8 +12,10 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.*; - +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -26,18 +28,24 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Random; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; import static java.util.stream.Collectors.toList; public class EarthKick extends EarthAbility implements AddonAbility { private final List temps = new ArrayList<>(); + private final Set hitEntities = new HashSet<>(); private BlockData materialData; private Location location; - private final Random rand = new Random(); + private Block block; + private boolean multipleHits; + private int sourceRange; + private int spread; + private double velocity; + private boolean allowMetal; @Attribute(Attribute.COOLDOWN) private long cooldown; @@ -49,15 +57,6 @@ public class EarthKick extends EarthAbility implements AddonAbility { private double metalDmg; @Attribute("CollisionRadius") private double entityCollisionRadius; - private Block block; - - private boolean multipleHits; - private int sourceRange; - private int spread; - private double velocity; - private boolean allowMetal; - - private Set hitEntities = new HashSet<>(); public EarthKick(Player player) { super(player); @@ -67,7 +66,9 @@ public EarthKick(Player player) { } setFields(); + location = player.getLocation(); + if ((player.getLocation().getPitch() > -5) && prepare()) { if (RegionProtection.isRegionProtected(this, block.getLocation())) { return; @@ -85,7 +86,6 @@ public void setFields() { damage = config.getDouble("Abilities.Earth.EarthKick.Damage.Normal"); metalDmg = config.getDouble("Abilities.Earth.EarthKick.Damage.Metal"); entityCollisionRadius = config.getDouble("Abilities.Earth.EarthKick.EntityCollisionRadius"); - multipleHits = config.getBoolean("Abilities.Earth.EarthKick.MultipleHits"); sourceRange = config.getInt("Abilities.Earth.EarthKick.SourceRange"); spread = config.getInt("Abilities.Earth.EarthKick.Spread"); @@ -137,6 +137,7 @@ public void progress() { } bPlayer.addCooldown(this); + track(); if (temps.isEmpty()) { @@ -148,6 +149,7 @@ private void launchBlocks() { if (getMovedEarth().containsKey(block)) { block.setType(Material.AIR); } + if (block.getType() != Material.AIR) { TempBlock air = new TempBlock(block, Material.AIR); air.setRevertTime(5000L); @@ -166,6 +168,8 @@ private void launchBlocks() { playEarthbendingSound(location); + ThreadLocalRandom rand = ThreadLocalRandom.current(); + for (int i = 0; i < earthBlocks; i++) { location.setYaw(yaw + rand.nextInt((spread * 2) + 1) - spread); location.setPitch(rand.nextInt(25) - 45); diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java index b0991dd..40ff0a5 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java @@ -2,10 +2,11 @@ import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; -import com.jedk1.jedcore.util.RegenTempBlock; - -import com.projectkorra.projectkorra.util.TempBlock; +import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; +import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; +import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.EarthAbility; @@ -13,12 +14,9 @@ import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.DamageHandler; - +import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempFallingBlock; - import org.bukkit.Effect; import org.bukkit.Location; import org.bukkit.Material; @@ -41,22 +39,22 @@ public class EarthLine extends EarthAbility implements AddonAbility { private boolean hitted; private int goOnAfterHit; private long removalTime = -1; - + private boolean allowChangeDirection; + private CompositeRemovalPolicy removalPolicy; private long useCooldown; private long prepareCooldown; + private double sourceKeepRange; + @Attribute(Attribute.DURATION) private long maxDuration; @Attribute(Attribute.RANGE) private double range; @Attribute(Attribute.SELECT_RANGE) private double prepareRange; - private double sourceKeepRange; @Attribute(Attribute.RADIUS) private int affectingRadius; @Attribute(Attribute.DAMAGE) private double damage; - private boolean allowChangeDirection; - private CompositeRemovalPolicy removalPolicy; public EarthLine(Player player) { super(player); @@ -69,6 +67,7 @@ public EarthLine(Player player) { goOnAfterHit = 1; setFields(); + if (prepare()) { start(); if (!isRemoved() && prepareCooldown != 0) { @@ -102,6 +101,7 @@ public void setFields() { public boolean prepare() { final Block block = getEarthSourceBlock(this.range); + if (block == null || !this.isEarthbendable(block)) { return false; } else if (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block)) { @@ -127,6 +127,7 @@ public boolean prepare() { this.sourceBlock = block; this.focusBlock(); + return true; } @@ -138,18 +139,14 @@ private void focusBlock() { if (this.sourceBlock.getType() == Material.SAND) { this.sourceType = Material.SAND; sourceTempBlock = new TempBlock(sourceBlock, Material.SANDSTONE.createBlockData()); - //this.sourceBlock.setType(Material.SANDSTONE); } else if (this.sourceBlock.getType() == Material.RED_SAND) { this.sourceType = Material.RED_SAND; sourceTempBlock = new TempBlock(sourceBlock, Material.RED_SANDSTONE.createBlockData()); - //this.sourceBlock.setType(Material.RED_SANDSTONE); } else if (this.sourceBlock.getType() == Material.STONE) { - //this.sourceBlock.setType(Material.COBBLESTONE); this.sourceType = Material.STONE; sourceTempBlock = new TempBlock(sourceBlock, Material.COBBLESTONE.createBlockData()); } else { this.sourceType = this.sourceBlock.getType(); - //this.sourceBlock.setType(Material.STONE); sourceTempBlock = new TempBlock(sourceBlock, Material.STONE.createBlockData()); } @@ -157,29 +154,30 @@ private void focusBlock() { } private void unfocusBlock() { - //sourceBlock.setType(sourceType); sourceTempBlock.revertBlock(); } @Override public void remove() { -// if (sourceBlock != null && sourceBlock.getType() != Material.AIR) { -// sourceBlock.setType(sourceType); // Ensure no duplication of the source block -// } sourceTempBlock.revertBlock(); super.remove(); } + // todo: static private static Location getTargetLocation(Player player) { ConfigurationSection config = JedCoreConfig.getConfig(player); + double range = config.getInt("Abilities.Earth.EarthLine.Range"); + Entity target = GeneralMethods.getTargetedEntity(player, range, player.getNearbyEntities(range, range, range)); Location location; + if (target == null) { location = GeneralMethods.getTargetedLocation(player, range); } else { location = ((LivingEntity) target).getEyeLocation(); } + return location; } @@ -246,8 +244,10 @@ public void progress() { double z1 = endLocation.getZ(); double x0 = sourceBlock.getX(); double z0 = sourceBlock.getZ(); + Vector looking = new Vector(x1 - x0, 0.0D, z1 - z0); Vector push = new Vector(x1 - x0, 0.34999999999999998D, z1 - z0); + if (location.distance(sourceBlock.getLocation()) < range) { Material cloneType = location.getBlock().getType(); Location locationYUP = location.getBlock().getLocation().clone().add(0.5, 0.1, 0.5); @@ -255,7 +255,6 @@ public void progress() { playEarthbendingSound(location); if (isEarthbendable(location.getBlock())) { - //new RegenTempBlock(location.getBlock(), Material.AIR, Material.AIR.createBlockData(), 700L); new TempBlock(location.getBlock(), Material.AIR.createBlockData(), 700L); new TempFallingBlock(locationYUP, cloneType.createBlockData(), new Vector(0.0, 0.35, 0.0), this); } @@ -276,9 +275,10 @@ public void progress() { } } else { for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, affectingRadius)) { - if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))){ + if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))) { return; } + if ((entity instanceof LivingEntity) && entity.getEntityId() != player.getEntityId()) { GeneralMethods.setVelocity(this, entity, push.normalize().multiply(2)); DamageHandler.damageEntity(entity, damage, this); @@ -489,4 +489,4 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Earth.EarthLine.Enabled"); } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java b/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java index 1935c15..75ce009 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java @@ -8,7 +8,6 @@ import com.projectkorra.projectkorra.earthbending.Collapse; import com.projectkorra.projectkorra.util.BlockSource; import com.projectkorra.projectkorra.util.ClickType; - import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java index ee392d3..451256f 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java @@ -1,16 +1,20 @@ package com.jedk1.jedcore.ability.earthbending; -import java.util.*; -import java.util.stream.Collectors; - +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.collision.AABB; import com.jedk1.jedcore.collision.CollisionDetector; import com.jedk1.jedcore.collision.CollisionUtil; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.BlockUtil; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; @@ -23,13 +27,9 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; public class EarthShard extends EarthAbility implements AddonAbility { @Attribute(Attribute.RANGE) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java b/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java index 83df672..151bdc9 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.TempBlock; - import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; @@ -24,7 +23,9 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; public class EarthSurf extends EarthAbility implements AddonAbility { private static final double TARGET_HEIGHT = 1.5; diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java b/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java index 65cdf08..d778648 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java @@ -1,16 +1,26 @@ package com.jedk1.jedcore.ability.earthbending; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; +import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; +import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; @@ -23,16 +33,9 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class LavaDisc extends LavaAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java b/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java index 6368fbf..d2abe08 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java @@ -1,16 +1,17 @@ package com.jedk1.jedcore.ability.earthbending; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.Information; +import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.TempBlock; import org.bukkit.Location; import org.bukkit.Material; @@ -26,14 +27,11 @@ import org.bukkit.util.BlockIterator; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; public class LavaFlux extends LavaAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java index 07bd010..a84d303 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java @@ -11,7 +11,6 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java b/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java index 4373c5c..d416565 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java @@ -2,12 +2,10 @@ import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; - import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.MetalAbility; import com.projectkorra.projectkorra.attribute.Attribute; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java b/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java index ca1861e..6390a3b 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java @@ -8,7 +8,6 @@ import com.projectkorra.projectkorra.earthbending.EarthArmor; import com.projectkorra.projectkorra.util.TempArmor; import com.projectkorra.projectkorra.util.TempPotionEffect; - import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java b/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java index 9a95cdd..4a89d95 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java @@ -13,7 +13,6 @@ import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempFallingBlock; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; @@ -28,7 +27,12 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Random; public class MetalFragments extends MetalAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java b/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java index 3cbf551..2ae0c7b 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java @@ -6,7 +6,6 @@ import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.MetalAbility; - import com.projectkorra.projectkorra.attribute.Attribute; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java b/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java index ef79f8c..537c60f 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java @@ -13,7 +13,6 @@ import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.TempBlock; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; diff --git a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java index 30e57f6..bd62b95 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java @@ -3,7 +3,12 @@ import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.collision.CollisionUtil; import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; +import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; +import com.jedk1.jedcore.policies.removal.OutOfRangeRemovalPolicy; +import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.Element; import com.projectkorra.projectkorra.GeneralMethods; @@ -17,7 +22,6 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.TempBlock; - import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; @@ -32,7 +36,14 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Random; +import java.util.Set; import java.util.stream.Collectors; public class MudSurge extends EarthAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java b/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java index a8ab2d0..aba3421 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java +++ b/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java @@ -10,11 +10,8 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.TempBlock; - import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java b/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java index f4e22c4..bbe292e 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java +++ b/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java @@ -11,8 +11,6 @@ import com.projectkorra.projectkorra.ability.util.ComboUtil; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ClickType; - import com.projectkorra.projectkorra.util.TempBlock; import org.bukkit.Location; import org.bukkit.Material; @@ -29,35 +27,35 @@ import java.util.List; import java.util.Objects; import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; public class Crevice extends EarthAbility implements AddonAbility, ComboAbility { - - @Attribute(Attribute.RANGE) - private double range; - private long regenDelay; - @Attribute("Depth") - private int randomDepth; - private int avatarDepth; - @Attribute(Attribute.COOLDOWN) - private long cooldown; + private final List> columns = new ArrayList<>(); private Location origin; private Location location; private Vector direction; private double travelled; private boolean skip; + private int avatarDepth; + private long regenDelay; - private final List> columns = new ArrayList<>(); - - private final Random rand = new Random(); + @Attribute(Attribute.RANGE) + private double range; + @Attribute("Depth") + private int randomDepth; + @Attribute(Attribute.COOLDOWN) + private long cooldown; public Crevice(Player player) { super(player); + if (!bPlayer.canBendIgnoreBinds(this)) { return; } setFields(); + createInstance(); } @@ -73,17 +71,21 @@ public void setFields() { private void createInstance() { origin = player.getTargetBlock(null, 6).getLocation(); + if (isEarthbendable(origin.getBlock())) { Location tempLoc = player.getLocation().clone(); tempLoc.setPitch(0); + direction = tempLoc.getDirection().clone(); - origin.setDirection(tempLoc.getDirection()); + origin.setDirection(tempLoc.getDirection()); // todo location = origin.clone(); + if (bPlayer.isAvatarState()) { randomDepth = avatarDepth; } start(); + if (!isRemoved()) { bPlayer.addCooldown(this); } @@ -97,6 +99,7 @@ public void progress() { remove(); return; } + if (travelled >= range || skip) { if (System.currentTimeMillis() > getStartTime() + regenDelay) { prepareRevert(); @@ -105,6 +108,7 @@ public void progress() { } return; } + advanceCrevice(); } @@ -116,6 +120,7 @@ public void remove() { public static void closeCrevice(Player player) { Block target = player.getTargetBlock(null, 10); + for (Block near : GeneralMethods.getBlocksAroundPoint(target.getLocation(), 2)) { for (Crevice c : getAbilities(Crevice.class)) { for (List tbs : c.columns) { @@ -132,7 +137,7 @@ public static void closeCrevice(Player player) { } private void advanceCrevice() { - switch (rand.nextInt(2)) { + switch (ThreadLocalRandom.current().nextInt(2)) { case 0: if (location.getYaw() <= origin.getYaw()) { location.setYaw(location.getYaw() + 40); @@ -186,7 +191,7 @@ private void advanceCrevice() { } private int randInt(int min, int max) { - return rand.nextInt(max - min) + min; + return ThreadLocalRandom.current().nextInt(max - min) + min; // todo: look into the necessity of this helper } private void removePillar(Location location, int depth) { diff --git a/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java b/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java index 9b1f9d7..7011750 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java +++ b/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java @@ -1,22 +1,20 @@ package com.jedk1.jedcore.ability.earthbending.combo; +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.MaterialUtil; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; - -import com.jedk1.jedcore.JedCore; import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.LavaAbility; import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.TempBlock; - import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; @@ -31,31 +29,23 @@ import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.util.Vector; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; public class MagmaBlast extends LavaAbility implements AddonAbility, ComboAbility { private static final int PARTICLE_COUNT = 20; private static final int RAISE_HEIGHT = 3; - private static final Random rand = new Random(); private final Set sources = new HashSet<>(); private final List blocks = new ArrayList<>(); private final List firedBlocks = new ArrayList<>(); - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long maxDuration; - private long shotCooldown; - @Attribute("MaxSources") - private int maxSources; - @Attribute(Attribute.SELECT_RANGE) - private int sourceRange; - @Attribute(Attribute.SELECT_RANGE) - private double selectRange; - @Attribute(Attribute.DAMAGE) - private double damage; private double fireSpeed; // How far away the player is allowed to be from the sources before the ability is destroyed. private double maxDistanceFromSources; @@ -64,12 +54,25 @@ public class MagmaBlast extends LavaAbility implements AddonAbility, ComboAbilit private boolean requireLavaFlow; private boolean playerCollisions; private boolean entitySelection; - private Location origin; private int counter; private long canLavaFlowTime; private long lastShot; private boolean stopFiring; + private long shotCooldown; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long maxDuration; + @Attribute("MaxSources") + private int maxSources; + @Attribute(Attribute.SELECT_RANGE) + private int sourceRange; + @Attribute(Attribute.SELECT_RANGE) + private double selectRange; + @Attribute(Attribute.DAMAGE) + private double damage; public MagmaBlast(Player player) { super(player); @@ -230,9 +233,7 @@ private void displayAnimation() { } } - for (TempBlock tb : blocks) { - playParticles(tb.getLocation()); - } + for (TempBlock tb : blocks) playParticles(tb.getLocation()); } private void doPlayerCollisions() { @@ -260,8 +261,10 @@ private void doPlayerCollisions() { private void playParticles(Location location) { location.add(.5,.5,.5); + ParticleEffect.LAVA.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); ParticleEffect.SMOKE_NORMAL.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); + for (int i = 0; i < 10; i++) { GeneralMethods.displayColoredParticle("FFA400", getOffsetLocation(location, 2)); GeneralMethods.displayColoredParticle("FF8C00", getOffsetLocation(location, 2)); @@ -395,6 +398,8 @@ private static void blastEffects(Location location, MagmaBlast mb) { ParticleEffect.SMOKE_LARGE.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); ParticleEffect.FIREWORKS_SPARK.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); + ThreadLocalRandom rand = ThreadLocalRandom.current(); + location.getWorld().playSound(location, (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 1f, 1f); @@ -405,6 +410,7 @@ private static void blastEffects(Location location, MagmaBlast mb) { // Generates a random number between -max and max. private static float randomBinomial(float max) { + ThreadLocalRandom rand = ThreadLocalRandom.current(); return (rand.nextFloat() * max) - (rand.nextFloat() * max); } @@ -612,4 +618,4 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.Enabled"); } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/ability/firebending/Combustion.java b/src/com/jedk1/jedcore/ability/firebending/Combustion.java index 1e4edff..2071fb8 100644 --- a/src/com/jedk1/jedcore/ability/firebending/Combustion.java +++ b/src/com/jedk1/jedcore/ability/firebending/Combustion.java @@ -5,16 +5,16 @@ import com.jedk1.jedcore.collision.CollisionDetector; import com.jedk1.jedcore.collision.Sphere; import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; +import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; +import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; import com.jedk1.jedcore.util.FireTick; - -import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; -import org.bukkit.Tag; import com.jedk1.jedcore.util.MaterialUtil; import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.AirAbility; import com.projectkorra.projectkorra.ability.CombustionAbility; @@ -25,10 +25,12 @@ import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.TempBlock; - +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.Sound; +import org.bukkit.Tag; import org.bukkit.block.Block; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; diff --git a/src/com/jedk1/jedcore/ability/firebending/Discharge.java b/src/com/jedk1/jedcore/ability/firebending/Discharge.java index 49e62dc..1f27388 100644 --- a/src/com/jedk1/jedcore/ability/firebending/Discharge.java +++ b/src/com/jedk1/jedcore/ability/firebending/Discharge.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.configuration.ConfigurationSection; diff --git a/src/com/jedk1/jedcore/ability/firebending/FireBall.java b/src/com/jedk1/jedcore/ability/firebending/FireBall.java index 7d739f0..2631565 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FireBall.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireBall.java @@ -1,16 +1,26 @@ package com.jedk1.jedcore.ability.firebending; import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.collision.CollisionDetector; import com.jedk1.jedcore.collision.Sphere; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.AirShieldReflector; import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.airbending.AirShield; import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.BlazeArc; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -18,17 +28,6 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; - public class FireBall extends FireAbility implements AddonAbility { private Location location; diff --git a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java index 8795627..fa46395 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java @@ -1,18 +1,24 @@ package com.jedk1.jedcore.ability.firebending; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.UUID; - import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.listener.CommandListener; import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.BlazeArc; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.ChatUtil; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Particle; @@ -23,18 +29,11 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.UUID; public class FireBreath extends FireAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/firebending/FireComet.java b/src/com/jedk1/jedcore/ability/firebending/FireComet.java index d49f2d4..2cdd262 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FireComet.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireComet.java @@ -13,7 +13,6 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/com/jedk1/jedcore/ability/firebending/FirePunch.java b/src/com/jedk1/jedcore/ability/firebending/FirePunch.java index 8dfc35c..c80d53c 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FirePunch.java +++ b/src/com/jedk1/jedcore/ability/firebending/FirePunch.java @@ -1,11 +1,6 @@ package com.jedk1.jedcore.ability.firebending; import com.jedk1.jedcore.JCMethods; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.FireTick; @@ -18,6 +13,10 @@ import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.inventory.MainHand; public class FirePunch extends FireAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/firebending/FireSki.java b/src/com/jedk1/jedcore/ability/firebending/FireSki.java index 0b5648d..d43de8a 100644 --- a/src/com/jedk1/jedcore/ability/firebending/FireSki.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireSki.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.Location; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; diff --git a/src/com/jedk1/jedcore/ability/passive/WallRun.java b/src/com/jedk1/jedcore/ability/passive/WallRun.java index a60418f..816dab9 100644 --- a/src/com/jedk1/jedcore/ability/passive/WallRun.java +++ b/src/com/jedk1/jedcore/ability/passive/WallRun.java @@ -10,7 +10,6 @@ import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java b/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java index 6e3bf14..52e2078 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java +++ b/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java @@ -1,27 +1,39 @@ package com.jedk1.jedcore.ability.waterbending; -import java.util.*; - +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.BloodAbility; import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.*; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Blaze; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Fireball; +import org.bukkit.entity.Ghast; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.ThrownPotion; +import org.bukkit.entity.Witch; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.BloodAbility; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.util.DamageHandler; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; public class BloodPuppet extends BloodAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java b/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java index 5c2e122..d19cabb 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java +++ b/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java @@ -14,10 +14,13 @@ import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.*; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.util.Vector; import java.util.ArrayList; diff --git a/src/com/jedk1/jedcore/ability/waterbending/Drain.java b/src/com/jedk1/jedcore/ability/waterbending/Drain.java index ea33485..8be1480 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/Drain.java +++ b/src/com/jedk1/jedcore/ability/waterbending/Drain.java @@ -11,7 +11,6 @@ import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.waterbending.util.WaterReturn; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; diff --git a/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java b/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java index 7656c6f..1912d14 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java +++ b/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java @@ -8,7 +8,6 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.TempBlock; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.data.Levelled; diff --git a/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java b/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java index c5aa09f..861c2d9 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java +++ b/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java @@ -13,9 +13,10 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.TempBlock; - import com.projectkorra.projectkorra.waterbending.util.WaterReturn; -import org.bukkit.*; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Server; import org.bukkit.block.Block; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Damageable; diff --git a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java index 37478f0..794225a 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java @@ -6,13 +6,11 @@ import com.projectkorra.projectkorra.Element; import com.projectkorra.projectkorra.ability.IceAbility; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import org.bukkit.permissions.Permission; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; diff --git a/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java b/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java index 26ada5f..6cf92d3 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java +++ b/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java @@ -8,7 +8,6 @@ import com.projectkorra.projectkorra.util.BlockSource; import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; diff --git a/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java b/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java index 44d4266..bd562ea 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java +++ b/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.BlockFace; diff --git a/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java b/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java index ec02664..55c0a35 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java +++ b/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java @@ -14,7 +14,6 @@ import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.waterbending.Torrent; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; diff --git a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java index ee9c1f8..c1adb24 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java +++ b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java @@ -6,7 +6,10 @@ import com.jedk1.jedcore.util.MaterialUtil; import com.jedk1.jedcore.util.RegenTempBlock; import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; import com.projectkorra.projectkorra.ability.util.ComboUtil; import com.projectkorra.projectkorra.airbending.AirSpout; @@ -19,7 +22,6 @@ import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.waterbending.WaterManipulation; import com.projectkorra.projectkorra.waterbending.WaterSpout; - import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.util.WaterReturn; import org.bukkit.Location; diff --git a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java index 6fe64ca..9fed934 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java +++ b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java @@ -17,9 +17,8 @@ import com.projectkorra.projectkorra.util.BlockSource; import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.WaterManipulation; import com.projectkorra.projectkorra.waterbending.Torrent; - +import com.projectkorra.projectkorra.waterbending.WaterManipulation; import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.util.WaterReturn; diff --git a/src/com/jedk1/jedcore/collision/CollisionDetector.java b/src/com/jedk1/jedcore/collision/CollisionDetector.java index 8ff839a..95440c1 100644 --- a/src/com/jedk1/jedcore/collision/CollisionDetector.java +++ b/src/com/jedk1/jedcore/collision/CollisionDetector.java @@ -12,7 +12,9 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.util.*; +import java.util.Collections; +import java.util.Optional; +import java.util.Set; public class CollisionDetector { public static boolean checkEntityCollisions(Player player, Collider collider, CollisionCallback function) { diff --git a/src/com/jedk1/jedcore/command/JedCoreCommand.java b/src/com/jedk1/jedcore/command/JedCoreCommand.java index f2534ca..1db12e9 100644 --- a/src/com/jedk1/jedcore/command/JedCoreCommand.java +++ b/src/com/jedk1/jedcore/command/JedCoreCommand.java @@ -1,15 +1,14 @@ package com.jedk1.jedcore.command; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.command.PKCommand; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.command.PKCommand; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; public class JedCoreCommand extends PKCommand { private static final String DOWNLOAD_URL = "https://github.com/CozmycDev/JedCore"; diff --git a/src/com/jedk1/jedcore/configuration/Config.java b/src/com/jedk1/jedcore/configuration/Config.java index d4c427b..06355d5 100644 --- a/src/com/jedk1/jedcore/configuration/Config.java +++ b/src/com/jedk1/jedcore/configuration/Config.java @@ -1,7 +1,6 @@ package com.jedk1.jedcore.configuration; import com.jedk1.jedcore.JedCore; - import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -11,7 +10,7 @@ public class Config { JedCore plugin; - private File file; + private final File file; public FileConfiguration config; public Config(File file) { diff --git a/src/com/jedk1/jedcore/listener/CommandListener.java b/src/com/jedk1/jedcore/listener/CommandListener.java index 3e3f803..5b296c8 100644 --- a/src/com/jedk1/jedcore/listener/CommandListener.java +++ b/src/com/jedk1/jedcore/listener/CommandListener.java @@ -5,7 +5,6 @@ import com.jedk1.jedcore.event.PKCommandEvent; import com.jedk1.jedcore.event.PKCommandEvent.CommandType; import com.projectkorra.projectkorra.command.PKCommand; - import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.event.EventHandler; diff --git a/src/com/jedk1/jedcore/listener/JCListener.java b/src/com/jedk1/jedcore/listener/JCListener.java index 4479168..ac3868c 100644 --- a/src/com/jedk1/jedcore/listener/JCListener.java +++ b/src/com/jedk1/jedcore/listener/JCListener.java @@ -4,24 +4,26 @@ import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.ability.chiblocking.Backstab; import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; -import com.jedk1.jedcore.ability.earthbending.*; +import com.jedk1.jedcore.ability.earthbending.EarthSurf; +import com.jedk1.jedcore.ability.earthbending.LavaDisc; +import com.jedk1.jedcore.ability.earthbending.MetalFragments; +import com.jedk1.jedcore.ability.earthbending.MetalShred; +import com.jedk1.jedcore.ability.earthbending.MudSurge; import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; import com.jedk1.jedcore.ability.firebending.FireBreath; import com.jedk1.jedcore.ability.firebending.FirePunch; import com.jedk1.jedcore.ability.firebending.FireSki; import com.jedk1.jedcore.ability.waterbending.IceClaws; import com.jedk1.jedcore.ability.waterbending.IceWall; -import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.LightManager; import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.IceAbility; import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; -import com.projectkorra.projectkorra.event.*; - +import com.projectkorra.projectkorra.event.AbilityStartEvent; +import com.projectkorra.projectkorra.event.BendingReloadEvent; +import com.projectkorra.projectkorra.event.HorizontalVelocityChangeEvent; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; @@ -29,7 +31,9 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.command.CommandSender; -import org.bukkit.entity.*; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -39,9 +43,9 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.inventory.InventoryPickupItemEvent; -import org.bukkit.event.player.*; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerToggleSprintEvent; import org.bukkit.scheduler.BukkitRunnable; public class JCListener implements Listener { diff --git a/src/com/jedk1/jedcore/util/AbilitySelector.java b/src/com/jedk1/jedcore/util/AbilitySelector.java index fb1a8f5..62fe6f6 100644 --- a/src/com/jedk1/jedcore/util/AbilitySelector.java +++ b/src/com/jedk1/jedcore/util/AbilitySelector.java @@ -2,10 +2,26 @@ import com.jedk1.jedcore.ability.waterbending.WaterBlast; import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.earthbending.*; -import com.projectkorra.projectkorra.firebending.*; -import com.projectkorra.projectkorra.waterbending.*; -import com.projectkorra.projectkorra.waterbending.ice.*; +import com.projectkorra.projectkorra.earthbending.Collapse; +import com.projectkorra.projectkorra.earthbending.CollapseWall; +import com.projectkorra.projectkorra.earthbending.RaiseEarth; +import com.projectkorra.projectkorra.earthbending.RaiseEarthWall; +import com.projectkorra.projectkorra.earthbending.Ripple; +import com.projectkorra.projectkorra.earthbending.Shockwave; +import com.projectkorra.projectkorra.firebending.Blaze; +import com.projectkorra.projectkorra.firebending.BlazeArc; +import com.projectkorra.projectkorra.firebending.BlazeRing; +import com.projectkorra.projectkorra.firebending.FireBlast; +import com.projectkorra.projectkorra.firebending.FireBlastCharged; +import com.projectkorra.projectkorra.waterbending.SurgeWall; +import com.projectkorra.projectkorra.waterbending.SurgeWave; +import com.projectkorra.projectkorra.waterbending.Torrent; +import com.projectkorra.projectkorra.waterbending.TorrentWave; +import com.projectkorra.projectkorra.waterbending.WaterSpout; +import com.projectkorra.projectkorra.waterbending.WaterSpoutWave; +import com.projectkorra.projectkorra.waterbending.ice.IceSpikeBlast; +import com.projectkorra.projectkorra.waterbending.ice.IceSpikePillar; +import com.projectkorra.projectkorra.waterbending.ice.IceSpikePillarField; import java.util.HashMap; import java.util.Map; diff --git a/src/com/jedk1/jedcore/util/LightManager.java b/src/com/jedk1/jedcore/util/LightManager.java index a48727d..2a44fce 100644 --- a/src/com/jedk1/jedcore/util/LightManager.java +++ b/src/com/jedk1/jedcore/util/LightManager.java @@ -11,8 +11,19 @@ import org.bukkit.block.data.Waterlogged; import org.bukkit.entity.Player; -import java.util.*; -import java.util.concurrent.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; public class LightManager { diff --git a/src/com/jedk1/jedcore/util/MaterialUtil.java b/src/com/jedk1/jedcore/util/MaterialUtil.java index 25d74c7..1180a2f 100644 --- a/src/com/jedk1/jedcore/util/MaterialUtil.java +++ b/src/com/jedk1/jedcore/util/MaterialUtil.java @@ -1,7 +1,6 @@ package com.jedk1.jedcore.util; import com.projectkorra.projectkorra.GeneralMethods; - import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; @@ -13,16 +12,16 @@ public class MaterialUtil { // todo: use the registry/tags (with config) or grab directly from PKs config maybe? - private static final List TRANSPARENT_MATERIALS = new ArrayList(){{ + private static final List TRANSPARENT_MATERIALS = new ArrayList<>() {{ addAll(Arrays.asList( - Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.OAK_SAPLING, Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, - Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING, Material.WATER, - Material.LAVA, Material.COBWEB, Material.TALL_GRASS, Material.GRASS, Material.FERN, Material.DEAD_BUSH, - Material.DANDELION, Material.POPPY, Material.BLUE_ORCHID, Material.ALLIUM, - Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, - Material.OXEYE_DAISY, Material.BROWN_MUSHROOM, Material.RED_MUSHROOM, Material.TORCH, Material.FIRE, - Material.WHEAT, Material.SNOW, Material.SUGAR_CANE, Material.VINE, Material.SUNFLOWER, Material.LILAC, - Material.LARGE_FERN, Material.ROSE_BUSH, Material.PEONY)); + Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.OAK_SAPLING, Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, + Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING, Material.WATER, + Material.LAVA, Material.COBWEB, Material.TALL_GRASS, Material.GRASS, Material.FERN, Material.DEAD_BUSH, + Material.DANDELION, Material.POPPY, Material.BLUE_ORCHID, Material.ALLIUM, + Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, + Material.OXEYE_DAISY, Material.BROWN_MUSHROOM, Material.RED_MUSHROOM, Material.TORCH, Material.FIRE, + Material.WHEAT, Material.SNOW, Material.SUGAR_CANE, Material.VINE, Material.SUNFLOWER, Material.LILAC, + Material.LARGE_FERN, Material.ROSE_BUSH, Material.PEONY)); if (GeneralMethods.getMCVersion() >= 1170) { add(Material.getMaterial("LIGHT")); } diff --git a/src/com/jedk1/jedcore/util/RegenTempBlock.java b/src/com/jedk1/jedcore/util/RegenTempBlock.java index 56794f6..3afa11d 100644 --- a/src/com/jedk1/jedcore/util/RegenTempBlock.java +++ b/src/com/jedk1/jedcore/util/RegenTempBlock.java @@ -2,7 +2,6 @@ import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.util.TempBlock; - import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockState; @@ -38,7 +37,6 @@ public RegenTempBlock(Block block, Material material, BlockData data, long delay * @param delay Delay until block regens. * @param temp Use TempBlock or BlockState. */ - @SuppressWarnings("deprecation") public RegenTempBlock(Block block, Material material, BlockData data, long delay, boolean temp) { this(block, material, data, delay, temp, null); } @@ -147,11 +145,8 @@ public static void revertAll() { * @return */ public static boolean hasBlock(Block block) { - if (blocks.containsKey(block)) { - return true; - } - return false; - } + return blocks.containsKey(block); + } /** * Returns true if the block is stored as a temp block. @@ -159,11 +154,8 @@ public static boolean hasBlock(Block block) { * @return */ public static boolean isTempBlock(Block block) { - if (temps.containsKey(block)) { - return true; - } - return false; - } + return temps.containsKey(block); + } /** * Returns true if the block is stored as a block state. @@ -171,11 +163,8 @@ public static boolean isTempBlock(Block block) { * @return */ public static boolean isBlockState(Block block) { - if (states.containsKey(block)) { - return true; - } - return false; - } + return states.containsKey(block); + } private static class RegenBlockData { long endTime; diff --git a/src/com/jedk1/jedcore/util/ThrownEntityTracker.java b/src/com/jedk1/jedcore/util/ThrownEntityTracker.java index a2ac646..9c6fb7d 100644 --- a/src/com/jedk1/jedcore/util/ThrownEntityTracker.java +++ b/src/com/jedk1/jedcore/util/ThrownEntityTracker.java @@ -4,7 +4,6 @@ import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.Ability; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -15,12 +14,12 @@ public class ThrownEntityTracker { - public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap instances = new ConcurrentHashMap<>(); public static boolean collisions = JedCore.plugin.getConfig().getBoolean("Properties.MobCollisions.Enabled"); private long delay; - private long fireTime; - private Entity entity; - private Player instigator; + private final long fireTime; + private final Entity entity; + private final Player instigator; private Vector thisVelocity; private Ability ability; @@ -38,18 +37,18 @@ public void update() { if (System.currentTimeMillis() < fireTime + delay) { return; } + if (!collisions || entity.isOnGround()) { remove(); return; } + thisVelocity = entity.getVelocity().clone(); + List nearby = GeneralMethods.getEntitiesAroundPoint(entity.getLocation(), 2D); - if (nearby.contains(entity)) { - nearby.remove(entity); - } - if (nearby.contains(instigator)) { - nearby.remove(instigator); - } + nearby.remove(entity); + nearby.remove(instigator); + if (nearby.size() != 0) { entity.setVelocity(thisVelocity.multiply(0.5D)); for(Entity e : nearby){ From 74af50b385c73d3d55c01ccee45a668c0c984456 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 9 Jul 2025 18:55:11 -0400 Subject: [PATCH 33/61] Fix fissure at y < 1 --- src/com/jedk1/jedcore/ability/earthbending/Fissure.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/Fissure.java b/src/com/jedk1/jedcore/ability/earthbending/Fissure.java index 7f947a5..9fa731e 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/Fissure.java +++ b/src/com/jedk1/jedcore/ability/earthbending/Fissure.java @@ -116,7 +116,7 @@ private boolean prepareLine() { while (bi.hasNext()) { Block b = bi.next(); - if (b.getY() > 1 && b.getY() < 255 && !RegionProtection.isRegionProtected(this, b.getLocation())) { + if (b.getY() > b.getWorld().getMinHeight() && b.getY() < b.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, b.getLocation())) { if (EarthAbility.getMovedEarth().containsKey(b)){ Information info = EarthAbility.getMovedEarth().get(b); if(!info.getBlock().equals(b)) { @@ -196,7 +196,7 @@ private void expandFissure() { } private void expand(Block block) { - if (block != null && block.getY() > 1 && block.getY() < 255 && !RegionProtection.isRegionProtected(this, block.getLocation())) { + if (block != null && block.getY() > block.getWorld().getMinHeight() && block.getY() < block.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, block.getLocation())) { if (EarthAbility.getMovedEarth().containsKey(block)){ Information info = EarthAbility.getMovedEarth().get(block); if(!info.getBlock().equals(block)) { @@ -206,7 +206,7 @@ private void expand(Block block) { while (!isEarthbendable(player, block)) { block = block.getRelative(BlockFace.DOWN); - if (block.getY() < 1 || block.getY() > 255) { + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { break; } if (isEarthbendable(player, block)) { @@ -216,7 +216,7 @@ private void expand(Block block) { while (!isTransparent(player, block.getRelative(BlockFace.UP))) { block = block.getRelative(BlockFace.UP); - if (block.getY() < 1 || block.getY() > 255) { + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { break; } if (isEarthbendable(player, block.getRelative(BlockFace.UP))) { From bdf4ac3aa108763910818c17613805924a4cde7d Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 9 Jul 2025 19:11:36 -0400 Subject: [PATCH 34/61] Fix IceWall at y < 1 --- src/com/jedk1/jedcore/ability/waterbending/IceWall.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceWall.java b/src/com/jedk1/jedcore/ability/waterbending/IceWall.java index 31ec8ff..b41793d 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/IceWall.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IceWall.java @@ -173,7 +173,7 @@ public void loadAffectedBlocks(Player player, Block block) { if (ElementalAbility.isAir(b.getType())) { while (ElementalAbility.isAir(b.getType())) { - if (b.getY() < 0) + if (b.getY() < world.getMinHeight()) return; b = b.getRelative(BlockFace.DOWN); From cc598d30142e1481f15a61c7a7c9bf183ee71884 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 9 Jul 2025 19:25:09 -0400 Subject: [PATCH 35/61] Add `Speed` config for AirPunch and AirBlade --- .../jedcore/ability/airbending/AirBlade.java | 27 +++++++++++++------ .../jedcore/ability/airbending/AirPunch.java | 25 ++++++++++++----- .../jedcore/configuration/JedCoreConfig.java | 2 ++ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java index f0a6d9b..4fd64bf 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java @@ -33,15 +33,17 @@ public class AirBlade extends AirAbility implements AddonAbility { private double damage; @Attribute("CollisionRadius") private double entityCollisionRadius; + @Attribute("Speed") + private double speed; public AirBlade(Player player) { super(player); if (!bPlayer.canBend(this)) { return; } - + setFields(); - + this.location = player.getEyeLocation().clone(); this.direction = player.getEyeLocation().getDirection().clone(); @@ -57,8 +59,9 @@ public void setFields() { range = config.getDouble("Abilities.Air.AirBlade.Range"); damage = config.getDouble("Abilities.Air.AirBlade.Damage"); entityCollisionRadius = config.getDouble("Abilities.Air.AirBlade.EntityCollisionRadius"); + speed = config.getDouble("Abilities.Air.AirBlade.Speed"); } - + @Override public void progress() { if (player.isDead() || !player.isOnline()) { @@ -98,9 +101,9 @@ private void progressBlade() { } private boolean moveAndCheckCollision() { - location = location.add(direction.multiply(1)); + location = location.add(direction.multiply(speed)); playAirbendingSound(location); - travelled++; + travelled += speed; growth += 0.125; if (travelled >= range || @@ -178,7 +181,7 @@ public double getCollisionRadius() { public long getCooldown() { return cooldown; } - + public void setCooldown(long cooldown) { this.cooldown = cooldown; } @@ -262,15 +265,23 @@ public void setEntityCollisionRadius(double entityCollisionRadius) { this.entityCollisionRadius = entityCollisionRadius; } + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + @Override public void load() {} @Override public void stop() {} - + @Override public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Air.AirBlade.Enabled"); } -} +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/airbending/AirPunch.java b/src/com/jedk1/jedcore/ability/airbending/AirPunch.java index eac83b2..b01492b 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirPunch.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirPunch.java @@ -37,6 +37,8 @@ public class AirPunch extends AirAbility implements AddonAbility { private double damage; @Attribute("CollisionRadius") private double entityCollisionRadius; + @Attribute("Speed") + private double speed; public AirPunch(Player player) { super(player); @@ -50,14 +52,14 @@ public AirPunch(Player player) { ap.createShot(); return; } - + setFields(); start(); if (!isRemoved()) createShot(); } - + public void setFields() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); @@ -67,6 +69,7 @@ public void setFields() { range = config.getDouble("Abilities.Air.AirPunch.Range"); damage = config.getDouble("Abilities.Air.AirPunch.Damage"); entityCollisionRadius = config.getDouble("Abilities.Air.AirPunch.EntityCollisionRadius"); + speed = config.getDouble("Abilities.Air.AirPunch.Speed"); } @Override @@ -131,7 +134,7 @@ private ShotResult simulateShotProgression(Location startLoc, double startDist) boolean moved = false; for (int i = 0; i < 3 && !shouldRemove; i++) { - dist++; + dist += speed; if (dist >= range) { shouldRemove = true; } else { @@ -154,7 +157,7 @@ private ShotResult simulateShotProgression(Location startLoc, double startDist) } private Location calculateNextLocation(Location currentLocation) { - return currentLocation.add(currentLocation.getDirection().clone().multiply(1)); + return currentLocation.add(currentLocation.getDirection().clone().multiply(speed)); } private boolean isPathBlocked(Location location) { @@ -172,7 +175,7 @@ private boolean checkAndHandleCollision(Location location) { return true; }); } - + @Override public long getCooldown() { return cooldown; @@ -282,15 +285,23 @@ public void setLastShotTime(long lastShotTime) { this.lastShotTime = lastShotTime; } + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + @Override public void load() {} @Override public void stop() {} - + @Override public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Air.AirPunch.Enabled"); } -} +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 168026d..2800b9f 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -120,6 +120,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.AirBlade.Cooldown", 3000); config.addDefault("Abilities.Air.AirBlade.Range", 30.0); config.addDefault("Abilities.Air.AirBlade.Damage", 4.0); + config.addDefault("Abilities.Air.AirBlade.Speed", 1.0); config.addDefault("Abilities.Air.AirBlade.EntityCollisionRadius", 1.0); config.addDefault("Abilities.Air.AirBlade.AbilityCollisionRadius", 1.0); config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.Enabled",true); @@ -170,6 +171,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.AirPunch.Shots", 4); config.addDefault("Abilities.Air.AirPunch.Range", 30); config.addDefault("Abilities.Air.AirPunch.Damage", 1.0); + config.addDefault("Abilities.Air.AirPunch.Speed", 1.0); config.addDefault("Abilities.Air.AirPunch.EntityCollisionRadius", 1.0); config.addDefault("Abilities.Air.AirPunch.AbilityCollisionRadius", 1.0); config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.Enabled", true); From 270f0d77e7596eb8d5083021746f5471ecf83353 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 9 Jul 2025 20:02:39 -0400 Subject: [PATCH 36/61] Add more `KnockUp` options for EarthShard --- .../ability/earthbending/EarthShard.java | 151 +++++++++++++----- .../jedcore/configuration/JedCoreConfig.java | 10 +- 2 files changed, 115 insertions(+), 46 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java index 451256f..50866e6 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java @@ -18,6 +18,7 @@ import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; @@ -57,6 +58,11 @@ public class EarthShard extends EarthAbility implements AddonAbility { private boolean allowKnockup; private double knockupVelocity; + private double knockupRange; + + private boolean allowKnockupSelf; + private double knockupSelfVelocity; + private double knockupSelfRange; public EarthShard(Player player) { super(player); @@ -87,7 +93,7 @@ public EarthShard(Player player) { public void setFields() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); - + range = config.getInt("Abilities.Earth.EarthShard.PrepareRange"); abilityRange = config.getInt("Abilities.Earth.EarthShard.AbilityRange"); normalDmg = config.getDouble("Abilities.Earth.EarthShard.Damage.Normal"); @@ -96,8 +102,12 @@ public void setFields() { cooldown = config.getLong("Abilities.Earth.EarthShard.Cooldown"); abilityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); entityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); - allowKnockup = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Allow"); - knockupVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Velocity"); + allowKnockup = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Others.Allow"); + knockupVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Velocity"); + knockupRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Range"); + allowKnockupSelf = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Self.Allow"); + knockupSelfVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Velocity"); + knockupSelfRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Range"); } public void select() { @@ -105,60 +115,65 @@ public void select() { } public void raiseEarthBlock(Block block) { - if (block == null) { - return; - } - - if (tblockTracker.size() >= maxShards) { - return; - } + if (block == null) return; + if (tblockTracker.size() >= maxShards) return; Vector blockVector = block.getLocation().toVector().toBlockVector().setY(0); for (TempBlock tempBlock : tblockTracker) { - if (tempBlock.getLocation().getWorld() != block.getWorld()) { - continue; - } + if (tempBlock.getLocation().getWorld() != block.getWorld()) continue; Vector tempBlockVector = tempBlock.getLocation().toVector().toBlockVector().setY(0); - - if (tempBlockVector.equals(blockVector)) { - return; - } + if (tempBlockVector.equals(blockVector)) return; } - + for (int i = 1; i < 4; i++) { - if (!isTransparent(block.getRelative(BlockFace.UP, i))) { - return; - } + if (!isTransparent(block.getRelative(BlockFace.UP, i))) return; } - if (isEarthbendable(block)) { - if (isMetal(block)) { - playMetalbendingSound(block.getLocation()); - } else { - ParticleEffect.BLOCK_CRACK.display(block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData()); - playEarthbendingSound(block.getLocation()); - } + if (!isEarthbendable(block)) return; - Material material = getCorrectType(block); + if (isMetal(block)) { + playMetalbendingSound(block.getLocation()); + } else { + ParticleEffect.BLOCK_CRACK.display( + block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData() + ); + playEarthbendingSound(block.getLocation()); + } - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } + Material material = getCorrectType(block); + + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + Location loc = block.getLocation().add(0.5, 0, 0.5); + new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); + TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); + tblockTracker.add(tb); + + handleKnockup(block); + } + + private void handleKnockup(Block origin) { + if (!allowKnockup && !allowKnockupSelf) return; + + Location originLoc = origin.getLocation(); + World world = origin.getWorld(); + + for (Entity entity : world.getNearbyEntities(originLoc, Math.max(knockupRange, knockupSelfRange), knockupRange, knockupRange)) { + if (entity instanceof FallingBlock) continue; - Location loc = block.getLocation().add(0.5, 0, 0.5); - new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); - TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); - tblockTracker.add(tb); - - if (!allowKnockup) return; - for (Entity entity : block.getWorld().getNearbyEntities(block.getLocation(), 1.5, 1.5, 1.5)) { - if (entity instanceof FallingBlock) continue; - Location entityLoc = entity.getLocation(); - if (entityLoc.getY() >= block.getY()) { - Vector velocity = new Vector(0, knockupVelocity, 0); - entity.setVelocity(entity.getVelocity().add(velocity)); + if (entity.equals(player)) { + if (!allowKnockupSelf) continue; + if (entity.getLocation().distance(originLoc) <= knockupSelfRange) { + entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupSelfVelocity, 0))); + } + } else { + if (!allowKnockup) continue; + if (entity.getLocation().distance(originLoc) <= knockupRange) { + entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupVelocity, 0))); } } } @@ -450,6 +465,54 @@ public List getFallingBlocks() { return fallingBlocks; } + public boolean isAllowKnockup() { + return allowKnockup; + } + + public void setAllowKnockup(boolean allowKnockup) { + this.allowKnockup = allowKnockup; + } + + public double getKnockupVelocity() { + return knockupVelocity; + } + + public void setKnockupVelocity(double knockupVelocity) { + this.knockupVelocity = knockupVelocity; + } + + public double getKnockupRange() { + return knockupRange; + } + + public void setKnockupRange(double knockupRange) { + this.knockupRange = knockupRange; + } + + public boolean isAllowKnockupSelf() { + return allowKnockupSelf; + } + + public void setAllowKnockupSelf(boolean allowKnockupSelf) { + this.allowKnockupSelf = allowKnockupSelf; + } + + public double getKnockupSelfVelocity() { + return knockupSelfVelocity; + } + + public void setKnockupSelfVelocity(double knockupSelfVelocity) { + this.knockupSelfVelocity = knockupSelfVelocity; + } + + public double getKnockupSelfRange() { + return knockupSelfRange; + } + + public void setKnockupSelfRange(double knockupSelfRange) { + this.knockupSelfRange = knockupSelfRange; + } + @Override public void load() {} diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 2800b9f..7ee0cc6 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -323,8 +323,14 @@ private void loadConfigCore() { config.addDefault("Abilities.Earth.EarthShard.PrepareRange", 5); config.addDefault("Abilities.Earth.EarthShard.AbilityRange", 30); config.addDefault("Abilities.Earth.EarthShard.MaxShards", 3); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Allow", true); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Velocity", 1.0); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Allow", true); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Velocity", 1.0); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Range", 1.5); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Allow", true); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Velocity", 1.0); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Range", 1.5); +// config.addDefault("Abilities.Earth.EarthShard.KnockUp.Allow", true); +// config.addDefault("Abilities.Earth.EarthShard.KnockUp.Velocity", 1.0); config.addDefault("Abilities.Earth.EarthShard.AbilityCollisionRadius", 2.0); config.addDefault("Abilities.Earth.EarthShard.EntityCollisionRadius", 1.4); From b8aecf2ca9fc1622dd951956e7e50f850cb8be93 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Wed, 9 Jul 2025 23:52:48 -0400 Subject: [PATCH 37/61] Invert EarthLine cooldown defaults --- src/com/jedk1/jedcore/configuration/JedCoreConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 7ee0cc6..0344bb2 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -293,8 +293,8 @@ private void loadConfigCore() { + "If you then Left-Click at an object or player, a small piece of earth will come up " + "from the ground and move towards your target to deal damage and knock them back. " + "Additionally, hold Sneak to control the flow of the line!"); - config.addDefault("Abilities.Earth.EarthLine.Cooldown", 0); - config.addDefault("Abilities.Earth.EarthLine.PrepareCooldown", 3000); + config.addDefault("Abilities.Earth.EarthLine.Cooldown", 3000); + config.addDefault("Abilities.Earth.EarthLine.PrepareCooldown", 0); config.addDefault("Abilities.Earth.EarthLine.Range", 30); config.addDefault("Abilities.Earth.EarthLine.PrepareRange", 3); config.addDefault("Abilities.Earth.EarthLine.SourceKeepRange", 7); From 8bffbd7b8b9f17fc670f63965108056b7a0dd465 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Thu, 10 Jul 2025 00:50:41 -0400 Subject: [PATCH 38/61] Add `BlockCutting` and `KnockBack` options to AirBlade --- .../jedcore/ability/airbending/AirBlade.java | 60 +++++++++++++++++-- .../jedcore/configuration/JedCoreConfig.java | 39 +++++++++--- 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java index 4fd64bf..caa5e51 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java @@ -9,19 +9,31 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Tag; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.util.Vector; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class AirBlade extends AirAbility implements AddonAbility { + private Set cuttableBlocks; + private Location location; private Vector direction; private double travelled; + private boolean blockCuttingEnabled; + private boolean revertCutBlocks; + private long revertTime; @Attribute("Growth") private double growth = 1; @@ -33,8 +45,10 @@ public class AirBlade extends AirAbility implements AddonAbility { private double damage; @Attribute("CollisionRadius") private double entityCollisionRadius; - @Attribute("Speed") + @Attribute(Attribute.SPEED) private double speed; + @Attribute(Attribute.KNOCKBACK) + private double knockback; public AirBlade(Player player) { super(player); @@ -60,6 +74,14 @@ public void setFields() { damage = config.getDouble("Abilities.Air.AirBlade.Damage"); entityCollisionRadius = config.getDouble("Abilities.Air.AirBlade.EntityCollisionRadius"); speed = config.getDouble("Abilities.Air.AirBlade.Speed"); + knockback = config.getDouble("Abilities.Air.AirBlade.Knockback"); + + ConfigurationSection cuttingConfig = config.getConfigurationSection("Abilities.Air.AirBlade.BlockCutting"); + + blockCuttingEnabled = cuttingConfig.getBoolean("Enabled"); + revertCutBlocks = cuttingConfig.getBoolean("Revert"); + revertTime = cuttingConfig.getLong("RevertTime"); + cuttableBlocks = loadCuttableBlocks(cuttingConfig.getStringList("Materials")); } @Override @@ -90,6 +112,14 @@ private void progressBlade() { Location tempLoc = calculateParticleLocation(i); playAirbendingParticles(tempLoc, 1, (float) Math.random() / 2, (float) Math.random() / 2, (float) Math.random() / 2); + if (j == 0 && blockCuttingEnabled && cuttableBlocks.contains(tempLoc.getBlock().getType()) && !RegionProtection.isRegionProtected(this.player, tempLoc)) { + if (revertCutBlocks) { + new TempBlock(tempLoc.getBlock(), Material.AIR.createBlockData(), revertTime); + } else { + tempLoc.getBlock().breakNaturally(); + } + } + if (j == 0 && !lastLoc.getBlock().getLocation().equals(tempLoc.getBlock().getLocation())) { if (handleEntityCollision(tempLoc)) { return; @@ -127,16 +157,34 @@ private Location calculateParticleLocation(double angle) { } private boolean handleEntityCollision(Location tempLoc) { - boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), entity -> { + return CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), entity -> { DamageHandler.damageEntity(entity, damage, this); + + if (knockback > 0) { + Vector knockDir = entity.getLocation().toVector().subtract(location.toVector()).normalize(); + entity.setVelocity(entity.getVelocity().add(knockDir.multiply(knockback))); + } + remove(); return true; }); - if (hit) { - remove(); - return true; + } + + private Set loadCuttableBlocks(List entries) { + Set result = new HashSet<>(); + for (String entry : entries) { + if (entry.startsWith("#")) { + String tagKey = entry.substring(1).toLowerCase(); + NamespacedKey ns = NamespacedKey.minecraft(tagKey); + Tag tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, ns, Material.class); + if (tag != null) tag.getValues().forEach(result::add); + } else { + try { + result.add(Material.valueOf(entry.toUpperCase())); + } catch (IllegalArgumentException ignored) {} + } } - return false; + return result; } @Override diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 0344bb2..31e4d64 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -113,7 +113,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Enabled", true); config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Radius", 3); config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Regen", 20000); - + config.addDefault("Abilities.Air.AirBlade.Enabled", true); config.addDefault("Abilities.Air.AirBlade.Description", "With this ability bound, Left-Click to shoot " + "a strong blade of air at your targets to deal some damage!"); @@ -121,14 +121,39 @@ private void loadConfigCore() { config.addDefault("Abilities.Air.AirBlade.Range", 30.0); config.addDefault("Abilities.Air.AirBlade.Damage", 4.0); config.addDefault("Abilities.Air.AirBlade.Speed", 1.0); + config.addDefault("Abilities.Air.AirBlade.Knockback", 0.0); config.addDefault("Abilities.Air.AirBlade.EntityCollisionRadius", 1.0); config.addDefault("Abilities.Air.AirBlade.AbilityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.Enabled",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveFirst",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveSecond",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.Enabled",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveFirst",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveSecond",false); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveFirst", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveSecond", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveFirst", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveSecond", false); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.Revert", true); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.RevertTime", 5000); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.Materials", Arrays.asList( + "#small_flowers", + "#flowers", + "#crops", + "#saplings", + "BIG_DRIPLEAF_STEM", + "BIG_DRIPLEAF", + "CAVE_VINES", + "CAVE_VINES_PLANT", + "VINE", + "FERN", + "LARGE_FERN", + "SHORT_GRASS", + "TALL_GRASS", + "DEAD_BUSH", + "SEA_PICKLE", + "CACTUS_FLOWER", + "BERRY_BUSH", + "RED_MUSHROOM", + "BROWN_MUSHROOM" + )); config.addDefault("Abilities.Air.AirBreath.Enabled", true); config.addDefault("Abilities.Air.AirBreath.Description", "To use, hold Sneak (Default: Shift) to release " From 47b22a54e9006b7d35395f2b25e388710771b894 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Thu, 10 Jul 2025 01:14:18 -0400 Subject: [PATCH 39/61] Add `ReplaceSource` option to EarthKick to toggle holes --- .../jedcore/ability/earthbending/EarthKick.java | 16 ++++++++++------ .../jedcore/configuration/JedCoreConfig.java | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java index bac1840..1f35dab 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -46,6 +46,7 @@ public class EarthKick extends EarthAbility implements AddonAbility { private int spread; private double velocity; private boolean allowMetal; + private boolean replaceSource; @Attribute(Attribute.COOLDOWN) private long cooldown; @@ -91,6 +92,7 @@ public void setFields() { spread = config.getInt("Abilities.Earth.EarthKick.Spread"); velocity = config.getDouble("Abilities.Earth.EarthKick.Velocity"); allowMetal = config.getBoolean("Abilities.Earth.EarthKick.AllowMetal"); + replaceSource = config.getBoolean("Abilities.Earth.EarthKick.ReplaceSource"); if (entityCollisionRadius < 1.0) { entityCollisionRadius = 1.0; @@ -146,13 +148,15 @@ public void progress() { } private void launchBlocks() { - if (getMovedEarth().containsKey(block)) { - block.setType(Material.AIR); - } + if (replaceSource) { + if (getMovedEarth().containsKey(block)) { + block.setType(Material.AIR); + } - if (block.getType() != Material.AIR) { - TempBlock air = new TempBlock(block, Material.AIR); - air.setRevertTime(5000L); + if (block.getType() != Material.AIR) { + TempBlock air = new TempBlock(block, Material.AIR); + air.setRevertTime(5000L); + } } location.setPitch(0); diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 31e4d64..a1f5637 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -286,6 +286,7 @@ private void loadConfigCore() { config.addDefault("Abilities.Earth.EarthKick.Spread", 20); config.addDefault("Abilities.Earth.EarthKick.Velocity", 0.7); config.addDefault("Abilities.Earth.EarthKick.AllowMetal", true); + config.addDefault("Abilities.Earth.EarthKick.ReplaceSource", false); config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.Enabled", true); config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveFirst", false); config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveSecond", true); From 1bfb7973ec2f9809a1952b10b9b3482614a10bdc Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 15 Jul 2025 02:04:05 -0400 Subject: [PATCH 40/61] Patch LavaDisc and LavaThrow --- .../ability/earthbending/LavaDisc.java | 42 +++++++++++-------- .../ability/earthbending/LavaThrow.java | 9 ++-- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java b/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java index d778648..547a666 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java @@ -14,6 +14,7 @@ import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; @@ -25,6 +26,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; +import org.bukkit.Sound; import org.bukkit.block.Block; import org.bukkit.block.data.Levelled; import org.bukkit.configuration.ConfigurationSection; @@ -85,7 +87,7 @@ public LavaDisc(Player player) { public void setFields() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); - + damage = config.getDouble("Abilities.Earth.LavaDisc.Damage"); cooldown = config.getLong("Abilities.Earth.LavaDisc.Cooldown"); duration = config.getLong("Abilities.Earth.LavaDisc.Duration"); @@ -109,16 +111,16 @@ private boolean prepare() { boolean lavaOnly = config.getBoolean("Abilities.Earth.LavaDisc.Source.LavaOnly"); double sourceRange = config.getDouble("Abilities.Earth.LavaDisc.Source.Range"); - if (getLavaSourceBlock(player, sourceRange) != null) { - Block block = getLavaSourceBlock(player, sourceRange); - new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); - return true; - } else if (getEarthSourceBlock(sourceRange) != null) { - if (lavaOnly) - return false; - Block block = getEarthSourceBlock(sourceRange); - new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); + Block lavaSource = getLavaSourceBlock(player, sourceRange); + if (lavaSource != null && !EarthAbility.getMovedEarth().containsKey(lavaSource)) { + new RegenTempBlock(lavaSource, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); return true; + } else { + Block earthSource = getEarthSourceBlock(sourceRange); + if (earthSource != null && !lavaOnly && !EarthAbility.getMovedEarth().containsKey(earthSource)) { + new RegenTempBlock(earthSource, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); + return true; + } } return false; @@ -188,7 +190,7 @@ private void doDamage(Entity entity) { new FireDamageTimer(entity, player, this); ParticleEffect.LAVA.display(entity.getLocation(), 15, Math.random(), Math.random(), Math.random(), 0.1); } - + @Override public long getCooldown() { return cooldown; @@ -534,18 +536,24 @@ void render(Location location, boolean largeLava) { } private void damageBlocks(Location l) { + Block block = l.getBlock(); + if (EarthAbility.getMovedEarth().containsKey(block)) { + ParticleEffect.LAVA.display(l, 20, 0.5, 0.5, 0.5, 0.2); + ParticleEffect.BLOCK_CRACK.display(l, 15, 0.3, 0.3, 0.3, 0.15, Material.LAVA.createBlockData()); + return; + } if (!RegionProtection.isRegionProtected(player, l, LavaDisc.this)) { - if (!TempBlock.isTempBlock(l.getBlock()) && (isEarthbendable(player, l.getBlock()) || isMetal(l.getBlock()) || meltable.contains(l.getBlock().getType().name()))) { - if (DensityShift.isPassiveSand(l.getBlock())) { - DensityShift.revertSand(l.getBlock()); + if (!TempBlock.isTempBlock(block) && (isEarthbendable(player, block) || isMetal(block) || meltable.contains(block.getType().name()))) { + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); } if (lavaTrail) { - new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled) bd).setLevel(4)), regenTime); + new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled) bd).setLevel(4)), regenTime); - trailBlocks.add(l.getBlock()); + trailBlocks.add(block); } else { - new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), regenTime); + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), regenTime); } ParticleEffect.LAVA.display(l, particles * 2, Math.random(), Math.random(), Math.random(), 0.2); diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java index a84d303..2f7e624 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java @@ -11,6 +11,7 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.Material; @@ -118,11 +119,12 @@ public void progress() { private boolean prepare() { Block targetBlock = getTargetLavaBlock(sourceRange); - if (targetBlock != null) { + if (targetBlock != null && !TempBlock.isTempBlock(targetBlock)) { selectedSource = targetBlock; + return true; } - return selectedSource != null; + return false; } public Block getTargetLavaBlock(int maxDistance) { @@ -164,8 +166,7 @@ public void createBlast() { blasts.put(head, origin); new RegenTempBlock(selectedSource.getRelative(BlockFace.UP), Material.LAVA, - Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); - new RegenTempBlock(selectedSource, Material.AIR, Material.AIR.createBlockData(), sourceRegen, false); + Material.LAVA.createBlockData(), 200); } } From d5c7ab0b4cc55d01b60c6b46a6d4573f9c5c4a75 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 15 Jul 2025 03:18:08 -0400 Subject: [PATCH 41/61] More options for IceClaws (suggestion by Prusakov Aleksandr) --- .../ability/waterbending/IceClaws.java | 127 +++++++++++------- .../jedcore/configuration/JedCoreConfig.java | 12 +- 2 files changed, 90 insertions(+), 49 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java b/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java index e211317..c32736d 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java @@ -22,15 +22,23 @@ public class IceClaws extends IceAbility implements AddonAbility { @Attribute(Attribute.COOLDOWN) - private long cooldown; + private long punchCooldown; + @Attribute(Attribute.COOLDOWN) + private long throwCooldown; @Attribute(Attribute.CHARGE_DURATION) private long chargeUp; - private int slowDur; + private int punchSlowDur; + private int throwSlowDur; + private int punchSlownessLevel; + private int throwSlownessLevel; + @Attribute(Attribute.DAMAGE) + private double punchDamage; @Attribute(Attribute.DAMAGE) - private double damage; + private double throwDamage; @Attribute(Attribute.RANGE) private double range; private boolean throwable; + private double throwSpeed; private Location head; private Location origin; @@ -59,19 +67,29 @@ public IceClaws(Player player) { public void setFields() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); - cooldown = config.getLong("Abilities.Water.IceClaws.Cooldown"); - chargeUp = config.getLong("Abilities.Water.IceClaws.ChargeTime"); - slowDur = config.getInt("Abilities.Water.IceClaws.SlowDuration")/50; - damage = config.getDouble("Abilities.Water.IceClaws.Damage"); - range = config.getDouble("Abilities.Water.IceClaws.Range"); - throwable = config.getBoolean("Abilities.Water.IceClaws.Throwable"); - + punchCooldown = config.getLong("Abilities.Water.IceClaws.Punch.Cooldown", 4000); + punchDamage = config.getDouble("Abilities.Water.IceClaws.Punch.Damage", 2.0); + punchSlownessLevel = config.getInt("Abilities.Water.IceClaws.Punch.Slowness", 3); + punchSlowDur = config.getInt("Abilities.Water.IceClaws.Punch.SlowDuration", 5000); + + throwCooldown = config.getLong("Abilities.Water.IceClaws.Throw.Cooldown", 4000); + throwDamage = config.getDouble("Abilities.Water.IceClaws.Throw.Damage", 2.0); + throwSlownessLevel = config.getInt("Abilities.Water.IceClaws.Throw.Slowness", 3); + throwSlowDur = config.getInt("Abilities.Water.IceClaws.Throw.SlowDuration", 5000); + throwSpeed = config.getDouble("Abilities.Water.IceClaws.Throw.Speed", 1.0); + + chargeUp = config.getLong("Abilities.Water.IceClaws.ChargeTime", 1000); + range = config.getDouble("Abilities.Water.IceClaws.Range", 10); + throwable = config.getBoolean("Abilities.Water.IceClaws.Throwable", true); + applyModifiers(); } private void applyModifiers() { - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - damage = getNightFactor(damage); + punchCooldown -= ((long) getNightFactor(punchCooldown) - punchCooldown); + throwCooldown -= ((long) getNightFactor(throwCooldown) - throwCooldown); + punchDamage = getNightFactor(punchDamage); + throwDamage = getNightFactor(throwDamage); range = getNightFactor(range); } @@ -102,6 +120,8 @@ public void progress() { public static void swapHands(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + if (!config.getBoolean("Abilities.Water.IceClaws.AllowHandSwap", true)) return; IceClaws ic = getAbility(player, IceClaws.class); if (ic == null) return; @@ -117,8 +137,8 @@ public Location getRightHandPos() { } public boolean shoot() { - for (double i = 0; i < 1; i+=.5) { - head.add(origin.clone().getDirection().multiply(.5)); + for (double i = 0; i < 1; i += throwSpeed) { + head.add(origin.clone().getDirection().multiply(throwSpeed)); if (origin.distance(head) >= range) return false; if (!isTransparent(head.getBlock())) return false; GeneralMethods.displayColoredParticle("66FFFF", head); @@ -126,13 +146,12 @@ public boolean shoot() { ParticleEffect.SNOW_SHOVEL.display(head, 1, 0, 0, 0, 0); for (Entity entity : GeneralMethods.getEntitiesAroundPoint(head, 1.5)) { if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { - freezeEntity((LivingEntity) entity); + freezeEntity((LivingEntity) entity, false); return false; } } } return true; - } public static void throwClaws(Player player) { @@ -166,19 +185,24 @@ public static boolean freezeEntity(Player player, LivingEntity entity) { } private void freezeEntity(LivingEntity entity) { + freezeEntity(entity, true); + } + + private void freezeEntity(LivingEntity entity, boolean isPunch) { if (entity.hasPotionEffect(PotionEffectType.SPEED)) { entity.removePotionEffect(PotionEffectType.SPEED); } - // todo: doesnt seem to be affecting mobs? frostbreath does. - entity.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect(slowDur, 3)); + int duration = isPunch ? punchSlowDur : throwSlowDur; + int level = isPunch ? punchSlownessLevel : throwSlownessLevel; + entity.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect(duration, level)); bPlayer.addCooldown(this); remove(); - DamageHandler.damageEntity(entity, damage, this); + DamageHandler.damageEntity(entity, isPunch ? punchDamage : throwDamage, this); } @Override public long getCooldown() { - return cooldown; + return launched ? throwCooldown : punchCooldown; } @Override @@ -217,33 +241,18 @@ public String getDescription() { return "* JedCore Addon *\n" + config.getString("Abilities.Water.IceClaws.Description"); } - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getChargeUp() { - return chargeUp; - } - - public void setChargeUp(long chargeUp) { - this.chargeUp = chargeUp; - } - - public int getSlowDuration() { - return slowDur; - } - - public void setSlowDuration(int slowDuration) { - this.slowDur = slowDuration; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } + public void setPunchCooldown(long punchCooldown) { this.punchCooldown = punchCooldown; } + public long getPunchCooldown() { return punchCooldown; } + public void setThrowCooldown(long throwCooldown) { this.throwCooldown = throwCooldown; } + public long getThrowCooldown() { return throwCooldown; } + public void setPunchDamage(double punchDamage) { this.punchDamage = punchDamage; } + public double getPunchDamage() { return punchDamage; } + public void setThrowDamage(double throwDamage) { this.throwDamage = throwDamage; } + public double getThrowDamage() { return throwDamage; } + public void setPunchSlowDur(int punchSlowDur) { this.punchSlowDur = punchSlowDur; } + public int getPunchSlowDur() { return punchSlowDur; } + public void setThrowSlowDur(int throwSlowDur) { this.throwSlowDur = throwSlowDur; } + public int getThrowSlowDur() { return throwSlowDur; } public double getRange() { return range; @@ -296,4 +305,28 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Water.IceClaws.Enabled"); } + + public int getPunchSlownessLevel() { + return punchSlownessLevel; + } + + public void setPunchSlownessLevel(int punchSlownessLevel) { + this.punchSlownessLevel = punchSlownessLevel; + } + + public int getThrowSlownessLevel() { + return throwSlownessLevel; + } + + public void setThrowSlownessLevel(int throwSlownessLevel) { + this.throwSlownessLevel = throwSlownessLevel; + } + + public double getThrowSpeed() { + return throwSpeed; + } + + public void setThrowSpeed(double throwSpeed) { + this.throwSpeed = throwSpeed; + } } \ No newline at end of file diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index a1f5637..36a24e7 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -864,10 +864,18 @@ private void loadConfigCore() { + "tips, then attack an enemy to slow them down and do a bit of damage!"); config.addDefault("Abilities.Water.IceClaws.Cooldown", 6000); config.addDefault("Abilities.Water.IceClaws.ChargeTime", 1000); - config.addDefault("Abilities.Water.IceClaws.SlowDuration", 5000); - config.addDefault("Abilities.Water.IceClaws.Damage", 3.0); config.addDefault("Abilities.Water.IceClaws.Range", 10); config.addDefault("Abilities.Water.IceClaws.Throwable", true); + config.addDefault("Abilities.Water.IceClaws.Punch.Cooldown", 4000); + config.addDefault("Abilities.Water.IceClaws.Punch.Damage", 2.0); + config.addDefault("Abilities.Water.IceClaws.Punch.Slowness", 3); + config.addDefault("Abilities.Water.IceClaws.Punch.SlowDuration", 5000); + config.addDefault("Abilities.Water.IceClaws.Throw.Cooldown", 4000); + config.addDefault("Abilities.Water.IceClaws.Throw.Damage", 2.0); + config.addDefault("Abilities.Water.IceClaws.Throw.Slowness", 3); + config.addDefault("Abilities.Water.IceClaws.Throw.SlowDuration", 5000); + config.addDefault("Abilities.Water.IceClaws.Throw.Speed", 1.0); + config.addDefault("Abilities.Water.IceClaws.AllowHandSwap", true); config.addDefault("Abilities.Water.IceWall.Enabled", true); config.addDefault("Abilities.Water.IceWall.Description", "IceWall allows an icebender to create a wall of ice, similar to " From c89c8ae55622d41a6d37821e760c89d7150a70e9 Mon Sep 17 00:00:00 2001 From: cozmyc <172064888+CozmycDev@users.noreply.github.com> Date: Tue, 15 Jul 2025 03:55:40 -0400 Subject: [PATCH 42/61] FirePunch can burn items you drop while active (suggestion by Prusakov Aleksandr) --- .../jedcore/configuration/JedCoreConfig.java | 3 ++- .../jedk1/jedcore/listener/AbilityListener.java | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 36a24e7..710e78f 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -718,7 +718,8 @@ private void loadConfigCore() { config.addDefault("Abilities.Fire.FirePunch.Cooldown", 4000); config.addDefault("Abilities.Fire.FirePunch.FireTicks", 2000); config.addDefault("Abilities.Fire.FirePunch.Damage", 2.0); - + config.addDefault("Abilities.Fire.FirePunch.BurnsDroppedItems", true); + config.addDefault("Abilities.Fire.FireShots.Enabled", true); config.addDefault("Abilities.Fire.FireShots.Description", "To use, tap Sneak (Default: Shift) to summon a " + "FireBalls at your hand, then Left Click to shoot off each ball! " diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java index 31c033a..9373862 100644 --- a/src/com/jedk1/jedcore/listener/AbilityListener.java +++ b/src/com/jedk1/jedcore/listener/AbilityListener.java @@ -63,6 +63,7 @@ import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; import com.projectkorra.projectkorra.firebending.FireJet; import com.projectkorra.projectkorra.util.MovementHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.waterbending.blood.Bloodbending; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -156,6 +157,21 @@ public void onPlayerSwingBypassCancel(PlayerInteractEvent event) { @EventHandler(priority = EventPriority.LOWEST) public void onPlayerDropItemEvent(PlayerDropItemEvent event) { recentlyDropped.add(event.getPlayer().getUniqueId()); + + // FirePunch item burn effect + Player player = event.getPlayer(); + FirePunch fp = FirePunch.getAbility(player, FirePunch.class); + boolean burnEnabled = com.jedk1.jedcore.configuration.JedCoreConfig.getConfig((Player)null).getBoolean("Abilities.Fire.FirePunch.BurnsDroppedItems", true); + if (fp != null && burnEnabled) { + var item = event.getItemDrop(); + var loc = fp.getRightHandPos(); + ParticleEffect.LAVA.display(loc, 5, 0.1, 0.1, 0.1, 0.05); + ParticleEffect.FLAME.display(loc, 3, 0.1, 0.1, 0.1, 0.01); + ParticleEffect.SMOKE_NORMAL.display(loc, 2, 0.05, 0.05, 0.05, 0.01); + loc.getWorld().playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, 0.3f, 1.4f); + item.remove(); + } + Bukkit.getScheduler().runTaskLater(ProjectKorra.plugin, () -> recentlyDropped.remove(event.getPlayer().getUniqueId()), 2L); } From 69bc6525ef784e6eb34fd62d8a132cd4c2298d4b Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Fri, 1 Aug 2025 19:18:37 -0700 Subject: [PATCH 43/61] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 717e9d0..1fedc93 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[![GitHub Pre-Release](https://img.shields.io/github/release-pre/CozmycDev/JedCore.svg)](https://github.com/CozmycDev/JedCore/releases) -[![Github All Releases](https://img.shields.io/github/downloads/CozmycDev/JedCore/total.svg)](https://github.com/CozmycDev/JedCore/releases) -![Size](https://img.shields.io/github/repo-size/CozmycDev/JedCore.svg) +[![GitHub Pre-Release](https://img.shields.io/github/release-pre/Hihelloy-main/JedCore.svg)](https://github.com/CozmycDev/JedCore/releases) +[![Github All Releases](https://img.shields.io/github/downloads/Hihelloy-main/JedCore/total.svg)](https://github.com/CozmycDev/JedCore/releases) +![Size](https://img.shields.io/github/repo-size/Hihelloy-main/JedCore.svg) # JedCore This is my fork of plushmonkey's fork of jedk1's JedCore addon for ProjectKorra. -Download releases [here](https://github.com/CozmycDev/JedCore/releases). -Join our [Discord](https://discord.gg/gh9MfDmwZm) to discuss the plugin, suggest changes, report bugs, etc. +Download releases [here](https://github.com/Hihelloy-main/JedCore/releases). +Join our [Discord]() to discuss the plugin, suggest changes, report bugs, etc (new Discord soon). ## Changelog From a6fae4fa54ebbebc72106c9971640cc5d5fe43bd Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Fri, 1 Aug 2025 19:22:02 -0700 Subject: [PATCH 44/61] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fedc93..96909e1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Size](https://img.shields.io/github/repo-size/Hihelloy-main/JedCore.svg) # JedCore -This is my fork of plushmonkey's fork of jedk1's JedCore addon for ProjectKorra. +This is my fork of Cozymc's fork of plushmonkey's fork of jedk1's JedCore addon for ProjectKorra. Download releases [here](https://github.com/Hihelloy-main/JedCore/releases). Join our [Discord]() to discuss the plugin, suggest changes, report bugs, etc (new Discord soon). From c37e814c3c621aca5861217eb601597b23e248c8 Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 3 Aug 2025 19:13:02 -0700 Subject: [PATCH 45/61] added some new files --- plugin.yml | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ pom.xml | 27 +++++++------ 2 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 plugin.yml diff --git a/plugin.yml b/plugin.yml new file mode 100644 index 0000000..5eb7f75 --- /dev/null +++ b/plugin.yml @@ -0,0 +1,109 @@ +name: JedCore +main: com.jedk1.jedcore.JedCore +version: ${project.version} +authors: ['jedk1'] +depend: [ProjectKorra] +folia-supported: true +api-version: '1.20' +load: POSTWORLD +description: "A cool ProjectKorra addon plugin" + +permissions: + # OP permissions + jedcore.admin: + default: op + description: Access to abilities and commands. + children: + jedcore.admin.notify: true + bending.ability.SwiftStream: true + bending.ability.BloodPuppet: true + bending.ability.PlantDrain: true + bending.ability.Fissure: true + bending.ability.LavaFlux: true + bending.ability.FireBreath.RainbowBreath: true + bending.ability.ElementSphere: true + bending.ability.ElementSphere.Air: true + bending.ability.ElementSphere.Earth: true + bending.ability.ElementSphere.Fire: true + bending.ability.ElementSphere.Water: true + bending.ability.ElementSphere.Stream: true + bending.ability.Maelstrom: true + bending.ability.SpiritBeam: true + + # Player Permissions + jedcore.commands: + default: true + description: Access to player commands. + children: + bending.command.jedcore: true + + jedcore.passive: + default: true + description: Access to passive abilities. + children: + bending.ability.WallRun: true + + jedcore.air: + default: true + description: Access to air abilities. + children: + bending.ability.AirBlade: true + bending.ability.AirBreath: true + bending.ability.AirPunch: true + bending.ability.AirGlide: true + bending.ability.Meditate: true + bending.ability.SonicBlast: true + bending.ability.AirSlam: true + + jedcore.water: + default: true + description: Access to water abilities. + children: + bending.ability.FrostBreath: true + bending.ability.IceClaws: true + bending.ability.IceSkate: true + bending.ability.IceWall: true + bending.ability.Drain: true + bending.ability.WakeFishing: true + bending.ability.WaterFlow: true + bending.ability.WaterGimbal: true + + jedcore.earth: + default: true + description: Access to earth abilities. + children: + bending.ability.Crevice: true + bending.ability.EarthKick: true + bending.ability.EarthLine: true + bending.ability.EarthPillar: true + bending.ability.EarthShard: true + bending.ability.EarthSurf: true + bending.ability.LavaDisc: true + bending.ability.LavaThrow: true + bending.ability.MagnetShield: true + bending.ability.MetalFragments: true + bending.ability.MetalHook: true + bending.ability.MetalShred: true + bending.ability.MudSurge: true + bending.ability.SandBlast: true + bending.ability.MagmaBlast: true + + jedcore.fire: + default: true + description: Access to fire abilities. + children: + bending.ability.Combustion: true + bending.ability.Discharge: true + bending.ability.FireBall: true + bending.ability.FireBreath: true + bending.ability.FireComet: true + bending.ability.FirePunch: true + bending.ability.FireShots: true + bending.ability.LightningBurst: true + + jedcore.chi: + default: true + description: Access to chi abilities. + children: + bending.ability.Backstab: true + bending.ability.DaggerThrow: true diff --git a/pom.xml b/pom.xml index 647a300..06eff36 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.jedk1 jedcore - 2.15.0-PK1.11.1 + 2.15.1-PRE-RELEASE-1-PK1.12.0 jar JedCore @@ -13,21 +13,26 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + papermc + https://repo.papermc.io/repository/maven-public/ + + - - - org.spigotmc - spigot-api - 1.20.2-R0.1-SNAPSHOT - provided - com.projectkorra projectkorra - 1.11.1 + 1.12.0 + + + + io.papermc.paper + paper-api + 1.20.2-R0.1-SNAPSHOT + provided @@ -51,8 +56,8 @@ maven-compiler-plugin 3.8.0 - 9 - 9 + 16 + 16 From 5f85f47acd2b0fd9dca29acf45f7a95e21d8911f Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 3 Aug 2025 19:13:56 -0700 Subject: [PATCH 46/61] Delete src/com/jedk1/jedcore directory --- src/com/jedk1/jedcore/JCManager.java | 27 - src/com/jedk1/jedcore/JCMethods.java | 356 ------ src/com/jedk1/jedcore/JedCore.java | 126 -- .../jedcore/ability/airbending/AirBlade.java | 335 ----- .../jedcore/ability/airbending/AirBreath.java | 395 ------ .../jedcore/ability/airbending/AirGlide.java | 259 ---- .../jedcore/ability/airbending/AirPunch.java | 307 ----- .../jedcore/ability/airbending/Meditate.java | 234 ---- .../ability/airbending/SonicBlast.java | 221 ---- .../ability/airbending/combo/AirSlam.java | 188 --- .../ability/airbending/combo/SwiftStream.java | 197 --- .../jedcore/ability/avatar/SpiritBeam.java | 279 ----- .../ability/avatar/elementsphere/ESAir.java | 223 ---- .../ability/avatar/elementsphere/ESEarth.java | 219 ---- .../ability/avatar/elementsphere/ESFire.java | 299 ----- .../avatar/elementsphere/ESStream.java | 406 ------ .../ability/avatar/elementsphere/ESWater.java | 259 ---- .../avatar/elementsphere/ElementSphere.java | 525 -------- .../jedcore/ability/chiblocking/Backstab.java | 113 -- .../ability/chiblocking/DaggerThrow.java | 350 ------ .../ability/earthbending/EarthKick.java | 343 ----- .../ability/earthbending/EarthLine.java | 492 -------- .../ability/earthbending/EarthPillar.java | 215 ---- .../ability/earthbending/EarthShard.java | 527 -------- .../ability/earthbending/EarthSurf.java | 504 -------- .../jedcore/ability/earthbending/Fissure.java | 441 ------- .../ability/earthbending/LavaDisc.java | 564 --------- .../ability/earthbending/LavaFlux.java | 449 ------- .../ability/earthbending/LavaThrow.java | 344 ----- .../ability/earthbending/MagnetShield.java | 279 ----- .../ability/earthbending/MetalArmor.java | 211 ---- .../ability/earthbending/MetalFragments.java | 434 ------- .../ability/earthbending/MetalHook.java | 395 ------ .../ability/earthbending/MetalShred.java | 482 ------- .../ability/earthbending/MudSurge.java | 665 ---------- .../ability/earthbending/SandBlast.java | 376 ------ .../ability/earthbending/combo/Crevice.java | 375 ------ .../earthbending/combo/MagmaBlast.java | 621 ---------- .../ability/firebending/Combustion.java | 631 ---------- .../ability/firebending/Discharge.java | 346 ------ .../jedcore/ability/firebending/FireBall.java | 307 ----- .../ability/firebending/FireBreath.java | 426 ------- .../ability/firebending/FireComet.java | 464 ------- .../ability/firebending/FirePunch.java | 179 --- .../ability/firebending/FireShots.java | 416 ------- .../jedcore/ability/firebending/FireSki.java | 332 ----- .../ability/firebending/LightningBurst.java | 370 ------ .../jedcore/ability/passive/WallRun.java | 264 ---- .../ability/waterbending/BloodPuppet.java | 523 -------- .../ability/waterbending/Bloodbending.java | 380 ------ .../jedcore/ability/waterbending/Drain.java | 604 --------- .../ability/waterbending/DrainBlast.java | 168 --- .../ability/waterbending/FrostBreath.java | 440 ------- .../ability/waterbending/HealingWaters.java | 268 ---- .../ability/waterbending/IceClaws.java | 332 ----- .../ability/waterbending/IcePassive.java | 69 -- .../jedcore/ability/waterbending/IceWall.java | 609 --------- .../ability/waterbending/WakeFishing.java | 235 ---- .../ability/waterbending/WaterBlast.java | 244 ---- .../ability/waterbending/combo/Maelstrom.java | 330 ----- .../ability/waterbending/combo/WaterFlow.java | 730 ----------- .../waterbending/combo/WaterGimbal.java | 648 ---------- src/com/jedk1/jedcore/collision/AABB.java | 183 --- src/com/jedk1/jedcore/collision/Collider.java | 12 - .../jedcore/collision/CollisionDetector.java | 127 -- .../jedcore/collision/CollisionUtil.java | 34 - src/com/jedk1/jedcore/collision/Ray.java | 38 - src/com/jedk1/jedcore/collision/Sphere.java | 53 - src/com/jedk1/jedcore/command/Commands.java | 9 - .../jedk1/jedcore/command/JedCoreCommand.java | 59 - .../jedk1/jedcore/configuration/Config.java | 66 - .../jedcore/configuration/JedCoreConfig.java | 1104 ----------------- .../SubsectionConfigurationDecorator.java | 668 ---------- .../jedk1/jedcore/event/PKCommandEvent.java | 69 -- .../jedcore/listener/AbilityListener.java | 584 --------- .../jedcore/listener/CommandListener.java | 74 -- .../jedk1/jedcore/listener/JCListener.java | 245 ---- .../removal/CannotBendRemovalPolicy.java | 44 - .../removal/CompositeRemovalPolicy.java | 87 -- .../policies/removal/IsDeadRemovalPolicy.java | 21 - .../removal/IsOfflineRemovalPolicy.java | 21 - .../removal/OutOfRangeRemovalPolicy.java | 37 - .../policies/removal/RemovalPolicy.java | 11 - .../removal/SwappedSlotsRemovalPolicy.java | 26 - .../jedk1/jedcore/util/AbilitySelector.java | 68 - .../jedcore/util/AirShieldReflector.java | 28 - src/com/jedk1/jedcore/util/BlockUtil.java | 19 - src/com/jedk1/jedcore/util/ChiRestrictor.java | 136 -- .../jedcore/util/CollisionInitializer.java | 96 -- src/com/jedk1/jedcore/util/FireTick.java | 65 - src/com/jedk1/jedcore/util/LightManager.java | 454 ------- src/com/jedk1/jedcore/util/MaterialUtil.java | 47 - src/com/jedk1/jedcore/util/MetricsLite.java | 535 -------- .../jedk1/jedcore/util/RegenTempBlock.java | 182 --- .../jedcore/util/TemporaryFallingBlock.java | 30 - .../jedcore/util/ThrownEntityTracker.java | 92 -- .../util/versionadapter/ParticleAdapter.java | 8 - .../ParticleAdapterFactory.java | 25 - .../ParticleAdapter_1_20_4.java | 30 - .../ParticleAdapter_1_20_5.java | 26 - .../versionadapter/PotionEffectAdapter.java | 15 - .../PotionEffectAdapterFactory.java | 25 - .../PotionEffectAdapter_1_20_4.java | 55 - .../PotionEffectAdapter_1_20_5.java | 55 - .../util/versionadapter/PotionMetaUtil.java | 29 - 105 files changed, 27942 deletions(-) delete mode 100644 src/com/jedk1/jedcore/JCManager.java delete mode 100644 src/com/jedk1/jedcore/JCMethods.java delete mode 100644 src/com/jedk1/jedcore/JedCore.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/AirBlade.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/AirBreath.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/AirGlide.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/AirPunch.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/Meditate.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/SonicBlast.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java delete mode 100644 src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java delete mode 100644 src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java delete mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java delete mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java delete mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java delete mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java delete mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java delete mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java delete mode 100644 src/com/jedk1/jedcore/ability/chiblocking/Backstab.java delete mode 100644 src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthKick.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthLine.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthShard.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/Fissure.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalHook.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalShred.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/MudSurge.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/SandBlast.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java delete mode 100644 src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/Combustion.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/Discharge.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/FireBall.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/FireBreath.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/FireComet.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/FirePunch.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/FireShots.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/FireSki.java delete mode 100644 src/com/jedk1/jedcore/ability/firebending/LightningBurst.java delete mode 100644 src/com/jedk1/jedcore/ability/passive/WallRun.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/Drain.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/IceClaws.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/IcePassive.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/IceWall.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java delete mode 100644 src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java delete mode 100644 src/com/jedk1/jedcore/collision/AABB.java delete mode 100644 src/com/jedk1/jedcore/collision/Collider.java delete mode 100644 src/com/jedk1/jedcore/collision/CollisionDetector.java delete mode 100644 src/com/jedk1/jedcore/collision/CollisionUtil.java delete mode 100644 src/com/jedk1/jedcore/collision/Ray.java delete mode 100644 src/com/jedk1/jedcore/collision/Sphere.java delete mode 100644 src/com/jedk1/jedcore/command/Commands.java delete mode 100644 src/com/jedk1/jedcore/command/JedCoreCommand.java delete mode 100644 src/com/jedk1/jedcore/configuration/Config.java delete mode 100644 src/com/jedk1/jedcore/configuration/JedCoreConfig.java delete mode 100644 src/com/jedk1/jedcore/configuration/SubsectionConfigurationDecorator.java delete mode 100644 src/com/jedk1/jedcore/event/PKCommandEvent.java delete mode 100644 src/com/jedk1/jedcore/listener/AbilityListener.java delete mode 100644 src/com/jedk1/jedcore/listener/CommandListener.java delete mode 100644 src/com/jedk1/jedcore/listener/JCListener.java delete mode 100644 src/com/jedk1/jedcore/policies/removal/CannotBendRemovalPolicy.java delete mode 100644 src/com/jedk1/jedcore/policies/removal/CompositeRemovalPolicy.java delete mode 100644 src/com/jedk1/jedcore/policies/removal/IsDeadRemovalPolicy.java delete mode 100644 src/com/jedk1/jedcore/policies/removal/IsOfflineRemovalPolicy.java delete mode 100644 src/com/jedk1/jedcore/policies/removal/OutOfRangeRemovalPolicy.java delete mode 100644 src/com/jedk1/jedcore/policies/removal/RemovalPolicy.java delete mode 100644 src/com/jedk1/jedcore/policies/removal/SwappedSlotsRemovalPolicy.java delete mode 100644 src/com/jedk1/jedcore/util/AbilitySelector.java delete mode 100644 src/com/jedk1/jedcore/util/AirShieldReflector.java delete mode 100644 src/com/jedk1/jedcore/util/BlockUtil.java delete mode 100644 src/com/jedk1/jedcore/util/ChiRestrictor.java delete mode 100644 src/com/jedk1/jedcore/util/CollisionInitializer.java delete mode 100644 src/com/jedk1/jedcore/util/FireTick.java delete mode 100644 src/com/jedk1/jedcore/util/LightManager.java delete mode 100644 src/com/jedk1/jedcore/util/MaterialUtil.java delete mode 100644 src/com/jedk1/jedcore/util/MetricsLite.java delete mode 100644 src/com/jedk1/jedcore/util/RegenTempBlock.java delete mode 100644 src/com/jedk1/jedcore/util/TemporaryFallingBlock.java delete mode 100644 src/com/jedk1/jedcore/util/ThrownEntityTracker.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/ParticleAdapterFactory.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_4.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_5.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapterFactory.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_4.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_5.java delete mode 100644 src/com/jedk1/jedcore/util/versionadapter/PotionMetaUtil.java diff --git a/src/com/jedk1/jedcore/JCManager.java b/src/com/jedk1/jedcore/JCManager.java deleted file mode 100644 index a1872aa..0000000 --- a/src/com/jedk1/jedcore/JCManager.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.jedk1.jedcore; - -import com.jedk1.jedcore.ability.waterbending.IceWall; -import com.jedk1.jedcore.ability.firebending.LightningBurst; -import com.jedk1.jedcore.ability.waterbending.HealingWaters; -import com.jedk1.jedcore.ability.waterbending.IcePassive; -import com.jedk1.jedcore.util.RegenTempBlock; -import org.bukkit.Bukkit; - -public class JCManager implements Runnable { - - public JedCore plugin; - - public JCManager(JedCore plugin) { - this.plugin = plugin; - } - - public void run() { - LightningBurst.progressAll(); - - HealingWaters.heal(Bukkit.getServer()); - IcePassive.handleSkating(); - IceWall.progressAll(); - - RegenTempBlock.manage(); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/JCMethods.java b/src/com/jedk1/jedcore/JCMethods.java deleted file mode 100644 index d1a802f..0000000 --- a/src/com/jedk1/jedcore/JCMethods.java +++ /dev/null @@ -1,356 +0,0 @@ -package com.jedk1.jedcore; - -import java.util.*; - -import com.jedk1.jedcore.util.*; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.region.RegionProtection; -import org.bukkit.*; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ProjectKorra; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager; -import com.projectkorra.projectkorra.util.TempBlock; - -public class JCMethods { - - // todo: either use PKs isPlant or the registry/tags (with config) - private static final ArrayList SMALL_PLANTS = new ArrayList(){{ - addAll(Arrays.asList(Material.GRASS, Material.FERN, Material.POPPY, Material.DANDELION, Material.OAK_SAPLING, - Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, - Material.DARK_OAK_SAPLING, Material.ALLIUM, Material.ORANGE_TULIP, Material.PINK_TULIP, Material.RED_TULIP, - Material.WHITE_TULIP, Material.ROSE_BUSH, Material.BLUE_ORCHID, Material.LILAC, Material.OXEYE_DAISY, - Material.AZURE_BLUET, Material.PEONY, Material.SUNFLOWER, Material.LARGE_FERN, Material.RED_MUSHROOM, - Material.BROWN_MUSHROOM, Material.PUMPKIN_STEM, Material.MELON_STEM, Material.WHEAT, Material.TALL_GRASS, - Material.BEETROOTS, Material.CARROTS, Material.POTATOES, Material.CRIMSON_FUNGUS, Material.WARPED_FUNGUS, - Material.BAMBOO, Material.BAMBOO_SAPLING)); - - int serverVersion = GeneralMethods.getMCVersion(); - if (serverVersion >= 1170) { - add(Material.getMaterial("AZALEA")); - add(Material.getMaterial("FLOWERING_AZALEA")); - add(Material.getMaterial("FLOWERING_AZALEA_LEAVES")); - add(Material.getMaterial("AZALEA_LEAVES")); - add(Material.getMaterial("BIG_DRIPLEAF")); - add(Material.getMaterial("BIG_DRIPLEAF_STEM")); - add(Material.getMaterial("SMALL_DRIPLEAF")); - add(Material.getMaterial("HANGING_ROOTS")); - add(Material.getMaterial("GLOW_LICHEN")); - add(Material.getMaterial("CAVE_VINES")); - add(Material.getMaterial("CAVE_VINES_PLANT")); - } - }}; - - private static List worlds = new ArrayList<>(); - private static List combos = new ArrayList<>(); - - public static List getDisabledWorlds() { - return JCMethods.worlds; - } - - public static void registerDisabledWorlds() { - worlds.clear(); - List registeredworlds = ProjectKorra.plugin.getConfig().getStringList("Properties.DisabledWorlds"); - if (!registeredworlds.isEmpty()) { - worlds.addAll(registeredworlds); - } - } - - public static boolean isDisabledWorld(World world) { - return getDisabledWorlds().contains(world.getName()); - } - - public static List getCombos() { - return JCMethods.combos; - } - - public static void registerCombos() { - combos.clear(); - combos.addAll(ComboManager.getComboAbilities().keySet()); - } - - /** - * Gets the points of a line between two points. - * @param startLoc - * @param endLoc - * @param points - * @return locations - */ - public static List getLinePoints(Location startLoc, Location endLoc, int points){ - List locations = new ArrayList(); - Location diff = endLoc.subtract(startLoc); - double diffX = diff.getX() / points; - double diffY = diff.getY() / points; - double diffZ = diff.getZ() / points; - Location loc = startLoc; - for(int i = 0; i < points; i++){ - loc.add(new Location(startLoc.getWorld(), diffX, diffY, diffZ)); - locations.add(loc.clone()); - } - return locations; - } - - public static List getCirclePoints(Location location, int points, double size) { - return getCirclePoints(location, points, size, 0); - } - - /** - * Gets points in a circle. - * @param location - * @param points - * @param size - * @return - */ - public static List getCirclePoints(Location location, int points, double size, double startangle){ - List locations = new ArrayList(); - for(int i = 0; i < 360; i += 360/points){ - double angle = (i * Math.PI / 180); - double x = size * Math.cos(angle + startangle); - double z = size * Math.sin(angle + startangle); - Location loc = location.clone(); - loc.add(x, 0, z); - locations.add(loc); - } - return locations; - } - - /** - * Gets points in a vertical circle. - * @param location - * @param points - * @param size - * @param yawOffset - * @return - */ - public static List getVerticalCirclePoints(Location location, int points, double size, float yawOffset) { - List locations = new ArrayList<>(); - Location fakeLoc = location.clone(); - fakeLoc.setPitch(0); - fakeLoc.setYaw(yawOffset); - Vector direction = fakeLoc.getDirection(); - - for(double j = -180; j <= 180; j += points){ - Location tempLoc = fakeLoc.clone(); - Vector newDir = direction.clone().multiply(size * Math.cos(Math.toRadians(j))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + size + (size * Math.sin(Math.toRadians(j)))); - locations.add(tempLoc.clone()); - } - return locations; - } - - /** - * Remove an item from a players inventory. - * @param player - * @param material - * @param amount - * @return - */ - public static boolean removeItemFromInventory(Player player, Material material, int amount) { - for (ItemStack item : player.getInventory().getContents()) { - if (item != null && item.getType() == material) { - if (item.getAmount() == amount) { - Map remaining = player.getInventory().removeItem(item); - - if (!remaining.isEmpty()) { - ItemStack offhand = player.getInventory().getItemInOffHand(); - - // Spigot seems to not handle offhand correctly with removeItem, so try to manually remove it. - if (offhand != null && offhand.getType() == material && offhand.getAmount() == amount) { - player.getInventory().setItemInOffHand(null); - } - } - } else if (item.getAmount() > amount) { - item.setAmount(item.getAmount() - amount); - } - - return true; - } - } - - return false; - } - - /** - * Gets points in a spiral shape. - * @param location - * @param points - * @param spiralCount - * @param startAngle - * @param startSize - * @param finalSize - * @param noClip - * @return - */ - public static List getSpiralPoints(Location location, int points, int spiralCount, int startAngle, double startSize, double finalSize, boolean noClip){ - return getSpiralPoints(location, points, spiralCount, 0.0D, startAngle, startSize, finalSize, noClip); - } - - /** - * Gets points in a vertical spiral shape, could be used for a tornado. - * @param location - * @param points - * @param spiralCount - * @param height - * @param startAngle - * @param startSize - * @param finalSize - * @param noClip - * @return - */ - public static List getSpiralPoints(Location location, int points, int spiralCount, double height, int startAngle, double startSize, double finalSize, boolean noClip){ - List locations = new ArrayList(); - - points = points/spiralCount; - double sizeIncr = ((finalSize - startSize) / points)/spiralCount; - double hightIncr = (height/points)/spiralCount; - double size = startSize; - for(int i = 0; i < spiralCount; i++){ - for(int j = 0; j < 360; j += 360/points){ - hightIncr = hightIncr + ((height/points)/spiralCount); - size = size + sizeIncr; - double angle = (j * Math.PI / 180); - double x = size * Math.cos(angle + startAngle); - double z = size * Math.sin(angle + startAngle); - Location loc = location.clone(); - loc.add(x, hightIncr, z); - if(!noClip && ElementalAbility.isAir(loc.getBlock().getType())) - locations.add(loc); - else if(noClip) - locations.add(loc); - } - } - - return locations; - } - - public static void extinguishBlocks(Player player, String ability, int range, int radius, boolean fire, boolean lava){ - for (Block block : GeneralMethods.getBlocksAroundPoint(player.getTargetBlock(null, range).getLocation(), radius)) { - Material mat = block.getType(); - if(mat != Material.FIRE && mat != Material.LAVA && mat != Material.SOUL_FIRE) - continue; - if (RegionProtection.isRegionProtected(player, block.getLocation(), ability)) - continue; - if (((mat == Material.FIRE || mat == Material.SOUL_FIRE) && fire)||(mat == Material.LAVA && lava)) { - block.setType(mat != Material.LAVA ? Material.AIR : isLiquidSource(block) ? Material.OBSIDIAN : Material.COBBLESTONE); - block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0); - } - } - } - - /** - * Checks if 3 blocks around the block are of the required type. - * @param block - * @param type - * @return - */ - public static boolean isAdjacentToThreeOrMoreSources(Block block, Material type) { - if (TempBlock.isTempBlock(block)) { - return false; - } - int sources = 0; - BlockFace[] faces = { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN }; - for (BlockFace face : faces) { - Block blocki = block.getRelative(face); - if ((blocki.getType() == type)) { - sources++; - } - } - if (sources >= 2) - return true; - return false; - } - - static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, - Material.NETHER_PORTAL, Material.END_PORTAL, - Material.END_PORTAL_FRAME, Material.OBSIDIAN}; - - public static boolean isUnbreakable(Block block) { - if (block.getState() instanceof InventoryHolder) { - return true; - } - if (Arrays.asList(unbreakables).contains(block.getType())) - return true; - return false; - } - - public static boolean isLiquidSource(Block block) { - if (!block.isLiquid()) { - return false; - } - - if (!(block.getBlockData() instanceof Levelled)) { - return false; - } - - Levelled levelData = (Levelled) block.getBlockData(); - - return levelData.getLevel() == 0; - } - - // TODO: Should this be reimplemented or has the rpg plugin been abandoned? - public static boolean isSozinsComet(World world) { - return false; - } - - // TODO: Should this be reimplemented or has the rpg plugin been abandoned? - public static boolean isLunarEclipse(World world) { - return false; - } - - // todo: see SMALL_PLANTS - public static boolean isDoublePlant(Material material) { - return material == Material.SUNFLOWER || material == Material.LILAC || material == Material.TALL_GRASS || - material == Material.LARGE_FERN || material == Material.ROSE_BUSH || material == Material.PEONY; - } - - public static boolean isSmallPlant(Block block) { - return isSmallPlant(block.getType()); - } - - public static boolean isSmallPlant(Material material) { - return WaterAbility.isPlant(material); - //return SMALL_PLANTS.contains(material); - } - - public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra) { - displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, 255); - } - - public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { - JedCore.plugin.getParticleAdapter().displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, alpha); - } - - public static void emitLight(Location loc) { - ConfigurationSection config = JedCoreConfig.getConfig((Player)null); - if (config.getBoolean("Properties.Fire.DynamicLight.Enabled")) { - int brightness = config.getInt("Properties.Fire.DynamicLight.Brightness"); - long keepAlive = config.getLong("Properties.Fire.DynamicLight.KeepAlive"); - - LightManager.createLight(loc).brightness(brightness).timeUntilFadeout(keepAlive).emit(); - } - } - - public static void reload() { - JedCore.log.info("JedCore Reloaded."); - JedCore.plugin.reloadConfig(); - JedCore.logDebug = JedCoreConfig.getConfig((World)null).getBoolean("Properties.LogDebug"); - CoreAbility.registerPluginAbilities(JedCore.plugin, "com.jedk1.jedcore.ability"); - registerDisabledWorlds(); - registerCombos(); - RegenTempBlock.revertAll(); - JedCore.plugin.initializeCollisions(); - FireTick.loadMethod(); - } -} diff --git a/src/com/jedk1/jedcore/JedCore.java b/src/com/jedk1/jedcore/JedCore.java deleted file mode 100644 index 9dc2ca2..0000000 --- a/src/com/jedk1/jedcore/JedCore.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.jedk1.jedcore; - -import java.io.IOException; -import java.util.logging.*; - -import com.google.common.reflect.ClassPath; -import com.jedk1.jedcore.util.*; -import com.jedk1.jedcore.util.versionadapter.ParticleAdapter; -import com.jedk1.jedcore.util.versionadapter.ParticleAdapterFactory; -import com.jedk1.jedcore.util.versionadapter.PotionEffectAdapter; -import com.jedk1.jedcore.util.versionadapter.PotionEffectAdapterFactory; -import org.bukkit.World; -import org.bukkit.plugin.java.JavaPlugin; - -import com.jedk1.jedcore.command.Commands; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.listener.AbilityListener; -import com.jedk1.jedcore.listener.CommandListener; -import com.jedk1.jedcore.listener.JCListener; -import com.projectkorra.projectkorra.ability.CoreAbility; -import org.bukkit.scheduler.BukkitRunnable; - -public class JedCore extends JavaPlugin { - - public static JedCore plugin; - public static Logger log; - public static String dev; - public static String version; - public static boolean logDebug; - - private ParticleAdapter particleAdapter; - private PotionEffectAdapter potionEffectAdapter; - - @Override - public void onEnable() { - plugin = this; - JedCore.log = this.getLogger(); - new JedCoreConfig(this); - - logDebug = JedCoreConfig.getConfig((World)null).getBoolean("Properties.LogDebug"); - - dev = this.getDescription().getAuthors().toString().replace("[", "").replace("]", ""); - version = this.getDescription().getVersion(); - - JCMethods.registerDisabledWorlds(); - CoreAbility.registerPluginAbilities(plugin, "com.jedk1.jedcore.ability"); - getServer().getPluginManager().registerEvents(new AbilityListener(this), this); - getServer().getPluginManager().registerEvents(new CommandListener(this), this); - getServer().getPluginManager().registerEvents(new JCListener(this), this); - getServer().getPluginManager().registerEvents(new ChiRestrictor(), this); - getServer().getScheduler().scheduleSyncRepeatingTask(this, new JCManager(this), 0, 1); - - new Commands(); - - FireTick.loadMethod(); - - ParticleAdapterFactory particleAdapterFactory = new ParticleAdapterFactory(); - particleAdapter = particleAdapterFactory.getAdapter(); - - PotionEffectAdapterFactory potionEffectAdapterFactory = new PotionEffectAdapterFactory(); - potionEffectAdapter = potionEffectAdapterFactory.getAdapter(); - - new BukkitRunnable() { - @Override - public void run() { - JCMethods.registerCombos(); - initializeCollisions(); - } - }.runTaskLater(this, 1); - - try { - MetricsLite metrics = new MetricsLite(this); - metrics.start(); - log.info("Initialized Metrics."); - } catch (IOException e) { - log.info("Failed to submit statistics for MetricsLite."); - } - } - - public void initializeCollisions() { - boolean enabled = this.getConfig().getBoolean("Properties.AbilityCollisions.Enabled"); - - if (!enabled) { - getLogger().info("Collisions disabled."); - return; - } - - try { - ClassPath cp = ClassPath.from(this.getClassLoader()); - - for (ClassPath.ClassInfo info : cp.getTopLevelClassesRecursive("com.jedk1.jedcore.ability")) { - try { - @SuppressWarnings("unchecked") - Class abilityClass = (Class)Class.forName(info.getName()); - - if (abilityClass == null) continue; - - CollisionInitializer initializer = new CollisionInitializer<>(abilityClass); - initializer.initialize(); - } catch (Exception e) { - - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void onDisable() { - RegenTempBlock.revertAll(); - } - - public static void logDebug(String message) { - if (logDebug) { - plugin.getLogger().info(message); - } - } - - public ParticleAdapter getParticleAdapter() { - return this.particleAdapter; - } - - public PotionEffectAdapter getPotionEffectAdapter() { - return this.potionEffectAdapter; - } -} diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java deleted file mode 100644 index caa5e51..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java +++ /dev/null @@ -1,335 +0,0 @@ -package com.jedk1.jedcore.ability.airbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Tag; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class AirBlade extends AirAbility implements AddonAbility { - - private Set cuttableBlocks; - - private Location location; - private Vector direction; - private double travelled; - private boolean blockCuttingEnabled; - private boolean revertCutBlocks; - private long revertTime; - - @Attribute("Growth") - private double growth = 1; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute("CollisionRadius") - private double entityCollisionRadius; - @Attribute(Attribute.SPEED) - private double speed; - @Attribute(Attribute.KNOCKBACK) - private double knockback; - - public AirBlade(Player player) { - super(player); - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - this.location = player.getEyeLocation().clone(); - this.direction = player.getEyeLocation().getDirection().clone(); - - start(); - if (!isRemoved()) - bPlayer.addCooldown(this); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Air.AirBlade.Cooldown"); - range = config.getDouble("Abilities.Air.AirBlade.Range"); - damage = config.getDouble("Abilities.Air.AirBlade.Damage"); - entityCollisionRadius = config.getDouble("Abilities.Air.AirBlade.EntityCollisionRadius"); - speed = config.getDouble("Abilities.Air.AirBlade.Speed"); - knockback = config.getDouble("Abilities.Air.AirBlade.Knockback"); - - ConfigurationSection cuttingConfig = config.getConfigurationSection("Abilities.Air.AirBlade.BlockCutting"); - - blockCuttingEnabled = cuttingConfig.getBoolean("Enabled"); - revertCutBlocks = cuttingConfig.getBoolean("Revert"); - revertTime = cuttingConfig.getLong("RevertTime"); - cuttableBlocks = loadCuttableBlocks(cuttingConfig.getStringList("Materials")); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (travelled >= range) { - remove(); - return; - } - - progressBlade(); - } - - private void progressBlade() { - for (int j = 0; j < 2; j++) { - if (!moveAndCheckCollision()) { - return; - } - - double pitch = -location.getPitch(); - Location lastLoc = location.clone(); - - for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { - Location tempLoc = calculateParticleLocation(i); - playAirbendingParticles(tempLoc, 1, (float) Math.random() / 2, (float) Math.random() / 2, (float) Math.random() / 2); - - if (j == 0 && blockCuttingEnabled && cuttableBlocks.contains(tempLoc.getBlock().getType()) && !RegionProtection.isRegionProtected(this.player, tempLoc)) { - if (revertCutBlocks) { - new TempBlock(tempLoc.getBlock(), Material.AIR.createBlockData(), revertTime); - } else { - tempLoc.getBlock().breakNaturally(); - } - } - - if (j == 0 && !lastLoc.getBlock().getLocation().equals(tempLoc.getBlock().getLocation())) { - if (handleEntityCollision(tempLoc)) { - return; - } - lastLoc = tempLoc; - } - } - } - } - - private boolean moveAndCheckCollision() { - location = location.add(direction.multiply(speed)); - playAirbendingSound(location); - travelled += speed; - growth += 0.125; - - if (travelled >= range || - !isTransparent(location.getBlock()) || - RegionProtection.isRegionProtected(player, player.getLocation(), this)) { - remove(); - return false; - } - return true; - } - - private Location calculateParticleLocation(double angle) { - Location tempLoc = location.clone(); - tempLoc.setPitch(0); - Vector tempDir = tempLoc.getDirection().clone(); - tempDir.setY(0); - Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(angle))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(angle)))); - return tempLoc; - } - - private boolean handleEntityCollision(Location tempLoc) { - return CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), entity -> { - DamageHandler.damageEntity(entity, damage, this); - - if (knockback > 0) { - Vector knockDir = entity.getLocation().toVector().subtract(location.toVector()).normalize(); - entity.setVelocity(entity.getVelocity().add(knockDir.multiply(knockback))); - } - - remove(); - return true; - }); - } - - private Set loadCuttableBlocks(List entries) { - Set result = new HashSet<>(); - for (String entry : entries) { - if (entry.startsWith("#")) { - String tagKey = entry.substring(1).toLowerCase(); - NamespacedKey ns = NamespacedKey.minecraft(tagKey); - Tag tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, ns, Material.class); - if (tag != null) tag.getValues().forEach(result::add); - } else { - try { - result.add(Material.valueOf(entry.toUpperCase())); - } catch (IllegalArgumentException ignored) {} - } - } - return result; - } - - @Override - public Player getPlayer() { - return player; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public List getLocations() { - List locations = new ArrayList<>(); - - double pitch = -location.getPitch(); - - for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { - Location tempLoc = location.clone(); - tempLoc.setPitch(0); - - Vector tempDir = tempLoc.getDirection().clone(); - tempDir.setY(0); - - Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(i))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(i)))); - - locations.add(tempLoc); - } - - return locations; - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Air.AirBlade.AbilityCollisionRadius"); - } - - public long getCooldown() { - return cooldown; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - @Override - public String getName() { - return "AirBlade"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirBlade.Description"); - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getTravelled() { - return travelled; - } - - public void setTravelled(double travelled) { - this.travelled = travelled; - } - - public double getGrowth() { - return growth; - } - - public void setGrowth(double growth) { - this.growth = growth; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.AirBlade.Enabled"); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBreath.java b/src/com/jedk1/jedcore/ability/airbending/AirBreath.java deleted file mode 100644 index 497af20..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/AirBreath.java +++ /dev/null @@ -1,395 +0,0 @@ -package com.jedk1.jedcore.ability.airbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; - -public class AirBreath extends AirAbility implements AddonAbility { - - private int particles; - private boolean coolLava; - private boolean extinguishFire; - private boolean extinguishMobs; - private boolean damageEnabled; - private double launch; - private boolean regenOxygen; - private boolean avatarAmplify; - private int avatarRange; - private double avatarKnockback; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.DAMAGE) - private double playerDamage; - @Attribute(Attribute.DAMAGE) - private double mobDamage; - @Attribute(Attribute.KNOCKBACK) - private double knockback; - @Attribute(Attribute.RANGE) - private int range; - - public AirBreath(Player player) { - super(player); - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - if (bPlayer.isAvatarState() && avatarAmplify) { - range = avatarRange; - knockback = avatarKnockback; - } - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Air.AirBreath.Cooldown"); - duration = config.getLong("Abilities.Air.AirBreath.Duration"); - particles = config.getInt("Abilities.Air.AirBreath.Particles"); - coolLava = config.getBoolean("Abilities.Air.AirBreath.AffectBlocks.Lava"); - extinguishFire = config.getBoolean("Abilities.Air.AirBreath.AffectBlocks.Fire"); - extinguishMobs = config.getBoolean("Abilities.Air.AirBreath.ExtinguishEntities"); - damageEnabled = config.getBoolean("Abilities.Air.AirBreath.Damage.Enabled"); - playerDamage = config.getDouble("Abilities.Air.AirBreath.Damage.Player"); - mobDamage = config.getDouble("Abilities.Air.AirBreath.Damage.Mob"); - knockback = config.getDouble("Abilities.Air.AirBreath.Knockback"); - range = config.getInt("Abilities.Air.AirBreath.Range"); - launch = config.getDouble("Abilities.Air.AirBreath.LaunchPower"); - regenOxygen = config.getBoolean("Abilities.Air.AirBreath.RegenTargetOxygen"); - avatarAmplify = config.getBoolean("Abilities.Air.AirBreath.Avatar.Enabled"); - avatarRange = config.getInt("Abilities.Air.AirBreath.Avatar.Range"); - avatarKnockback = config.getDouble("Abilities.Air.AirBreath.Avatar.Knockback"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!(bPlayer.getBoundAbility() instanceof AirBreath)) { - bPlayer.addCooldown(this); - remove(); - return; - } - - if (!player.isSneaking()) { - bPlayer.addCooldown(this); - remove(); - return; - } - - if (System.currentTimeMillis() < getStartTime() + duration) { - playAirbendingSound(player.getLocation()); - createBeam(); - } else { - bPlayer.addCooldown(this); - remove(); - } - } - - private boolean isLocationSafe(Location loc) { - Block block = loc.getBlock(); - - if (RegionProtection.isRegionProtected(player, loc, this)) { - return false; - } - - return isTransparent(block); - } - - private void createBeam() { - Location loc = player.getEyeLocation(); - Vector dir = player.getLocation().getDirection(); - double step = 1; - double size = 0; - double damageregion = 1.5; - - for (double i = 0; i < range; i += step) { - loc = loc.add(dir.clone().multiply(step)); - size += 0.005; - damageregion += 0.01; - - if (!handleLocationSafety(loc)) { - return; - } - - handleEntityCollisions(loc, dir, damageregion); - displayBeamParticles(loc, size); - handleBlockEffects(); - } - } - - private boolean handleLocationSafety(Location loc) { - if (!isLocationSafe(loc)) { - if (!isTransparent(loc.getBlock()) && player.getLocation().getPitch() > 30) { - GeneralMethods.setVelocity(this, player, player.getLocation().getDirection().multiply(-launch)); - } - return false; - } - return true; - } - - private void handleEntityCollisions(Location loc, Vector dir, double damageregion) { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageregion)) { - if (isValidTarget(entity)) { - if (isEntityProtected(entity)) { - continue; - } - applyEntityEffects(entity, dir); - } - } - } - - private boolean isValidTarget(Entity entity) { - return entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand); - } - - private boolean isEntityProtected(Entity entity) { - return RegionProtection.isRegionProtected(this, entity.getLocation()) || (entity instanceof Player && Commands.invincible.contains(entity.getName())); - } - - private void applyEntityEffects(Entity entity, Vector dir) { - if (entity instanceof LivingEntity livingEntity) { - applyDamage(livingEntity); - applyOxygenRegen(livingEntity); - if (extinguishMobs) { - livingEntity.setFireTicks(0); - } - } - dir.multiply(knockback); - GeneralMethods.setVelocity(this, entity, dir); - } - - private void applyDamage(LivingEntity entity) { - if (damageEnabled) { - if (entity instanceof Player) { - DamageHandler.damageEntity(entity, playerDamage, this); - } else { - DamageHandler.damageEntity(entity, mobDamage, this); - } - } - } - - private void applyOxygenRegen(LivingEntity entity) { - if (regenOxygen && isWater(entity.getLocation().getBlock()) && !entity.hasPotionEffect(PotionEffectType.WATER_BREATHING)) { - entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 100, 2)); - } - } - - private void displayBeamParticles(Location loc, double size) { - if (isWater(loc.getBlock())) { - ParticleEffect.WATER_BUBBLE.display(loc, particles, Math.random(), Math.random(), Math.random(), size); - } - - ParticleEffect mainParticle = getAirbendingParticles(); - if (mainParticle == ParticleEffect.CLOUD) { - ParticleEffect.CLOUD.display(loc, particles, Math.random(), Math.random(), Math.random(), size); - JCMethods.displayColoredParticles("#FFFFFF", loc, particles, Math.random(), Math.random(), Math.random(), 0f); - JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particles, Math.random(), Math.random(), Math.random(), size, 50); - } else if (mainParticle != null) { - mainParticle.display(loc, particles, Math.random(), Math.random(), Math.random(), size); - } - } - - private void handleBlockEffects() { - JCMethods.extinguishBlocks(player, "AirBreath", range, 2, extinguishFire, coolLava); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return player.getEyeLocation(); - } - - @Override - public String getName() { - return "AirBreath"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirBreath.Description"); - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public int getParticles() { - return particles; - } - - public void setParticles(int particles) { - this.particles = particles; - } - - public boolean isCoolLava() { - return coolLava; - } - - public void setCoolLava(boolean coolLava) { - this.coolLava = coolLava; - } - - public boolean canExtinguishFire() { - return extinguishFire; - } - - public void setExtinguishFire(boolean extinguishFire) { - this.extinguishFire = extinguishFire; - } - - public boolean canExtinguishMobs() { - return extinguishMobs; - } - - public void setExtinguishMobs(boolean extinguishMobs) { - this.extinguishMobs = extinguishMobs; - } - - public boolean isDamageEnabled() { - return damageEnabled; - } - - public void setDamageEnabled(boolean damageEnabled) { - this.damageEnabled = damageEnabled; - } - - public double getPlayerDamage() { - return playerDamage; - } - - public void setPlayerDamage(double playerDamage) { - this.playerDamage = playerDamage; - } - - public double getMobDamage() { - return mobDamage; - } - - public void setMobDamage(double mobDamage) { - this.mobDamage = mobDamage; - } - - public double getKnockback() { - return knockback; - } - - public void setKnockback(double knockback) { - this.knockback = knockback; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public double getLaunch() { - return launch; - } - - public void setLaunch(double launch) { - this.launch = launch; - } - - public boolean canRegenOxygen() { - return regenOxygen; - } - - public void setRegenOxygen(boolean regenOxygen) { - this.regenOxygen = regenOxygen; - } - - public boolean isAvatarAmplify() { - return avatarAmplify; - } - - public void setAvatarAmplify(boolean avatarAmplify) { - this.avatarAmplify = avatarAmplify; - } - - public int getAvatarRange() { - return avatarRange; - } - - public void setAvatarRange(int avatarRange) { - this.avatarRange = avatarRange; - } - - public double getAvatarKnockback() { - return avatarKnockback; - } - - public void setAvatarKnockback(double avatarKnockback) { - this.avatarKnockback = avatarKnockback; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.AirBreath.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/airbending/AirGlide.java b/src/com/jedk1/jedcore/ability/airbending/AirGlide.java deleted file mode 100644 index 77c0b1d..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/AirGlide.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.jedk1.jedcore.ability.airbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.airbending.AirSpout; -import com.projectkorra.projectkorra.attribute.Attribute; -import org.bukkit.Location; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class AirGlide extends AirAbility implements AddonAbility { - - private double fallSpeed; - private int particles; - private boolean airspout; - private long lastCooldown; - private boolean progressing; - // The player must touch the ground for the cooldown to start if this is true. - private boolean requireGround; - - @Attribute(Attribute.SPEED) - private double speed; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - - public AirGlide(Player player) { - super(player); - - if (hasAbility(player, AirGlide.class)) { - AirGlide ag = getAbility(player, AirGlide.class); - ag.remove(); - return; - } - - if (bPlayer.isOnCooldown(this) || CollisionDetector.isOnGround(player)) { - return; - } - - setFields(); - - this.progressing = true; - - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - speed = config.getDouble("Abilities.Air.AirGlide.Speed"); - fallSpeed = config.getDouble("Abilities.Air.AirGlide.FallSpeed"); - particles = config.getInt("Abilities.Air.AirGlide.Particles"); - airspout = config.getBoolean("Abilities.Air.AirGlide.AllowAirSpout"); - cooldown = config.getLong("Abilities.Air.AirGlide.Cooldown"); - duration = config.getLong("Abilities.Air.AirGlide.Duration"); - requireGround = config.getBoolean("Abilities.Air.AirGlide.RequireGround") && cooldown > 0; - } - - public void progress() { - long time = System.currentTimeMillis(); - - if (this.progressing) { - update(time); - } else { - if (player.isDead() || !player.isOnline()) { - this.requireGround = false; - remove(); - return; - } - - if (CollisionDetector.isOnGround(this.player)) { - this.requireGround = false; - remove(); - } else { - if (time > lastCooldown + cooldown / 2) { - bPlayer.addCooldown(this); - lastCooldown = time; - } - } - } - } - - @SuppressWarnings("deprecation") - private void update(long time) { - if (this.duration > 0 && time >= this.getStartTime() + this.duration) { - remove(); - return; - } - - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!hasAbility(player, AirGlide.class)) { - remove(); - return; - } - - if ((airspout && hasAbility(player, AirSpout.class)) || !hasAirGlide()) { - remove(); - return; - } - - if (!player.isOnGround()) { - Location firstLocation = player.getEyeLocation(); - - Vector directionVector = firstLocation.getDirection().normalize(); - double distanceFromPlayer = speed; - - Vector shootFromPlayer = new Vector(directionVector.getX() * distanceFromPlayer, -fallSpeed, directionVector.getZ() * distanceFromPlayer); - firstLocation.add(shootFromPlayer.getX(), shootFromPlayer.getY(), shootFromPlayer.getZ()); - - GeneralMethods.setVelocity(this, player, shootFromPlayer); - - playAirbendingParticles(player.getLocation(), particles); - } else if (!isTransparent(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) { - remove(); - } - } - - @Override - public void remove() { - this.progressing = false; - bPlayer.addCooldown(this); - - if (!this.requireGround) { - super.remove(); - } - } - - private boolean hasAirGlide() { - return bPlayer.getAbilities().containsValue("AirGlide"); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return player.getLocation(); - } - - @Override - public String getName() { - return "AirGlide"; - } - - @Override - public boolean isHarmlessAbility() { - return true; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirGlide.Description"); - } - - public boolean isRequireGround() { - return requireGround; - } - - public void setRequireGround(boolean requireGround) { - this.requireGround = requireGround; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - } - - public double getFallSpeed() { - return fallSpeed; - } - - public void setFallSpeed(double fallSpeed) { - this.fallSpeed = fallSpeed; - } - - public int getParticles() { - return particles; - } - - public void setParticles(int particles) { - this.particles = particles; - } - - public boolean allowsAirSpout() { - return airspout; - } - - public void setAllowAirSpout(boolean airspout) { - this.airspout = airspout; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public long getLastCooldown() { - return lastCooldown; - } - - public void setLastCooldown(long lastCooldown) { - this.lastCooldown = lastCooldown; - } - - public boolean isProgressing() { - return progressing; - } - - public void setProgressing(boolean progressing) { - this.progressing = progressing; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.AirGlide.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/airbending/AirPunch.java b/src/com/jedk1/jedcore/ability/airbending/AirPunch.java deleted file mode 100644 index b01492b..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/AirPunch.java +++ /dev/null @@ -1,307 +0,0 @@ -package com.jedk1.jedcore.ability.airbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class AirPunch extends AirAbility implements AddonAbility { - - private final Map locations = new ConcurrentHashMap<>(); - - private int shots; - private long lastShotTime; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private long threshold; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.COOLDOWN) - private double damage; - @Attribute("CollisionRadius") - private double entityCollisionRadius; - @Attribute("Speed") - private double speed; - - public AirPunch(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, AirPunch.class)) { - AirPunch ap = getAbility(player, AirPunch.class); - ap.createShot(); - return; - } - - setFields(); - - start(); - - if (!isRemoved()) createShot(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Air.AirPunch.Cooldown"); - threshold = config.getLong("Abilities.Air.AirPunch.Threshold"); - shots = config.getInt("Abilities.Air.AirPunch.Shots"); - range = config.getDouble("Abilities.Air.AirPunch.Range"); - damage = config.getDouble("Abilities.Air.AirPunch.Damage"); - entityCollisionRadius = config.getDouble("Abilities.Air.AirPunch.EntityCollisionRadius"); - speed = config.getDouble("Abilities.Air.AirPunch.Speed"); - } - - @Override - public void progress() { - progressShots(); - - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - prepareRemove(); - return; - } - - if (shots == 0 || System.currentTimeMillis() > lastShotTime + threshold) { - prepareRemove(); - } - } - - private void prepareRemove() { - if (player.isOnline() && !bPlayer.isOnCooldown(this)) { - bPlayer.addCooldown(this); - } - - if (locations.isEmpty()) { - remove(); - } - } - - private void createShot() { - if (shots >= 1) { - lastShotTime = System.currentTimeMillis(); - shots--; - locations.put(player.getEyeLocation().add(player.getLocation().getDirection().multiply(1.5).normalize()), 0D); - } - } - - private void progressShots() { - Iterator> iterator = locations.entrySet().iterator(); - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - Location originalLoc = entry.getKey(); - double dist = entry.getValue(); - ShotResult result = simulateShotProgression(originalLoc, dist); - - iterator.remove(); - - if (result.moved) { - locations.put(result.newLoc, result.newDist); - } - } - } - - private record ShotResult(Location newLoc, double newDist, boolean moved) {} - - private ShotResult simulateShotProgression(Location startLoc, double startDist) { - Location loc = startLoc.clone(); - double dist = startDist; - boolean shouldRemove = false; - boolean moved = false; - - for (int i = 0; i < 3 && !shouldRemove; i++) { - dist += speed; - if (dist >= range) { - shouldRemove = true; - } else { - Location nextLoc = calculateNextLocation(loc); - if (isPathBlocked(nextLoc)) { - shouldRemove = true; - } else { - applyShotEffects(nextLoc); - if (checkAndHandleCollision(nextLoc)) { - shouldRemove = true; - } else { - loc = nextLoc; - moved = true; - } - } - } - } - - return new ShotResult(loc, dist, moved); - } - - private Location calculateNextLocation(Location currentLocation) { - return currentLocation.add(currentLocation.getDirection().clone().multiply(speed)); - } - - private boolean isPathBlocked(Location location) { - return GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock()) || RegionProtection.isRegionProtected(player, location, this); - } - - private void applyShotEffects(Location location) { - getAirbendingParticles().display(location, 2, Math.random() / 5, Math.random() / 5, Math.random() / 5, 0.0); - playAirbendingSound(location); - } - - private boolean checkAndHandleCollision(Location location) { - return CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), entityCollisionRadius), entity -> { - DamageHandler.damageEntity(entity, damage, this); - return true; - }); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Air.AirPunch.AbilityCollisionRadius"); - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - Location location = collision.getLocationFirst(); - - locations.remove(location); - } - } - - @Override - public List getLocations() { - return new ArrayList<>(locations.keySet()); - } - - @Override - public String getName() { - return "AirPunch"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirPunch.Description"); - } - - public long getThreshold() { - return threshold; - } - - public void setThreshold(long threshold) { - this.threshold = threshold; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - public int getShots() { - return shots; - } - - public void setShots(int shots) { - this.shots = shots; - } - - public long getLastShotTime() { - return lastShotTime; - } - - public void setLastShotTime(long lastShotTime) { - this.lastShotTime = lastShotTime; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.AirPunch.Enabled"); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/airbending/Meditate.java b/src/com/jedk1/jedcore/ability/airbending/Meditate.java deleted file mode 100644 index c240829..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/Meditate.java +++ /dev/null @@ -1,234 +0,0 @@ -package com.jedk1.jedcore.ability.airbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.SpiritualAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -public class Meditate extends SpiritualAbility implements AddonAbility { - - private double startHealth; - private String unfocusMsg; - private long warmup; - private int particleDensity; - private boolean lossFocusMessage; - private int absorptionBoost; - private int speedBoost; - private int jumpBoost; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private int boostDuration; - - public Meditate(Player player) { - super(player); - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - unfocusMsg = config.getString("Abilities.Air.Meditate.UnfocusMessage"); - lossFocusMessage = config.getBoolean("Abilities.Air.Meditate.LossFocusMessage"); - warmup = config.getLong("Abilities.Air.Meditate.ChargeTime"); - cooldown = config.getLong("Abilities.Air.Meditate.Cooldown"); - boostDuration = config.getInt("Abilities.Air.Meditate.BoostDuration"); - particleDensity = config.getInt("Abilities.Air.Meditate.ParticleDensity"); - absorptionBoost = config.getInt("Abilities.Air.Meditate.AbsorptionBoost"); - speedBoost = config.getInt("Abilities.Air.Meditate.SpeedBoost"); - jumpBoost = config.getInt("Abilities.Air.Meditate.JumpBoost"); - - startHealth = player.getHealth(); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - - if (player.getHealth() < startHealth) { - if (lossFocusMessage) player.sendMessage(Element.SPIRITUAL.getColor() + unfocusMsg); - remove(); - return; - } - - if (System.currentTimeMillis() > getStartTime() + warmup) { - player.spawnParticle(Particle.ELECTRIC_SPARK, player.getLocation(), 3, 0.5, 0.5, 0.5, 0.003F); - - JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particleDensity, Math.random(), Math.random(), Math.random(), 0f); - - if (!player.isSneaking()) { - bPlayer.addCooldown(this); - givePlayerBuffs(); - remove(); - } - } else if (player.isSneaking()) { - JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particleDensity, Math.random(), Math.random(), Math.random(), 0f, 50); - } else { - remove(); - } - } - - private void givePlayerBuffs() { - if (player.hasPotionEffect(PotionEffectType.SPEED)) { - player.removePotionEffect(PotionEffectType.SPEED); - } - - player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, boostDuration/50, speedBoost - 1)); - - JedCore.plugin.getPotionEffectAdapter().applyJumpBoost(player, boostDuration, jumpBoost); - - if (player.hasPotionEffect(PotionEffectType.ABSORPTION)) { - player.removePotionEffect(PotionEffectType.ABSORPTION); - } - - player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, boostDuration/50, absorptionBoost - 1)); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return player.getLocation(); - } - - @Override - public String getName() { - return "Meditate"; - } - - @Override - public boolean isHarmlessAbility() { - return true; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.Meditate.Description"); - } - - public double getStartHealth() { - return startHealth; - } - - public void setStartHealth(double startHealth) { - this.startHealth = startHealth; - } - - public String getUnfocusMsg() { - return unfocusMsg; - } - - public void setUnfocusMsg(String unfocusMsg) { - this.unfocusMsg = unfocusMsg; - } - - public boolean hasUnfocusMessage() { - return lossFocusMessage; - } - - public void setHasUnfocusMessage(boolean hasUnfocusMessage) { - this.lossFocusMessage = hasUnfocusMessage; - } - - public long getWarmup() { - return warmup; - } - - public void setWarmup(long warmup) { - this.warmup = warmup; - } - - public int getBoostDuration() { - return boostDuration; - } - - public void setBoostDuration(int boostDuration) { - this.boostDuration = boostDuration; - } - - public int getParticleDensity() { - return particleDensity; - } - - public void setParticleDensity(int particleDensity) { - this.particleDensity = particleDensity; - } - - public int getAbsorptionBoost() { - return absorptionBoost; - } - - public void setAbsorptionBoost(int absorptionBoost) { - this.absorptionBoost = absorptionBoost; - } - - public int getSpeedBoost() { - return speedBoost; - } - - public void setSpeedBoost(int speedBoost) { - this.speedBoost = speedBoost; - } - - public int getJumpBoost() { - return jumpBoost; - } - - public void setJumpBoost(int jumpBoost) { - this.jumpBoost = jumpBoost; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.Meditate.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java b/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java deleted file mode 100644 index 5ae22f2..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.jedk1.jedcore.ability.airbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; - -public class SonicBlast extends AirAbility implements AddonAbility { - - private Location location; - private Vector direction; - private boolean isCharged; - private int travelled; - private int nauseaDur; - private int blindDur; - private boolean chargeSwapping; - - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.RANGE) - private double range; - @Attribute("CollisionRadius") - private double entityCollisionRadius; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("WarmUp") - private long warmup; - - public SonicBlast(Player player) { - super(player); - - if (hasAbility(player, SonicBlast.class) || bPlayer.isOnCooldown(this)) { - return; - } - - setFields(); - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - damage = config.getDouble("Abilities.Air.SonicBlast.Damage"); - range = config.getDouble("Abilities.Air.SonicBlast.Range"); - entityCollisionRadius = config.getDouble("Abilities.Air.SonicBlast.EntityCollisionRadius"); - cooldown = config.getLong("Abilities.Air.SonicBlast.Cooldown"); - warmup = config.getLong("Abilities.Air.SonicBlast.ChargeTime"); - chargeSwapping = config.getBoolean("Abilities.Air.SonicBlast.ChargeSwapping"); - nauseaDur = config.getInt("Abilities.Air.SonicBlast.Effects.NauseaDuration"); - blindDur = config.getInt("Abilities.Air.SonicBlast.Effects.BlindnessDuration"); - } - - @Override - public void progress() { - if (!checkPlayerState()) { - return; - } - - if (!canStartAbility()) { - remove(); - return; - } - - if (player.isSneaking() && travelled == 0) { - handleCharging(); - } else { - handleProgression(); - } - } - - private boolean checkPlayerState() { - return !player.isDead() && player.isOnline(); - } - - private boolean canStartAbility() { - CoreAbility boundAbility = bPlayer.getBoundAbility(); - return chargeSwapping || travelled > 0 || boundAbility instanceof SonicBlast; - } - - private void handleCharging() { - direction = player.getEyeLocation().getDirection().normalize(); - if (isCharged) { - playAirbendingParticles(player.getLocation().add(0, 1, 0), 5, (float) Math.random(), (float) Math.random(), (float) Math.random()); - } else if (System.currentTimeMillis() > getStartTime() + warmup) { - isCharged = true; - } - } - - private void handleProgression() { - if (isCharged) { - if (!bPlayer.isOnCooldown(this)) { - bPlayer.addCooldown(this); - } - if (travelled < range && isLocationSafe()) { - advanceLocation(); - } else { - remove(); - } - } else { - remove(); - } - } - - private boolean isLocationSafe() { - if (location == null) { - Location origin = player.getEyeLocation().clone(); - location = origin.clone(); - } - - return isTransparent(location.getBlock()); - } - - private void advanceLocation() { - travelled++; - - if (location == null) { - Location origin = player.getEyeLocation().clone(); - location = origin.clone(); - } - - for (int i = 0; i < 5; i++) { - for (int angle = 0; angle < 360; angle += 20) { - Location temp = location.clone(); - Vector dir = GeneralMethods.getOrthogonalVector(direction.clone(), angle, 1); - temp.add(dir); - playAirbendingParticles(temp, 1, 0, 0, 0); - } - - boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), entityCollisionRadius), entity -> { - DamageHandler.damageEntity(entity, damage, this); - LivingEntity lE = (LivingEntity) entity; - - lE.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getNauseaEffect(nauseaDur)); - lE.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindDur/50, 1)); - return true; - }); - - if (hit) { - remove(); - return; - } - - location = location.add(direction.clone().multiply(0.2)); - } - - location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 1, 0); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Air.SonicBlast.AbilityCollisionRadius"); - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "SonicBlast"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.SonicBlast.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.SonicBlast.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java b/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java deleted file mode 100644 index f2f99b3..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.jedk1.jedcore.ability.airbending.combo; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.ThrownEntityTracker; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; -import com.projectkorra.projectkorra.region.RegionProtection; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; - -public class AirSlam extends AirAbility implements AddonAbility, ComboAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.KNOCKBACK) - private double power; - @Attribute(Attribute.RANGE) - private int range; - - private LivingEntity target; - - public AirSlam(Player player) { - super(player); - - if (!bPlayer.canBendIgnoreBinds(this)) { - return; - } - - setFields(); - - Entity targetEntity = GeneralMethods.getTargetedEntity(player, range, new ArrayList<>()); - if (!(targetEntity instanceof LivingEntity) - || RegionProtection.isRegionProtected(this, targetEntity.getLocation()) - || ((targetEntity instanceof Player) && Commands.invincible.contains(targetEntity.getName()))) - return; - - this.target = (LivingEntity) targetEntity; - - start(); - - if (!isRemoved()) { - bPlayer.addCooldown(this); - GeneralMethods.setVelocity(this, target, new Vector(0, 2, 0)); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Air.AirCombo.AirSlam.Cooldown"); - power = config.getDouble("Abilities.Air.AirCombo.AirSlam.Power"); - range = config.getInt("Abilities.Air.AirCombo.AirSlam.Range"); - } - - @Override - public void progress() { - if (player == null || player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (System.currentTimeMillis() > getStartTime() + 50) { - Vector dir = player.getLocation().getDirection(); - GeneralMethods.setVelocity(this, target, new Vector(dir.getX(), 0.05, dir.getZ()).multiply(power)); - new HorizontalVelocityTracker(target, player, 0L, this); - new ThrownEntityTracker(this, target, player, 0L); - target.setFallDistance(0); - } - - if (System.currentTimeMillis() > getStartTime() + 400) { - remove(); - return; - } - - playAirbendingParticles(target.getLocation(), 10); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return target != null ? target.getLocation() : null; - } - - @Override - public String getName() { - return "AirSlam"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public Object createNewComboInstance(Player player) { - return new AirSlam(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Air.AirCombo.AirSlam.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Air.AirCombo.AirSlam.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirCombo.AirSlam.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public double getPower() { - return power; - } - - public void setPower(double power) { - this.power = power; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public LivingEntity getTarget() { - return target; - } - - public void setTarget(LivingEntity target) { - this.target = target; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.AirCombo.AirSlam.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java b/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java deleted file mode 100644 index 0b2929c..0000000 --- a/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.jedk1.jedcore.ability.airbending.combo; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.FlightAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; - -public class SwiftStream extends FlightAbility implements AddonAbility, ComboAbility { - - private final List affectedEntities = new ArrayList<>(); - - @Attribute(Attribute.COOLDOWN) - public long cooldown; - @Attribute("DragFactor") - public double dragFactor; - @Attribute(Attribute.DURATION) - public long duration; - - public SwiftStream(Player player) { - super(player); - - if (!bPlayer.canBendIgnoreBinds(this) || !bPlayer.canUseFlight()) { - return; - } - - setFields(); - start(); - - if (!isRemoved()) { - launch(); - bPlayer.addCooldown(this); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Air.AirCombo.SwiftStream.Cooldown"); - dragFactor = config.getDouble("Abilities.Air.AirCombo.SwiftStream.DragFactor"); - duration = config.getLong("Abilities.Air.AirCombo.SwiftStream.Duration"); - } - - public void launch() { - Vector v = player.getEyeLocation().getDirection().normalize(); - - v = v.multiply(5); - v.add(new Vector(0, 0.2, 0)); - - GeneralMethods.setVelocity(this, player, v); - } - - public void affectNearby() { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), 2.5)) { - if (e instanceof LivingEntity livingEntity && !affectedEntities.contains(e) && e.getEntityId() != player.getEntityId()) { - Vector v = player.getVelocity().clone(); - v = v.multiply(dragFactor); - v = v.setY(player.getVelocity().getY()); - v = v.add(new Vector(0, 0.15, 0)); - - GeneralMethods.setVelocity(this, e, v); - - affectedEntities.add(livingEntity); - - new HorizontalVelocityTracker(e, player, 200, this); - } - } - } - - @Override - public void progress() { - if (!player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - remove(); - return; - } - - if (System.currentTimeMillis() > getStartTime() + duration) { - remove(); - return; - } - - playAirbendingParticles(player.getLocation(), 4); - affectNearby(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return player.getLocation(); - } - - @Override - public String getName() { - return "SwiftStream"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public Object createNewComboInstance(Player player) { - return new SwiftStream(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Air.AirCombo.SwiftStream.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Air.AirCombo.SwiftStream.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirCombo.SwiftStream.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public double getDragFactor() { - return dragFactor; - } - - public void setDragFactor(double dragFactor) { - this.dragFactor = dragFactor; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public List getAffectedEntities() { - return affectedEntities; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.AirCombo.SwiftStream.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java b/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java deleted file mode 100644 index 689a3b5..0000000 --- a/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.jedk1.jedcore.ability.avatar; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class SpiritBeam extends AvatarAbility implements AddonAbility { - - private Location location; - private Vector direction; - private boolean damagesBlocks; - private long regen; - private boolean avatarOnly; - - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.RADIUS) - private double radius; - - public SpiritBeam(Player player) { - super(player); - - if (bPlayer.isOnCooldown(this)) return; - - setFields(); - - if (avatarOnly && !bPlayer.isAvatarState()) return; - - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - duration = config.getInt("Abilities.Avatar.SpiritBeam.Duration"); - cooldown = config.getInt("Abilities.Avatar.SpiritBeam.Cooldown"); - damage = config.getDouble("Abilities.Avatar.SpiritBeam.Damage"); - range = config.getInt("Abilities.Avatar.SpiritBeam.Range"); - avatarOnly = config.getBoolean("Abilities.Avatar.SpiritBeam.AvatarStateOnly"); - damagesBlocks = config.getBoolean("Abilities.Avatar.SpiritBeam.BlockDamage.Enabled"); - regen = config.getLong("Abilities.Avatar.SpiritBeam.BlockDamage.Regen"); - radius = config.getDouble("Abilities.Avatar.SpiritBeam.BlockDamage.Radius"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - bPlayer.addCooldown(this); - remove(); - return; - } - - if (System.currentTimeMillis() > getStartTime() + duration) { - bPlayer.addCooldown(this); - remove(); - return; - } - - if (!player.isSneaking()) { - bPlayer.addCooldown(this); - remove(); - return; - } - - if (avatarOnly && !bPlayer.isAvatarState()) { - bPlayer.addCooldown(this); - remove(); - return; - } - - createBeam(); - } - - private void createBeam() { - location = player.getLocation().add(0, 1.2, 0); - Vector beamDirection = location.getDirection().normalize().multiply(0.5); - - for (double i = 0; i < range; i += 0.5) { - location = location.add(beamDirection); - - if (isBeamObstructed(location)) { - return; - } - - displayBeamParticles(location, beamDirection); - JCMethods.emitLight(location); - damageNearbyEntities(location); - - if (handleBlockCollision(location)) { - return; - } - } - } - - private boolean isBeamObstructed(Location location) { - return RegionProtection.isRegionProtected(player, location, this); - } - - private void displayBeamParticles(Location location, Vector direction) { - String purple = "#A020F0"; - JCMethods.displayColoredParticles(purple, location, 1, 0f, 0f, 0f, 0f); - JCMethods.displayColoredParticles(purple, location, 1, (float) Math.random() / 3, (float) Math.random() / 3, (float) Math.random() / 3, 0f); - - float randomOffset = (float) Math.random() / 3; - ParticleEffect.BLOCK_CRACK.display(location, 1, randomOffset, randomOffset, randomOffset, 0.1F, Material.NETHER_PORTAL.createBlockData()); - ParticleEffect.BLOCK_CRACK.display(location, 1, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), 0.1F, Material.NETHER_PORTAL.createBlockData()); - } - - private void damageNearbyEntities(Location location) { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { - if (entity instanceof LivingEntity livingEntity && livingEntity.getEntityId() != player.getEntityId()) { - livingEntity.setFireTicks(100); - DamageHandler.damageEntity(livingEntity, damage, this); - } - } - } - - private boolean handleBlockCollision(Location location) { - if (location.getBlock().getType().isSolid()) { - location.getWorld().createExplosion(location, 0F); - if (damagesBlocks) { - damageBlocksInRadius(location); - } - return true; - } - return false; - } - - private void damageBlocksInRadius(Location center) { - for (Location loc : GeneralMethods.getCircle(center, (int) radius, 0, false, true, 0)) { - if (!JCMethods.isUnbreakable(loc.getBlock())) { - new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); - } - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "SpiritBeam"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Avatar.SpiritBeam.Description"); - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public boolean isAvatarOnly() { - return avatarOnly; - } - - public void setAvatarOnly(boolean avatarOnly) { - this.avatarOnly = avatarOnly; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean damagesBlocks() { - return damagesBlocks; - } - - public void setDamagesBlocks(boolean blockdamage) { - this.damagesBlocks = blockdamage; - } - - public long getRegen() { - return regen; - } - - public void setRegen(long regen) { - this.regen = regen; - } - - public double getRadius() { - return radius; - } - - public void setRadius(double radius) { - this.radius = radius; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.SpiritBeam.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java deleted file mode 100644 index a7e0820..0000000 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -public class ESAir extends AvatarAbility implements AddonAbility { - - private Location location; - private double travelled; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.KNOCKBACK) - private double knockback; - @Attribute(Attribute.SPEED) - private int speed; - - public ESAir(Player player) { - super(player); - - if (!hasAbility(player, ElementSphere.class)) { - return; - } - - ElementSphere currES = getAbility(player, ElementSphere.class); - if (currES.getAirUses() == 0) { - return; - } - - if (bPlayer.isOnCooldown("ESAir")) { - return; - } - - setFields(); - - if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), (int) range).getLocation())) { - return; - } - - location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); - - start(); - - if (!isRemoved()) { - bPlayer.addCooldown("ESAir", getCooldown()); - currES.setAirUses(currES.getAirUses() - 1); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Air.Cooldown"); - range = config.getDouble("Abilities.Avatar.ElementSphere.Air.Range"); - damage = config.getDouble("Abilities.Avatar.ElementSphere.Air.Damage"); - knockback = config.getDouble("Abilities.Avatar.ElementSphere.Air.Knockback"); - speed = config.getInt("Abilities.Avatar.ElementSphere.Air.Speed"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (travelled >= range) { - remove(); - return; - } - - advanceAttack(); - } - - private void advanceAttack() { - for (int i = 0; i < speed; i++) { - travelled++; - if (travelled >= range) return; - - location = location.add(location.getDirection().clone().multiply(1)); - - if (RegionProtection.isRegionProtected(this, location)) { - travelled = range; - return; - } - - if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { - travelled = range; - return; - } - - AirAbility.playAirbendingParticles(location, 5); - AirAbility.playAirbendingSound(location); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() - && !(entity instanceof ArmorStand) - && !RegionProtection.isRegionProtected(this, entity.getLocation()) - && !((entity instanceof Player targetPlayer) - && Commands.invincible.contains((targetPlayer).getName()))) { - DamageHandler.damageEntity(entity, damage, this); - GeneralMethods.setVelocity(this, entity, location.getDirection().multiply(knockback)); - travelled = range; - } - } - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "ElementSphereAir"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public double getDistanceTravelled() { - return travelled; - } - - public void setDistanceTravelled(double travelled) { - this.travelled = travelled; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getKnockback() { - return knockback; - } - - public void setKnockback(double knockback) { - this.knockback = knockback; - } - - public int getSpeed() { - return speed; - } - - public void setSpeed(int speed) { - this.speed = speed; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java deleted file mode 100644 index c4517b8..0000000 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java +++ /dev/null @@ -1,219 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; - -public class ESEarth extends AvatarAbility implements AddonAbility { - - static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, Material.NETHER_PORTAL, Material.END_PORTAL, - Material.END_PORTAL_FRAME, Material.ENDER_CHEST, Material.CHEST, Material.TRAPPED_CHEST }; - - private TempFallingBlock tfb; - private long revertDelay; - - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute("Size") - private int impactSize; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - public ESEarth(Player player) { - super(player); - if (!hasAbility(player, ElementSphere.class)) { - return; - } - ElementSphere currES = getAbility(player, ElementSphere.class); - if (currES.getEarthUses() == 0) { - return; - } - if (bPlayer.isOnCooldown("ESEarth")) { - return; - } - if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), 40).getLocation())) { - return; - } - setFields(); - start(); - if (!isRemoved()) { - bPlayer.addCooldown("ESEarth", getCooldown()); - currES.setEarthUses(currES.getEarthUses() - 1); - Location location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); - tfb = new TempFallingBlock(location, Material.DIRT.createBlockData(), location.getDirection().multiply(3), this); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - revertDelay = config.getLong("Abilities.Avatar.ElementSphere.Earth.ImpactRevert"); - damage = config.getDouble("Abilities.Avatar.ElementSphere.Earth.Damage"); - impactSize = config.getInt("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize"); - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Earth.Cooldown"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline()) { - tfb.remove(); - remove(); - return; - } - if (tfb.getFallingBlock().isDead()) { - remove(); - return; - } - if (RegionProtection.isRegionProtected(this, tfb.getLocation())){ - remove(); - return; - } - - EarthAbility.playEarthbendingSound(tfb.getLocation()); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), 2.5)) { - if (entity instanceof LivingEntity && !(entity instanceof ArmorStand) && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player targetPlayer) && Commands.invincible.contains(targetPlayer.getName()))) { - DamageHandler.damageEntity(entity, damage, this); - } - } - } - - // Unused - public static void explodeEarth(TempFallingBlock tempfallingblock) { - FallingBlock fb = tempfallingblock.getFallingBlock(); - ESEarth es = (ESEarth) tempfallingblock.getAbility(); - Player player = es.getPlayer(); - - ParticleEffect.SMOKE_LARGE.display(fb.getLocation(), 0, 0, 0, 0.3F, 25); - fb.getWorld().playSound(fb.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 2f, 0.5f); - - ThreadLocalRandom rand = ThreadLocalRandom.current(); - - for (Location l : GeneralMethods.getCircle(fb.getLocation(), es.impactSize, 1, false, true, 0)) { - if (isBreakable(l.getBlock()) && !RegionProtection.isRegionProtected(player, l, "ElementSphere") && EarthAbility.isEarthbendable(player, l.getBlock())) { - ParticleEffect.SMOKE_LARGE.display(l, 0, 0, 0, 0.1F, 2); - new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000), false); - } - - if (GeneralMethods.isSolid(l.getBlock().getRelative(BlockFace.DOWN)) && isBreakable(l.getBlock()) && ElementalAbility.isAir(l.getBlock().getType()) && rand.nextInt(20) == 0 && EarthAbility.isEarthbendable(player, l.getBlock().getRelative(BlockFace.DOWN))) { - Material type = l.getBlock().getRelative(BlockFace.DOWN).getType(); - new RegenTempBlock(l.getBlock(), type, type.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000)); - } - } - - tempfallingblock.remove(); - } - - public static boolean isBreakable(Block block) { - return !Arrays.asList(unbreakables).contains(block.getType()); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return tfb != null ? tfb.getLocation() : null; - } - - @Override - public String getName() { - return "ElementSphereEarth"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public long getRevertDelay() { - return revertDelay; - } - - public void setRevertDelay(long revertDelay) { - this.revertDelay = revertDelay; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getImpactSize() { - return impactSize; - } - - public void setImpactSize(int impactSize) { - this.impactSize = impactSize; - } - - public TempFallingBlock getTempFallingBlock() { - return tfb; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java deleted file mode 100644 index 32ec393..0000000 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java +++ /dev/null @@ -1,299 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class ESFire extends AvatarAbility implements AddonAbility { - - private Location location; - private Vector direction; - private double travelled; - private boolean controllable; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.FIRE_TICK) - private long burnTime; - @Attribute(Attribute.SPEED) - private int speed; - - public ESFire(Player player) { - super(player); - - if (!hasAbility(player, ElementSphere.class)) { - return; - } - - ElementSphere currES = getAbility(player, ElementSphere.class); - if (currES.getFireUses() == 0) { - return; - } - - if (bPlayer.isOnCooldown("ESFire")) { - return; - } - - setFields(); - start(); - - if (!isRemoved()) { - bPlayer.addCooldown("ESFire", getCooldown()); - currES.setFireUses(currES.getFireUses() - 1); - location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); - direction = location.getDirection().clone(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Fire.Cooldown"); - range = config.getDouble("Abilities.Avatar.ElementSphere.Fire.Range"); - damage = config.getDouble("Abilities.Avatar.ElementSphere.Fire.Damage"); - burnTime = config.getLong("Abilities.Avatar.ElementSphere.Fire.BurnDuration"); - speed = config.getInt("Abilities.Avatar.ElementSphere.Fire.Speed"); - controllable = config.getBoolean("Abilities.Avatar.ElementSphere.Fire.Controllable"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= (long) BlueFireAbility.getCooldownFactor(); - range *= BlueFireAbility.getRangeFactor(); - damage *= BlueFireAbility.getDamageFactor(); - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (travelled >= range) { - remove(); - return; - } - - advanceAttack(); - } - - private void advanceAttack() { - for (int i = 0; i < speed; i++) { - if (!incrementTravelledAndCheckRange()) { - return; - } - - updateDirectionIfControllable(); - - location.add(direction.clone().multiply(1)); - - if (checkEnvironmentCollision()) { - return; - } - - displayAttackParticles(); - playAttackSoundsAndLight(); - placeFire(); - handleEntityCollisions(); - } - } - - private boolean incrementTravelledAndCheckRange() { - travelled++; - return travelled < range; - } - - private void updateDirectionIfControllable() { - if (!player.isDead() && controllable) { - direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); - } - } - - private boolean checkEnvironmentCollision() { - if (RegionProtection.isRegionProtected(this, location) || GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { - travelled = range; - return true; - } - return false; - } - - private void displayAttackParticles() { - ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; - flame.display(location, 5, Math.random(), Math.random(), Math.random(), 0.02); - ParticleEffect.SMOKE_LARGE.display(location, 2, Math.random(), Math.random(), Math.random(), 0.01); - } - - private void playAttackSoundsAndLight() { - FireAbility.playFirebendingSound(location); - JCMethods.emitLight(location); - } - - private void handleEntityCollisions() { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (isAttackableEntity(entity)) { - DamageHandler.damageEntity(entity, damage, this); - entity.setFireTicks(Math.round(burnTime / 50F)); - travelled = range; - return; - } - } - } - - private boolean isAttackableEntity(Entity entity) { - return entity instanceof LivingEntity && - entity.getEntityId() != player.getEntityId() && - !(entity instanceof ArmorStand) && - !RegionProtection.isRegionProtected(this, entity.getLocation()) && - !((entity instanceof Player targetPlayer) && Commands.invincible.contains((targetPlayer).getName())); - } - - private void placeFire() { - if (GeneralMethods.isSolid(location.getBlock().getRelative(BlockFace.DOWN))) { - location.getBlock().setType(Material.FIRE); - new BlazeArc(player, location, direction, 2); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "ElementSphereFire"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getDistanceTravelled() { - return travelled; - } - - public void setDistanceTravelled(double travelled) { - this.travelled = travelled; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public long getBurnTime() { - return burnTime; - } - - public void setBurnTime(long burnTime) { - this.burnTime = burnTime; - } - - public int getSpeed() { - return speed; - } - - public void setSpeed(int speed) { - this.speed = speed; - } - - public boolean isControllable() { - return controllable; - } - - public void setControllable(boolean controllable) { - this.controllable = controllable; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java deleted file mode 100644 index efc8577..0000000 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java +++ /dev/null @@ -1,406 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.BlockState; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - -/** - * @author jedk1 - * @author Finn_Bueno_ - */ -public class ESStream extends AvatarAbility implements AddonAbility { - - private boolean cancelAbility; - private int requiredUses; - private long regen; - private Location stream; - private Location origin; - private Vector dir; - private int angle; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.KNOCKBACK) - private double knockback; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.RADIUS) - private double radius; - - public ESStream(Player player) { - super(player); - - if (!hasAbility(player, ElementSphere.class)) { - return; - } - - ElementSphere currES = getAbility(player, ElementSphere.class); - - if (bPlayer.isOnCooldown("ESStream")) { - return; - } - - setFields(); - - if (currES.getAirUses() < requiredUses - || currES.getEarthUses() < requiredUses - || currES.getFireUses() < requiredUses - || currES.getWaterUses() < requiredUses) { - return; - } - - if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), (int) range).getLocation())) { - return; - } - - if (cancelAbility) { - currES.remove(); - } else { - currES.setAirUses(currES.getAirUses()-requiredUses); - currES.setEarthUses(currES.getEarthUses()-requiredUses); - currES.setFireUses(currES.getFireUses()-requiredUses); - currES.setWaterUses(currES.getWaterUses()-requiredUses); - } - - stream = player.getEyeLocation(); - origin = player.getEyeLocation(); - dir = player.getEyeLocation().getDirection(); - angle = 0; - - start(); - - if (!isRemoved()) { - bPlayer.addCooldown("ESStream", getCooldown()); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Stream.Cooldown"); - range = config.getDouble("Abilities.Avatar.ElementSphere.Stream.Range"); - damage = config.getDouble("Abilities.Avatar.ElementSphere.Stream.Damage"); - knockback = config.getDouble("Abilities.Avatar.ElementSphere.Stream.Knockback"); - requiredUses = config.getInt("Abilities.Avatar.ElementSphere.Stream.RequiredUses"); - cancelAbility = config.getBoolean("Abilities.Avatar.ElementSphere.Stream.EndAbility"); - radius = config.getInt("Abilities.Avatar.ElementSphere.Stream.ImpactCraterSize"); - regen = config.getLong("Abilities.Avatar.ElementSphere.Stream.ImpactRevert"); - } - - @Override - public void progress() { - if (!checkStreamValidity()) { - return; - } - - if (checkStreamRangeAndProtection()) { - return; - } - - handleNearbyEntities(); - - updateStreamDirection(); - - stream.add(dir); - - if (handleBlockCollision()) { - return; - } - - playStreamParticles(); - } - - private boolean checkStreamValidity() { - return player != null && player.isOnline(); - } - - private boolean checkStreamRangeAndProtection() { - if (origin.distance(stream) >= range || RegionProtection.isRegionProtected(player, stream, this)) { - remove(); - return true; - } - return false; - } - - private void handleNearbyEntities() { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(stream, 1.5)) { - if (e instanceof Player && e == player) { - continue; - } - applyStreamEffects(e); - } - } - - private void applyStreamEffects(Entity entity) { - GeneralMethods.setVelocity(this, entity, dir.normalize().multiply(knockback)); - if (entity instanceof LivingEntity) { - DamageHandler.damageEntity(entity, damage, this); - } - } - - private void updateStreamDirection() { - if (!player.isDead() && hasAbility(player, ElementSphere.class)) { - Location loc = stream.clone(); - dir = GeneralMethods.getDirection(loc, player.getTargetBlock(null, (int) range).getLocation()).normalize().multiply(1.2); - } - } - - private boolean handleBlockCollision() { - if (!isTransparent(stream.getBlock())) { - triggerCollisionEffects(); - remove(); - return true; - } - return false; - } - - private void triggerCollisionEffects() { - ThreadLocalRandom rand = ThreadLocalRandom.current(); - List blocks = getAffectedBlocks(); - damageNearbyEntitiesOnCollision(); - displayCollisionParticles(); - playCollisionSounds(rand); - spawnFallingBlocks(rand, blocks); - } - - private List getAffectedBlocks() { - List blocks = new ArrayList<>(); - for (Location loc : GeneralMethods.getCircle(stream, (int) radius, 0, false, true, 0)) { - if (JCMethods.isUnbreakable(loc.getBlock()) || RegionProtection.isRegionProtected(this, loc)) continue; - blocks.add(loc.getBlock().getState()); - new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); - } - return blocks; - } - - private void damageNearbyEntitiesOnCollision() { - GeneralMethods.getEntitiesAroundPoint(stream, radius).stream().filter(e -> !(e instanceof Player) || e != player).filter(e -> !RegionProtection.isRegionProtected(this, e.getLocation()) && (!(e instanceof Player targetPlayer) || !Commands.invincible.contains((targetPlayer).getName()))).forEach(e -> { - GeneralMethods.setVelocity(this, e, dir.normalize().multiply(knockback)); - if (e instanceof LivingEntity) DamageHandler.damageEntity(e, damage, this); - }); - } - - private void displayCollisionParticles() { - ParticleEffect.FLAME.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); - ParticleEffect.SMOKE_LARGE.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); - ParticleEffect.FIREWORKS_SPARK.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); - ParticleEffect.SMOKE_LARGE.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); - ParticleEffect.EXPLOSION_HUGE.display(stream, 5, 0.5F, 0.5F, 0.5F, 0.5F); - } - - private void playCollisionSounds(ThreadLocalRandom rand) { - stream.getWorld().playSound(stream, rand.nextBoolean() ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 1f, 1f); - stream.getWorld().playSound(stream, rand.nextBoolean() ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, 1f, 1f); - } - - private void spawnFallingBlocks(ThreadLocalRandom rand, List blocks) { - for (BlockState block : blocks) { - double x = (rand.nextBoolean() ? -1 : 1) * rand.nextDouble() / 3; - double z = (rand.nextBoolean() ? -1 : 1) * rand.nextDouble() / 3; - new TempFallingBlock(block.getLocation().add(0, 1, 0), block.getBlockData(), dir.clone().add(new Vector(x, 0, z)).normalize().multiply(-1), this); - } - } - - private void playStreamParticles() { - angle += 20; - if (angle > 360) { - angle = 0; - } - for (int i = 0; i < 4; i++) { - playIndividualStreamParticles(i); - } - } - - private void playIndividualStreamParticles(int particleIndex) { - for (double d = -4; d <= 0; d += 0.1) { - if (origin.distance(stream) < d) continue; - Location l = stream.clone().add(dir.clone().normalize().multiply(d)); - double r = Math.min(0.75, d * -1 / 5); - Vector ov = GeneralMethods.getOrthogonalVector(dir, angle + (90 * particleIndex) + d, r); - Location pl = l.clone().add(ov.clone()); - displayStreamParticle(pl, particleIndex); - } - } - - private void displayStreamParticle(Location location, int index) { - ThreadLocalRandom rand = ThreadLocalRandom.current(); - switch (index) { - case 0: - ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; - flame.display(location, 1, 0.05F, 0.05F, 0.05F, 0.005F); - break; - case 1: - String color = "#FFFFFF"; - float offset = 0.05F; - float speed = 0.005F; - int viewDistance = 50; - if (rand.nextInt(30) == 0) { - JCMethods.displayColoredParticles(color, location, 1, 0, 0, 0, speed); - } else { - JCMethods.displayColoredParticles(color, location, 1, offset, offset, offset, speed, viewDistance); - } - break; - case 2: - GeneralMethods.displayColoredParticle("06C1FF", location); - break; - case 3: - GeneralMethods.displayColoredParticle("754719", location); - break; - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return stream; - } - - @Override - public String getName() { - return "ElementSphereStream"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public double getKnockback() { - return knockback; - } - - public void setKnockback(double knockback) { - this.knockback = knockback; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean cancelsAbility() { - return cancelAbility; - } - - public void setCancelsAbility(boolean cancelAbility) { - this.cancelAbility = cancelAbility; - } - - public int getRequiredUses() { - return requiredUses; - } - - public void setRequiredUses(int requiredUses) { - this.requiredUses = requiredUses; - } - - public double getRadius() { - return radius; - } - - public void setRadius(double radius) { - this.radius = radius; - } - - public long getRegenTime() { - return regen; - } - - public void setRegenTime(long regen) { - this.regen = regen; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public Vector getDirection() { - return dir; - } - - public void setDirection(Vector dir) { - this.dir = dir; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java deleted file mode 100644 index 8caf0da..0000000 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class ESWater extends AvatarAbility implements AddonAbility { - - private Location location; - private Vector direction; - private double travelled; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.SPEED) - private int speed; - - public ESWater(Player player) { - super(player); - - if (!hasAbility(player, ElementSphere.class)) { - return; - } - - ElementSphere currES = getAbility(player, ElementSphere.class); - if (currES.getWaterUses() == 0) { - return; - } - - if (bPlayer.isOnCooldown("ESWater")) { - return; - } - - setFields(); - - location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); - - start(); - - if (!isRemoved()) { - bPlayer.addCooldown("ESWater", getCooldown()); - currES.setWaterUses(currES.getWaterUses() - 1); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Water.Cooldown"); - range = config.getDouble("Abilities.Avatar.ElementSphere.Water.Range"); - damage = config.getDouble("Abilities.Avatar.ElementSphere.Water.Damage"); - speed = config.getInt("Abilities.Avatar.ElementSphere.Water.Speed"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (travelled >= range) { - remove(); - return; - } - - advanceAttack(); - } - - private void advanceAttack() { - for (int i = 0; i < speed; i++) { - if (!incrementTravelledAndCheckRange()) { - return; - } - - updateDirection(); - - location.add(direction.clone().multiply(1)); - - if (checkCollision()) { - return; - } - - playAttackEffects(); - handleBlockTransformation(); - handleEntityCollisions(); - } - } - - private boolean incrementTravelledAndCheckRange() { - travelled++; - return travelled < range; - } - - private void updateDirection() { - if (!player.isDead()) { - direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); - } - } - - private boolean checkCollision() { - if (RegionProtection.isRegionProtected(this, location) || GeneralMethods.isSolid(location.getBlock()) || !isTransparent(location.getBlock())) { - travelled = range; - return true; - } - return false; - } - - private void playAttackEffects() { - WaterAbility.playWaterbendingSound(location); - if (isWater(location.getBlock())) { - ParticleEffect.WATER_BUBBLE.display(location, 3, 0.5, 0.5, 0.5); - location.getWorld().spawnParticle(Particle.WATER_WAKE, location, 3, 0.0, 0.0, 0.0, 0.005F); - GeneralMethods.displayColoredParticle("06C1FF", location); - } - } - - private void handleBlockTransformation() { - new RegenTempBlock(location.getBlock(), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 100L); - } - - private void handleEntityCollisions() { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (isAttackableEntity(entity)) { - DamageHandler.damageEntity(entity, damage, this); - travelled = range; - return; - } - } - } - - private boolean isAttackableEntity(Entity entity) { - return entity instanceof LivingEntity && - entity.getEntityId() != player.getEntityId() && - !(entity instanceof ArmorStand) && - !RegionProtection.isRegionProtected(this, entity.getLocation()) && - !((entity instanceof Player targetPlayer) && Commands.invincible.contains((targetPlayer).getName())); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "ElementSphereWater"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getDistanceTravelled() { - return travelled; - } - - public void setDistanceTravelled(double travelled) { - this.travelled = travelled; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getSpeed() { - return speed; - } - - public void setSpeed(int speed) { - this.speed = speed; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java deleted file mode 100644 index aec8327..0000000 --- a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java +++ /dev/null @@ -1,525 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.MultiAbility; -import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; -import com.projectkorra.projectkorra.ability.util.MultiAbilityManager.MultiAbilityInfoSub; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.FlightHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.ChatColor; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ThreadLocalRandom; - -public class ElementSphere extends AvatarAbility implements AddonAbility, MultiAbility { - - protected static final ConcurrentMap> abilities = new ConcurrentHashMap<>(); - private static final ArrayList multiAbilityInfo = new ArrayList<>(); - - static { - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AIR)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.EARTH)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.FIRE)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.WATER)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AVATAR)); - } - - private World world; - private int airUses; - private int fireUses; - private int waterUses; - private int earthUses; - private boolean setup; - private Location location; - private double yaw; - private int point; - private long endTime; - private long lastClickTime; - - @Attribute(Attribute.COOLDOWN) - public long cooldown; - @Attribute(Attribute.DURATION) - public long duration; - @Attribute(Attribute.HEIGHT) - private double height; - @Attribute(Attribute.SPEED) - private double speed; - - public ElementSphere(Player player) { - super(player); - - ElementSphere oldES = getAbility(player, ElementSphere.class); - - if (handleExistingSphere(player, oldES)) { - return; - } - - if (canStartNewSphere()) { - initializeNewSphere(player); - } - } - - private boolean handleExistingSphere(Player player, ElementSphere oldES) { - if (oldES != null) { - if (player.isSneaking()) { - oldES.prepareCancel(); - } else { - if (oldES.setup) { - handleElementSwitch(player); - } - } - return true; - } - return false; - } - - private void handleElementSwitch(Player player) { - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - return; - } - - switch (player.getInventory().getHeldItemSlot()) { - case 0: - if (checkPermission(player, "Air")) new ESAir(player); - break; - case 1: - if (checkPermission(player, "Earth")) new ESEarth(player); - break; - case 2: - if (checkPermission(player, "Fire")) new ESFire(player); - break; - case 3: - if (checkPermission(player, "Water")) new ESWater(player); - break; - case 4: - if (checkPermission(player, "Stream")) new ESStream(player); - break; - } - } - - private boolean checkPermission(Player player, String element) { - return player.hasPermission("bending.ability.ElementSphere." + element); - } - - private boolean canStartNewSphere() { - return bPlayer.canBend(this); - } - - private void initializeNewSphere(Player player) { - setFields(); - location = player.getLocation().clone().subtract(0, 1, 0); - world = player.getWorld(); - endTime = System.currentTimeMillis() + duration; - start(); - - if (!isRemoved()) { - bindAndCooldown(player); - enableFlight(player); - checkBoundAbilityName(); - } - } - - private void bindAndCooldown(Player player) { - MultiAbilityManager.bindMultiAbility(player, "ElementSphere"); - bPlayer.addCooldown(this); - } - - private void enableFlight(Player player) { - flightHandler.createInstance(player, this.getName()); - } - - private void checkBoundAbilityName() { - if (ChatColor.stripColor(bPlayer.getBoundAbilityName()) == null) { - remove(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - airUses = config.getInt("Abilities.Avatar.ElementSphere.Air.Uses"); - fireUses = config.getInt("Abilities.Avatar.ElementSphere.Fire.Uses"); - waterUses = config.getInt("Abilities.Avatar.ElementSphere.Water.Uses"); - earthUses = config.getInt("Abilities.Avatar.ElementSphere.Earth.Uses"); - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Cooldown"); - duration = config.getLong("Abilities.Avatar.ElementSphere.Duration"); - height = config.getDouble("Abilities.Avatar.ElementSphere.MaxControlledHeight"); - speed = config.getDouble("Abilities.Avatar.ElementSphere.FlySpeed"); - } - - @Override - public void progress() { - if (!checkPlayerValidity()) { - return; - } - - if (!checkAbilityPrerequisites()) { - return; - } - - if (isDurationOver()) { - remove(); - return; - } - - if (!hasUsableElements()) { - remove(); - return; - } - - handlePlayerMovement(); - handleFlight(); - handleEntityPush(); - updateLocationAndPlayParticles(); - - setup = true; - } - - private boolean checkPlayerValidity() { - return !player.isDead() && player.isOnline() && world == player.getWorld() && !player.getGameMode().equals(GameMode.SPECTATOR); - } - - private boolean checkAbilityPrerequisites() { - return bPlayer.isToggled() && MultiAbilityManager.hasMultiAbilityBound(player, "ElementSphere"); - } - - private boolean isDurationOver() { - return duration > 0 && System.currentTimeMillis() > endTime; - } - - private boolean hasUsableElements() { - return airUses > 0 || fireUses > 0 || waterUses > 0 || earthUses > 0; - } - - private void handlePlayerMovement() { - player.setFallDistance(0); - if (player.isSneaking()) { - player.setVelocity(player.getLocation().getDirection().multiply(speed)); - } - } - - private void handleFlight() { - Block block = getGround(); - if (block != null) { - double dy = player.getLocation().getY() - block.getY(); - if (dy > height) { - removeFlight(); - } else { - allowFlight(); - } - } - } - - private void handleEntityPush() { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (isPushableEntity(entity)) { - entity.setVelocity(entity.getLocation().toVector().subtract(player.getLocation().toVector()).multiply(1)); - } - } - } - - private boolean isPushableEntity(Entity entity) { - return entity instanceof LivingEntity && - entity.getEntityId() != player.getEntityId() && - !(entity instanceof ArmorStand) && - !RegionProtection.isRegionProtected(player, entity.getLocation(), this); - } - - private void updateLocationAndPlayParticles() { - location = player.getLocation().clone().subtract(0, 1, 0); - playParticles(); - } - - private void allowFlight() { - if (!player.getAllowFlight()) { - player.setAllowFlight(true); - } - if (!player.isFlying()) { - player.setFlying(true); - } - } - - private void removeFlight() { - if (player.getAllowFlight()) { - player.setAllowFlight(false); - } - if (player.isFlying()) { - player.setFlying(false); - } - } - - private Block getGround() { - Block standingblock = player.getLocation().getBlock(); - - for (int i = 0; i <= height + 5; i++) { - Block block = standingblock.getRelative(BlockFace.DOWN, i); - if (GeneralMethods.isSolid(block) || block.isLiquid()) { - return block; - } - } - - return null; - } - - private void playParticles() { - playAirParticles(); - playFireParticles(); - playWaterEarthParticles(); - updatePointCounter(); - } - - private void playAirParticles() { - if (airUses != 0) { - double currentYaw = yaw + 40; - yaw = currentYaw; - Location fakeLoc = createRotatedLocation(location.clone(), 0, currentYaw); - Vector direction = fakeLoc.getDirection(); - for (double j = -180; j <= 180; j += 45) { - Location tempLoc = calculateAirParticleLocation(fakeLoc, direction, j); - displayAirParticle(tempLoc); - } - } - } - - private Location createRotatedLocation(Location baseLoc, double pitchOffset, double yawOffset) { - Location newLoc = baseLoc.clone(); - newLoc.setPitch((float) pitchOffset); - newLoc.setYaw((float) yawOffset); - return newLoc; - } - - private Location calculateAirParticleLocation(Location center, Vector direction, double angleDegrees) { - Location tempLoc = center.clone(); - double angleRadians = Math.toRadians(angleDegrees); - Vector newDir = direction.clone().multiply(2 * Math.cos(angleRadians)); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + 2 + (2 * Math.sin(angleRadians))); - return tempLoc; - } - - private void displayAirParticle(Location loc) { - String color = "#FFFFFF"; - int count = 1; - float offsetX = 0; - float offsetY = 0; - float offsetZ = 0; - float particleSpeed = 0.003f; - int viewDistance = 50; - - if (ThreadLocalRandom.current().nextInt(30) == 0) { - JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed); - } else { - JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed, viewDistance); - } - } - - private void playFireParticles() { - if (fireUses != 0) { - ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; - for (int i = -180; i < 180; i += 40) { - Location particleLoc = calculateCircularLocation(location, 2, i, 2); - flame.display(particleLoc, 0, 0, 0, 0, 1); - JCMethods.emitLight(particleLoc); - } - } - } - - private Location calculateCircularLocation(Location center, double radius, double angleOffsetDegrees, double yOffset) { - double angleRadians = Math.toRadians(angleOffsetDegrees); - double x = radius * Math.cos(angleRadians + point); - double z = radius * Math.sin(angleRadians + point); - return center.clone().add(x, yOffset, z); - } - - private void playWaterEarthParticles() { - Location centerLoc = location.clone().add(0, 2, 0); - double xRotation = Math.PI * 2.1 / 3; - double yawRadians = -(centerLoc.getYaw() * Math.PI / 180 - 1.575); - - for (int i = -180; i < 180; i += 30) { - double angle = Math.toRadians(i); - Vector v = new Vector(Math.cos(angle + point), Math.sin(angle + point), 0.0D).multiply(2); - Vector v1 = v.clone(); - - rotateAroundAxisX(v, xRotation); - rotateAroundAxisY(v, yawRadians); - rotateAroundAxisX(v1, -xRotation); - rotateAroundAxisY(v1, yawRadians); - if (waterUses != 0) { - centerLoc.getWorld().spawnParticle(Particle.WATER_WAKE, centerLoc.clone().add(v), 3, 0.0, 0.0, 0.0, 0.005F); - GeneralMethods.displayColoredParticle("06C1FF", centerLoc.clone().add(v)); - } - if (earthUses != 0) { - GeneralMethods.displayColoredParticle("754719", centerLoc.clone().add(v1)); - } - } - } - - private void updatePointCounter() { - point = (point + 1) % 360; - } - - private void rotateAroundAxisX(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double y = v.getY() * cos - v.getZ() * sin; - double z = v.getY() * sin + v.getZ() * cos; - v.setY(y).setZ(z); - } - - private void rotateAroundAxisY(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double x = v.getX() * cos + v.getZ() * sin; - double z = v.getX() * -sin + v.getZ() * cos; - v.setX(x).setZ(z); - } - - @Override - public void remove() { - super.remove(); - MultiAbilityManager.unbindMultiAbility(player); - flightHandler.removeInstance(player, this.getName()); - } - - public void prepareCancel() { - if (System.currentTimeMillis() < lastClickTime + 500L) { - remove(); - } else { - lastClickTime = System.currentTimeMillis(); - } - } - - public int getAirUses() { - return airUses; - } - - public void setAirUses(int airuses) { - this.airUses = airuses; - } - - public int getEarthUses() { - return earthUses; - } - - public void setEarthUses(int earthuses) { - this.earthUses = earthuses; - } - - public int getFireUses() { - return fireUses; - } - - public void setFireUses(int fireuses) { - this.fireUses = fireuses; - } - - public int getWaterUses() { - return waterUses; - } - - public void setWaterUses(int wateruses) { - this.waterUses = wateruses; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public boolean requireAvatar() { - return false; - } - - @Override - public String getName() { - return "ElementSphere"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Avatar.ElementSphere.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } - - @Override - public ArrayList getMultiAbilities() { - FileConfiguration lang = getLanguageConfig(); - - String airName = lang.getString("Abilities.Avatar.ElementSphereAir.Name"); - String fireName = lang.getString("Abilities.Avatar.ElementSphereFire.Name"); - String waterName = lang.getString("Abilities.Avatar.ElementSphereWater.Name"); - String earthName = lang.getString("Abilities.Avatar.ElementSphereEarth.Name"); - String streamName = lang.getString("Abilities.Avatar.ElementSphereStream.Name"); - - multiAbilityInfo.get(0).setName(airName); - multiAbilityInfo.get(1).setName(earthName); - multiAbilityInfo.get(2).setName(fireName); - multiAbilityInfo.get(3).setName(waterName); - multiAbilityInfo.get(4).setName(streamName); - - return multiAbilityInfo; - } -} diff --git a/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java b/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java deleted file mode 100644 index 701121a..0000000 --- a/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.jedk1.jedcore.ability.chiblocking; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.chiblocking.passive.ChiPassive; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class Backstab extends ChiAbility implements AddonAbility { - - public Backstab(Player player) { - super(player); - } - - @Override - public void progress() {} - - public static boolean punch(Player player, LivingEntity target) { - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - CoreAbility ability = CoreAbility.getAbility("Backstab"); - - if (bPlayer == null || !bPlayer.canBend(ability)) { - return false; - } - - ConfigurationSection config = JedCoreConfig.getConfig(player); - double activationAngle = Math.toRadians(config.getInt("Abilities.Chi.Backstab.MaxActivationAngle", 90)); - - Vector targetDirection = target.getLocation().getDirection().setY(0).normalize(); - Vector toTarget = target.getLocation().toVector().subtract(player.getLocation().toVector()).setY(0).normalize(); - - double angle = toTarget.angle(targetDirection); - - if (angle <= activationAngle && target.getLocation().distanceSquared(player.getLocation()) <= 5 * 5) { - bPlayer.addCooldown(ability); - - if (target instanceof Player) { - ChiPassive.blockChi((Player) target); - } - - return true; - } - - return false; - } - - public static double getDamage(World world) { - ConfigurationSection config = JedCoreConfig.getConfig(world); - return config.getDouble("Abilities.Chi.Backstab.Damage"); - } - - @Override - public long getCooldown() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getLong("Abilities.Chi.Backstab.Cooldown"); - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "Backstab"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Chi.Backstab.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Chi.Backstab.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java deleted file mode 100644 index d13d909..0000000 --- a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java +++ /dev/null @@ -1,350 +0,0 @@ -package com.jedk1.jedcore.ability.chiblocking; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.AbilitySelector; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -public class DaggerThrow extends ChiAbility implements AddonAbility { - private static final List INTERACTIONS = new ArrayList<>(); - - private final List arrows = new ArrayList<>(); - - private boolean limitEnabled; - private boolean requireArrows; - private boolean allowPickup; - private boolean particles; - private long endTime; - private int shots = 1; - private int hits = 0; - - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("MaxShots") - private int maxShots; - - public DaggerThrow(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (bPlayer.isOnCooldown("DaggerThrowShot")) { - return; - } - - if (hasAbility(player, DaggerThrow.class)) { - DaggerThrow dt = getAbility(player, DaggerThrow.class); - dt.shootArrow(); - return; - } - - setFields(); - - start(); - - if (!isRemoved()) { - shootArrow(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Chi.DaggerThrow.Cooldown"); - limitEnabled = config.getBoolean("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled"); - maxShots = config.getInt("Abilities.Chi.DaggerThrow.MaxDaggers.Amount"); - particles = config.getBoolean("Abilities.Chi.DaggerThrow.ParticleTrail"); - damage = config.getDouble("Abilities.Chi.DaggerThrow.Damage"); - requireArrows = config.getBoolean("Abilities.Chi.DaggerThrow.RequireArrows"); - allowPickup = config.getBoolean("Abilities.Chi.DaggerThrow.AllowPickup"); - - loadInteractions(); - } - - private void loadInteractions() { - INTERACTIONS.clear(); - - String path = "Abilities.Chi.DaggerThrow.Interactions"; - - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - ConfigurationSection section = config.getConfigurationSection(path); - - for (String abilityName : section.getKeys(false)) { - INTERACTIONS.add(new AbilityInteraction(abilityName)); - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (System.currentTimeMillis() > endTime) { - bPlayer.addCooldown(this); - remove(); - return; - } - - if (shots > maxShots && limitEnabled) { - bPlayer.addCooldown(this); - remove(); - } - } - - private void shootArrow() { - shots++; - Location location = player.getEyeLocation(); - - Vector vector = location.toVector(). - add(location.getDirection().multiply(2.5)). - toLocation(location.getWorld()).toVector(). - subtract(player.getEyeLocation().toVector()); - - if (requireArrows) JCMethods.removeItemFromInventory(player, Material.ARROW, 1); - - Arrow arrow = player.launchProjectile(Arrow.class); - arrow.setVelocity(vector); - arrow.getLocation().setDirection(vector); - arrow.setKnockbackStrength(0); - arrow.setBounce(false); - arrow.setMetadata("daggerthrow", new FixedMetadataValue(JedCore.plugin, "1")); - - if (!allowPickup) arrow.setPickupStatus(Arrow.PickupStatus.DISALLOWED); - - if (particles) { - arrow.setCritical(true); - } - - arrows.add(arrow); - endTime = System.currentTimeMillis() + 500; - bPlayer.addCooldown("DaggerThrowShot", 100); - } - - public void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { - if (!(arrow.getShooter() instanceof Player shooter)) return; - - if (RegionProtection.isRegionProtected(shooter, arrow.getLocation(), "DaggerThrow")) return; - - arrow.setVelocity(new Vector(0, 0, 0)); - entity.setNoDamageTicks(0); - - double prevHealth = entity.getHealth(); - - DamageHandler.damageEntity(entity, damage, this); - - if (prevHealth > entity.getHealth()) { - arrow.remove(); - } - - if (!(entity instanceof Player target)) { - return; - } - - DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); - if (daggerThrow == null) { - return; - } - - daggerThrow.hits++; - BendingPlayer targetBPlayer = BendingPlayer.getBendingPlayer(target); - - for (AbilityInteraction interaction : INTERACTIONS) { - if (!interaction.enabled || daggerThrow.hits < interaction.hitRequirement) { - continue; - } - - CoreAbility abilityDefinition = AbilitySelector.getAbility(interaction.name); - if (abilityDefinition == null) { - continue; - } - - CoreAbility ability = CoreAbility.getAbility(target, abilityDefinition.getClass()); - if (ability == null) { - continue; - } - - ability.remove(); - targetBPlayer.addCooldown(ability, interaction.cooldown); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - return arrows.stream().map(Arrow::getLocation).collect(Collectors.toList()); - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Chi.DaggerThrow.AbilityCollisionRadius"); - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - Location location = collision.getLocationFirst(); - - Optional collidedObject = arrows.stream().filter(arrow -> arrow.getLocation().equals(location)).findAny(); - - if (collidedObject.isPresent()) { - arrows.remove(collidedObject.get()); - collidedObject.get().remove(); - } - } - } - - @Override - public String getName() { - return "DaggerThrow"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Chi.DaggerThrow.Description"); - } - - public boolean hasParticleTrail() { - return particles; - } - - public double getDamage() { - return damage; - } - - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; - } - - public int getShots() { - return shots; - } - - public void setShots(int shots) { - this.shots = shots; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public boolean isLimitEnabled() { - return limitEnabled; - } - - public void setLimitEnabled(boolean limitEnabled) { - this.limitEnabled = limitEnabled; - } - - public int getMaxShots() { - return maxShots; - } - - public void setMaxShots(int maxShots) { - this.maxShots = maxShots; - } - - public int getHits() { - return hits; - } - - public void setHits(int hits) { - this.hits = hits; - } - - public List getArrows() { - return arrows; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Chi.DaggerThrow.Enabled"); - } - - private class AbilityInteraction { - public boolean enabled; - public long cooldown; - public int hitRequirement; - public String name; - - public AbilityInteraction(String abilityName) { - this.name = abilityName; - loadConfig(); - } - - public void loadConfig() { - ConfigurationSection config = JedCoreConfig.getConfig(player); - this.enabled = config.getBoolean("Abilities.Chi.DaggerThrow.Interactions." + name + ".Enabled", true); - this.cooldown = config.getLong("Abilities.Chi.DaggerThrow.Interactions." + name + ".Cooldown", 1000); - this.hitRequirement = config.getInt("Abilities.Chi.DaggerThrow.Interactions." + name + ".HitsRequired", 1); - } - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java deleted file mode 100644 index 1f35dab..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java +++ /dev/null @@ -1,343 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.AABB; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.CollisionUtil; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.BlockUtil; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; - -import static java.util.stream.Collectors.toList; - -public class EarthKick extends EarthAbility implements AddonAbility { - private final List temps = new ArrayList<>(); - private final Set hitEntities = new HashSet<>(); - - private BlockData materialData; - private Location location; - private Block block; - private boolean multipleHits; - private int sourceRange; - private int spread; - private double velocity; - private boolean allowMetal; - private boolean replaceSource; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("MaxShots") - private int earthBlocks; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.DAMAGE) - private double metalDmg; - @Attribute("CollisionRadius") - private double entityCollisionRadius; - - public EarthKick(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - location = player.getLocation(); - - if ((player.getLocation().getPitch() > -5) && prepare()) { - if (RegionProtection.isRegionProtected(this, block.getLocation())) { - return; - } - launchBlocks(); - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.EarthKick.Cooldown"); - earthBlocks = config.getInt("Abilities.Earth.EarthKick.EarthBlocks"); - damage = config.getDouble("Abilities.Earth.EarthKick.Damage.Normal"); - metalDmg = config.getDouble("Abilities.Earth.EarthKick.Damage.Metal"); - entityCollisionRadius = config.getDouble("Abilities.Earth.EarthKick.EntityCollisionRadius"); - multipleHits = config.getBoolean("Abilities.Earth.EarthKick.MultipleHits"); - sourceRange = config.getInt("Abilities.Earth.EarthKick.SourceRange"); - spread = config.getInt("Abilities.Earth.EarthKick.Spread"); - velocity = config.getDouble("Abilities.Earth.EarthKick.Velocity"); - allowMetal = config.getBoolean("Abilities.Earth.EarthKick.AllowMetal"); - replaceSource = config.getBoolean("Abilities.Earth.EarthKick.ReplaceSource"); - - if (entityCollisionRadius < 1.0) { - entityCollisionRadius = 1.0; - } - } - - private boolean prepare() { - block = player.getTargetBlock(getTransparentMaterialSet(), sourceRange); - - if (!isEarthbendable(player, block)) { - return false; - } - - if (TempBlock.isTempBlock(block)) { - TempBlock.get(block).revertBlock(); - } - - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - - if (block != null && (allowMetal || !isMetal(block))) { - materialData = block.getBlockData().clone(); - location.setX(block.getX() + 0.5); - location.setY(block.getY()); - location.setZ(block.getZ() + 0.5); - - return true; - } - - return false; - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - remove(); - return; - } - - bPlayer.addCooldown(this); - - track(); - - if (temps.isEmpty()) { - remove(); - } - } - - private void launchBlocks() { - if (replaceSource) { - if (getMovedEarth().containsKey(block)) { - block.setType(Material.AIR); - } - - if (block.getType() != Material.AIR) { - TempBlock air = new TempBlock(block, Material.AIR); - air.setRevertTime(5000L); - } - } - - location.setPitch(0); - location.add(location.getDirection()); - - if (!isAir(location.getBlock().getType())) { - location.setY(location.getY() + 1.0); - } - - ParticleEffect.CRIT.display(location, 10, Math.random(), Math.random(), Math.random(), 0.1); - - int yaw = Math.round(location.getYaw()); - - playEarthbendingSound(location); - - ThreadLocalRandom rand = ThreadLocalRandom.current(); - - for (int i = 0; i < earthBlocks; i++) { - location.setYaw(yaw + rand.nextInt((spread * 2) + 1) - spread); - location.setPitch(rand.nextInt(25) - 45); - - Vector v = location.clone().add(0, 0.8, 0).getDirection().normalize(); - Location location1 = location.clone().add(new Vector(v.getX() * 2, v.getY(), v.getZ() * 2)); - Vector dir = location1.setDirection(location.getDirection()).getDirection().multiply(velocity); - - temps.add(new TempFallingBlock(location, materialData, dir, this)); - } - } - - public void track() { - List destroy = new ArrayList<>(); - - for (TempFallingBlock tfb : temps) { - FallingBlock fb = tfb.getFallingBlock(); - - if (fb == null || fb.isDead()) { - destroy.add(tfb); - continue; - } - - for (int i = 0; i < 2; i++) { - ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.1, materialData); - ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.2, materialData); - } - - AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); - - CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { - UUID uuid = entity.getUniqueId(); - if (this.multipleHits || hitEntities.add(uuid)) { - DamageHandler.damageEntity(entity, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : damage, this); - } - return false; - }); - } - - temps.removeAll(destroy); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public List getLocations() { - return temps.stream().map(TempFallingBlock::getLocation).collect(toList()); - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Earth.EarthKick.AbilityCollisionRadius"); - } - - @Override - public void handleCollision(Collision collision) { - CollisionUtil.handleFallingBlockCollisions(collision, temps); - } - - @Override - public String getName() { - return "EarthKick"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthKick.Description"); - } - - public List getTemps() { - return temps; - } - - public BlockData getMaterialData() { - return materialData; - } - - public void setMaterialData(BlockData materialData) { - this.materialData = materialData; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getEarthBlocksQuantity() { - return earthBlocks; - } - - public void setEarthBlocksQuantity(int earthBlocks) { - this.earthBlocks = earthBlocks; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getMetalDmg() { - return metalDmg; - } - - public void setMetalDmg(double metalDmg) { - this.metalDmg = metalDmg; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - public Block getBlock() { - return block; - } - - public void setBlock(Block block) { - this.block = block; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthKick.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java deleted file mode 100644 index 40ff0a5..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java +++ /dev/null @@ -1,492 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; -import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; -import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Effect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class EarthLine extends EarthAbility implements AddonAbility { - - private Location location; - private Location endLocation; - private Block sourceBlock; - private TempBlock sourceTempBlock; - private Material sourceType; - private boolean progressing; - private boolean hitted; - private int goOnAfterHit; - private long removalTime = -1; - private boolean allowChangeDirection; - private CompositeRemovalPolicy removalPolicy; - private long useCooldown; - private long prepareCooldown; - private double sourceKeepRange; - - @Attribute(Attribute.DURATION) - private long maxDuration; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.SELECT_RANGE) - private double prepareRange; - @Attribute(Attribute.RADIUS) - private int affectingRadius; - @Attribute(Attribute.DAMAGE) - private double damage; - - public EarthLine(Player player) { - super(player); - - if (!isEnabled()) return; - - if (!bPlayer.canBend(this)) { - return; - } - goOnAfterHit = 1; - - setFields(); - - if (prepare()) { - start(); - if (!isRemoved() && prepareCooldown != 0) { - bPlayer.addCooldown(this, prepareCooldown); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new SwappedSlotsRemovalPolicy<>(bPlayer, EarthLine.class) - ); - - this.removalPolicy.load(config); - - useCooldown = config.getLong("Abilities.Earth.EarthLine.Cooldown"); - prepareCooldown = config.getLong("Abilities.Earth.EarthLine.PrepareCooldown"); - range = config.getInt("Abilities.Earth.EarthLine.Range"); - prepareRange = config.getDouble("Abilities.Earth.EarthLine.PrepareRange"); - sourceKeepRange = config.getDouble("Abilities.Earth.EarthLine.SourceKeepRange"); - affectingRadius = config.getInt("Abilities.Earth.EarthLine.AffectingRadius"); - damage = config.getDouble("Abilities.Earth.EarthLine.Damage"); - allowChangeDirection = config.getBoolean("Abilities.Earth.EarthLine.AllowChangeDirection"); - maxDuration = config.getLong("Abilities.Earth.EarthLine.MaxDuration"); - } - - public boolean prepare() { - final Block block = getEarthSourceBlock(this.range); - - if (block == null || !this.isEarthbendable(block)) { - return false; - } else if (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block)) { - return false; - } - - boolean selectedABlockInUse = false; - for (final EarthLine el : getAbilities(this.player, EarthLine.class)) { - if (!el.progressing) { - el.remove(); - } else if (block.equals(el.sourceBlock)) { - selectedABlockInUse = true; - } - } - - if (selectedABlockInUse) { - return false; - } - - if (block.getLocation().distanceSquared(this.player.getLocation()) > this.prepareRange * this.prepareRange) { - return false; - } - - this.sourceBlock = block; - this.focusBlock(); - - return true; - } - - private void focusBlock() { - if (DensityShift.isPassiveSand(this.sourceBlock)) { - DensityShift.revertSand(this.sourceBlock); - } - - if (this.sourceBlock.getType() == Material.SAND) { - this.sourceType = Material.SAND; - sourceTempBlock = new TempBlock(sourceBlock, Material.SANDSTONE.createBlockData()); - } else if (this.sourceBlock.getType() == Material.RED_SAND) { - this.sourceType = Material.RED_SAND; - sourceTempBlock = new TempBlock(sourceBlock, Material.RED_SANDSTONE.createBlockData()); - } else if (this.sourceBlock.getType() == Material.STONE) { - this.sourceType = Material.STONE; - sourceTempBlock = new TempBlock(sourceBlock, Material.COBBLESTONE.createBlockData()); - } else { - this.sourceType = this.sourceBlock.getType(); - sourceTempBlock = new TempBlock(sourceBlock, Material.STONE.createBlockData()); - } - - this.location = this.sourceBlock.getLocation(); - } - - private void unfocusBlock() { - sourceTempBlock.revertBlock(); - } - - @Override - public void remove() { - sourceTempBlock.revertBlock(); - super.remove(); - } - - // todo: static - private static Location getTargetLocation(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - - double range = config.getInt("Abilities.Earth.EarthLine.Range"); - - Entity target = GeneralMethods.getTargetedEntity(player, range, player.getNearbyEntities(range, range, range)); - Location location; - - if (target == null) { - location = GeneralMethods.getTargetedLocation(player, range); - } else { - location = ((LivingEntity) target).getEyeLocation(); - } - - return location; - } - - public void shootLine(Location endLocation) { - if (useCooldown != 0 && bPlayer.getCooldown(this.getName()) < useCooldown) bPlayer.addCooldown(this, useCooldown); - if (maxDuration > 0) removalTime = System.currentTimeMillis() + maxDuration; - this.endLocation = endLocation; - progressing = true; - sourceBlock.getWorld().playEffect(sourceBlock.getLocation(), Effect.GHAST_SHOOT, 0, 10); - } - - public static void shootLine(Player player) { - if (hasAbility(player, EarthLine.class)) { - EarthLine el = getAbility(player, EarthLine.class); - if (!el.progressing) { - el.shootLine(getTargetLocation(player)); - } - } - } - - private boolean sourceOutOfRange() { - return sourceBlock == null || sourceBlock.getLocation().add(0.5, 0.5, 0.5).distanceSquared(player.getLocation()) > sourceKeepRange * sourceKeepRange || sourceBlock.getWorld() != player.getWorld(); - } - - public void progress() { - if (!progressing) { - if (sourceOutOfRange()) { - unfocusBlock(); - remove(); - } - return; - } - - if (removalPolicy.shouldRemove()) { - remove(); - return; - } - - if (sourceBlock == null || RegionProtection.isRegionProtected(this, location)) { - remove(); - return; - } - - if (removalTime > -1 && System.currentTimeMillis() > removalTime) { - remove(); - return; - } - - if (sourceOutOfRange()) { - remove(); - return; - } - - if (RegionProtection.isRegionProtected(player, location, this)) { - remove(); - return; - } - - if (allowChangeDirection && player.isSneaking() && bPlayer.getBoundAbilityName().equalsIgnoreCase("EarthLine")) { - endLocation = getTargetLocation(player); - } - - double x1 = endLocation.getX(); - double z1 = endLocation.getZ(); - double x0 = sourceBlock.getX(); - double z0 = sourceBlock.getZ(); - - Vector looking = new Vector(x1 - x0, 0.0D, z1 - z0); - Vector push = new Vector(x1 - x0, 0.34999999999999998D, z1 - z0); - - if (location.distance(sourceBlock.getLocation()) < range) { - Material cloneType = location.getBlock().getType(); - Location locationYUP = location.getBlock().getLocation().clone().add(0.5, 0.1, 0.5); - - playEarthbendingSound(location); - - if (isEarthbendable(location.getBlock())) { - new TempBlock(location.getBlock(), Material.AIR.createBlockData(), 700L); - new TempFallingBlock(locationYUP, cloneType.createBlockData(), new Vector(0.0, 0.35, 0.0), this); - } - - location.add(looking.normalize()); - - if (!climb()) { - remove(); - return; - } - - if (hitted) { - if (goOnAfterHit != 0) { - goOnAfterHit--; - } else { - remove(); - return; - } - } else { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, affectingRadius)) { - if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))) { - return; - } - - if ((entity instanceof LivingEntity) && entity.getEntityId() != player.getEntityId()) { - GeneralMethods.setVelocity(this, entity, push.normalize().multiply(2)); - DamageHandler.damageEntity(entity, damage, this); - hitted = true; - } - } - } - } else { - remove(); - return; - } - - if (!isEarthbendable(player, location.getBlock()) && !isTransparent(location.getBlock())) { - remove(); - } - } - - private boolean climb() { - Block above = location.getBlock().getRelative(BlockFace.UP); - - if (!isTransparent(above)) { - // Attempt to climb since the current location has a block above it. - location.add(0, 1, 0); - above = location.getBlock().getRelative(BlockFace.UP); - - // The new location must be earthbendable and have something transparent above it. - return isEarthbendable(location.getBlock()) && isTransparent(above); - } else if (isTransparent(location.getBlock()) ) { - // Attempt to fall since the current location is transparent and the above block was transparent. - location.add(0, -1, 0); - - // The new location must be earthbendable and we already know the block above it is transparent. - return isEarthbendable(location.getBlock()); - } - - return true; - } - - @Override - public long getCooldown() { - return useCooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "EarthLine"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthLine.Description"); - } - - public Location getEndLocation() { - return endLocation; - } - - public void setEndLocation(Location endLocation) { - this.endLocation = endLocation; - } - - public Block getSourceBlock() { - return sourceBlock; - } - - public void setSourceBlock(Block sourceBlock) { - this.sourceBlock = sourceBlock; - } - - public Material getSourceType() { - return sourceType; - } - - public void setSourceType(Material sourceType) { - this.sourceType = sourceType; - } - - public boolean isProgressing() { - return progressing; - } - - public void setProgressing(boolean progressing) { - this.progressing = progressing; - } - - public int getGoOnAfterHit() { - return goOnAfterHit; - } - - public void setGoOnAfterHit(int goOnAfterHit) { - this.goOnAfterHit = goOnAfterHit; - } - - public long getRemovalTime() { - return removalTime; - } - - public void setRemovalTime(long removalTime) { - this.removalTime = removalTime; - } - - public long getUseCooldown() { - return useCooldown; - } - - public void setUseCooldown(long useCooldown) { - this.useCooldown = useCooldown; - } - - public long getPrepareCooldown() { - return prepareCooldown; - } - - public void setPrepareCooldown(long prepareCooldown) { - this.prepareCooldown = prepareCooldown; - } - - public long getMaxDuration() { - return maxDuration; - } - - public void setMaxDuration(long maxDuration) { - this.maxDuration = maxDuration; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getPrepareRange() { - return prepareRange; - } - - public void setPrepareRange(double prepareRange) { - this.prepareRange = prepareRange; - } - - public double getSourceKeepRange() { - return sourceKeepRange; - } - - public void setSourceKeepRange(double sourceKeepRange) { - this.sourceKeepRange = sourceKeepRange; - } - - public int getAffectingRadius() { - return affectingRadius; - } - - public void setAffectingRadius(int affectingRadius) { - this.affectingRadius = affectingRadius; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean isAllowChangeDirection() { - return allowChangeDirection; - } - - public void setAllowChangeDirection(boolean allowChangeDirection) { - this.allowChangeDirection = allowChangeDirection; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthLine.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java b/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java deleted file mode 100644 index 75ce009..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java +++ /dev/null @@ -1,215 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.Collapse; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -public class EarthPillar extends EarthAbility implements AddonAbility { - - private static final ConcurrentHashMap AFFECTED_BLOCKS = new ConcurrentHashMap<>(); - private static final ConcurrentHashMap> AFFECTED = new ConcurrentHashMap<>(); - - private Block block; - private BlockFace face; - @Attribute(Attribute.HEIGHT) - private int height; - @Attribute(Attribute.RANGE) - private int range; - private int step; - - private final List blocks = new ArrayList<>(); - - public EarthPillar(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - Block target = BlockSource.getEarthSourceBlock(player, range, ClickType.SHIFT_DOWN); - if (target != null && !AFFECTED_BLOCKS.containsKey(target)) { - List blocks = player.getLastTwoTargetBlocks(null, range); - if (blocks.size() > 1) { - this.player = player; - face = blocks.get(1).getFace(blocks.get(0)); - block = blocks.get(1); - height = getEarthbendableBlocksLength(block, getDirection(face).clone().multiply(-1), height); - start(); - } - } else if (target != null && AFFECTED_BLOCKS.containsKey(target)) { - List blocks = AFFECTED.get(AFFECTED_BLOCKS.get(target)); - if (blocks != null && !blocks.isEmpty()) { - for (Block b : blocks) { - Collapse.revertBlock(b); - } - playEarthbendingSound(target.getLocation()); - AFFECTED.remove(AFFECTED_BLOCKS.get(target)); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - height = config.getInt("Abilities.Earth.EarthPillar.Height"); - range = config.getInt("Abilities.Earth.EarthPillar.Range"); - } - - @Override - public void progress() { - if (step < height) { - step++; - movePillar(); - } else { - AFFECTED.put(this, blocks); - remove(); - } - } - - private void movePillar() { - moveEarth(block, getDirection(face), height); - block = block.getRelative(face); - AFFECTED_BLOCKS.put(block, this); - blocks.add(block); - } - - private Vector getDirection(BlockFace face) { - switch (face) { - case UP: - return new Vector(0, 1, 0); - case DOWN: - return new Vector(0, -1, 0); - case NORTH: - return new Vector(0, 0, -1); - case SOUTH: - return new Vector(0, 0, 1); - case EAST: - return new Vector(1, 0, 0); - case WEST: - return new Vector(-1, 0, 0); - default: - return null; - } - } - - public static void progressAll() { - for (Block block : AFFECTED_BLOCKS.keySet()) { - if (!EarthAbility.isEarthbendable(AFFECTED_BLOCKS.get(block).getPlayer(), block)) { - AFFECTED_BLOCKS.remove(block); - } - } - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return block != null ? block.getLocation() : null; - } - - @Override - public String getName() { - return "EarthPillar"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthPillar.Description"); - } - - public Block getBlock() { - return block; - } - - public void setBlock(Block block) { - this.block = block; - } - - public BlockFace getFace() { - return face; - } - - public void setFace(BlockFace face) { - this.face = face; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public int getStep() { - return step; - } - - public void setStep(int step) { - this.step = step; - } - - public List getBlocks() { - return blocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthPillar.Enabled"); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java deleted file mode 100644 index 50866e6..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java +++ /dev/null @@ -1,527 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.AABB; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.CollisionUtil; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.BlockUtil; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -public class EarthShard extends EarthAbility implements AddonAbility { - @Attribute(Attribute.RANGE) - public static int range; - public static int abilityRange; - - @Attribute(Attribute.DAMAGE) - public static double normalDmg; - @Attribute(Attribute.DAMAGE) - public static double metalDmg; - - @Attribute("MaxShots") - public static int maxShards; - @Attribute(Attribute.COOLDOWN) - public static long cooldown; - - private boolean isThrown = false; - private Location origin; - private double abilityCollisionRadius; - private double entityCollisionRadius; - - private final List tblockTracker = new ArrayList<>(); - private final List readyBlocksTracker = new ArrayList<>(); - private final List fallingBlocks = new ArrayList<>(); - - private boolean allowKnockup; - private double knockupVelocity; - private double knockupRange; - - private boolean allowKnockupSelf; - private double knockupSelfVelocity; - private double knockupSelfRange; - - public EarthShard(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, EarthShard.class)) { - for (EarthShard es : EarthShard.getAbilities(player, EarthShard.class)) { - if (es.isThrown && System.currentTimeMillis() - es.getStartTime() >= 20000) { - // Remove the old instance because it got into a broken state. - // This shouldn't affect normal gameplay because the cooldown is long enough that the - // shards should have already hit their target. - es.remove(); - } else { - es.select(); - return; - } - } - } - - setFields(); - origin = player.getLocation().clone(); - raiseEarthBlock(getEarthSourceBlock(range)); - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - range = config.getInt("Abilities.Earth.EarthShard.PrepareRange"); - abilityRange = config.getInt("Abilities.Earth.EarthShard.AbilityRange"); - normalDmg = config.getDouble("Abilities.Earth.EarthShard.Damage.Normal"); - metalDmg = config.getDouble("Abilities.Earth.EarthShard.Damage.Metal"); - maxShards = config.getInt("Abilities.Earth.EarthShard.MaxShards"); - cooldown = config.getLong("Abilities.Earth.EarthShard.Cooldown"); - abilityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); - entityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); - allowKnockup = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Others.Allow"); - knockupVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Velocity"); - knockupRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Range"); - allowKnockupSelf = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Self.Allow"); - knockupSelfVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Velocity"); - knockupSelfRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Range"); - } - - public void select() { - raiseEarthBlock(getEarthSourceBlock(range)); - } - - public void raiseEarthBlock(Block block) { - if (block == null) return; - if (tblockTracker.size() >= maxShards) return; - - Vector blockVector = block.getLocation().toVector().toBlockVector().setY(0); - - for (TempBlock tempBlock : tblockTracker) { - if (tempBlock.getLocation().getWorld() != block.getWorld()) continue; - - Vector tempBlockVector = tempBlock.getLocation().toVector().toBlockVector().setY(0); - if (tempBlockVector.equals(blockVector)) return; - } - - for (int i = 1; i < 4; i++) { - if (!isTransparent(block.getRelative(BlockFace.UP, i))) return; - } - - if (!isEarthbendable(block)) return; - - if (isMetal(block)) { - playMetalbendingSound(block.getLocation()); - } else { - ParticleEffect.BLOCK_CRACK.display( - block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData() - ); - playEarthbendingSound(block.getLocation()); - } - - Material material = getCorrectType(block); - - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - - Location loc = block.getLocation().add(0.5, 0, 0.5); - new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); - TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); - tblockTracker.add(tb); - - handleKnockup(block); - } - - private void handleKnockup(Block origin) { - if (!allowKnockup && !allowKnockupSelf) return; - - Location originLoc = origin.getLocation(); - World world = origin.getWorld(); - - for (Entity entity : world.getNearbyEntities(originLoc, Math.max(knockupRange, knockupSelfRange), knockupRange, knockupRange)) { - if (entity instanceof FallingBlock) continue; - - if (entity.equals(player)) { - if (!allowKnockupSelf) continue; - if (entity.getLocation().distance(originLoc) <= knockupSelfRange) { - entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupSelfVelocity, 0))); - } - } else { - if (!allowKnockup) continue; - if (entity.getLocation().distance(originLoc) <= knockupRange) { - entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupVelocity, 0))); - } - } - } - } - - public Material getCorrectType(Block block) { - if (block.getType() == Material.SAND) { - return Material.SANDSTONE; - } - if (block.getType() == Material.RED_SAND) { - return Material.RED_SANDSTONE; - } - if (block.getType() == Material.GRAVEL) { - return Material.COBBLESTONE; - } - if (block.getType().name().endsWith("CONCRETE_POWDER")) { - return Material.getMaterial(block.getType().name().replace("_POWDER", "")); - } - - return block.getType(); - } - - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (!isThrown) { - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - - if (tblockTracker.isEmpty()) { - remove(); - return; - } - - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fb = tfb.getFallingBlock(); - - if (fb.isDead() || fb.getLocation().getBlockY() == origin.getBlockY() + 2) { - TempBlock tb = new TempBlock(fb.getLocation().getBlock(), fb.getBlockData()); - readyBlocksTracker.add(tb); - tfb.remove(); - } - } - } else { - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fb = tfb.getFallingBlock(); - - AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); - - CollisionDetector.checkEntityCollisions(player, collider, (e) -> { - DamageHandler.damageEntity(e, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : normalDmg, this); - ((LivingEntity) e).setNoDamageTicks(0); - ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 20, 0, 0, 0, 0, fb.getBlockData()); - tfb.remove(); - return false; - }); - - if (fb.isDead()) { - tfb.remove(); - } - } - - if (TempFallingBlock.getFromAbility(this).isEmpty()) { - remove(); - } - } - } - - public static void throwShard(Player player) { - if (hasAbility(player, EarthShard.class)) { - for (EarthShard es : EarthShard.getAbilities(player, EarthShard.class)) { - if (!es.isThrown) { - es.throwShard(); - break; - } - } - } - } - - public void throwShard() { - if (isThrown || tblockTracker.size() > readyBlocksTracker.size()) { - return; - } - - Location targetLocation = GeneralMethods.getTargetedLocation(player, abilityRange); - - if (GeneralMethods.getTargetedEntity(player, abilityRange, new ArrayList<>()) != null) { - targetLocation = GeneralMethods.getTargetedEntity(player, abilityRange, new ArrayList<>()).getLocation(); - } - - Vector vel = null; - - for (TempBlock tb : readyBlocksTracker) { - Location target = player.getTargetBlock(null, 30).getLocation(); - - if (target.getBlockX() == tb.getBlock().getX() && target.getBlockY() == tb.getBlock().getY() && target.getBlockZ() == tb.getBlock().getZ()) { - vel = player.getEyeLocation().getDirection().multiply(2).add(new Vector(0, 0.2, 0)); - break; - } - - vel = GeneralMethods.getDirection(tb.getLocation(), targetLocation).normalize().multiply(2).add(new Vector(0, 0.2, 0)); - } - - for (TempBlock tb : readyBlocksTracker) { - fallingBlocks.add(new TempFallingBlock(tb.getLocation(), tb.getBlock().getBlockData(), vel, this)); - tb.revertBlock(); - } - - revertBlocks(); - - isThrown = true; - - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - } - - public void revertBlocks() { - for (TempBlock tb : tblockTracker) { - tb.revertBlock(); - } - - for (TempBlock tb : readyBlocksTracker) { - tb.revertBlock(); - } - - tblockTracker.clear(); - readyBlocksTracker.clear(); - } - - @Override - public void remove() { - // Destroy any remaining falling blocks. - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - tfb.remove(); - } - - revertBlocks(); - - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); - } - - @Override - public void handleCollision(Collision collision) { - CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); - } - - @Override - public double getCollisionRadius() { - return abilityCollisionRadius; - } - - @Override - public String getName() { - return "EarthShard"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthShard.Description"); - } - - public static int getRange() { - return range; - } - - public static void setRange(int range) { - EarthShard.range = range; - } - - public static int getAbilityRange() { - return abilityRange; - } - - public static void setAbilityRange(int abilityRange) { - EarthShard.abilityRange = abilityRange; - } - - public static double getNormalDmg() { - return normalDmg; - } - - public static void setNormalDmg(double normalDmg) { - EarthShard.normalDmg = normalDmg; - } - - public static double getMetalDmg() { - return metalDmg; - } - - public static void setMetalDmg(double metalDmg) { - EarthShard.metalDmg = metalDmg; - } - - public static int getMaxShards() { - return maxShards; - } - - public static void setMaxShards(int maxShards) { - EarthShard.maxShards = maxShards; - } - - public static void setCooldown(long cooldown) { - EarthShard.cooldown = cooldown; - } - - public boolean isThrown() { - return isThrown; - } - - public void setThrown(boolean thrown) { - isThrown = thrown; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public double getAbilityCollisionRadius() { - return abilityCollisionRadius; - } - - public void setAbilityCollisionRadius(double abilityCollisionRadius) { - this.abilityCollisionRadius = abilityCollisionRadius; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - public List getTblockTracker() { - return tblockTracker; - } - - public List getReadyBlocksTracker() { - return readyBlocksTracker; - } - - public List getFallingBlocks() { - return fallingBlocks; - } - - public boolean isAllowKnockup() { - return allowKnockup; - } - - public void setAllowKnockup(boolean allowKnockup) { - this.allowKnockup = allowKnockup; - } - - public double getKnockupVelocity() { - return knockupVelocity; - } - - public void setKnockupVelocity(double knockupVelocity) { - this.knockupVelocity = knockupVelocity; - } - - public double getKnockupRange() { - return knockupRange; - } - - public void setKnockupRange(double knockupRange) { - this.knockupRange = knockupRange; - } - - public boolean isAllowKnockupSelf() { - return allowKnockupSelf; - } - - public void setAllowKnockupSelf(boolean allowKnockupSelf) { - this.allowKnockupSelf = allowKnockupSelf; - } - - public double getKnockupSelfVelocity() { - return knockupSelfVelocity; - } - - public void setKnockupSelfVelocity(double knockupSelfVelocity) { - this.knockupSelfVelocity = knockupSelfVelocity; - } - - public double getKnockupSelfRange() { - return knockupSelfRange; - } - - public void setKnockupSelfRange(double knockupSelfRange) { - this.knockupSelfRange = knockupSelfRange; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthShard.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java b/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java deleted file mode 100644 index 151bdc9..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java +++ /dev/null @@ -1,504 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.MaterialUtil; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -public class EarthSurf extends EarthAbility implements AddonAbility { - private static final double TARGET_HEIGHT = 1.5; - - private Location location; - private double prevHealth; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private long minimumCooldown; - @Attribute(Attribute.DURATION) - private long duration; - private boolean cooldownEnabled; - private boolean durationEnabled; - private boolean removeOnAnyDamage; - @Attribute(Attribute.SPEED) - private double speed; - private double springStiffness; - private final Set ridingBlocks = new HashSet<>(); - private CollisionDetector collisionDetector = new DefaultCollisionDetector(); - private DoubleSmoother heightSmoother; - - public EarthSurf(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, EarthSurf.class)) { - getAbility(player, EarthSurf.class).remove(); - return; - } - - setFields(); - - location = player.getLocation(); - - if (canStart()) { - prevHealth = player.getHealth(); - - this.flightHandler.createInstance(player, this.getName()); - player.setAllowFlight(true); - player.setFlying(false); - start(); - } - } - - private boolean canStart() { - Block beneath = getBlockBeneath(player.getLocation().clone()); - double maxHeight = getMaxHeight(); - - return isEarthbendable(player, beneath) && !isMetal(beneath) && beneath.getLocation().distanceSquared(player.getLocation()) <= maxHeight * maxHeight; - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.Cooldown"); - minimumCooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown"); - duration = config.getLong("Abilities.Earth.EarthSurf.Duration.Duration"); - cooldownEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Enabled"); - durationEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Duration.Enabled"); - removeOnAnyDamage = config.getBoolean("Abilities.Earth.EarthSurf.RemoveOnAnyDamage"); - speed = config.getDouble("Abilities.Earth.EarthSurf.Speed"); - springStiffness = config.getDouble("Abilities.Earth.EarthSurf.SpringStiffness"); - - int smootherSize = config.getInt("Abilities.Earth.EarthSurf.HeightTolerance"); - this.heightSmoother = new DoubleSmoother(Math.max(smootherSize, 1)); - - if (config.getBoolean("Abilities.Earth.EarthSurf.RelaxedCollisions")) { - this.collisionDetector = new RelaxedCollisionDetector(); - } - - if (!config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Scaled")) { - minimumCooldown = cooldown; - } - } - - @Override - public void progress() { - if (shouldRemove()) { - remove(); - return; - } - - this.player.setFlying(false); - - if (!collisionDetector.isColliding(player) && player.getHealth() >= prevHealth) { - movePlayer(); - - if (removeOnAnyDamage) { - prevHealth = player.getHealth(); - } - } else { - remove(); - } - } - - private boolean shouldRemove() { - if (player == null || player.isDead() || !player.isOnline()) return true; - if (!bPlayer.canBendIgnoreCooldowns(this)) return true; - if (!isEarthbendable(player, getBlockBeneath(player.getLocation().clone()))) return true; - if (durationEnabled && System.currentTimeMillis() > getStartTime() + duration) return true; - - return player.isSneaking(); - } - - private void movePlayer() { - location = player.getEyeLocation().clone(); - location.setPitch(0); - Vector direction = location.getDirection().normalize(); - - // How far the player is above the ground. - double height = getPlayerDistance(); - double maxHeight = getMaxHeight(); - double smoothedHeight = heightSmoother.add(height); - - // Destroy ability if player gets too far from ground. - if (smoothedHeight > maxHeight) { - remove(); - return; - } - - // Calculate the spring force to push the player back to the target height. - double displacement = height - TARGET_HEIGHT; - double force = -springStiffness * displacement; - - double maxForce = 0.5; - if (Math.abs(force) > maxForce) { - // Cap the force to maxForce so the player isn't instantly pulled to the ground. - force = force / Math.abs(force) * maxForce; - } - - Vector velocity = direction.clone().multiply(speed).setY(force); - - rideWave(); - - player.setVelocity(velocity); - player.setFallDistance(0); - } - - private double getMaxHeight() { - return TARGET_HEIGHT + 2.0; - } - - private double getPlayerDistance() { - Location l = player.getLocation().clone(); - while (true) { - if (l.getBlockY() <= l.getWorld().getMinHeight()) break; - if (ElementalAbility.isAir(l.getBlock().getType()) && ridingBlocks.contains(l.getBlock())) break; - if (GeneralMethods.isSolid(l.getBlock())) break; - - l.add(0, -0.1, 0); - } - return player.getLocation().getY() - l.getY(); - } - - private Block getBlockBeneath(Location l) { - while (l.getBlockY() > l.getWorld().getMinHeight() && MaterialUtil.isTransparent(l.getBlock())) { - l.add(0, -0.5, 0); - } - return l.getBlock(); - } - - private void rideWave() { - for (int i = 0; i < 3; i++) { - Location loc = location.clone(); - if (i < 2) - loc.add(getSideDirection(i)); - - //Player Positioning - double distOffset = 2.5; - Location bL = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); - while (!ElementalAbility.isAir(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()).getBlock().getType())) { - loc.add(0, 0.1, 0); - } - - if (isEarthbendable(player, getBlockBeneath(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()))) && getBlockBeneath(bL) != null) { - Block block = loc.clone().add(0, -3.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset - 0.5)).toLocation(player.getWorld()).getBlock(); - Location temp = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); - - if (RegionProtection.isRegionProtected(this, block.getLocation())) { - continue; - } - // Don't render blocks above the player because it looks bad. - // TODO: Change this check to see if it's a reachable position instead. - if (block.getLocation().getY() > this.player.getLocation().getY()) { - continue; - } - - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - - if (!GeneralMethods.isSolid(block.getLocation().add(0, 1, 0).getBlock()) && !ElementalAbility.isAir(block.getLocation().add(0, 1, 0).getBlock().getType())) { - if (DensityShift.isPassiveSand(block.getRelative(BlockFace.UP))) { - DensityShift.revertSand(block.getRelative(BlockFace.UP)); - } - - new TempBlock(block.getRelative(BlockFace.UP), Material.AIR.createBlockData()); - } - - if (GeneralMethods.isSolid(block)) { - ridingBlocks.add(block); - new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L, true, ridingBlocks::remove); - } else { - new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L); - } - - new TempFallingBlock(temp, getBlockBeneath(bL).getBlockData(), new Vector(0, 0.25, 0), this, true); - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()), 1.5D)) { - if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { - e.setVelocity(new Vector(0, 0.3, 0)); - } - } - } - } - } - - private Vector getSideDirection(int side) { - Vector direction = location.clone().getDirection().normalize(); - switch (side) { - case 0: // RIGHT - return new Vector(-direction.getZ(), 0.0, direction.getX()).normalize(); - case 1: // LEFT - return new Vector(direction.getZ(), 0.0, -direction.getX()).normalize(); - default: - break; - } - - return null; - } - - @Override - public void remove() { - this.flightHandler.removeInstance(player, this.getName()); - - if (cooldownEnabled && player.isOnline()) { - long scaledCooldown = cooldown; - - if (durationEnabled && duration > 0) { - double t = Math.min((System.currentTimeMillis() - this.getStartTime()) / (double) duration, 1.0); - scaledCooldown = Math.max((long) (cooldown * t), minimumCooldown); - } - - bPlayer.addCooldown(this, scaledCooldown); - } - - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "EarthSurf"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthSurf.Description"); - } - - public static double getTargetHeight() { - return TARGET_HEIGHT; - } - - public void setLocation(Location location) { - this.location = location; - } - - public double getPrevHealth() { - return prevHealth; - } - - public void setPrevHealth(double prevHealth) { - this.prevHealth = prevHealth; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getMinimumCooldown() { - return minimumCooldown; - } - - public void setMinimumCooldown(long minimumCooldown) { - this.minimumCooldown = minimumCooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public boolean isCooldownEnabled() { - return cooldownEnabled; - } - - public void setCooldownEnabled(boolean cooldownEnabled) { - this.cooldownEnabled = cooldownEnabled; - } - - public boolean isDurationEnabled() { - return durationEnabled; - } - - public void setDurationEnabled(boolean durationEnabled) { - this.durationEnabled = durationEnabled; - } - - public boolean isRemoveOnAnyDamage() { - return removeOnAnyDamage; - } - - public void setRemoveOnAnyDamage(boolean removeOnAnyDamage) { - this.removeOnAnyDamage = removeOnAnyDamage; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - } - - public double getSpringStiffness() { - return springStiffness; - } - - public void setSpringStiffness(double springStiffness) { - this.springStiffness = springStiffness; - } - - public Set getRidingBlocks() { - return ridingBlocks; - } - - public CollisionDetector getCollisionDetector() { - return collisionDetector; - } - - public void setCollisionDetector(CollisionDetector collisionDetector) { - this.collisionDetector = collisionDetector; - } - - public DoubleSmoother getHeightSmoother() { - return heightSmoother; - } - - public void setHeightSmoother(DoubleSmoother heightSmoother) { - this.heightSmoother = heightSmoother; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - return config.getBoolean("Abilities.Earth.EarthSurf.Enabled"); - } - - private interface CollisionDetector { - boolean isColliding(Player player); - } - - private abstract static class AbstractCollisionDetector implements CollisionDetector { - protected boolean isCollision(Location location) { - Block block = location.getBlock(); - return !MaterialUtil.isTransparent(block) || block.isLiquid() || block.getType().isSolid(); - } - } - - private class DefaultCollisionDetector extends AbstractCollisionDetector { - @Override - public boolean isColliding(Player player) { - // The location in front of the player, where the player will be in one second. - Location front = player.getEyeLocation().clone(); - front.setPitch(0); - - Vector direction = front.getDirection().clone().setY(0).normalize(); - double playerSpeed = player.getVelocity().clone().setY(0).length(); - - front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); - - for (int i = 0; i < 3; ++i) { - Location location = front.clone().add(0, -i, 0); - if (isCollision(location)) { - return true; - } - } - - return false; - } - } - - private class RelaxedCollisionDetector extends AbstractCollisionDetector { - @Override - public boolean isColliding(Player player) { - // The location in front of the player, where the player will be in one second. - Location front = player.getEyeLocation().clone().subtract(0.0, 0.5, 0.0); - front.setPitch(0); - - Vector direction = front.getDirection().clone().setY(0).normalize(); - double playerSpeed = player.getVelocity().clone().setY(0).length(); - - front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); - - return isCollision(front); - } - } - - private static class DoubleSmoother { - private final double[] values; - private final int size; - private int index; - - public DoubleSmoother(int size) { - this.size = size; - this.index = 0; - - values = new double[size]; - } - - public double add(double value) { - values[index] = value; - index = (index + 1) % size; - return get(); - } - - public double get() { - return Arrays.stream(this.values).sum() / this.size; - } - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/Fissure.java b/src/com/jedk1/jedcore/ability/earthbending/Fissure.java deleted file mode 100644 index 9fa731e..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/Fissure.java +++ /dev/null @@ -1,441 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.Information; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.BlockIterator; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -public class Fissure extends LavaAbility implements AddonAbility { - - @Attribute(Attribute.RANGE) - private int slapRange; - @Attribute(Attribute.WIDTH) - private int maxWidth; - private long slapDelay; - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - private Location location; - private Vector direction; - private Vector blockDirection; - private long time; - private long step; - private int slap; - private int width; - private boolean progressed; - - static Random rand = new Random(); - - private final List centerSlap = new ArrayList<>(); - private final List blocks = new ArrayList<>(); - private final List tempblocks = new ArrayList<>(); - - public Fissure(Player player) { - super(player); - - if (!bPlayer.canBend(this) || hasAbility(player, Fissure.class) || !bPlayer.canLavabend()) { - return; - } - - setFields(); - time = System.currentTimeMillis(); - step = System.currentTimeMillis() + slapDelay; - location = player.getLocation().clone(); - location.setPitch(0); - direction = location.getDirection(); - blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); - blockDirection = blockDirection.setZ(Math.round(direction.getZ())); - if (prepareLine()) { - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - slapRange = config.getInt("Abilities.Earth.Fissure.SlapRange"); - maxWidth = config.getInt("Abilities.Earth.Fissure.MaxWidth"); - slapDelay = config.getInt("Abilities.Earth.Fissure.SlapDelay"); - duration = config.getInt("Abilities.Earth.Fissure.Duration"); - cooldown = config.getInt("Abilities.Earth.Fissure.Cooldown"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (System.currentTimeMillis() > step && slap <= centerSlap.size()) { - time = System.currentTimeMillis(); - step = System.currentTimeMillis() + slapDelay; - slapCenter(); - slap++; - } - if (System.currentTimeMillis() > time + duration) { - remove(); - } - } - - private boolean prepareLine() { - direction = player.getEyeLocation().getDirection().setY(0).normalize(); - blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); - blockDirection = blockDirection.setZ(Math.round(direction.getZ())); - Location origin = player.getLocation().add(0, -1, 0).add(blockDirection.multiply(2)); - if (isEarthbendable(player, origin.getBlock())) { - BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, slapRange); - - while (bi.hasNext()) { - Block b = bi.next(); - - if (b.getY() > b.getWorld().getMinHeight() && b.getY() < b.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, b.getLocation())) { - if (EarthAbility.getMovedEarth().containsKey(b)){ - Information info = EarthAbility.getMovedEarth().get(b); - if(!info.getBlock().equals(b)) { - continue; - } - } - - while (!isEarthbendable(player, b)) { - b = b.getRelative(BlockFace.DOWN); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b)) { - break; - } - } - - while (!isTransparent(b.getRelative(BlockFace.UP))) { - b = b.getRelative(BlockFace.UP); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(player, b)) { - centerSlap.add(b.getLocation()); - } else { - break; - } - } - } - return true; - } - return false; - } - - private void slapCenter() { - for (Location location : centerSlap) { - if (centerSlap.indexOf(location) == slap) { - addTempBlock(location.getBlock(), Material.LAVA); - } - } - if (slap >= centerSlap.size()) { - progressed = true; - } - } - - public static void performAction(Player player) { - if (hasAbility(player, Fissure.class)) { - getAbility(player, Fissure.class).performAction(); - } - } - - private void performAction() { - if (width < maxWidth) { - expandFissure(); - } else if (blocks.contains(player.getTargetBlock(null, 10))) { - forceRevert(); - } - } - - private void expandFissure() { - if (progressed && width <= maxWidth) { - width++; - for (Location location : centerSlap) { - Block left = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)), width); - expand(left); - - Block right = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)).getOppositeFace(), width); - expand(right); - } - } - Collections.reverse(blocks); - } - - private void expand(Block block) { - if (block != null && block.getY() > block.getWorld().getMinHeight() && block.getY() < block.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, block.getLocation())) { - if (EarthAbility.getMovedEarth().containsKey(block)){ - Information info = EarthAbility.getMovedEarth().get(block); - if(!info.getBlock().equals(block)) { - return; - } - } - - while (!isEarthbendable(player, block)) { - block = block.getRelative(BlockFace.DOWN); - if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, block)) { - break; - } - } - - while (!isTransparent(player, block.getRelative(BlockFace.UP))) { - block = block.getRelative(BlockFace.UP); - if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, block.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(player, block)) { - addTempBlock(block, Material.LAVA); - } - } - } - - private void addTempBlock(Block block, Material material) { - ParticleEffect.LAVA.display(block.getLocation(), 0, 0, 0, 0, 1); - playEarthbendingSound(block.getLocation()); - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - tempblocks.add(new TempBlock(block, material.createBlockData(), this)); - blocks.add(block); - } - - public BlockFace getLeftBlockFace(BlockFace forward) { - switch (forward) { - case NORTH: - return BlockFace.WEST; - case SOUTH: - return BlockFace.EAST; - case WEST: - return BlockFace.SOUTH; - case EAST: - return BlockFace.NORTH; - case NORTH_WEST: - return BlockFace.SOUTH_WEST; - case NORTH_EAST: - return BlockFace.NORTH_WEST; - case SOUTH_WEST: - return BlockFace.SOUTH_EAST; - case SOUTH_EAST: - return BlockFace.NORTH_EAST; - default: - return BlockFace.NORTH; - } - } - - private void forceRevert() { - coolLava(); - } - - private void coolLava() { - tempblocks.forEach(TempBlock::revertBlock); - for (Block block : blocks) { - new TempBlock(block, Material.STONE.createBlockData(), 500 + (long) rand.nextInt((int) 1000)); - } - blocks.clear(); - tempblocks.clear(); - } - - @Override - public void remove() { - coolLava(); - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "Fissure"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.Fissure.Description"); - } - - public int getSlapRange() { - return slapRange; - } - - public void setSlapRange(int slapRange) { - this.slapRange = slapRange; - } - - public int getMaxWidth() { - return maxWidth; - } - - public void setMaxWidth(int maxWidth) { - this.maxWidth = maxWidth; - } - - public long getSlapDelay() { - return slapDelay; - } - - public void setSlapDelay(long slapDelay) { - this.slapDelay = slapDelay; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public void setLocation(Location location) { - this.location = location; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public Vector getBlockDirection() { - return blockDirection; - } - - public void setBlockDirection(Vector blockDirection) { - this.blockDirection = blockDirection; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public long getStep() { - return step; - } - - public void setStep(long step) { - this.step = step; - } - - public int getSlap() { - return slap; - } - - public void setSlap(int slap) { - this.slap = slap; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - public boolean isProgressed() { - return progressed; - } - - public void setProgressed(boolean progressed) { - this.progressed = progressed; - } - - public List getCenterSlap() { - return centerSlap; - } - - public List getBlocks() { - return blocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.Fissure.Enabled"); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java b/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java deleted file mode 100644 index 547a666..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java +++ /dev/null @@ -1,564 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; -import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; -import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class LavaDisc extends LavaAbility implements AddonAbility { - - private Location location; - private int recallCount; - - private long time; - - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - private int recallLimit; - private boolean trailFlow; - - private CompositeRemovalPolicy removalPolicy; - private DiscRenderer discRenderer; - private State state; - private final Set trailBlocks = new HashSet<>(); - - public LavaDisc(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { - return; - } - - // Allow new LavaDisc if all existing instances for that player are in CleanupState. - for (LavaDisc disc : CoreAbility.getAbilities(player, LavaDisc.class)) { - if (!(disc.state instanceof CleanupState)) { - return; - } - } - - state = new HoldState(); - time = System.currentTimeMillis(); - discRenderer = new DiscRenderer(this.player); - - setFields(); - - if (prepare()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - damage = config.getDouble("Abilities.Earth.LavaDisc.Damage"); - cooldown = config.getLong("Abilities.Earth.LavaDisc.Cooldown"); - duration = config.getLong("Abilities.Earth.LavaDisc.Duration"); - recallLimit = config.getInt("Abilities.Earth.LavaDisc.RecallLimit") - 1; - trailFlow = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.TrailFlow"); - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new SwappedSlotsRemovalPolicy<>(bPlayer, LavaDisc.class) - ); - - this.removalPolicy.load(config); - } - - private boolean prepare() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - long sourceRegen = config.getLong("Abilities.Earth.LavaDisc.Source.RegenTime"); - boolean lavaOnly = config.getBoolean("Abilities.Earth.LavaDisc.Source.LavaOnly"); - double sourceRange = config.getDouble("Abilities.Earth.LavaDisc.Source.Range"); - - Block lavaSource = getLavaSourceBlock(player, sourceRange); - if (lavaSource != null && !EarthAbility.getMovedEarth().containsKey(lavaSource)) { - new RegenTempBlock(lavaSource, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); - return true; - } else { - Block earthSource = getEarthSourceBlock(sourceRange); - if (earthSource != null && !lavaOnly && !EarthAbility.getMovedEarth().containsKey(earthSource)) { - new RegenTempBlock(earthSource, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); - return true; - } - } - - return false; - } - - @Override - public void progress() { - if (this.removalPolicy.shouldRemove()) { - if (!player.isOnline()) { - // Revert all of the lava blocks if the player goes offline. - for (Block block : trailBlocks) { - RegenTempBlock.revert(block); - } - bPlayer.addCooldown(this); - remove(); - return; - } else if (!(state instanceof CleanupState)) { - state = new CleanupState(); - } - } - - if (!hasAbility(player, LavaDisc.class)) { - return; - } - - state.update(); - } - - public static boolean canFlowFrom(Block from) { - Material type = from.getType(); - if (type != Material.LAVA && !ElementalAbility.isAir(type)) { - return true; - } - - for (LavaDisc disc : CoreAbility.getAbilities(LavaDisc.class)) { - if (disc.trailFlow) continue; - - if (disc.trailBlocks.contains(from)) { - return false; - } - } - - return true; - } - - private boolean isLocationSafe() { - if (!isLocationSafe(location)) { - return false; - } - - Block block = location.getBlock(); - - return isTransparent(block); - } - - private boolean isLocationSafe(Location location) { - if (location == null || location.getWorld() == null) { - return false; - } - - return location.getY() >= location.getWorld().getMinHeight() && location.getY() <= (location.getWorld().getMaxHeight() - 1); - } - - private void doDamage(Entity entity) { - DamageHandler.damageEntity(entity, damage, this); - entity.setFireTicks(20); - new FireDamageTimer(entity, player, this); - ParticleEffect.LAVA.display(entity.getLocation(), 15, Math.random(), Math.random(), Math.random(), 0.1); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "LavaDisc"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaDisc.Description"); - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getRecallCount() { - return recallCount; - } - - public void setRecallCount(int recallCount) { - this.recallCount = recallCount; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public int getRecallLimit() { - return recallLimit; - } - - public void setRecallLimit(int recallLimit) { - this.recallLimit = recallLimit; - } - - public boolean isTrailFlow() { - return trailFlow; - } - - public void setTrailFlow(boolean trailFlow) { - this.trailFlow = trailFlow; - } - - public DiscRenderer getDiscRenderer() { - return discRenderer; - } - - public void setDiscRenderer(DiscRenderer discRenderer) { - this.discRenderer = discRenderer; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - public Set getTrailBlocks() { - return trailBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.LavaDisc.Enabled"); - } - - private interface State { - void update(); - } - - // Renders the particles showing that the player is holding lava. - // Transitions to ForwardTravelState when the player stops sneaking. - private class HoldState implements State { - @Override - public void update() { - location = player.getEyeLocation(); - Vector dV = location.getDirection().normalize(); - location.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); - - dV = dV.multiply(0.1); - - while (!isLocationSafe() && isLocationSafe(player.getLocation())) { - location.subtract(dV); - if (location.distanceSquared(player.getEyeLocation()) > (3 * 3)) { - break; - } - } - - discRenderer.render(location, false); - - location.setPitch(0); - - if (!player.isSneaking()) { - time = System.currentTimeMillis(); - state = new ForwardTravelState(location.getDirection().normalize()); - } - } - } - - private abstract class TravelState implements State { - private final boolean passHit; - - protected Vector direction; - protected boolean hasHit; - - public TravelState() { - this(player.getEyeLocation().getDirection()); - } - - public TravelState(Vector direction) { - this.direction = direction; - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - passHit = config.getBoolean("Abilities.Earth.LavaDisc.ContinueAfterEntityHit"); - } - - protected void move() { - for (int i = 0; i < 5; i++) { - location = location.add(direction.clone().multiply(0.15)); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.0D)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - doDamage(entity); - if (!passHit) { - hasHit = true; - return; - } - } - } - } - } - } - - // Moves the disc forward. Makes the disc destroy blocks if enabled. - // Transitions to ReverseTravelState if the player starts sneaking and can recall. - // Transitions to CleanupState if it times out or hits an entity. - private class ForwardTravelState extends TravelState { - public ForwardTravelState() { - this(player.getEyeLocation().getDirection()); - } - - public ForwardTravelState(Vector direction) { - super(direction); - } - - @Override - public void update() { - if (!isLocationSafe() || System.currentTimeMillis() > time + duration) { - state = new CleanupState(); - return; - } - - if (player.isSneaking() && recallCount <= recallLimit) { - state = new ReverseTravelState(); - return; - } - - alterPitch(); - move(); - discRenderer.render(location, true); - - if (hasHit) { - state = new CleanupState(); - } - } - - private void alterPitch() { - Location loc = player.getLocation().clone(); - - if (loc.getPitch() < -20) - loc.setPitch(-20); - if (loc.getPitch() > 20) - loc.setPitch(20); - - direction = loc.getDirection().normalize(); - } - } - - // Returns the disc to the player. - // Transitions to ForwardTravelState if the player stops sneaking. - // Transitions to HoldState if the disc gets close enough to the player. - private class ReverseTravelState extends TravelState { - @Override - public void update() { - if (!player.isSneaking()) { - state = new ForwardTravelState(); - return; - } - - Location loc = player.getEyeLocation(); - Vector dV = loc.getDirection().normalize(); - loc.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); - - Vector vector = loc.toVector().subtract(location.toVector()); - direction = loc.setDirection(vector).getDirection().normalize(); - - move(); - discRenderer.render(location, true); - - double distanceAway = location.distance(loc); - if (distanceAway < 0.5) { - recallCount++; - // Player is holding the disc when it gets close enough to them. - state = new HoldState(); - } - } - } - - // Waits for the RegenTempBlocks to revert. - // This exists so the instance stays alive and block flow events can stop the lava from flowing. - private class CleanupState implements State { - private final long startTime; - private final long regenTime; - - public CleanupState() { - this.startTime = System.currentTimeMillis(); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); - bPlayer.addCooldown(LavaDisc.this); - } - - @Override - public void update() { - if (System.currentTimeMillis() >= startTime + regenTime || trailBlocks.isEmpty()) { - remove(); - } - } - } - - private class DiscRenderer { - private final Player player; - private int angle; - - private final boolean damageBlocks; - private final List meltable; - private final long regenTime; - private final boolean lavaTrail; - - private final int particles; - - - public DiscRenderer(Player player) { - this.player = player; - this.angle = 0; - - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - damageBlocks = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.BlockDamage"); - meltable = config.getStringList("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks"); - regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); - lavaTrail = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.LavaTrail"); - particles = config.getInt("Abilities.Earth.LavaDisc.Particles"); - } - - void render(Location location, boolean largeLava) { - if (largeLava) - ParticleEffect.LAVA.display(location, particles * 2, Math.random(), Math.random(), Math.random(), 0.1); - else - ParticleEffect.LAVA.display(location, 1, Math.random(), Math.random(), Math.random(), 0.1); - - angle += 1; - if (angle > 360) - angle = 0; - - for (Location l : JCMethods.getCirclePoints(location, 20, 1, angle)) { - ParticleEffect.REDSTONE.display(l, 0, 196, 93, 0, 0.005F, new Particle.DustOptions(Color.fromRGB(196, 93, 0), 1)); - if (largeLava && damageBlocks) - damageBlocks(l); - } - - for (Location l : JCMethods.getCirclePoints(location, 10, 0.5, angle)) { - ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.01); - ParticleEffect.SMOKE_NORMAL.display(l, 1, 0, 0, 0, 0.05); - if (largeLava && damageBlocks) - damageBlocks(l); - } - } - - private void damageBlocks(Location l) { - Block block = l.getBlock(); - if (EarthAbility.getMovedEarth().containsKey(block)) { - ParticleEffect.LAVA.display(l, 20, 0.5, 0.5, 0.5, 0.2); - ParticleEffect.BLOCK_CRACK.display(l, 15, 0.3, 0.3, 0.3, 0.15, Material.LAVA.createBlockData()); - return; - } - if (!RegionProtection.isRegionProtected(player, l, LavaDisc.this)) { - if (!TempBlock.isTempBlock(block) && (isEarthbendable(player, block) || isMetal(block) || meltable.contains(block.getType().name()))) { - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - - if (lavaTrail) { - new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled) bd).setLevel(4)), regenTime); - - trailBlocks.add(block); - } else { - new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), regenTime); - } - - ParticleEffect.LAVA.display(l, particles * 2, Math.random(), Math.random(), Math.random(), 0.2); - } - } - } - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java b/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java deleted file mode 100644 index d2abe08..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java +++ /dev/null @@ -1,449 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.Information; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Bisected; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.BlockIterator; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -public class LavaFlux extends LavaAbility implements AddonAbility { - - @Attribute(Attribute.SPEED) - private int speed; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - private long cleanup; - @Attribute(Attribute.DAMAGE) - private double damage; - private boolean wave; - - private Location location; - private int step; - private int counter; - private long time; - private boolean complete; - - private double knockUp; - private double knockBack; - - Random rand = new Random(); - - private static final BlockData LAVA = Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(1)); - - private final List flux = new ArrayList<>(); - - private Map blocks = new HashMap<>(); - private Map above = new HashMap<>(); - - public LavaFlux(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { - return; - } - - setFields(); - time = System.currentTimeMillis(); - if (prepareLine()) { - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - speed = config.getInt("Abilities.Earth.LavaFlux.Speed"); - if (speed < 1) speed = 1; - range = config.getInt("Abilities.Earth.LavaFlux.Range"); - cooldown = config.getLong("Abilities.Earth.LavaFlux.Cooldown"); - duration = config.getLong("Abilities.Earth.LavaFlux.Duration"); - cleanup = config.getLong("Abilities.Earth.LavaFlux.Cleanup"); - damage = config.getDouble("Abilities.Earth.LavaFlux.Damage"); - wave = config.getBoolean("Abilities.Earth.LavaFlux.Wave"); - knockUp = config.getDouble("Abilities.Earth.LavaFlux.KnockUp"); - knockBack = config.getDouble("Abilities.Earth.LavaFlux.KnockBack"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - counter++; - if (!complete) { - if (speed <= 1 || counter % speed == 0) { - for (int i = 0; i <= 2; i++) { - step++; - progressFlux(); - } - } - } else if (duration > cleanup) { - if (System.currentTimeMillis() > time + duration) { - for (TempBlock tb : blocks.values()) { - if (!tb.isReverted()) tb.setType(Material.STONE); - } - remove(); - } - } - } - - private boolean prepareLine() { - Vector direction = player.getEyeLocation().getDirection().setY(0).normalize(); - Vector blockdirection = direction.clone().setX(Math.round(direction.getX())); - blockdirection = blockdirection.setZ(Math.round(direction.getZ())); - Location origin = player.getLocation().add(0, -1, 0).add(blockdirection.multiply(2)); - if (isEarthbendable(player, origin.getBlock())) { - BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, range); - - while (bi.hasNext()) { - Block b = bi.next(); - - if (b.getY() > b.getWorld().getMinHeight() && b.getY() < b.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, b.getLocation()) && !EarthAbility.getMovedEarth().containsKey(b)) { - if (isWater(b)) break; - while (!isEarthbendable(player, b)) { - b = b.getRelative(BlockFace.DOWN); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b)) { - break; - } - } - - while (!isTransparent(b.getRelative(BlockFace.UP))) { - b = b.getRelative(BlockFace.UP); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(player, b)) { - flux.add(b.getLocation()); - Block left = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)), 1); - expand(left); - Block right = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)).getOppositeFace(), 1); - expand(right); - } else { - break; - } - } - } - return true; - } - return false; - } - - private void progressFlux() { - for (Location location : flux) { - if (flux.indexOf(location) <= step) { - if (!blocks.containsKey(location.getBlock())) { //Make a new temp block if we haven't made one there before - blocks.put(location.getBlock(), new TempBlock(location.getBlock(), LAVA, duration + cleanup, this)); - } - - //new RegenTempBlock(location.getBlock(), Material.LAVA, LAVA, duration + cleanup); - this.location = location; - if (flux.indexOf(location) == step) { - Block above = location.getBlock().getRelative(BlockFace.UP); - ParticleEffect.LAVA.display(above.getLocation(), 2, Math.random(), Math.random(), Math.random(), 0); - applyDamageFromWave(above.getLocation()); - - if (isPlant(above) || isSnow(above)) { - final Block above2 = above.getRelative(BlockFace.UP); - if (isPlant(above) || isSnow(above)) { - TempBlock tb = new TempBlock(above, Material.AIR.createBlockData(), duration + cleanup, this); - this.above.put(above, tb); - if (isPlant(above2) && above2.getBlockData() instanceof Bisected) { - TempBlock tb2 = new TempBlock(above2, Material.AIR.createBlockData(), duration + cleanup + 30_000, this); - tb.addAttachedBlock(tb2); - } - } - } else if (wave && isTransparent(above)) { - new TempBlock(location.getBlock().getRelative(BlockFace.UP), LAVA, speed * 150L, this); - } - } - } - } - if (step >= flux.size()) { - wave = false; - complete = true; - time = System.currentTimeMillis(); - - for (TempBlock tb : blocks.values()) { //Make sure they all revert at the same time because it looks nice - long time = duration + cleanup + rand.nextInt(1000); - tb.setRevertTime(time); - - if (this.above.containsKey(tb.getBlock().getRelative(BlockFace.UP))) { - this.above.get(tb.getBlock().getRelative(BlockFace.UP)).setRevertTime(time); - } - } - } - } - - private void applyDamageFromWave(Location location) { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 1.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - LivingEntity livingEntity = (LivingEntity) entity; - - DamageHandler.damageEntity(entity, damage, this); - new FireDamageTimer(entity, player, this); - - Vector direction = livingEntity.getLocation().toVector().subtract(player.getLocation().toVector()).normalize(); - Vector knockbackVelocity = direction.multiply(knockBack).setY(knockUp); - - livingEntity.setVelocity(knockbackVelocity); - } - } - } - - private void expand(Block block) { - if (block != null && block.getY() > block.getWorld().getMinHeight() && block.getY() < block.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, block.getLocation())) { - if (EarthAbility.getMovedEarth().containsKey(block)){ - Information info = EarthAbility.getMovedEarth().get(block); - if(!info.getBlock().equals(block)) { - return; - } - } - - if (isWater(block)) return; - while (!isEarthbendable(block)) { - block = block.getRelative(BlockFace.DOWN); - if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(block)) { - break; - } - } - - while (!isTransparent(block.getRelative(BlockFace.UP))) { - block = block.getRelative(BlockFace.UP); - if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(block.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(block)) { - flux.add(block.getLocation()); - } - } - } - - public BlockFace getLeftBlockFace(BlockFace forward) { - switch (forward) { - case NORTH: - return BlockFace.WEST; - case SOUTH: - return BlockFace.EAST; - case WEST: - return BlockFace.SOUTH; - case NORTH_WEST: - return BlockFace.SOUTH_WEST; - case NORTH_EAST: - return BlockFace.NORTH_WEST; - case SOUTH_WEST: - return BlockFace.SOUTH_EAST; - case SOUTH_EAST: - return BlockFace.NORTH_EAST; - default: - return BlockFace.NORTH; - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "LavaFlux"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaFlux.Description"); - } - - public int getSpeed() { - return speed; - } - - public void setSpeed(int speed) { - this.speed = speed; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public long getCleanup() { - return cleanup; - } - - public void setCleanup(long cleanup) { - this.cleanup = cleanup; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean isWave() { - return wave; - } - - public void setWave(boolean wave) { - this.wave = wave; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getStep() { - return step; - } - - public void setStep(int step) { - this.step = step; - } - - public int getCounter() { - return counter; - } - - public void setCounter(int counter) { - this.counter = counter; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public boolean isComplete() { - return complete; - } - - public void setComplete(boolean complete) { - this.complete = complete; - } - - public List getFlux() { - return flux; - } - - @Override - public void load() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - if (config.get("Abilities.Earth.LavaFlux.Speed") instanceof String) { - config.set("Abilities.Earth.LavaFlux.Speed", 1); - JedCore.plugin.saveConfig(); - JedCore.plugin.reloadConfig(); - } - } - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.LavaFlux.Enabled"); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java deleted file mode 100644 index 2f7e624..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java +++ /dev/null @@ -1,344 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.FluidCollisionMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.RayTraceResult; -import org.bukkit.util.Vector; - -import java.util.concurrent.ConcurrentHashMap; - -public class LavaThrow extends LavaAbility implements AddonAbility { - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.SELECT_RANGE) - private int sourceRange; - private long sourceRegen; - @Attribute("MaxShots") - private int shotMax; - @Attribute(Attribute.FIRE_TICK) - private int fireTicks; - @Attribute("CurveFactor") - private double curveFactor; - - private Location location; - private int shots; - private Block selectedSource; - private boolean isInitialState = true; - - private final ConcurrentHashMap blasts = new ConcurrentHashMap<>(); - - public LavaThrow(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { - return; - } - - setFields(); - - location = player.getLocation(); - location.setPitch(0); - - if (prepare()) { - player.getWorld().playSound(selectedSource.getLocation(), Sound.ITEM_BUCKET_FILL_LAVA, 1.0f, 1.0f); - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.LavaThrow.Cooldown"); - range = config.getInt("Abilities.Earth.LavaThrow.Range"); - damage = config.getDouble("Abilities.Earth.LavaThrow.Damage"); - sourceRange = config.getInt("Abilities.Earth.LavaThrow.SourceGrabRange"); - sourceRegen = config.getLong("Abilities.Earth.LavaThrow.SourceRegenDelay"); - shotMax = config.getInt("Abilities.Earth.LavaThrow.MaxShots"); - fireTicks = config.getInt("Abilities.Earth.LavaThrow.FireTicks"); - curveFactor = config.getDouble("Abilities.Earth.LavaThrow.CurveFactor"); - } - - @Override - public void progress() { - if (player == null || player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.getBoundAbilityName().equalsIgnoreCase("LAVATHROW")) { - remove(); - if (shots > 0) bPlayer.addCooldown(this); - return; - } - - if (player.getLocation().distance(selectedSource.getLocation()) >= sourceRange) { - remove(); - if (shots > 0) bPlayer.addCooldown(this); - return; - } - - if (blasts.isEmpty() && shots >= shotMax && !isInitialState) { - remove(); - bPlayer.addCooldown(this); - return; - } - - selectedSource.getWorld().spawnParticle(Particle.FLAME, selectedSource.getLocation(), 2, 0.3, 1.0, 0.3, 0.05); - selectedSource.getWorld().spawnParticle(Particle.LAVA, selectedSource.getLocation(), 2, 0.2, 0.2, 0.2, 0); - - handleBlasts(); - } - - private boolean prepare() { - Block targetBlock = getTargetLavaBlock(sourceRange); - - if (targetBlock != null && !TempBlock.isTempBlock(targetBlock)) { - selectedSource = targetBlock; - return true; - } - - return false; - } - - public Block getTargetLavaBlock(int maxDistance) { - Location eyeLocation = player.getEyeLocation(); - Vector direction = eyeLocation.getDirection(); - World world = player.getWorld(); - - RayTraceResult result = world.rayTraceBlocks( - eyeLocation, direction, maxDistance, - FluidCollisionMode.ALWAYS, true - ); - - if (result != null) { - Block hitBlock = result.getHitBlock(); - if (LavaAbility.isLava(hitBlock)) { - return hitBlock; - } - } - return null; - } - - public void createBlast() { - if (selectedSource != null && shots < shotMax) { - isInitialState = false; - shots++; - - if (shots >= shotMax) { - bPlayer.addCooldown(this); - } - - Location origin = selectedSource.getLocation().clone().add(0, 2, 0); - player.getWorld().playSound(origin, Sound.ITEM_BUCKET_EMPTY_LAVA, 1.0f, 1.0f); - double viewRange = range + origin.distance(player.getEyeLocation()); - Location viewTarget = GeneralMethods.getTargetedLocation(player, viewRange, Material.WATER, Material.LAVA); - Vector direction = viewTarget.clone().subtract(origin).toVector().normalize(); - Location head = origin.clone(); - - head.setDirection(direction); - blasts.put(head, origin); - - new RegenTempBlock(selectedSource.getRelative(BlockFace.UP), Material.LAVA, - Material.LAVA.createBlockData(), 200); - } - } - - public void handleBlasts() { - for (Location l : blasts.keySet()) { - Location head = l.clone(); - Location origin = blasts.get(l); - - if (l.distance(origin) > range) { - blasts.remove(l); - continue; - } - - if (GeneralMethods.isSolid(l.getBlock())) { - blasts.remove(l); - continue; - } - - Vector currentDirection = head.getDirection(); - Vector playerLookDirection = player.getEyeLocation().getDirection(); - - Vector curveVector = playerLookDirection.clone() - .subtract(currentDirection) - .multiply(curveFactor); - - Vector newDirection = currentDirection.clone() - .add(curveVector) - .normalize(); - - head.setDirection(newDirection); - head = head.add(newDirection.multiply(1)); - - new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); - ParticleEffect.LAVA.display(head, 1, Math.random(), Math.random(), Math.random(), 0); - - boolean hit = false; - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 2.0D)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { - DamageHandler.damageEntity(entity, damage, this); - blasts.remove(l); - - hit = true; - entity.setFireTicks(this.fireTicks); - } - } - - if (!hit) { - blasts.remove(l); - blasts.put(head, origin); - } - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "LavaThrow"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaThrow.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getSourceRange() { - return sourceRange; - } - - public void setSourceRange(int sourceRange) { - this.sourceRange = sourceRange; - } - - public long getSourceRegen() { - return sourceRegen; - } - - public void setSourceRegen(long sourceRegen) { - this.sourceRegen = sourceRegen; - } - - public int getShotMax() { - return shotMax; - } - - public void setShotMax(int shotMax) { - this.shotMax = shotMax; - } - - public int getFireTicks() { - return fireTicks; - } - - public void setFireTicks(int fireTicks) { - this.fireTicks = fireTicks; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getShots() { - return shots; - } - - public void setShots(int shots) { - this.shots = shots; - } - - public ConcurrentHashMap getBlasts() { - return blasts; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.LavaThrow.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java b/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java deleted file mode 100644 index d416565..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; - - -public class MagnetShield extends MetalAbility implements AddonAbility { - - private static List METAL_LIST; - - private boolean isClickState = false; - private long startTime; - - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.RANGE) - private double range; - - private double velocity; - private boolean repelArrows; - private boolean repelLivingEntities; - private long shiftCooldown; - private long clickCooldown; - - public MagnetShield(Player player) { - super(player); - - if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { - return; - } - - if (!bPlayer.canBend(this)) { - return; - } - - player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); - - setFields(); - loadMaterialsFromConfig(); - start(); - } - - public MagnetShield(Player player, boolean isClickState) { - super(player); - - if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { - return; - } - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, MagnetShield.class)) { - getAbility(player, MagnetShield.class).remove(); - return; - } - - setFields(); - - if (isClickState) { - this.isClickState = true; - startTime = System.currentTimeMillis(); - bPlayer.addCooldown(this, duration + 1); - } - - player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); - - loadMaterialsFromConfig(); - start(); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - remove(); - return; - } - - if (isClickState) { - if (System.currentTimeMillis() - startTime >= duration) { - bPlayer.addCooldown(this, clickCooldown); - remove(); - return; - } - } else { - if (!player.isSneaking()) { - bPlayer.addCooldown(this, shiftCooldown); - remove(); - return; - } - } - - renderMagneticFieldLines(); - repelMetal(); - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return player.getLocation(); - } - - @Override - public String getName() { - return "MagnetShield"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MagnetShield.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MagnetShield.Enabled"); - } - - private void renderMagneticFieldLines() { - Location playerLocation = player.getLocation(); - int numLoops = 5; - int pointsPerLoop = 30; - double verticalSpacing = 0.06; - - for (int loop = 0; loop < numLoops; loop++) { - double currentRadius = range * (1 - (double) loop / numLoops); - double currentHeight = ((loop - numLoops / 2.0) * verticalSpacing) + 0.3; - - for (int i = 0; i < pointsPerLoop; i++) { - double angle = 2 * Math.PI * i / pointsPerLoop; - double x = currentRadius * Math.cos(angle); - double z = currentRadius * Math.sin(angle); - Location particleLocation = playerLocation.clone().add(x, currentHeight, z); - JedCore.plugin.getParticleAdapter().displayMagneticParticles(particleLocation); - } - } - } - - private void loadMaterialsFromConfig() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - List materialNames = config.getStringList("Abilities.Earth.MagnetShield.Materials"); - METAL_LIST = new ArrayList<>(); - - for (String materialName : materialNames) { - Material material = Material.getMaterial(materialName.toUpperCase()); - if (material != null) { - METAL_LIST.add(material); - } else { - System.out.println("Invalid material in config: " + materialName); - } - } - } - - private void repelMetal() { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), range)) { - if (e instanceof Item) { - Item i = (Item) e; - if (isMetalMaterial(i.getItemStack().getType())) { - Vector direction = GeneralMethods.getDirection(player.getLocation(), i.getLocation()).multiply(velocity); - i.setVelocity(direction); - } - } else if (e instanceof FallingBlock) { - FallingBlock fb = (FallingBlock) e; - - if (isMetalMaterial(fb.getBlockData().getMaterial())) { - Vector direction = GeneralMethods.getDirection(player.getLocation(), fb.getLocation()).multiply(velocity); - fb.setVelocity(direction); - fb.setDropItem(false); - } - } else if (e instanceof Arrow && repelArrows) { - Arrow arrow = (Arrow) e; - Vector currentVelocity = arrow.getVelocity(); - Vector reversedVelocity = currentVelocity.multiply(-1); - arrow.setVelocity(reversedVelocity); - } else if (e instanceof LivingEntity && repelLivingEntities) { - LivingEntity livingEntity = (LivingEntity) e; - - if (livingEntity.getUniqueId().equals(player.getUniqueId())) continue; - - EntityEquipment equipment = livingEntity.getEquipment(); - if (equipment == null) continue; - - ItemStack mainHand = equipment.getItemInMainHand(); - ItemStack offHand = equipment.getItemInOffHand(); - ItemStack helmet = equipment.getHelmet(); - ItemStack chestplate = equipment.getChestplate(); - ItemStack leggings = equipment.getLeggings(); - ItemStack boots = equipment.getBoots(); - - boolean isMetal = isMetalItem(mainHand) || isMetalItem(offHand) || - isMetalItem(helmet) || isMetalItem(chestplate) || - isMetalItem(leggings) || isMetalItem(boots); - - if (isMetal) { - Vector direction = GeneralMethods.getDirection(player.getLocation(), e.getLocation()).multiply(velocity); - livingEntity.setVelocity(direction); - } - } - } - } - - private boolean isMetalItem(ItemStack itemStack) { - return itemStack != null && METAL_LIST.contains(itemStack.getType()); - } - - private boolean isMetalMaterial(Material material) { - return METAL_LIST.contains(material); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - duration = config.getLong("Abilities.Earth.MagnetShield.Duration"); - shiftCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Shift"); - clickCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Click"); - range = config.getDouble("Abilities.Earth.MagnetShield.Range"); - repelArrows = config.getBoolean("Abilities.Earth.MagnetShield.RepelArrows"); - repelLivingEntities = config.getBoolean("Abilities.Earth.MagnetShield.RepelLivingEntities"); - velocity = config.getDouble("Abilities.Earth.MagnetShield.Velocity"); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java b/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java deleted file mode 100644 index 6390a3b..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.earthbending.EarthArmor; -import com.projectkorra.projectkorra.util.TempArmor; -import com.projectkorra.projectkorra.util.TempPotionEffect; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.LeatherArmorMeta; -import org.bukkit.potion.PotionEffect; - -import java.util.Arrays; -import java.util.List; - -public class MetalArmor extends EarthAbility implements AddonAbility { - - private static final int GOLD_BLOCK_COLOR = 0xF2F204; - private static final List METAL_COLORS = Arrays.asList( - 0xa39d91, 0xf4f4f4, 0xa2a38f, 0xF2F204, 0xb75656, 0xfff4f4 - ); - - private boolean useIronArmor; - private int resistStrength; - private int resistDuration; - - public MetalArmor(Player player) { - super(player); - - if (bPlayer == null || !bPlayer.canBendIgnoreCooldowns(CoreAbility.getAbility(EarthArmor.class)) || !bPlayer.canMetalbend()) { - return; - } - - if (!CoreAbility.hasAbility(player, EarthArmor.class)) { - return; - } - - setFields(); - start(); - } - - private void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - useIronArmor = config.getBoolean("Abilities.Earth.EarthArmor.UseIronArmor"); - resistStrength = config.getInt("Abilities.Earth.EarthArmor.Resistance.Strength"); - resistDuration = config.getInt("Abilities.Earth.EarthArmor.Resistance.Duration"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (!CoreAbility.hasAbility(player, EarthArmor.class)) { - remove(); - return; - } - - EarthArmor ea = CoreAbility.getAbility(player, EarthArmor.class); - if (!bPlayer.isToggled()) { - remove(); - ea.remove(); - return; - } - - if (ea.isFormed()) { - if (isMetalHelmet()) { - ItemStack[] armors = { new ItemStack(Material.CHAINMAIL_BOOTS, 1), - new ItemStack(Material.CHAINMAIL_LEGGINGS, 1), - new ItemStack(Material.CHAINMAIL_CHESTPLATE, 1), - new ItemStack(Material.CHAINMAIL_HELMET, 1) }; - - if(useIronArmor){ - armors = new ItemStack[]{ new ItemStack(Material.IRON_BOOTS, 1), - new ItemStack(Material.IRON_LEGGINGS, 1), - new ItemStack(Material.IRON_CHESTPLATE, 1), - new ItemStack(Material.IRON_HELMET, 1) }; - } - - if(useIronArmor && getHelmetColor().equals(Color.fromRGB(GOLD_BLOCK_COLOR))) { - armors = new ItemStack[]{ new ItemStack(Material.GOLDEN_BOOTS, 1), - new ItemStack(Material.GOLDEN_LEGGINGS, 1), - new ItemStack(Material.GOLDEN_CHESTPLATE, 1), - new ItemStack(Material.GOLDEN_HELMET, 1) }; - } - - player.getInventory().setArmorContents(armors); - - PotionEffect resistance = JedCore.plugin.getPotionEffectAdapter().getResistanceEffect(resistDuration, resistStrength); - new TempPotionEffect(player, resistance); - } - - remove(); - } - } - - private boolean isMetalHelmet() { - Color color = getHelmetColor(); - - return METAL_COLORS.contains(color.asRGB()); - } - - private Color getHelmetColor() { - if (!TempArmor.hasTempArmor(player)) { - return Color.BLACK; - } - - ItemStack helm = player.getInventory().getHelmet(); - if (helm.getType() != Material.LEATHER_HELMET) { - return Color.BLACK; - } - - LeatherArmorMeta meta = (LeatherArmorMeta)helm.getItemMeta(); - if (meta == null) { - return Color.BLACK; - } - - return meta.getColor(); - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalArmor"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public boolean isUseIronArmor() { - return useIronArmor; - } - - public void setUseIronArmor(boolean useIronArmor) { - this.useIronArmor = useIronArmor; - } - - public int getResistStrength() { - return resistStrength; - } - - public void setResistStrength(int resistStrength) { - this.resistStrength = resistStrength; - } - - public int getResistDuration() { - return resistDuration; - } - - public void setResistDuration(int resistDuration) { - this.resistDuration = resistDuration; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthArmor.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java b/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java deleted file mode 100644 index 4a89d95..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java +++ /dev/null @@ -1,434 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Random; - -public class MetalFragments extends MetalAbility implements AddonAbility { - - @Attribute("MaxSources") - private int maxSources; - @Attribute(Attribute.SELECT_RANGE) - private int selectRange; - @Attribute("MaxShots") - private int maxFragments; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private double velocity; - - public List sources = new ArrayList<>(); - private final List thrownFragments = new ArrayList<>(); - private final List tblockTracker = new ArrayList<>(); - //private List fblockTracker = new ArrayList<>(); - private final HashMap counters = new HashMap<>(); - - public MetalFragments(Player player) { - super(player); - - if (hasAbility(player, MetalFragments.class)) { - MetalFragments.selectAnotherSource(player); - return; - } - - if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { - return; - } - - setFields(); - - if (tblockTracker.size() >= maxSources) { - return; - } - - if (prepare()) { - Block b = selectSource(); - if (RegionProtection.isRegionProtected(player, b.getLocation(), this)) { - return; - } - - start(); - if (!isRemoved()) { - translateUpward(b); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - maxSources = config.getInt("Abilities.Earth.MetalFragments.MaxSources"); - selectRange = config.getInt("Abilities.Earth.MetalFragments.SourceRange"); - maxFragments = config.getInt("Abilities.Earth.MetalFragments.MaxFragments"); - damage = config.getDouble("Abilities.Earth.MetalFragments.Damage"); - cooldown = config.getInt("Abilities.Earth.MetalFragments.Cooldown"); - velocity = config.getDouble("Abilities.Earth.MetalFragments.Velocity"); - } - - public static void shootFragment(Player player) { - if (hasAbility(player, MetalFragments.class)) { - getAbility(player, MetalFragments.class).shootFragment(); - } - } - - private void shootFragment() { - if (sources.size() <= 0) - return; - - Random randy = new Random(); - int i = randy.nextInt(sources.size()); - Block source = sources.get(i); - ItemStack is; - - switch (source.getType()) { - case GOLD_BLOCK: - case GOLD_ORE: - is = new ItemStack(Material.GOLD_INGOT, 1); - break; - case COAL_BLOCK: - is = new ItemStack(Material.COAL, 1); - break; - case COAL_ORE: - is = new ItemStack(Material.COAL_ORE, 1); - break; - default: - is = new ItemStack(Material.IRON_INGOT, 1); - break; - } - - Vector direction; - if (GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()) != null) { - direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()).getLocation()); - } else { - direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedLocation(player, 30)); - } - - Item ii = player.getWorld().dropItemNaturally(source.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(direction)).getLocation(), is); - ii.setPickupDelay(Integer.MAX_VALUE); - ii.setVelocity(direction.normalize().multiply(velocity)); - playMetalbendingSound(ii.getLocation()); - thrownFragments.add(ii); - - if (counters.containsKey(source)) { - int count = counters.get(source); - count++; - - if (count >= maxFragments) { - counters.remove(source); - source.getWorld().spawnFallingBlock(source.getLocation().add(0.5, 0, 0.5), source.getBlockData()); - TempBlock tempBlock = TempBlock.get(source); - if (tempBlock != null) { - tempBlock.revertBlock(); - } - sources.remove(source); - source.getWorld().playSound(source.getLocation(), Sound.ENTITY_ITEM_BREAK, 10, 5); - } else { - counters.put(source, count); - } - - if (sources.size() == 0) { - remove(); - } - } - } - - public static void selectAnotherSource(Player player) { - if (hasAbility(player, MetalFragments.class)) { - getAbility(player, MetalFragments.class).selectAnotherSource(); - } - } - - private void selectAnotherSource() { - if (tblockTracker.size() >= maxSources) - return; - - if (prepare()) { - Block b = selectSource(); - translateUpward(b); - } - } - - public boolean prepare() { - Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); - - if (block == null) - return false; - - return isMetal(block); - } - - public Block selectSource() { - Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); - if (isMetal(block)) - return block; - return null; - } - - public void translateUpward(Block block) { - if (block == null) - return; - - if (sources.contains(block)) - return; - - if (block.getRelative(BlockFace.UP).getType().isSolid()) - return; - - if (isEarthbendable(player, block)) { - new TempFallingBlock(block.getLocation().add(0.5, 0, 0.5), block.getBlockData(), new Vector(0, 0.8, 0), this); - block.setType(Material.AIR); - - playMetalbendingSound(block.getLocation()); - } - } - - public void progress() { - if (player == null || player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!hasAbility(player, MetalFragments.class)) { - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - - Iterator itr = tblockTracker.iterator(); - while (itr.hasNext()) { - TempBlock tb = itr.next(); - if (player.getLocation().distance(tb.getLocation()) >= 10) { - player.getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlockData()); - sources.remove(tb.getBlock()); - tb.revertBlock(); - itr.remove(); - } - } - - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fb = tfb.getFallingBlock(); - if (fb.getLocation().getY() >= player.getEyeLocation().getY() + 1) { - Block block = fb.getLocation().getBlock(); - TempBlock tb = new TempBlock(block, fb.getBlockData()); - - tblockTracker.add(tb); - sources.add(tb.getBlock()); - counters.put(tb.getBlock(), 0); - tfb.remove(); - } - - if (fb.isOnGround()) { - fb.getLocation().getBlock().setBlockData(fb.getBlockData()); - } - } - for (ListIterator iterator = thrownFragments.listIterator(); iterator.hasNext();) { - Item f = iterator.next(); - - boolean touchedLiving = false; - for (Entity e : GeneralMethods.getEntitiesAroundPoint(f.getLocation(), 1)) { - if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { - touchedLiving = true; - DamageHandler.damageEntity(e, damage, this); - } - } - if (touchedLiving || f.isOnGround() || f.isDead()) { - ParticleEffect.ITEM_CRACK.display(f.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, f.getItemStack()); - f.remove(); - iterator.remove(); - } - } - - //removeDeadFBlocks(); - } - - /* - public void removeDeadFBlocks() { - for (int i = 0; i < fblockTracker.size(); i++) - if (fblockTracker.get(i).isDead()) - fblockTracker.remove(i); - } - */ - - public void removeDeadItems() { - thrownFragments.removeIf(Item::isDead); - } - - - public void dropSources() { - for (TempBlock tb : tblockTracker) { - tb.getBlock().getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlock().getBlockData()); - tb.revertBlock(); - } - - tblockTracker.clear(); - } - - public void removeFragments() { - for (Item i : thrownFragments) { - ParticleEffect.ITEM_CRACK.display(i.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, i.getItemStack()); - i.remove(); - } - thrownFragments.clear(); - } - - public static void remove(Player player, Block block) { - if (hasAbility(player, MetalFragments.class)) { - MetalFragments mf = getAbility(player, MetalFragments.class); - if (mf.sources.contains(block)) { - mf.remove(); - } - } - } - - @Override - public void remove() { - dropSources(); - removeFragments(); - removeDeadItems(); - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalFragments"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalFragments.Description"); - } - - public int getMaxSources() { - return maxSources; - } - - public void setMaxSources(int maxSources) { - this.maxSources = maxSources; - } - - public int getSelectRange() { - return selectRange; - } - - public void setSelectRange(int selectRange) { - this.selectRange = selectRange; - } - - public int getMaxFragments() { - return maxFragments; - } - - public void setMaxFragments(int maxFragments) { - this.maxFragments = maxFragments; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public List getSources() { - return sources; - } - - public void setSources(List sources) { - this.sources = sources; - } - - public List getThrownFragments() { - return thrownFragments; - } - - public List getTblockTracker() { - return tblockTracker; - } - - public HashMap getCounters() { - return counters; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MetalFragments.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java b/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java deleted file mode 100644 index 2ae0c7b..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java +++ /dev/null @@ -1,395 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class MetalHook extends MetalAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private int range; - @Attribute("MaxHooks") - private int maxHooks; - private int totalHooks; - private int hooksUsed; - private boolean noSource; - private boolean barrierHooking; - - private boolean hasHook; - private boolean wasSprinting; - private long time; - - private Location destination; - - private final ConcurrentHashMap hooks = new ConcurrentHashMap<>(); - private final List hookIds = new ArrayList<>(); - - public MetalHook(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { - return; - } - - if (hasAbility(player, MetalHook.class)) { - MetalHook mh = getAbility(player, MetalHook.class); - mh.launchHook(); - return; - } - - setFields(); - - if (!hasRequiredInv()) { - return; - } - - wasSprinting = player.isSprinting(); - flightHandler.createInstance(player, this.getName()); - player.setAllowFlight(true); - - start(); - launchHook(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.MetalHook.Cooldown"); - range = config.getInt("Abilities.Earth.MetalHook.Range"); - maxHooks = config.getInt("Abilities.Earth.MetalHook.MaxHooks"); - totalHooks = config.getInt("Abilities.Earth.MetalHook.TotalHooks"); - noSource = config.getBoolean("Abilities.Earth.MetalHook.RequireItem"); - barrierHooking = config.getBoolean("Abilities.Earth.MetalHook.BarrierHooking"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - removeAllArrows(); - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this) || hooks.isEmpty()) { - removeAllArrows(); - remove(); - return; - } - - if (!wasSprinting && player.isSprinting()) { - removeAllArrows(); - remove(); - return; - } - - wasSprinting = player.isSprinting(); - - if (player.isSneaking()) { - player.setVelocity(new Vector()); - - if (System.currentTimeMillis() > (time + 1000)) { - removeAllArrows(); - remove(); - return; - } - } else { - time = System.currentTimeMillis(); - } - - Vector target = new Vector(); - - for (Arrow a : hooks.keySet()) { - if (a != null) { - if (!isActiveArrow(a)) { - hooks.remove(a); - hookIds.remove(a.getUniqueId()); - a.remove(); - continue; - } - - if (a.getAttachedBlock() == null) { - hooks.replace(a, hooks.get(a), false); - } else { - hooks.replace(a, hooks.get(a), true); - hasHook = true; - } - - //Draws the particle lines. - for (Location location : JCMethods.getLinePoints(player.getLocation().add(0, 1, 0), a.getLocation(), ((int) player.getLocation().add(0,1,0).distance(a.getLocation()) * 2))) { - GeneralMethods.displayColoredParticle("#CCCCCC", location); - } - - if (hooks.get(a)) { - target.add(GeneralMethods.getDirection(player.getEyeLocation(), a.getLocation())); - } - } - } - - if (hasHook) { - destination = player.getLocation().clone().add(target); - - if (player.getLocation().distance(destination) > 2) { - player.setFlying(false); - double velocity = 0.8; - - GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); - } else if (player.getLocation().distance(destination) < 2 && player.getLocation().distance(destination) >= 1) { - player.setFlying(false); - double velocity = 0.35; - - GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); - } else { - GeneralMethods.setVelocity(this, player, new Vector(0, 0, 0)); - - if (player.getAllowFlight()) { - player.setFlying(true); - } - } - } - } - - private boolean isActiveArrow(Arrow arrow) { - if (arrow.isDead()) return false; - if (player.getWorld() != arrow.getWorld()) return false; - - Block attached = arrow.getAttachedBlock(); - - if (!barrierHooking && attached != null && attached.getType() == Material.BARRIER) return false; - - return player.getEyeLocation().distanceSquared(arrow.getLocation()) < range * range; - } - - @Override - public void remove() { - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - - flightHandler.removeInstance(player, this.getName()); - - super.remove(); - } - - public void launchHook() { - if (!hasRequiredInv()) return; - - Vector dir = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, range)); - - if (!hookIds.isEmpty() && hookIds.size() > (maxHooks - 1)) { - for (Arrow a : hooks.keySet()) { - if (a.getUniqueId().equals(hookIds.get(0))) { - hooks.remove(a); - hookIds.remove(0); - a.remove(); - break; - } - } - } - - if (totalHooks > 0 && hooksUsed++ > totalHooks) { - remove(); - return; - } - - Arrow a = player.getWorld().spawnArrow(player.getEyeLocation().add(player.getLocation().getDirection().multiply(2)), dir, 3, 0f); - a.setMetadata("metalhook", new FixedMetadataValue(JedCore.plugin, "1")); - - hooks.put(a, false); - hookIds.add(a.getUniqueId()); - } - - public void removeAllArrows() { - for (Arrow a : hooks.keySet()) { - a.remove(); - } - } - - public boolean hasRequiredInv() { - if (noSource) return true; - - if (player.getInventory().getChestplate() != null) { - Material[] chestplates = {Material.IRON_CHESTPLATE, Material.CHAINMAIL_CHESTPLATE}; - Material playerChest = player.getInventory().getChestplate().getType(); - - if (Arrays.asList(chestplates).contains(playerChest)) { - return true; - } - } - - Material[] metals = {Material.IRON_INGOT, Material.IRON_BLOCK}; - - for (ItemStack items : player.getInventory()) { - if (items != null && Arrays.asList(metals).contains(items.getType())) { - return true; - } - } - - return false; - } - - public int getMaxHooks() { - return this.maxHooks; - } - - public void setMaxHooks(int maxhooks) { - this.maxHooks = maxhooks; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalHook"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalHook.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public int getTotalHooks() { - return totalHooks; - } - - public void setTotalHooks(int totalHooks) { - this.totalHooks = totalHooks; - } - - public int getHooksUsed() { - return hooksUsed; - } - - public void setHooksUsed(int hooksUsed) { - this.hooksUsed = hooksUsed; - } - - public boolean isNoSource() { - return noSource; - } - - public void setNoSource(boolean noSource) { - this.noSource = noSource; - } - - public boolean isBarrierHooking() { - return barrierHooking; - } - - public void setBarrierHooking(boolean barrierHooking) { - this.barrierHooking = barrierHooking; - } - - public boolean isHasHook() { - return hasHook; - } - - public void setHasHook(boolean hasHook) { - this.hasHook = hasHook; - } - - public boolean isWasSprinting() { - return wasSprinting; - } - - public void setWasSprinting(boolean wasSprinting) { - this.wasSprinting = wasSprinting; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public Location getDestination() { - return destination; - } - - public void setDestination(Location destination) { - this.destination = destination; - } - - public ConcurrentHashMap getHooks() { - return hooks; - } - - public List getHookIds() { - return hookIds; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MetalHook.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java b/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java deleted file mode 100644 index 537c60f..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java +++ /dev/null @@ -1,482 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; - -public class MetalShred extends MetalAbility implements AddonAbility { - - @Attribute(Attribute.SELECT_RANGE) - private int selectRange; - private int extendTick; - @Attribute(Attribute.DAMAGE) - private double damage; - - private boolean horizontal = false; - private boolean started = false; - private boolean stop = false; - private boolean stopCoil = false; - private boolean extending = false; - private int length = 0; - private int fullLength = 0; - private long lastExtendTime; - private Block source; - private Block lastBlock; - private final List tblocks = new ArrayList<>(); - - public MetalShred(Player player) { - super(player); - - if (hasAbility(player, MetalShred.class)) { - getAbility(player, MetalShred.class).remove(); - } - - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - if (selectSource()) { - if (horizontal) { - raiseBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); - } else { - shiftBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); - } - - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - selectRange = config.getInt("Abilities.Earth.MetalShred.SourceRange"); - extendTick = config.getInt("Abilities.Earth.MetalShred.ExtendTick"); - damage = config.getDouble("Abilities.Earth.MetalShred.Damage"); - } - - public boolean selectSource() { - Block b = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); - - if (!isMetal(b)) - return false; - - source = b; - - if (ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType()) && !isMetal(source.getRelative(BlockFace.DOWN))) { - horizontal = true; - } - - return true; - } - - public void raiseBlock(Block b, Vector d) { - Block up = b.getRelative(BlockFace.UP); - Block away = b.getRelative(GeneralMethods.getCardinalDirection(d)); - Block awayup = away.getRelative(BlockFace.UP); - Block deeperb = b.getRelative(BlockFace.DOWN); - Block deepera = away.getRelative(BlockFace.DOWN); - - for (TempBlock tb : tblocks) { - if (!ElementalAbility.isAir(tb.getBlock().getType())) - tb.setType(Material.AIR); - } - - if (!up.getType().isSolid()) { - TempBlock tbu = new TempBlock(up, b.getBlockData()); - tblocks.add(tbu); - } - - if (!awayup.getType().isSolid()) { - TempBlock tbau = new TempBlock(awayup, away.getBlockData()); - tblocks.add(tbau); - } - - if (isMetal(b)) { - TempBlock tbd = new TempBlock(b, Material.AIR.createBlockData()); - tblocks.add(tbd); - } - - if (isMetal(away)) { - TempBlock tba = new TempBlock(away, Material.AIR.createBlockData()); - tblocks.add(tba); - } - - if (isMetal(deeperb)) { - TempBlock tbdb = new TempBlock(deeperb, Material.AIR.createBlockData()); - tblocks.add(tbdb); - } - - if (isMetal(deepera)) { - TempBlock tbda = new TempBlock(deepera, Material.AIR.createBlockData()); - tblocks.add(tbda); - } - - playMetalbendingSound(b.getLocation()); - } - - public void shiftBlock(Block b, Vector d) { - Block under = b.getRelative(BlockFace.DOWN); - Block side = b.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); - Block underside = under.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); - - for (TempBlock tb : tblocks) { - if (!ElementalAbility.isAir(tb.getBlock().getType())) - tb.setType(Material.AIR); - } - - if (!side.getType().isSolid()) { - TempBlock tbs = new TempBlock(side, b.getBlockData()); - tblocks.add(tbs); - } - - if (!underside.getType().isSolid()) { - TempBlock tbus = new TempBlock(underside, under.getBlockData()); - tblocks.add(tbus); - } - - if (isMetal(b)) { - TempBlock tb1 = new TempBlock(b, Material.AIR.createBlockData()); - tblocks.add(tb1); - } - - if (isMetal(under)) { - TempBlock tb2 = new TempBlock(under, Material.AIR.createBlockData()); - tblocks.add(tb2); - } - - playMetalbendingSound(b.getLocation()); - } - - private void peelCoil(Block b) { - Block under = b.getRelative(BlockFace.DOWN); - - if (length <= 0) - return; - - if (!b.getType().isSolid()) { - TempBlock tbb = new TempBlock(b, Material.IRON_BLOCK.createBlockData()); - tblocks.add(tbb); - } - - else - stopCoil = true; - - if (!under.getType().isSolid()) { - TempBlock tbu = new TempBlock(under, Material.IRON_BLOCK.createBlockData()); - tblocks.add(tbu); - } - - else - stopCoil = true; - - playMetalbendingSound(b.getLocation()); - - length--; - } - - public static void startShred(Player player) { - if (hasAbility(player, MetalShred.class)) { - getAbility(player, MetalShred.class).startShred(); - } - } - - private void startShred() { - started = true; - } - - public static void extend(Player player) { - if (hasAbility(player, MetalShred.class)) { - getAbility(player, MetalShred.class).extend(); - } - } - - private void extend() { - if (extending) { - extending = false; - return; - } - - if (!stop) - return; - - lastExtendTime = System.currentTimeMillis(); - fullLength = length; - if (lastBlock != null) - lastBlock = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(player.getLocation(), lastBlock.getLocation())).getOppositeFace()); - else { - return; - } - extending = true; - } - - @Override - public void progress() { - if (!player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - - if (!player.isSprinting()) { - if (started) - stop = true; - } - - if (!horizontal && stop && !stopCoil && extending && System.currentTimeMillis() > lastExtendTime + extendTick) { - lastExtendTime = System.currentTimeMillis(); - if (length > 0) { - - Block b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(lastBlock.getLocation(), GeneralMethods.getTargetedLocation(player, fullLength)))); - - peelCoil(b); - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(b.getLocation(), 2)) { - if (!(e instanceof LivingEntity) || e.getEntityId() == player.getEntityId()) { - continue; - } - if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))) { - continue; - } - DamageHandler.damageEntity(e, damage, this); - GeneralMethods.setVelocity(this, e, e.getVelocity().add(player.getLocation().getDirection().add(new Vector(0, 0.1, 0)))); - } - - lastBlock = b; - } - - return; - } - - if (stop || !started) - return; - - Block b; - - if (lastBlock != null) { - b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); - } - - else { - b = source.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); - } - - if (!isMetal(b)) { - if (!ElementalAbility.isAir(b.getType())) { - remove(); - } - return; - } - - if (b.getLocation().getX() == player.getLocation().getBlockX() || b.getLocation().getZ() == player.getLocation().getBlockZ()) { - if (horizontal) - raiseBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); - else - shiftBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); - - length++; - lastBlock = b; - } - } - - private void revertAll() { - for (TempBlock tb : tblocks) { - tb.revertBlock(); - } - } - - @Override - public void remove() { - revertAll(); - super.remove(); - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalShred"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalShred.Description"); - } - - public int getSelectRange() { - return selectRange; - } - - public void setSelectRange(int selectRange) { - this.selectRange = selectRange; - } - - public int getExtendTick() { - return extendTick; - } - - public void setExtendTick(int extendTick) { - this.extendTick = extendTick; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean isHorizontal() { - return horizontal; - } - - public void setHorizontal(boolean horizontal) { - this.horizontal = horizontal; - } - - @Override - public boolean isStarted() { - return started; - } - - public void setStarted(boolean started) { - this.started = started; - } - - public boolean isStop() { - return stop; - } - - public void setStop(boolean stop) { - this.stop = stop; - } - - public boolean isStopCoil() { - return stopCoil; - } - - public void setStopCoil(boolean stopCoil) { - this.stopCoil = stopCoil; - } - - public boolean isExtending() { - return extending; - } - - public void setExtending(boolean extending) { - this.extending = extending; - } - - public int getLength() { - return length; - } - - public void setLength(int length) { - this.length = length; - } - - public int getFullLength() { - return fullLength; - } - - public void setFullLength(int fullLength) { - this.fullLength = fullLength; - } - - public long getLastExtendTime() { - return lastExtendTime; - } - - public void setLastExtendTime(long lastExtendTime) { - this.lastExtendTime = lastExtendTime; - } - - public Block getSource() { - return source; - } - - public void setSource(Block source) { - this.source = source; - } - - public Block getLastBlock() { - return lastBlock; - } - - public void setLastBlock(Block lastBlock) { - this.lastBlock = lastBlock; - } - - public List getTblocks() { - return tblocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MetalShred.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java deleted file mode 100644 index bd62b95..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java +++ /dev/null @@ -1,665 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionUtil; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; -import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; -import com.jedk1.jedcore.policies.removal.OutOfRangeRemovalPolicy; -import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.ListIterator; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; - -public class MudSurge extends EarthAbility implements AddonAbility { - private int prepareRange; - private int blindChance; - private int blindTicks; - private boolean multipleHits; - @Attribute(Attribute.DAMAGE) - private double damage; - private int waves; - private int waterSearchRadius; - private boolean wetSource; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("CollisionRadius") - private double collisionRadius; - - public static int surgeInterval = 300; - public static int mudPoolRadius = 2; - public static Set mudTypes = new HashSet<>(); - - static { - mudTypes.addAll(Arrays.asList(Material.SAND, Material.RED_SAND, Material.CLAY, Material.TERRACOTTA, Material.BLACK_TERRACOTTA, Material.BLUE_TERRACOTTA, - Material.BROWN_TERRACOTTA, Material.CYAN_TERRACOTTA, Material.GRAY_TERRACOTTA, Material.GREEN_TERRACOTTA, - Material.LIGHT_BLUE_TERRACOTTA, Material.LIGHT_GRAY_TERRACOTTA, Material.LIME_TERRACOTTA, - Material.MAGENTA_TERRACOTTA, Material.ORANGE_TERRACOTTA, Material.PINK_TERRACOTTA, - Material.PURPLE_TERRACOTTA, Material.RED_TERRACOTTA, Material.WHITE_TERRACOTTA, Material.YELLOW_TERRACOTTA, - Material.GRASS_BLOCK, Material.DIRT, Material.MYCELIUM, Material.COARSE_DIRT, - Material.SOUL_SAND, Material.SOUL_SOIL, Material.RED_SANDSTONE, Material.SANDSTONE, Material.CHISELED_SANDSTONE, - Material.CHISELED_RED_SANDSTONE, Material.SMOOTH_SANDSTONE, Material.SMOOTH_RED_SANDSTONE, Material.CUT_SANDSTONE, - Material.CUT_RED_SANDSTONE)); - if (GeneralMethods.getMCVersion() >= 1170) { - mudTypes.add(Material.getMaterial("ROOTED_DIRT")); - } - if (GeneralMethods.getMCVersion() >= 1190) { - mudTypes.add(Material.getMaterial("MUD")); - mudTypes.add(Material.getMaterial("MUDDY_MANGROVE_ROOTS")); - mudTypes.add(Material.getMaterial("PACKED_MUD")); - } - } - - private CompositeRemovalPolicy removalPolicy; - - private Block source; - - private int wavesOnTheRun = 0; - private boolean mudFormed = false; - private boolean doNotSurge = false; - public boolean started = false; - - private final List mudArea = new ArrayList<>(); - private ListIterator mudAreaItr; - private final List mudBlocks = new ArrayList<>(); - private final List blind = new ArrayList<>(); - private final List affectedEntities = new ArrayList<>(); - - private final List fallingBlocks = new ArrayList<>(); - - private final Random rand = new Random(); - - public MudSurge(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, MudSurge.class)) { - MudSurge ms = getAbility(player, MudSurge.class); - if (!ms.hasStarted()) { - ms.remove(); - } else { - return; - } - } - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new OutOfRangeRemovalPolicy(this.player, 25.0, () -> this.source.getLocation()), - new SwappedSlotsRemovalPolicy<>(bPlayer, MudSurge.class) - ); - - setFields(); - - if (getSource()) { - start(); - if (!isRemoved()) { - loadMudPool(); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - this.removalPolicy.load(config); - - prepareRange = config.getInt("Abilities.Earth.MudSurge.SourceRange"); - blindChance = config.getInt("Abilities.Earth.MudSurge.BlindChance"); - damage = config.getDouble("Abilities.Earth.MudSurge.Damage"); - waves = config.getInt("Abilities.Earth.MudSurge.Waves"); - waterSearchRadius = config.getInt("Abilities.Earth.MudSurge.WaterSearchRadius"); - wetSource = config.getBoolean("Abilities.Earth.MudSurge.WetSourceOnly"); - cooldown = config.getLong("Abilities.Earth.MudSurge.Cooldown"); - blindTicks = config.getInt("Abilities.Earth.MudSurge.BlindTicks"); - multipleHits = config.getBoolean("Abilities.Earth.MudSurge.MultipleHits"); - collisionRadius = config.getDouble("Abilities.Earth.MudSurge.CollisionRadius"); - } - - @Override - public void progress() { - if (removalPolicy.shouldRemove()) { - remove(); - return; - } - - long lastSurgeTime = 0; - if (mudFormed && started && System.currentTimeMillis() > lastSurgeTime + surgeInterval) { - surge(); - affect(); - if (TempFallingBlock.getFromAbility(this).isEmpty()) { - remove(); - return; - } - return; - } - - if (!mudFormed) { - createMudPool(); - } - } - - private boolean getSource() { - Block block = getMudSourceBlock(prepareRange); - - if (block != null) { - if (isMudBlock(block)) { - boolean water = true; - - if (wetSource) { - water = false; - List nearby = GeneralMethods.getBlocksAroundPoint(block.getLocation(), waterSearchRadius); - - for (Block b : nearby) { - if (b.getType() == Material.WATER) { - water = true; - break; - } - } - } - - if (water) { - this.source = block; - return true; - } - } - } - - return false; - } - - private void startSurge() { - started = true; - this.bPlayer.addCooldown(this); - - // Clear out the policies that only apply while sourcing. - this.removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); - this.removalPolicy.removePolicyType(OutOfRangeRemovalPolicy.class); - this.removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); - } - - private boolean hasStarted() { - return this.started; - } - - public static boolean isSurgeBlock(Block block) { - if (block.getType() != Material.BROWN_TERRACOTTA) { - return false; - } - - for (MudSurge surge : CoreAbility.getAbilities(MudSurge.class)) { - if (surge.mudArea.contains(block)) { - return true; - } - } - - return false; - } - - // Returns true if the event should be cancelled. - public static boolean onFallDamage(Player player) { - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null || !bPlayer.hasElement(Element.EARTH)) { - return false; - } - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - boolean fallDamage = config.getBoolean("Abilities.Earth.MudSurge.AllowFallDamage"); - if (fallDamage) { - return false; - } - - Block block = player.getLocation().clone().subtract(0, 0.1, 0).getBlock(); - return isSurgeBlock(block); - } - - public static void mudSurge(Player player) { - if (!hasAbility(player, MudSurge.class)) - return; - - getAbility(player, MudSurge.class).startSurge(); - } - - private Block getMudSourceBlock(int range) { - Block testBlock = GeneralMethods.getTargetedLocation(player, range, ElementalAbility.getTransparentMaterials()).getBlock(); - if (isMudBlock(testBlock)) - return testBlock; - - Location loc = player.getEyeLocation(); - Vector dir = player.getEyeLocation().getDirection().clone().normalize(); - - for (int i = 0; i <= range; i++) { - Block block = loc.clone().add(dir.clone().multiply(i == 0 ? 1 : i)).getBlock(); - if (RegionProtection.isRegionProtected(player, block.getLocation(), this)) - continue; - - if (isMudBlock(block)) - return block; - } - - return null; - } - - private boolean isMudBlock(Block block) { - for (Material mat : mudTypes) { - if (mat.name().equalsIgnoreCase(block.getType().name())) - return true; - } - - return false; - } - - private void createMud(Block block) { - mudBlocks.add(new TempBlock(block, Material.BROWN_TERRACOTTA.createBlockData())); - } - - private void loadMudPool() { - List area = GeneralMethods.getCircle(source.getLocation(), mudPoolRadius, 3, false, true, 0); - - for (Location l : area) { - Block b = l.getBlock(); - - if (isMudBlock(b)) { - if (isTransparent(b.getRelative(BlockFace.UP))) { - boolean water = true; - - if (wetSource) { - water = false; - List nearby = GeneralMethods.getBlocksAroundPoint(l, waterSearchRadius); - - for (Block block : nearby) { - if (block.getType() == Material.WATER) { - water = true; - break; - } - } - } - - if (water) { - mudArea.add(b); - playEarthbendingSound(b.getLocation()); - } - } - } - } - - Collections.shuffle(mudArea); - mudAreaItr = mudArea.listIterator(); - } - - private void createMudPool() { - if (!mudAreaItr.hasNext()) { - mudFormed = true; - return; - } - - Block b = mudAreaItr.next(); - - if (b != null) - createMud(b); - } - - private void revertMudPool() { - for (TempBlock tb : mudBlocks) - tb.revertBlock(); - - mudBlocks.clear(); - } - - private void surge() { - if (wavesOnTheRun >= waves) { - doNotSurge = true; - return; - } - - if (doNotSurge) - return; - - for (TempBlock tb : mudBlocks) { - Vector direction = GeneralMethods.getDirection(tb.getLocation().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, 30)).multiply(0.07); - - double x = rand.nextDouble() / 5; - double z = rand.nextDouble() / 5; - - x = (rand.nextBoolean()) ? -x : x; - z = (rand.nextBoolean()) ? -z : z; - - fallingBlocks.add(new TempFallingBlock(tb.getLocation().add(0.5, 1, 0.5), Material.BROWN_TERRACOTTA.createBlockData(), direction.clone().add(new Vector(x, 0.2, z)), this)); - - playEarthbendingSound(tb.getLocation()); - } - - wavesOnTheRun++; - } - - private void affect() { - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fb = tfb.getFallingBlock(); - if (fb.isDead()) { - tfb.remove(); - continue; - } - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(fb.getLocation(), 1.5)) { - if (fb.isDead()) { - tfb.remove(); - continue; - } - if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))){ - continue; - } - - if (e instanceof LivingEntity) { - if (this.multipleHits || !this.affectedEntities.contains(e)) { - DamageHandler.damageEntity(e, damage, this); - if (!this.multipleHits) { - this.affectedEntities.add(e); - } - } - - if (e instanceof Player) { - if (e.getEntityId() == player.getEntityId()) - continue; - - if (rand.nextInt(100) < blindChance && !blind.contains(e)) { - ((Player) e).addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, this.blindTicks, 2)); - } - - blind.add((Player) e); - } - - e.setVelocity(fb.getVelocity().multiply(0.8)); - tfb.remove(); - } - } - } - } - - @Override - public void remove() { - revertMudPool(); - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); - } - - @Override - public void handleCollision(Collision collision) { - CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); - } - - @Override - public double getCollisionRadius() { - return collisionRadius; - } - - @Override - public String getName() { - return "MudSurge"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MudSurge.Description"); - } - - public int getPrepareRange() { - return prepareRange; - } - - public void setPrepareRange(int prepareRange) { - this.prepareRange = prepareRange; - } - - public int getBlindChance() { - return blindChance; - } - - public void setBlindChance(int blindChance) { - this.blindChance = blindChance; - } - - public int getBlindTicks() { - return blindTicks; - } - - public void setBlindTicks(int blindTicks) { - this.blindTicks = blindTicks; - } - - public boolean isMultipleHits() { - return multipleHits; - } - - public void setMultipleHits(boolean multipleHits) { - this.multipleHits = multipleHits; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getWaves() { - return waves; - } - - public void setWaves(int waves) { - this.waves = waves; - } - - public int getWaterSearchRadius() { - return waterSearchRadius; - } - - public void setWaterSearchRadius(int waterSearchRadius) { - this.waterSearchRadius = waterSearchRadius; - } - - public boolean isWetSource() { - return wetSource; - } - - public void setWetSource(boolean wetSource) { - this.wetSource = wetSource; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public void setCollisionRadius(double collisionRadius) { - this.collisionRadius = collisionRadius; - } - - public static int getSurgeInterval() { - return surgeInterval; - } - - public static void setSurgeInterval(int surgeInterval) { - MudSurge.surgeInterval = surgeInterval; - } - - public static int getMudPoolRadius() { - return mudPoolRadius; - } - - public static void setMudPoolRadius(int mudPoolRadius) { - MudSurge.mudPoolRadius = mudPoolRadius; - } - - public static Material[] getMudTypes() { - return mudTypes.toArray(new Material[0]); - } - - public static Set getMudTypesSet() { - return mudTypes; - } - - public static void setMudTypes(Material[] mudTypes) { - MudSurge.mudTypes.clear(); - MudSurge.mudTypes.addAll(Arrays.asList(mudTypes)); - } - - public CompositeRemovalPolicy getRemovalPolicy() { - return removalPolicy; - } - - public void setRemovalPolicy(CompositeRemovalPolicy removalPolicy) { - this.removalPolicy = removalPolicy; - } - - public void setSource(Block source) { - this.source = source; - } - - public int getWavesOnTheRun() { - return wavesOnTheRun; - } - - public void setWavesOnTheRun(int wavesOnTheRun) { - this.wavesOnTheRun = wavesOnTheRun; - } - - public boolean isMudFormed() { - return mudFormed; - } - - public void setMudFormed(boolean mudFormed) { - this.mudFormed = mudFormed; - } - - public boolean isDoNotSurge() { - return doNotSurge; - } - - public void setDoNotSurge(boolean doNotSurge) { - this.doNotSurge = doNotSurge; - } - - @Override - public boolean isStarted() { - return started; - } - - public void setStarted(boolean started) { - this.started = started; - } - - public List getMudArea() { - return mudArea; - } - - public ListIterator getMudAreaItr() { - return mudAreaItr; - } - - public void setMudAreaItr(ListIterator mudAreaItr) { - this.mudAreaItr = mudAreaItr; - } - - public List getMudBlocks() { - return mudBlocks; - } - - public List getBlind() { - return blind; - } - - public List getAffectedEntities() { - return affectedEntities; - } - - public List getFallingBlocks() { - return fallingBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MudSurge.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java b/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java deleted file mode 100644 index aba3421..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java +++ /dev/null @@ -1,376 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.SandAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import java.util.stream.Collectors; - -public class SandBlast extends SandAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.SELECT_RANGE) - private double sourceRange; - @Attribute(Attribute.RANGE) - private int range; - @Attribute("MaxShots") - private int maxBlasts; - @Attribute(Attribute.DAMAGE) - private static double damage; - - private Block source; - private BlockData sourceData; - private int blasts; - private boolean blasting; - private Vector direction; - private TempBlock tempBlock; - private final List affectedEntities = new ArrayList<>(); - private final List fallingBlocks = new ArrayList<>(); - - Random rand = new Random(); - - public SandBlast(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, SandBlast.class)) { - SandBlast sb = getAbility(player, SandBlast.class); - sb.remove(); - } - - setFields(); - if (prepare()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.SandBlast.Cooldown"); - sourceRange = config.getDouble("Abilities.Earth.SandBlast.SourceRange"); - range = config.getInt("Abilities.Earth.SandBlast.Range"); - maxBlasts = config.getInt("Abilities.Earth.SandBlast.MaxSandBlocks"); - damage = config.getDouble("Abilities.Earth.SandBlast.Damage"); - } - - private boolean prepare() { - source = getEarthSourceBlock(sourceRange); - - if (source != null) { - if (isSand(source) && ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType())) { - this.sourceData = source.getBlockData().clone(); - if (DensityShift.isPassiveSand(source)) { - DensityShift.revertSand(source); - } - tempBlock = new TempBlock(source, Material.SANDSTONE.createBlockData()); - return true; - } - } - return false; - } - - @Override - public void progress() { - if (!hasAbility(player, SandBlast.class)) { - return; - } - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (player.getWorld() != source.getWorld()) { - remove(); - return; - } - if (blasting) { - if (blasts <= maxBlasts) { - blastSand(); - blasts++; - } else { - if (TempFallingBlock.getFromAbility(this).isEmpty()) { - remove(); - return; - } - } - affect(); - } - } - - @Override - public void remove() { - if (this.tempBlock != null) { - this.tempBlock.revertBlock(); - } - super.remove(); - } - - public static void blastSand(Player player) { - if (hasAbility(player, SandBlast.class)) { - SandBlast sb = getAbility(player, SandBlast.class); - if (sb.blasting) { - return; - } - sb.blastSand(); - } - } - - private void blastSand() { - if (!blasting) { - blasting = true; - direction = GeneralMethods.getDirection(source.getLocation().clone().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, range)).multiply(0.07); - this.bPlayer.addCooldown(this); - } - tempBlock.revertBlock(); - - //FallingBlock fblock = source.getWorld().spawnFallingBlock(source.getLocation().clone().add(0, 1, 0), source.getType(), source.getData()); - - if (rand.nextInt(2) == 0) { - DensityShift.playSandbendingSound(source.getLocation().add(0, 1, 0)); - } - - double x = rand.nextDouble() / 10; - double z = rand.nextDouble() / 10; - - x = (rand.nextBoolean()) ? -x : x; - z = (rand.nextBoolean()) ? -z : z; - - //fblock.setVelocity(direction.clone().add(new Vector(x, 0.2, z))); - //fblock.setDropItem(false); - //fblocks.put(fblock, player); - - fallingBlocks.add(new TempFallingBlock(source.getLocation().add(0, 1, 0), sourceData, direction.clone().add(new Vector(x, 0.2, z)), this)); - - } - - public void affect() { - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fblock = tfb.getFallingBlock(); - if (fblock.isDead()) { - tfb.remove(); - continue; - } - - if (RegionProtection.isRegionProtected(player, fblock.getLocation(), this)) { - tfb.remove(); - continue; - } - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(fblock.getLocation(), 1.5)) { - if (entity instanceof LivingEntity && !(entity instanceof ArmorStand)) { - if (entity == this.player) continue; - if (affectedEntities.contains(entity)) continue; - - if (!entity.isDead()) { - DamageHandler.damageEntity(entity, damage, this); - - affectedEntities.add(entity); - - LivingEntity le = (LivingEntity) entity; - if (le.hasPotionEffect(PotionEffectType.BLINDNESS)) { - le.removePotionEffect(PotionEffectType.BLINDNESS); - } - - le.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 60, 1)); - } - } - } - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - Location location = collision.getLocationFirst(); - - Optional collidedObject = fallingBlocks.stream().filter(temp -> temp.getLocation().equals(location)).findAny(); - - if (collidedObject.isPresent()) { - fallingBlocks.remove(collidedObject.get()); - collidedObject.get().remove(); - } - } - } - - @Override - public String getName() { - return "SandBlast"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.SandBlast.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public double getSourceRange() { - return sourceRange; - } - - public void setSourceRange(double sourceRange) { - this.sourceRange = sourceRange; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public int getMaxBlasts() { - return maxBlasts; - } - - public void setMaxBlasts(int maxBlasts) { - this.maxBlasts = maxBlasts; - } - - public static double getDamage() { - return damage; - } - - public static void setDamage(double damage) { - SandBlast.damage = damage; - } - - public Block getSource() { - return source; - } - - public void setSource(Block source) { - this.source = source; - } - - public BlockData getSourceData() { - return sourceData; - } - - public void setSourceData(BlockData sourceData) { - this.sourceData = sourceData; - } - - public int getBlasts() { - return blasts; - } - - public void setBlasts(int blasts) { - this.blasts = blasts; - } - - public boolean isBlasting() { - return blasting; - } - - public void setBlasting(boolean blasting) { - this.blasting = blasting; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public TempBlock getTempBlock() { - return tempBlock; - } - - public void setTempBlock(TempBlock tempBlock) { - this.tempBlock = tempBlock; - } - - public List getAffectedEntities() { - return affectedEntities; - } - - public List getFallingBlocks() { - return fallingBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.SandBlast.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java b/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java deleted file mode 100644 index bbe292e..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java +++ /dev/null @@ -1,375 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending.combo; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -public class Crevice extends EarthAbility implements AddonAbility, ComboAbility { - private final List> columns = new ArrayList<>(); - - private Location origin; - private Location location; - private Vector direction; - private double travelled; - private boolean skip; - private int avatarDepth; - private long regenDelay; - - @Attribute(Attribute.RANGE) - private double range; - @Attribute("Depth") - private int randomDepth; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - public Crevice(Player player) { - super(player); - - if (!bPlayer.canBendIgnoreBinds(this)) { - return; - } - - setFields(); - - createInstance(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - range = config.getDouble("Abilities.Earth.EarthCombo.Crevice.Range"); - regenDelay = config.getLong("Abilities.Earth.EarthCombo.Crevice.RevertDelay"); - randomDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.Depth"); - avatarDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth"); - cooldown = config.getLong("Abilities.Earth.EarthCombo.Crevice.Cooldown"); - } - - private void createInstance() { - origin = player.getTargetBlock(null, 6).getLocation(); - - if (isEarthbendable(origin.getBlock())) { - Location tempLoc = player.getLocation().clone(); - tempLoc.setPitch(0); - - direction = tempLoc.getDirection().clone(); - origin.setDirection(tempLoc.getDirection()); // todo - location = origin.clone(); - - if (bPlayer.isAvatarState()) { - randomDepth = avatarDepth; - } - - start(); - - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - prepareRevert(); - remove(); - return; - } - - if (travelled >= range || skip) { - if (System.currentTimeMillis() > getStartTime() + regenDelay) { - prepareRevert(); - remove(); - return; - } - return; - } - - advanceCrevice(); - } - - @Override - public void remove() { - prepareRevert(); - super.remove(); - } - - public static void closeCrevice(Player player) { - Block target = player.getTargetBlock(null, 10); - - for (Block near : GeneralMethods.getBlocksAroundPoint(target.getLocation(), 2)) { - for (Crevice c : getAbilities(Crevice.class)) { - for (List tbs : c.columns) { - for (TempBlock tb : tbs) { - if (near.getLocation().equals(tb.getLocation())) { - c.prepareRevert(); - c.remove(); - return; - } - } - } - } - } - } - - private void advanceCrevice() { - switch (ThreadLocalRandom.current().nextInt(2)) { - case 0: - if (location.getYaw() <= origin.getYaw()) { - location.setYaw(location.getYaw() + 40); - direction = location.getDirection().clone(); - } - break; - case 1: - if (location.getYaw() >= origin.getYaw()) { - location.setYaw(location.getYaw() - 40); - direction = location.getDirection().clone(); - } - break; - default: - direction = location.getDirection().clone(); - break; - } - - Location tempLoc = location.clone(); - location = location.add(direction.multiply(1)); - playEarthbendingSound(tempLoc); - location.getWorld().playSound(location, Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, (float) 0.5, (float) 0.5); - if (skip) { - return; - } - - travelled++; - if (travelled >= range) - return; - - if (RegionProtection.isRegionProtected(player, location, "RaiseEarth")) { - return; - } - - if (!isTransparent(location.getBlock().getRelative(BlockFace.UP))) { - location.add(0, 1, 0); - if (!isTransparent(location.getBlock().getRelative(BlockFace.UP)) || !isEarthbendable(location.getBlock())) { - skip = true; - return; - } - } else if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { - location.subtract(0, 1, 0); - if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { - skip = true; - return; - } - } - - removePillar(tempLoc, randInt(randomDepth + 1 - 2, randomDepth + 1 + 2)); - removePillar(GeneralMethods.getRightSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); - removePillar(GeneralMethods.getLeftSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); - } - - private int randInt(int min, int max) { - return ThreadLocalRandom.current().nextInt(max - min) + min; // todo: look into the necessity of this helper - } - - private void removePillar(Location location, int depth) { - List blocks = new ArrayList<>(); - Location tempLoc = location.clone().getBlock().getLocation(); - tempLoc.add(0, 1, 0); - for (int i = 0; i < depth + 1; i++) { - if (tempLoc.getY() < Objects.requireNonNull(tempLoc.getWorld()).getMinHeight() || tempLoc.getY() > tempLoc.getWorld().getMaxHeight()) { - break; - } - if (RegionProtection.isRegionProtected(player, tempLoc, this)) { - continue; - } - if (i == 0 && !isTransparent(tempLoc.getBlock())) { - continue; - } - if (i > 0 && !isEarthbendable(tempLoc.getBlock())) { - continue; - } - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tempLoc, 1)) { - entity.setVelocity(new Vector(0, -0.75, 0)); - } - - - blocks.add(new TempBlock(tempLoc.getBlock(), Material.AIR.createBlockData())); - tempLoc.subtract(0, 1, 0); - } - - Collections.reverse(blocks); - - columns.add(blocks); - } - - private void prepareRevert() { - for (int i = 0; i < columns.size(); ++i) { - List tbs = columns.get(i); - for (TempBlock tb : tbs) { - tb.revertBlock(); - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 1)) { - entity.setVelocity(new Vector(0, 0.7, 0)); - } - new RegenTempBlock(tb.getBlock(), Material.AIR, Material.AIR.createBlockData(), i * 50L); - } - } - columns.clear(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "Crevice"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public Object createNewComboInstance(Player player) { - return new Crevice(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.Crevice.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.Crevice.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.Crevice.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public long getRegenDelay() { - return regenDelay; - } - - public void setRegenDelay(long regenDelay) { - this.regenDelay = regenDelay; - } - - public int getDepth() { - return randomDepth; - } - - public void setDepth(int depth) { - this.randomDepth = depth; - } - - public int getAvatarDepth() { - return avatarDepth; - } - - public void setAvatarDepth(int avatarDepth) { - this.avatarDepth = avatarDepth; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getDistanceTravelled() { - return travelled; - } - - public void setDistanceTravelled(double travelled) { - this.travelled = travelled; - } - - public List> getColumns() { - return columns; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthCombo.Crevice.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java b/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java deleted file mode 100644 index 7011750..0000000 --- a/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java +++ /dev/null @@ -1,621 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending.combo; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.MaterialUtil; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Collectors; - -public class MagmaBlast extends LavaAbility implements AddonAbility, ComboAbility { - private static final int PARTICLE_COUNT = 20; - private static final int RAISE_HEIGHT = 3; - - private final Set sources = new HashSet<>(); - private final List blocks = new ArrayList<>(); - private final List firedBlocks = new ArrayList<>(); - - private double fireSpeed; - // How far away the player is allowed to be from the sources before the ability is destroyed. - private double maxDistanceFromSources; - private float explosionRadius = 2.0f; - // This will destroy the instance if LavaFlow is on cooldown. - private boolean requireLavaFlow; - private boolean playerCollisions; - private boolean entitySelection; - private Location origin; - private int counter; - private long canLavaFlowTime; - private long lastShot; - private boolean stopFiring; - private long shotCooldown; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long maxDuration; - @Attribute("MaxSources") - private int maxSources; - @Attribute(Attribute.SELECT_RANGE) - private int sourceRange; - @Attribute(Attribute.SELECT_RANGE) - private double selectRange; - @Attribute(Attribute.DAMAGE) - private double damage; - - public MagmaBlast(Player player) { - super(player); - setFields(); - - if (!bPlayer.canBendIgnoreBinds(this)) { - return; - } - - origin = player.getLocation().clone(); - - if (raiseSources()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - maxSources = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots"); - sourceRange = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange"); - damage = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage"); - cooldown = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown"); - requireLavaFlow = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow"); - playerCollisions = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions"); - entitySelection = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection"); - selectRange = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange"); - explosionRadius = (float) config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius"); - fireSpeed = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed"); - maxDuration = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration"); - maxDistanceFromSources = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources"); - shotCooldown = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown"); - } - - // Select random nearby earth blocks as sources and raise them in the air. - private boolean raiseSources() { - List potentialBlocks = GeneralMethods.getBlocksAroundPoint(origin, sourceRange).stream().filter(ElementalAbility::isEarth).collect(Collectors.toList()); - - Collections.shuffle(potentialBlocks); - - for (Block newSource : potentialBlocks) { - if (!isValidSource(newSource)) continue; - - newSource.getWorld().playSound(newSource.getLocation(), Sound.ENTITY_GHAST_SHOOT, 0.8f, 0.3f); - sources.add(new TempFallingBlock(newSource.getLocation().add(0, 1, 0), Material.MAGMA_BLOCK.createBlockData(), new Vector(0, 0.9, 0), this)); - - if (sources.size() >= maxSources) { - break; - } - } - - return !sources.isEmpty(); - } - - // Checks to make sure the source block has room to fly upwards. - private boolean isValidSource(Block block) { - for (int i = 0; i <= RAISE_HEIGHT; ++i) { - if (!MaterialUtil.isTransparent(block.getRelative(BlockFace.UP, i + 1)) || block.isLiquid()) { - return false; - } - } - - return true; - } - - public boolean shouldBlockLavaFlow() { - long time = System.currentTimeMillis(); - return time < canLavaFlowTime; - } - - @Override - public void progress() { - stopFiring = false; - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (System.currentTimeMillis() > this.getStartTime() + maxDuration) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBinds(this) || !(bPlayer.getBoundAbility() instanceof LavaFlow)) { - remove(); - return; - } - - if (requireLavaFlow && !bPlayer.canBend(getAbility("LavaFlow"))) { - remove(); - return; - } - - displayAnimation(); - handleSources(); - - if (playerCollisions) { - doPlayerCollisions(); - } - - if (sources.isEmpty() && firedBlocks.isEmpty() && blocks.isEmpty()) { - remove(); - return; - } - - if (hasBlocks() && this.player.getLocation().distanceSquared(origin) > maxDistanceFromSources * maxDistanceFromSources) { - remove(); - } - } - - @Override - public void remove() { - bPlayer.addCooldown(this); - super.remove(); - - for (TempFallingBlock ftb : sources) { - ftb.remove(); - } - - for (TempBlock tb : blocks) { - tb.revertBlock(); - } - - for (TempFallingBlock tfb : firedBlocks) { - tfb.remove(); - } - } - - private void handleSources() { - if (sources.isEmpty()) return; - - for (Iterator iter = sources.iterator(); iter.hasNext();) { - TempFallingBlock tfb = iter.next(); - - if (tfb.getLocation().getBlockY() >= (origin.getBlockY() + RAISE_HEIGHT)) { - blocks.add(new TempBlock(tfb.getLocation().getBlock(), Material.MAGMA_BLOCK.createBlockData())); - iter.remove(); - tfb.remove(); - } - } - } - - private void displayAnimation() { - if (++counter == 3) { - counter = 0; - } else { - return; - } - - for (Iterator iterator = firedBlocks.iterator(); iterator.hasNext();) { - TempFallingBlock tfb = iterator.next(); - - if (!tfb.getFallingBlock().isDead()) { - playParticles(tfb.getLocation()); - } else { - tfb.remove(); - iterator.remove(); - } - } - - for (TempBlock tb : blocks) playParticles(tb.getLocation()); - } - - private void doPlayerCollisions() { - List blocksCopy = new ArrayList<>(firedBlocks); - - for (TempFallingBlock tfb : blocksCopy) { - if (!firedBlocks.contains(tfb)) continue; - - boolean didExplode = false; - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), this.explosionRadius)) { - if (!(e instanceof LivingEntity)) continue; - if (e == this.player) continue; - - if (blast(tfb, true)) { - didExplode = true; - } - } - - if (didExplode) { - firedBlocks.remove(tfb); - } - } - } - - private void playParticles(Location location) { - location.add(.5,.5,.5); - - ParticleEffect.LAVA.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); - ParticleEffect.SMOKE_NORMAL.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); - - for (int i = 0; i < 10; i++) { - GeneralMethods.displayColoredParticle("FFA400", getOffsetLocation(location, 2)); - GeneralMethods.displayColoredParticle("FF8C00", getOffsetLocation(location, 2)); - } - } - - // Returns true if any source blocks still exist. Returns false is all of the source blocks have been fired. - public boolean hasBlocks() { - return !sources.isEmpty() || !blocks.isEmpty(); - } - - private Location getOffsetLocation(Location loc, double offset) { - return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); - } - - public static void performAction(Player player) { - MagmaBlast mb = getAbility(player, MagmaBlast.class); - - if (mb != null) { - mb.performAction(); - } - } - - private void performAction() { - long time = System.currentTimeMillis(); - - if (blocks.isEmpty() || stopFiring || time < lastShot + shotCooldown) return; - - Location target = null; - - if (entitySelection) { - Entity targetEntity = GeneralMethods.getTargetedEntity(player, selectRange); - - if (targetEntity instanceof LivingEntity) { - target = ((LivingEntity) targetEntity).getEyeLocation(); - } - } - - if (target == null) { - target = GeneralMethods.getTargetedLocation(player, selectRange, Material.MAGMA_BLOCK); - } - - TempBlock tb = getClosestSource(target); - - if (tb == null) return; - - stopFiring = true; - canLavaFlowTime = time + 1000; - blocks.remove(tb); - - Vector direction = GeneralMethods.getDirection(tb.getLocation().clone().add(0.5f, 0.5f, 0.5f), target).normalize(); - - tb.revertBlock(); - - FallingBlock fallingBlock = tb.getLocation().getWorld().spawnFallingBlock( - tb.getLocation().clone().add(0.5, 0.5, 0.5), - Material.MAGMA_BLOCK.createBlockData() - ); - - fallingBlock.setTicksLived(Integer.MAX_VALUE); - fallingBlock.setMetadata("magmablast", new FixedMetadataValue(JedCore.plugin, "1")); - fallingBlock.setDropItem(false); - fallingBlock.setCancelDrop(true); - - TempFallingBlock tfb = new TempFallingBlock(tb.getLocation(), Material.MAGMA_BLOCK.createBlockData(), direction.multiply(fireSpeed), this, true); - firedBlocks.add(tfb); - - lastShot = time; - } - - // Get the closest fireable source block to the target location. - private TempBlock getClosestSource(Location target) { - double distanceSq = Double.MAX_VALUE; - TempBlock closest = null; - - for (TempBlock tempBlock : blocks) { - double currentDistSq = tempBlock.getLocation().distanceSquared(target); - - if (currentDistSq < distanceSq) { - distanceSq = currentDistSq; - closest = tempBlock; - } - } - - return closest; - } - - public static void blast(TempFallingBlock tfb) { - blast(tfb, false); - } - - public static boolean blast(TempFallingBlock tfb, boolean entityCollision) { - MagmaBlast mb = (MagmaBlast) tfb.getAbility(); - Location location = tfb.getLocation().clone().add(0.5, 0.5, 0.5); - - Block hitBlock = location.getBlock(); - if (hitBlock.getType().isSolid()) { - blastEffects(location, mb); - tfb.remove(); - mb.firedBlocks.remove(tfb); - return true; - } - - float radius = mb.explosionRadius; - boolean didHit = false; - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, radius)) { - if (!(entity instanceof LivingEntity)) continue; - if (entity == mb.player) continue; - - DamageHandler.damageEntity(entity, mb.getDamage(), mb); - ((LivingEntity) entity).setNoDamageTicks(0); - didHit = true; - } - - if (didHit || entityCollision) { - blastEffects(location, mb); - tfb.remove(); - mb.firedBlocks.remove(tfb); - return true; - } - - return false; - } - - private static void blastEffects(Location location, MagmaBlast mb) { - float radius = mb.explosionRadius; - float speed = 0.1f; - - ParticleEffect.FLAME.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - ParticleEffect.SMOKE_LARGE.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - ParticleEffect.FIREWORKS_SPARK.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - - ThreadLocalRandom rand = ThreadLocalRandom.current(); - - location.getWorld().playSound(location, - (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, - 1f, 1f); - location.getWorld().playSound(location, - (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, - 1f, 1f); - } - - // Generates a random number between -max and max. - private static float randomBinomial(float max) { - ThreadLocalRandom rand = ThreadLocalRandom.current(); - return (rand.nextFloat() * max) - (rand.nextFloat() * max); - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MagmaBlast"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public Object createNewComboInstance(Player player) { - return new MagmaBlast(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.MagmaBlast.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.MagmaBlast.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.MagmaBlast.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public Set getSources() { - return sources; - } - - public List getBlocks() { - return blocks; - } - - public List getFiredBlocks() { - return firedBlocks; - } - - public long getMaxDuration() { - return maxDuration; - } - - public void setMaxDuration(long maxDuration) { - this.maxDuration = maxDuration; - } - - public long getShotCooldown() { - return shotCooldown; - } - - public void setShotCooldown(long shotCooldown) { - this.shotCooldown = shotCooldown; - } - - public int getMaxSources() { - return maxSources; - } - - public void setMaxSources(int maxSources) { - this.maxSources = maxSources; - } - - public int getSourceRange() { - return sourceRange; - } - - public void setSourceRange(int sourceRange) { - this.sourceRange = sourceRange; - } - - public double getSelectRange() { - return selectRange; - } - - public void setSelectRange(double selectRange) { - this.selectRange = selectRange; - } - - public double getFireSpeed() { - return fireSpeed; - } - - public void setFireSpeed(double fireSpeed) { - this.fireSpeed = fireSpeed; - } - - public double getMaxDistanceFromSources() { - return maxDistanceFromSources; - } - - public void setMaxDistanceFromSources(double maxDistanceFromSources) { - this.maxDistanceFromSources = maxDistanceFromSources; - } - - public float getExplosionRadius() { - return explosionRadius; - } - - public void setExplosionRadius(float explosionRadius) { - this.explosionRadius = explosionRadius; - } - - public boolean isRequireLavaFlow() { - return requireLavaFlow; - } - - public void setRequireLavaFlow(boolean requireLavaFlow) { - this.requireLavaFlow = requireLavaFlow; - } - - public boolean isPlayerCollisions() { - return playerCollisions; - } - - public void setPlayerCollisions(boolean playerCollisions) { - this.playerCollisions = playerCollisions; - } - - public boolean isEntitySelection() { - return entitySelection; - } - - public void setEntitySelection(boolean entitySelection) { - this.entitySelection = entitySelection; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public long getCanLavaFlowTime() { - return canLavaFlowTime; - } - - public void setCanLavaFlowTime(long canLavaFlowTime) { - this.canLavaFlowTime = canLavaFlowTime; - } - - public long getLastShotTime() { - return lastShot; - } - - public void setLastShotTime(long lastShot) { - this.lastShot = lastShot; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/Combustion.java b/src/com/jedk1/jedcore/ability/firebending/Combustion.java deleted file mode 100644 index 2071fb8..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/Combustion.java +++ /dev/null @@ -1,631 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; -import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; -import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; -import com.jedk1.jedcore.util.FireTick; -import com.jedk1.jedcore.util.MaterialUtil; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.CombustionAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Sound; -import org.bukkit.Tag; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.stream.Collectors; - -public class Combustion extends CombustionAbility implements AddonAbility { - - private State state; - private Location location; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private CompositeRemovalPolicy removalPolicy; - - private ArrayList skipMaterials; // use a configured list of blocks to skip through - - public Combustion(Player player) { - super(player); - - if (!isEnabled()) return; - - if (this.player == null || !bPlayer.canBend(this) || !bPlayer.canCombustionbend()) { - return; - } - - if (hasAbility(player, Combustion.class)) { - Combustion c = getAbility(player, Combustion.class); - if (c.state instanceof ChargeState) - return; - } - - setFields(); - - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.Combustion.Cooldown"); - - this.location = null; - this.state = new ChargeState(); - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new SwappedSlotsRemovalPolicy<>(bPlayer, Combustion.class) - ); - - this.removalPolicy.load(config, "Abilities.Fire.Combustion"); - - this.skipMaterials = loadSkipMaterials(); - } - - @Override - public void progress() { - if (this.removalPolicy.shouldRemove()) { - remove(); - return; - } - - state.update(); - } - - public static void combust(Player player) { - if(hasAbility(player, Combustion.class)) { - Combustion c = getAbility(player, Combustion.class); - - c.selfCombust(); - } - } - - public void selfCombust() { - if (this.state instanceof TravelState) { - this.state = new CombustState(location); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - // Only enable the collision while traveling. - if (state instanceof TravelState) { - return location; - } - - return null; - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Fire.Combustion.AbilityCollisionRadius"); - } - - @Override - public String getName() { - return "Combustion"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.Combustion.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.Combustion.Enabled"); - } - - private ArrayList loadSkipMaterials() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - ArrayList skipList = new ArrayList<>(); - - if (config.contains("Abilities.Fire.Combustion.SkipMaterials")) { - List configuredSkipList = config.getStringList("Abilities.Fire.Combustion.SkipMaterials"); - - for (String entry : configuredSkipList) { - if (entry.startsWith("#")) { - String tagName = entry.substring(1).toLowerCase(); - - NamespacedKey tagKey = NamespacedKey.minecraft(tagName); - Tag materialTag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, tagKey, Material.class); - - if (materialTag != null) { - skipList.addAll(materialTag.getValues().stream() - .map(material -> material.name().toLowerCase()) - .collect(Collectors.toList())); - } - } else { - skipList.add(entry.toLowerCase()); - } - } - } - - return skipList; - } - - private interface State { - void update(); - } - - // This is the initial state of Combustion. - // It's used to render the particle ring that happens during charging. - // This state transitions to TravelState if the player stops sneaking after charging is done. - // This state transitions to CombustState if the player takes damage while charging. - private class ChargeState implements State { - private final long startTime; - private int currPoint = (int) player.getLocation().getYaw() + 90; - private final long warmup; - private final double playerStartHealth; - private final boolean instantExplodeIfHit; - - public ChargeState() { - this.startTime = System.currentTimeMillis(); - this.playerStartHealth = player.getHealth(); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - this.instantExplodeIfHit = config.getBoolean("Abilities.Fire.Combustion.InstantExplodeIfHit"); - this.warmup = config.getLong("Abilities.Fire.Combustion.Warmup"); - } - - @Override - public void update() { - long time = System.currentTimeMillis(); - - boolean charged = time >= this.startTime + warmup; - - if (player.isSneaking()) { - if (!bPlayer.canBendIgnoreBinds(Combustion.this)) { - remove(); - return; - } - - playParticleRing(60, 1.75F, 2); - - if (instantExplodeIfHit && player.getHealth() < playerStartHealth) { - // Remove and combust at player's location - state = new CombustState(player.getLocation(), true); - bPlayer.addCooldown(Combustion.this); - return; - } - - if (charged) { - ParticleEffect.SMOKE_LARGE.display(player.getLocation(), 1, Math.random(), Math.random(), Math.random(), 0.1); - } - } else { - if (charged) { - state = new TravelState(); - bPlayer.addCooldown(Combustion.this); - } else { - remove(); - } - } - } - - private void playParticleRing(int points, float size, int speed) { - for (int i = 0; i < speed; ++i) { - currPoint += 360 / points; - - if (currPoint > 360) { - currPoint = 0; - } - - double angle = currPoint * 3.141592653589793D / 180.0D; - double x = size * Math.cos(angle); - double z = size * Math.sin(angle); - - Location loc = player.getLocation().add(x, 1.0D, z); - playFirebendingParticles(loc, 3, 0.0, 0.0, 0.0); - ParticleEffect.SMOKE_NORMAL.display(loc, 4, 0.0, 0.0, 0.0, 0.01); - JCMethods.emitLight(loc); - } - } - } - - // This state is used after the player releases a charged Combustion. - // It's used for moving and rendering the projectile. - // This state transitions to CombustState when it collides with terrain or an entity. - private class TravelState implements State { - private Vector direction; - private final int range; - private final double speed; - private final boolean explodeOnDeath; - private final double entityCollisionRadius; - private double distanceTraveled; - - public TravelState() { - removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); - - Location origin = player.getEyeLocation().clone(); - origin.setY(origin.getY() - 0.8D); - location = origin.clone(); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - range = config.getInt("Abilities.Fire.Combustion.Range"); - speed = config.getDouble("Abilities.Fire.Combustion.Speed"); - explodeOnDeath = config.getBoolean("Abilities.Fire.Combustion.ExplodeOnDeath"); - entityCollisionRadius = config.getDouble("Abilities.Fire.Combustion.EntityCollisionRadius"); - - if (explodeOnDeath) { - removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); - removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); - } - - direction = player.getEyeLocation().getDirection().normalize(); - distanceTraveled = 0; - } - - @Override - public void update() { - if (explodeOnDeath && player.isDead()) { - state = new CombustState(location); - return; - } - - // Manually handle the region protection check because the CannotBendRemovalPolicy no longer checks it - // when explodeOnDeath is true. This stops players from firing Combustion and then walking into a - // protected area. - if (explodeOnDeath) { - if (RegionProtection.isRegionProtected(Combustion.this, player.getLocation())) { - remove(); - return; - } - } - - if (distanceTraveled >= range) { - remove(); - return; - } - - travel(); - } - - private void travel() { - double stepDistance = speed; - - for (int i = 0; i < (int) (speed * 5); ++i) { - render(); - - Sphere collider = new Sphere(location.toVector(), entityCollisionRadius); - - boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { - location = entity.getLocation(); - state = new CombustState(location); - return true; - }); - - if (hit) { - return; - } - - if (!MaterialUtil.isTransparent(location.getBlock()) || isWater(location.getBlock())) { - Material blockMaterial = location.getBlock().getType(); - String blockMaterialName = blockMaterial.name().toLowerCase(); - - boolean shouldSkip = skipMaterials.contains(blockMaterialName); - - if (!shouldSkip) { - state = new CombustState(location); - return; - } - } - - direction = player.getEyeLocation().getDirection().normalize(); - location = location.add(direction.clone().multiply(stepDistance)); - - distanceTraveled += stepDistance; - - if (distanceTraveled >= range) { - remove(); - return; - } - } - } - - private void render() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - ParticleEffect.SOUL_FIRE_FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); - } else { - ParticleEffect.FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); - } - ParticleEffect.SMOKE_LARGE.display(location, 1, 0.0, 0.0, 0.0F, 0.06); - ParticleEffect.FIREWORKS_SPARK.display(location, 1, 0.0, 0.0, 0.0F, 0.06); - - location.getWorld().playSound(location, Sound.ENTITY_FIREWORK_ROCKET_BLAST, 1.0F, 0.01F); - - JCMethods.emitLight(location); - } - } - - @Override - public void handleCollision(final Collision collision) { - super.handleCollision(collision); - - if (collision.isRemovingFirst()) { - state = new CombustState(collision.getLocationFirst()); - } - } - - // This state is used for doing the explosion. - // ChargeState can transition to this state if the player takes damage while charging. - // TravelState can transition to this state if the projectile collides with terrain, entity, or collidable ability. - private class CombustState implements State { - private final long startTime; - private final long regenTime; - private boolean waitForRegen; - - public CombustState(Location location) { - this(location, false); - } - - public CombustState(Location location, boolean misfire) { - removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); - // This stops players from moving into a protected area to bypass the regen wait time. - removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - this.startTime = System.currentTimeMillis(); - this.regenTime = config.getLong("Abilities.Fire.Combustion.RegenTime"); - this.waitForRegen = config.getBoolean("Abilities.Fire.Combustion.WaitForRegen"); - - double damage = config.getDouble("Abilities.Fire.Combustion.Damage"); - int fireTick = config.getInt("Abilities.Fire.Combustion.FireTick"); - int power = config.getInt("Abilities.Fire.Combustion.Power"); - boolean damageBlocks = config.getBoolean("Abilities.Fire.Combustion.DamageBlocks"); - boolean regenBlocks = config.getBoolean("Abilities.Fire.Combustion.RegenBlocks"); - - ExplosionMethod explosionMethod; - if (regenBlocks) { - explosionMethod = new RegenExplosionMethod(damageBlocks, regenTime); - } else { - explosionMethod = new PermanentExplosionMethod(damageBlocks); - } - - // Don't wait for regen if the blocks aren't even being destroyed. - if (!damageBlocks) { - waitForRegen = false; - } - - double modifier = 0; - if (misfire) { - modifier = config.getInt("Abilities.Fire.Combustion.MisfireModifier"); - } - - int destroyedCount = explosionMethod.explode(location, power + modifier, damage + modifier, fireTick); - - // Don't wait for regen if nothing was actually destroyed. - if (destroyedCount <= 0) { - waitForRegen = false; - } - - AirAbility.removeAirSpouts(location, power, player); - WaterAbility.removeWaterSpouts(location, power, player); - } - - @Override - public void update() { - if (!waitForRegen || System.currentTimeMillis() >= (this.startTime + this.regenTime)) { - remove(); - } - } - } - - private interface ExplosionMethod { - // Returns how many blocks were destroyed. - int explode(Location location, double size, double damage, int fireTick); - } - - private abstract class AbstractExplosionMethod implements ExplosionMethod { - protected List blocks = Arrays.asList( - Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.BEDROCK, Material.CHEST, Material.TRAPPED_CHEST, Material.OBSIDIAN, - Material.NETHER_PORTAL, Material.END_PORTAL, Material.END_PORTAL_FRAME, Material.FIRE, - Material.WATER, Material.LAVA, Material.DROPPER, Material.FURNACE, - Material.DISPENSER, Material.HOPPER, Material.BEACON, Material.BARRIER, Material.SPAWNER - ); - - private final boolean destroy; - private final Random rand = new Random(); - - public AbstractExplosionMethod(boolean destroy) { - this.destroy = destroy; - } - - public int explode(Location location, double size, double damage, int fireTick) { - render(location); - - if (!destroy) { - return 0; - } - - location.getWorld().createExplosion(location, 0.0F); - int destroyCount = destroyBlocks(location, (int)size); - damageEntities(location, size, damage, fireTick); - - return destroyCount; - } - - private void render(Location location) { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - ParticleEffect.SOUL_FIRE_FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - } else { - ParticleEffect.FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - } - ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.FIREWORKS_SPARK.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random()); - ParticleEffect.EXPLOSION_HUGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - - location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 1f, 1f); - } - - private int destroyBlocks(Location location, int size) { - int count = 0; - - for (Location l : GeneralMethods.getCircle(location, size, size, false, true, 0)) { - if (!RegionProtection.isRegionProtected(Combustion.this, l)) { - if (destroyBlock(l)) { - ++count; - } - } - } - - return count; - } - - private void damageEntities(Location location, double size, double damage, int fireTick) { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, size)) { - if (e instanceof LivingEntity) { - if (!RegionProtection.isRegionProtected(Combustion.this, e.getLocation())) { - DamageHandler.damageEntity(e, damage, Combustion.this); - FireTick.set(e, fireTick); - } - } - } - } - - protected void placeRandomFire(Location location) { - int chance = rand.nextInt(3); - - if ((!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) || (chance != 0)) - return; - - location.getBlock().setType(Material.FIRE); - } - - protected void placeRandomBlock(Location location) { - int chance = rand.nextInt(3); - - if (!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) - return; - - Material block = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType(); - - if (chance == 0) - location.getBlock().setType(block); - } - - // Returns how many blocks were destroyed. - public abstract boolean destroyBlock(Location location); - } - - private class RegenExplosionMethod extends AbstractExplosionMethod { - private final long regenTime; - - public RegenExplosionMethod(boolean destroy, long regenTime) { - super(destroy); - this.regenTime = regenTime; - } - - @Override - public boolean destroyBlock(Location l) { - Block block = l.getBlock(); - - if (TempBlock.isTempBlock(block)) - TempBlock.revertBlock(block, Material.AIR); - if (TempBlock.isTempBlock(block)) - TempBlock.removeBlock(block); - - if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { - new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), regenTime, false); - placeRandomBlock(l); - placeRandomFire(l); - - return true; - } - - return false; - } - } - - private class PermanentExplosionMethod extends AbstractExplosionMethod { - public PermanentExplosionMethod(boolean destroy) { - super(destroy); - } - - @Override - public boolean destroyBlock(Location l) { - Block block = l.getBlock(); - - if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { - Block newBlock = l.getWorld().getBlockAt(l); - newBlock.setType(Material.AIR); - placeRandomBlock(l); - placeRandomFire(l); - - return true; - } - - return false; - } - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/Discharge.java b/src/com/jedk1/jedcore/ability/firebending/Discharge.java deleted file mode 100644 index 1f27388..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/Discharge.java +++ /dev/null @@ -1,346 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LightningAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Random; - -public class Discharge extends LightningAbility implements AddonAbility { - private final HashMap branches = new HashMap<>(); - - private Location location; - private Vector direction; - private boolean hit; - private int spaces; - private double branchSpace; - private final Random rand = new Random(); - - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.COOLDOWN) - private long cooldown, avatarCooldown; - @Attribute(Attribute.DURATION) - private long duration; - private boolean slotSwapping; - @Attribute("CollisionRadius") - private double entityCollisionRadius; - - private float soundVolume; - private int soundInterval; - - public Discharge(Player player) { - super(player); - - if (!bPlayer.canBend(this) || hasAbility(player, Discharge.class) || !bPlayer.canLightningbend()) { - return; - } - - setFields(); - - direction = player.getEyeLocation().getDirection().normalize(); - - if (bPlayer.isAvatarState() || JCMethods.isSozinsComet(player.getWorld())) { - this.cooldown = avatarCooldown; - } - - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - damage = config.getDouble("Abilities.Fire.Discharge.Damage"); - cooldown = config.getLong("Abilities.Fire.Discharge.Cooldown"); - avatarCooldown = config.getLong("Abilities.Fire.Discharge.AvatarCooldown"); - duration = config.getLong("Abilities.Fire.Discharge.Duration"); - slotSwapping = config.getBoolean("Abilities.Fire.Discharge.SlotSwapping"); - entityCollisionRadius = config.getDouble("Abilities.Fire.Discharge.EntityCollisionRadius"); - - soundVolume = (float) config.getDouble("Abilities.Fire.Discharge.Sound.Volume"); - soundInterval = config.getInt("Abilities.Fire.Discharge.Sound.Interval"); - - branchSpace = 0.2; - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!canBend()) { - remove(); - return; - } - - if (System.currentTimeMillis() < (getStartTime() + duration) && !hit) { - advanceLocation(); - } else { - remove(); - } - } - - private boolean canBend() { - if (!slotSwapping) { - return bPlayer.canBendIgnoreCooldowns(this); - } else { - return bPlayer.canBendIgnoreBindsCooldowns(this); - } - } - - private void advanceLocation() { - if (location == null) { - Location origin = player.getEyeLocation().clone(); - location = origin.clone(); - branches.put(branches.size() + 1, location); - } - - spaces++; - if (spaces % 3 == 0) { - Location prevBranch = branches.get(1); - branches.put(branches.size() + 1, prevBranch); - } - - List cleanup = new ArrayList<>(); - - for (int i : branches.keySet()) { - Location origin = branches.get(i); - - if (origin != null) { - Location l = origin.clone(); - - if (!isTransparent(l.getBlock())) { - cleanup.add(i); - continue; - } - - l.add(createBranch(), createBranch(), createBranch()); - branchSpace += 0.001; - - for (int j = 0; j < 5; j++) { - playLightningbendingParticle(l.clone(), 0f, 0f, 0f); - JCMethods.emitLight(l.clone()); - - if (rand.nextInt(soundInterval) == 0) { - player.getWorld().playSound(l, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); - } - - Vector vec = l.toVector(); - - hit = CollisionDetector.checkEntityCollisions(player, new Sphere(l.toVector(), entityCollisionRadius), (entity) -> { - if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))) { - return true; - } - Vector knockbackVector = entity.getLocation().toVector().subtract(vec).normalize().multiply(0.8); - GeneralMethods.setVelocity(this, entity, knockbackVector); - - DamageHandler.damageEntity(entity, damage, this); - - for (int k = 0; k < 5; k++) { - playLightningbendingParticle(entity.getLocation(), (float) Math.random(), (float) Math.random(), (float) Math.random()); - JCMethods.emitLight(entity.getLocation()); - } - - entity.getWorld().playSound(entity.getLocation(), Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); - player.getWorld().playSound(player.getLocation(), Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); - - return true; - }); - - l = l.add(direction.clone().multiply(0.2)); - } - - branches.put(i, l); - } - } - - for (int i : cleanup) { - branches.remove(i); - } - - cleanup.clear(); - } - - private double createBranch() { - int i = rand.nextInt(3); - - switch (i) { - case 0: - return branchSpace; - case 2: - return -branchSpace; - default: - return 0.0; - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public List getLocations() { - return new ArrayList<>(branches.values()); - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Fire.Discharge.AbilityCollisionRadius"); - } - - @Override - public String getName() { - return "Discharge"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.Discharge.Description"); - } - - public HashMap getBranches() { - return branches; - } - - public void setLocation(Location location) { - this.location = location; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public boolean isHit() { - return hit; - } - - public void setHit(boolean hit) { - this.hit = hit; - } - - public int getSpaces() { - return spaces; - } - - public void setSpaces(int spaces) { - this.spaces = spaces; - } - - public double getBranchSpace() { - return branchSpace; - } - - public void setBranchSpace(double branchSpace) { - this.branchSpace = branchSpace; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getAvatarCooldown() { - return avatarCooldown; - } - - public void setAvatarCooldown(long avatarCooldown) { - this.avatarCooldown = avatarCooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public boolean isSlotSwapping() { - return slotSwapping; - } - - public void setSlotSwapping(boolean slotSwapping) { - this.slotSwapping = slotSwapping; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.Discharge.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/FireBall.java b/src/com/jedk1/jedcore/ability/firebending/FireBall.java deleted file mode 100644 index 2631565..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/FireBall.java +++ /dev/null @@ -1,307 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.AirShieldReflector; -import com.jedk1.jedcore.util.FireTick; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.airbending.AirShield; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class FireBall extends FireAbility implements AddonAbility { - - private Location location; - private Vector direction; - private double distanceTravelled; - - @Attribute(Attribute.RANGE) - private long range; - @Attribute(Attribute.FIRE_TICK) - private long fireTicks; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DAMAGE) - private double damage; - private boolean controllable; - private boolean fireTrail; - @Attribute("CollisionRadius") - private double collisionRadius; - - public FireBall(Player player) { - super(player); - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - location = player.getEyeLocation(); - direction = player.getEyeLocation().getDirection().normalize(); - - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - range = config.getLong("Abilities.Fire.FireBall.Range"); - fireTicks = config.getLong("Abilities.Fire.FireBall.FireDuration"); - cooldown = config.getLong("Abilities.Fire.FireBall.Cooldown"); - damage = config.getDouble("Abilities.Fire.FireBall.Damage"); - controllable = config.getBoolean("Abilities.Fire.FireBall.Controllable"); - fireTrail = config.getBoolean("Abilities.Fire.FireBall.FireTrail"); - collisionRadius = config.getDouble("Abilities.Fire.FireBall.CollisionRadius"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - range *= BlueFireAbility.getRangeFactor(); - cooldown *= BlueFireAbility.getCooldownFactor(); - damage *= BlueFireAbility.getDamageFactor(); - } - - if (isDay(player.getWorld())) { - range = (long) getDayFactor(range); - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - damage = getDayFactor(damage); - } - } - - @Override - public void progress(){ - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (distanceTravelled >= range) { - remove(); - return; - } - - if (RegionProtection.isRegionProtected(player, location, this)) { - remove(); - return; - } - - progressFireball(); - } - - private void progressFireball() { - for (int i = 0; i < 2; i++) { - distanceTravelled ++; - if (distanceTravelled >= range) { - return; - } - - if (controllable) { - direction = player.getLocation().getDirection(); - } - - location = location.add(direction); - if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { - distanceTravelled = range; - return; - } - - ParticleEffect.SMOKE_LARGE.display(location, 1, 0, 0, 0, 0); - ParticleEffect.SMOKE_LARGE.display(location, 1, 0, 0, 0, 0); - for (int j = 0; j < 5; j++) { - playFirebendingParticles(location, 1, 0, 0, 0); - } - - JCMethods.emitLight(location); - - boolean hitTarget = CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), collisionRadius), this::doDamage); - - if (!hitTarget) { - if (this.distanceTravelled > 2 && this.fireTrail) { - new BlazeArc(player, location.clone().subtract(direction).subtract(direction), direction, 2); - } - } else { - remove(); - return; - } - } - } - - private boolean doDamage(Entity entity) { - if (!(entity instanceof LivingEntity)) return false; - - distanceTravelled = range; - DamageHandler.damageEntity(entity, damage, this); - - FireTick.set(entity, Math.round(fireTicks / 50F)); - new FireDamageTimer(entity, player, this); - return false; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - remove(); - } else { - CoreAbility second = collision.getAbilitySecond(); - if (second instanceof AirShield) { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - boolean reflect = config.getBoolean("Abilities.Fire.FireBall.Collisions.AirShield.Reflect", true); - - if (reflect) { - AirShield shield = (AirShield) second; - AirShieldReflector.reflect(shield, this.location, this.direction); - } - } - } - } - - @Override - public String getName() { - return "FireBall"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireBall.Description"); - } - - public void setLocation(Location location) { - this.location = location; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getDistanceTravelled() { - return distanceTravelled; - } - - public void setDistanceTravelled(double distanceTravelled) { - this.distanceTravelled = distanceTravelled; - } - - public long getRange() { - return range; - } - - public void setRange(long range) { - this.range = range; - } - - public long getFireTicks() { - return fireTicks; - } - - public void setFireTicks(long fireTicks) { - this.fireTicks = fireTicks; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean isControllable() { - return controllable; - } - - public void setControllable(boolean controllable) { - this.controllable = controllable; - } - - public boolean isFireTrail() { - return fireTrail; - } - - public void setFireTrail(boolean fireTrail) { - this.fireTrail = fireTrail; - } - - @Override - public double getCollisionRadius() { - return collisionRadius; - } - - public void setCollisionRadius(double collisionRadius) { - this.collisionRadius = collisionRadius; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FireBall.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java deleted file mode 100644 index fa46395..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java +++ /dev/null @@ -1,426 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.listener.CommandListener; -import com.jedk1.jedcore.util.FireTick; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ChatUtil; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.UUID; - -public class FireBreath extends FireAbility implements AddonAbility { - - public static List rainbowPlayer = new ArrayList<>(); - - private int ticks; - Random rand = new Random(); - private final List locations = new ArrayList<>(); - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - private int particles; - @Attribute("Player" + Attribute.DAMAGE) - private double playerDamage; - @Attribute("Mob" + Attribute.DAMAGE) - private double mobDamage; - @Attribute(Attribute.DURATION) - private int fireDuration; - @Attribute(Attribute.RANGE) - private int range; - private boolean spawnFire; - private boolean meltEnabled; - private int meltChance; - - - public FireBreath(Player player) { - super(player); - if (!bPlayer.canBend(this) || hasAbility(player, FireBreath.class)) { - return; - } - - setFields(); - - if (bPlayer.isAvatarState()) { - range = range * 2; - playerDamage = playerDamage * 1.5; - mobDamage = mobDamage * 2; - duration = duration * 3; - } else if (JCMethods.isSozinsComet(player.getWorld())) { - range = range * 2; - playerDamage = playerDamage * 1.5; - mobDamage = mobDamage * 2; - } - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.FireBreath.Cooldown"); - duration = config.getLong("Abilities.Fire.FireBreath.Duration"); - particles = config.getInt("Abilities.Fire.FireBreath.Particles"); - playerDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Player"); - mobDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Mob"); - fireDuration = config.getInt("Abilities.Fire.FireBreath.FireDuration"); - range = config.getInt("Abilities.Fire.FireBreath.Range"); - spawnFire = config.getBoolean("Abilities.Fire.FireBreath.Avatar.FireEnabled"); - meltEnabled = config.getBoolean("Abilities.Fire.FireBreath.Melt.Enabled"); - meltChance = config.getInt("Abilities.Fire.FireBreath.Melt.Chance"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); - range *= BlueFireAbility.getRangeFactor(); - playerDamage *= BlueFireAbility.getDamageFactor(); - mobDamage *= BlueFireAbility.getDamageFactor(); - } - - if (isDay(player.getWorld())) { - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - range = (int) getDayFactor(range); - playerDamage = getDayFactor(playerDamage); - mobDamage = getDayFactor(mobDamage); - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (!player.isSneaking()) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (System.currentTimeMillis() < getStartTime() + duration) { - createBeam(); - } else { - bPlayer.addCooldown(this); - remove(); - } - } - - private boolean isLocationSafe(Location loc) { - Block block = loc.getBlock(); - if (RegionProtection.isRegionProtected(player, loc, this)) { - return false; - } - if (!isTransparent(block)) { - return false; - } - return !isWater(block); - } - - private void createBeam() { - Location loc = player.getEyeLocation(); - Vector dir = player.getLocation().getDirection(); - double step = 1; - double size = 0; - double offset = 0; - double damageRegion = 1.5; - - locations.clear(); - - for (double k = 0; k < range; k += step) { - loc = loc.add(dir.clone().multiply(step)); - size += 0.005; - offset += 0.3; - damageRegion += 0.01; - if (meltEnabled) { - for (Block b : GeneralMethods.getBlocksAroundPoint(loc, damageRegion)) { - if (isIce(b) && rand.nextInt(meltChance) == 0) { - if (TempBlock.isTempBlock(b)) { - TempBlock temp = TempBlock.get(b); - if (PhaseChange.getFrozenBlocksMap().containsKey(temp)) { - temp.revertBlock(); - PhaseChange.getFrozenBlocksMap().remove(temp); - } - } - } - } - } - if (!isLocationSafe(loc)) - return; - - locations.add(loc); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - if (entity instanceof Player) { - FireTick.set(entity, fireDuration / 50); - DamageHandler.damageEntity(entity, playerDamage, this); - } else { - FireTick.set(entity, fireDuration / 50); - DamageHandler.damageEntity(entity, mobDamage, this); - } - } - } - - playFirebendingSound(loc); - if (bPlayer.isAvatarState() && spawnFire) { - new BlazeArc(player, loc, dir, 2); - } - - if (rainbowPlayer.contains(player.getUniqueId())) { - ticks++; - if (ticks >= 301) - ticks = 0; - if (isInRange(ticks, 0, 50)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 140, 32, 32); - } else if (isInRange(ticks, 51, 100)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 196, 93, 0); - } else if (isInRange(ticks, 101, 150)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 186, 166, 37); - } else if (isInRange(ticks, 151, 200)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 36, 171, 47); - } else if (isInRange(ticks, 201, 250)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 36, 142, 171); - } else if (isInRange(ticks, 251, 300)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 128, 36, 171); - } - } else { - playFirebendingParticles(loc, particles, Math.random(), Math.random(), Math.random()); - ParticleEffect.SMOKE_NORMAL.display(loc, particles, Math.random(), Math.random(), Math.random(), size); - JCMethods.emitLight(loc); - } - } - } - - private void displayParticle(Location location, int amount, int r, int g, int b) { - ParticleEffect.REDSTONE.display(location, amount, 0, 0, 0, 0.005, new Particle.DustOptions(Color.fromRGB(r, g, b), 1)); - JCMethods.emitLight(location); - } - - private boolean isInRange(int x, int min, int max) { - return min <= x && x <= max; - } - - /** - * Generates an offset location around a given location with variable offset - * amount. - */ - private Location getOffsetLocation(Location loc, double offset) { - return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); - } - - public static void toggleRainbowBreath(Player player, boolean activate) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - - boolean easterEgg = config.getBoolean("Abilities.Fire.FireBreath.RainbowBreath.Enabled"); - String bindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "")); - String unbindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "")); - String deniedMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "")); - - if (easterEgg && (player.hasPermission("bending.ability.FireBreath.RainbowBreath") - || Arrays.asList(CommandListener.developers).contains(player.getUniqueId().toString()))) { - if (activate) { - if (!rainbowPlayer.contains(player.getUniqueId())) { - rainbowPlayer.add(player.getUniqueId()); - if (!bindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + bindMsg); - } - } else { - if (rainbowPlayer.contains(player.getUniqueId())) { - rainbowPlayer.remove(player.getUniqueId()); - if (!unbindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + unbindMsg); - } - } - } else if (!deniedMsg.equals("")) { - player.sendMessage(Element.FIRE.getColor() + deniedMsg); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return player.getLocation(); - } - - @Override - public List getLocations() { - return locations; - } - - @Override - public String getName() { - return "FireBreath"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireBreath.Description"); - } - - public static List getRainbowPlayer() { - return rainbowPlayer; - } - - public static void setRainbowPlayer(List rainbowPlayer) { - FireBreath.rainbowPlayer = rainbowPlayer; - } - - public int getTicks() { - return ticks; - } - - public void setTicks(int ticks) { - this.ticks = ticks; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public int getParticles() { - return particles; - } - - public void setParticles(int particles) { - this.particles = particles; - } - - public double getPlayerDamage() { - return playerDamage; - } - - public void setPlayerDamage(double playerDamage) { - this.playerDamage = playerDamage; - } - - public double getMobDamage() { - return mobDamage; - } - - public void setMobDamage(double mobDamage) { - this.mobDamage = mobDamage; - } - - public int getFireDuration() { - return fireDuration; - } - - public void setFireDuration(int fireDuration) { - this.fireDuration = fireDuration; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public boolean isSpawnFire() { - return spawnFire; - } - - public void setSpawnFire(boolean spawnFire) { - this.spawnFire = spawnFire; - } - - public boolean isMeltEnabled() { - return meltEnabled; - } - - public void setMeltEnabled(boolean meltEnabled) { - this.meltEnabled = meltEnabled; - } - - public int getMeltChance() { - return meltChance; - } - - public void setMeltChance(int meltChance) { - this.meltChance = meltChance; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FireBreath.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/FireComet.java b/src/com/jedk1/jedcore/ability/firebending/FireComet.java deleted file mode 100644 index 2cdd262..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/FireComet.java +++ /dev/null @@ -1,464 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.BlockState; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Random; - -public class FireComet extends FireAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.CHARGE_DURATION) - private long charge; - private long regen; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.RADIUS) - private double blastRadius; - private boolean cometOnly; - private boolean avatarBypass; - private Location location; - private Location launchLoc; - private Vector vector; - - //Charging Animation - private int angle; - - private boolean fire; - private long time; - private boolean charged; - - private int point; - - private final Random rand = new Random(); - - public FireComet(Player player) { - super(player); - - if (!bPlayer.canBend(this) || hasAbility(player, FireComet.class)) { - return; - } - - setFields(); - - if (!JCMethods.isSozinsComet(player.getWorld())) { - if (GeneralMethods.hasRPG() && getSozinsCometOnly()) { - if (!(bPlayer.isAvatarState() && getAvatarBypassComet())) { - return; - } - } - } - - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - if (JCMethods.isSozinsComet(player.getWorld()) || bPlayer.isAvatarState()) { - cooldown = config.getLong("Abilities.Fire.FireComet.SozinsComet.Cooldown"); - charge = config.getLong("Abilities.Fire.FireComet.SozinsComet.ChargeUp"); - damage = config.getDouble("Abilities.Fire.FireComet.SozinsComet.Damage"); - blastRadius = config.getDouble("Abilities.Fire.FireComet.SozinsComet.BlastRadius"); - } else { - cooldown = config.getLong("Abilities.Fire.FireComet.Cooldown"); - charge = config.getLong("Abilities.Fire.FireComet.ChargeUp"); - damage = config.getDouble("Abilities.Fire.FireComet.Damage"); - blastRadius = config.getDouble("Abilities.Fire.FireComet.BlastRadius"); - } - - regen = config.getLong("Abilities.Fire.FireComet.RegenDelay"); - range = config.getInt("Abilities.Fire.FireComet.Range"); - cometOnly = config.getBoolean("Abilities.Fire.FireComet.SozinsCometOnly"); - avatarBypass = config.getBoolean("Abilities.Fire.FireComet.AvatarStateBypassComet"); - time = System.currentTimeMillis(); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); - damage *= BlueFireAbility.getDamageFactor(); - range *= BlueFireAbility.getRangeFactor(); - } - - if (isDay(player.getWorld())) { - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - damage = getDayFactor(damage); - range = (int) getDayFactor(range); - } - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (System.currentTimeMillis() > getTime() + getCharge()) { - if (RegionProtection.isRegionProtected(this, player.getLocation())) { - remove(); - return; - } - - if (!charged) { - charged = true; - Objects.requireNonNull(location.getWorld()).playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 2F, 0.8F); - } - - if (!isFired()) { - if (!player.isSneaking()) { - vector = player.getLocation().getDirection(); - - if (location == null) { - location = GeneralMethods.getTargetedLocation(player, 6); - } - - launchLoc = location.clone(); - setFired(true); - } else { - location = GeneralMethods.getTargetedLocation(player, 6); - } - } else { - if (!advance()) { - blast(); - remove(); - return; - } - } - - displayComet(); - } else { - if (!player.isSneaking()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - remove(); - return; - } - - location = GeneralMethods.getTargetedLocation(player, 6); - displayChargingAnim(); - } - } - - public boolean advance() { - location = location.add(vector.multiply(1)); - - playFirebendingSound(location); - - if (location.distance(launchLoc) > range || !isTransparent(location.getBlock())) { - return false; - } - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, 3.0)) { - if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { - return false; - } - } - - return true; - } - - public void blast() { - List blocks = new ArrayList<>(); - - for (Location loc : GeneralMethods.getCircle(location, (int) blastRadius, 0, false, true, 0)) { - if (JCMethods.isUnbreakable(loc.getBlock())) continue; - if (RegionProtection.isRegionProtected(this, loc)) continue; - - blocks.add(loc.getBlock().getState()); - new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), getRegenDelay(), false); - } - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, blastRadius)) { - if (e instanceof Player && e == player) { - continue; - } - - if (RegionProtection.isRegionProtected(this, e.getLocation())) { - continue; - } - - if (e instanceof LivingEntity) { - DamageHandler.damageEntity(e, getDamage(), this); - } - } - - playFirebendingParticles(location, 20, Math.random(), Math.random(), Math.random()); - ParticleEffect.FIREWORKS_SPARK.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - - JCMethods.emitLight(location); - - location.getWorld().playSound(location, (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 5F, 1F); - location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 5F, 0.8F); - - int i = 0; - for (BlockState block : blocks) { - double x = rand.nextDouble() / 3; - double z = rand.nextDouble() / 3; - - x = (rand.nextBoolean()) ? -x : x; - z = (rand.nextBoolean()) ? -z : z; - - i++; - - if (i % 2 == 0) { - new TempFallingBlock(block.getLocation(), block.getBlockData(), vector.clone().add(new Vector(x, 0, z)).normalize().multiply(-1), this); - } - } - } - - public void displayChargingAnim() { - this.angle += 10; - - Location location = this.location.clone(); - double angle = (this.angle * Math.PI / 180); - double xRotation = 3.141592653589793D / 3 * 2.1; - Vector v = new Vector(Math.cos(angle + point), Math.sin(angle), 0.0D).multiply(2.2); - Vector v1 = v.clone(); - - rotateAroundAxisX(v, xRotation); - rotateAroundAxisY(v, -((location.getYaw() * Math.PI / 180) - 1.575)); - rotateAroundAxisX(v1, -xRotation); - rotateAroundAxisY(v1, -((location.getYaw() * Math.PI / 180) - 1.575)); - -// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { -// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); -// } else { -// ParticleEffect.FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); -// } - playFirebendingParticles(location.clone().add(v), 1, 0, 0, 0); - playFirebendingParticles(location.clone().add(v1), 1, 0, 0, 0); - ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); - ParticleEffect.SMOKE_LARGE.display(location.clone().add(v1), 1, 0, 0, 0, 0.02); - - JCMethods.emitLight(location.clone().add(v)); - JCMethods.emitLight(location.clone().add(v1)); - - if (this.angle == 360) { - this.angle = 0; - } - - long init = getTime() + getCharge(); - int percentage = (int) (((init - System.currentTimeMillis()) * 100) / getCharge()); - double size = (1 - (percentage / 100.0F)) * 1.5; - - for (int i = 0; i < 360; i += 45) { - for (Location l : JCMethods.getVerticalCirclePoints(location.clone().subtract(0, size, 0), 45, size, i)) { -// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { -// ParticleEffect.SOUL_FIRE_FLAME.display(l, 1, 0, 0, 0, 0.02); -// } else { -// ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.02); -// } - playFirebendingParticles(l, 1, 0, 0, 0); - JCMethods.emitLight(l); - } - } - - if (size == 1.5) { - ParticleEffect.EXPLOSION_LARGE.display(this.location, 3, Math.random(), Math.random(), Math.random(), 0.03); - } - } - - public void displayComet() { - for (int angle = 0; angle < 360; angle += 45) { - for (Location l : JCMethods.getVerticalCirclePoints(location.clone().subtract(0, 1.5, 0), 45, 1.5, angle)) { -// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { -// ParticleEffect.SOUL_FIRE_FLAME.display(l, 1, 0, 0, 0, 0.05); -// } else { -// ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.05); -// } - playFirebendingParticles(l, 1, 0, 0, 0); - JCMethods.emitLight(l); - } - } - - point++; - - Location location = this.location.clone(); - for (int i = -180; i < 180; i += 45) { - double angle = (i * Math.PI / 180); - double xRotation = 3.141592653589793D / 3 * 2.1; - Vector v = new Vector(Math.cos(angle + point), Math.sin(angle + point), 0.0D).multiply(2.2); - Vector v1 = v.clone(); - - rotateAroundAxisX(v, xRotation); - rotateAroundAxisY(v, -((location.getYaw() * Math.PI / 180) - 1.575)); - rotateAroundAxisX(v1, -xRotation); - rotateAroundAxisY(v1, -((location.getYaw() * Math.PI / 180) - 1.575)); - -// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { -// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); -// } else { -// ParticleEffect.FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); -// ParticleEffect.FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); -// } - playFirebendingParticles(location.clone().add(v), 1, 0, 0, 0); - playFirebendingParticles(location.clone().add(v1), 1, 0, 0, 0); - ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); - ParticleEffect.SMOKE_LARGE.display(location.clone().add(v1), 1, 0, 0, 0, 0.02); - - JCMethods.emitLight(location.clone().add(v)); - JCMethods.emitLight(location.clone().add(v1)); - } - - if (point == 360) { - point = 0; - } - } - - private void rotateAroundAxisX(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double y = v.getY() * cos - v.getZ() * sin; - double z = v.getY() * sin + v.getZ() * cos; - - v.setY(y).setZ(z); - } - - private void rotateAroundAxisY(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double x = v.getX() * cos + v.getZ() * sin; - double z = v.getX() * -sin + v.getZ() * cos; - - v.setX(x).setZ(z); - } - - @Override - public void remove() { - if (player != null && player.isOnline() && isFired()) { - bPlayer.addCooldown(this); - } - - super.remove(); - } - - public double getDamage() { - return damage; - } - - public int getRange() { - return range; - } - - public void setFired(boolean fire) { - this.fire = fire; - } - - public boolean isFired() { - return fire; - } - - public long getCharge() { - return charge; - } - - public long getTime() { - return time; - } - - public boolean getSozinsCometOnly() { - return cometOnly; - } - - public boolean getAvatarBypassComet() { - return avatarBypass; - } - - public long getRegenDelay() { - return regen; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "FireComet"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireComet.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FireComet.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/FirePunch.java b/src/com/jedk1/jedcore/ability/firebending/FirePunch.java deleted file mode 100644 index c80d53c..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/FirePunch.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.FireTick; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.MainHand; - -public class FirePunch extends FireAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.FIRE_TICK) - private int fireTicks; - - private Boolean flameInMainHand = null; - - private Location location; - - public FirePunch(Player player) { - super(player); - - if (!bPlayer.canBend(this) || hasAbility(player, this.getClass())) - return; - - setFields(); - - start(); - } - - private void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(player); - - cooldown = config.getLong("Abilities.Fire.FirePunch.Cooldown"); - damage = config.getDouble("Abilities.Fire.FirePunch.Damage"); - fireTicks = config.getInt("Abilities.Fire.FirePunch.FireTicks"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(Element.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); - damage *= BlueFireAbility.getDamageFactor(); - } - - if (isDay(player.getWorld())) { - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - damage = getDayFactor(damage); - } - } - - @Override - public void progress() { - if (!player.isOnline() || player.isDead() || !bPlayer.canBend(this)) { - remove(); - return; - } - - Location hand = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); - - playFirebendingParticles(hand, 3, 0, 0, 0); - ParticleEffect.SMOKE_NORMAL.display(hand, 1); - JCMethods.emitLight(hand); - } - - public static void swapHands(Player player) { - FirePunch fp = getAbility(player, FirePunch.class); - if (fp == null) - return; - if (fp.flameInMainHand == null) - fp.flameInMainHand = true; - else fp.flameInMainHand = !fp.flameInMainHand; - } - - public Location getRightHandPos() { - return (player.getMainHand() == MainHand.RIGHT == ((flameInMainHand == null) || flameInMainHand) ? - GeneralMethods.getRightSide(player.getLocation(), .55) : - GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); - } - - public void punch(LivingEntity target) { - remove(); - DamageHandler.damageEntity(target, damage, this); - FireTick.set(target, fireTicks / 50); - if (cooldown > fireTicks) { - new FireDamageTimer(target, player, this); - } - bPlayer.addCooldown(this); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "FirePunch"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FirePunch.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getFireTicks() { - return fireTicks; - } - - public void setFireTicks(int fireTicks) { - this.fireTicks = fireTicks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FirePunch.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/FireShots.java b/src/com/jedk1/jedcore/ability/firebending/FireShots.java deleted file mode 100644 index a03efeb..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/FireShots.java +++ /dev/null @@ -1,416 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.AirShieldReflector; -import com.jedk1.jedcore.util.FireTick; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.airbending.AirShield; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.Ability; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.inventory.MainHand; -import org.bukkit.util.Vector; - -public class FireShots extends FireAbility implements AddonAbility { - - private final List shots = new ArrayList<>(); - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("MaxShots") - private int startAmount; - @Attribute(Attribute.FIRE_TICK) - private int fireticks; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute("CollisionRadius") - private double collisionRadius; - private Boolean flameInMainHand = null; - - public int amount; - - public FireShots(Player player){ - super(player); - - if (!bPlayer.canBend(this) || hasAbility(player, FireShots.class)) { - return; - } - - if (!player.hasGravity()) - player.setGravity(true); - - setFields(); - - amount = startAmount; - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.FireShots.Cooldown"); - startAmount = config.getInt("Abilities.Fire.FireShots.FireBalls"); - fireticks = config.getInt("Abilities.Fire.FireShots.FireDuration"); - range = config.getInt("Abilities.Fire.FireShots.Range"); - damage = config.getDouble("Abilities.Fire.FireShots.Damage"); - collisionRadius = config.getDouble("Abilities.Fire.FireShots.CollisionRadius"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); - range *= BlueFireAbility.getRangeFactor(); - damage *= BlueFireAbility.getDamageFactor(); - } - - if (isDay(player.getWorld())) { - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - range = (int) getDayFactor(range); - damage = getDayFactor(damage); - } - } - - public class FireShot { - - private final Ability ability; - private final Player player; - private Location location; - private final int range; - private final int fireTicks; - private double distanceTravelled; - private final double damage; - private Vector direction = null; - - public FireShot(Ability ability, Player player, Location location, int range, int fireTicks, double damage) { - this.ability = ability; - this.player = player; - this.location = location; - this.range = range; - this.fireTicks = fireTicks; - this.damage = damage; - } - - public boolean progress() { - if (player.isDead() || !player.isOnline()) { - return false; - } - if (distanceTravelled >= range) { - return false; - } - for (int i = 0; i < 2; i++) { - distanceTravelled ++; - if (distanceTravelled >= range) - return false; - - Vector dir = direction; - if (dir == null) { - dir = this.player.getLocation().getDirection().clone(); - } - - location = location.add(dir); - - if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())){ - return false; - } - - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - ParticleEffect.SOUL_FIRE_FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); - } else { - ParticleEffect.FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); - } - ParticleEffect.SMOKE_NORMAL.display(location, 2, 0.0, 0.0, 0.0, 0.01); - - JCMethods.emitLight(location); - - Sphere collider = new Sphere(location.toVector(), collisionRadius); - - boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { - DamageHandler.damageEntity(entity, damage, ability); - FireTick.set(entity, Math.round(fireTicks / 50F)); - new FireDamageTimer(entity, player, FireShots.this); - return true; - }); - - if (hit) { - return false; - } - } - return true; - } - - public Ability getAbility() { - return ability; - } - - public Player getPlayer() { - return player; - } - - public Location getLocation() { - return location; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getRange() { - return range; - } - - public int getFireTicks() { - return fireTicks; - } - - public double getDistanceTravelled() { - return distanceTravelled; - } - - public void setDistanceTravelled(double distanceTravelled) { - this.distanceTravelled = distanceTravelled; - } - - public double getDamage() { - return damage; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreCooldowns(this)) { - amount = 0; - if (!bPlayer.isOnCooldown(this)) { - bPlayer.addCooldown(this); - } - } - - shots.removeIf(shot -> !shot.progress()); - - if (amount <= 0 && shots.isEmpty()) { - remove(); - return; - } - - if (amount > 0) { - displayFireBalls(); - } - } - - public static void fireShot(Player player) { - FireShots fs = getAbility(player, FireShots.class); - if (fs != null) { - fs.fireShot(); - } - } - - public static void swapHands(Player player) { - FireShots fs = getAbility(player, FireShots.class); - if (fs == null) - return; - if (fs.flameInMainHand == null) - fs.flameInMainHand = true; - else fs.flameInMainHand = !fs.flameInMainHand; - } - - public void fireShot() { - if (amount >= 1) { - if (--amount <= 0) { - bPlayer.addCooldown(this); - } - shots.add(new FireShot(this, player, getRightHandPos(), range, fireticks, damage)); - } - } - - public Location getRightHandPos() { - return (player.getMainHand()==MainHand.RIGHT == ((flameInMainHand == null) || flameInMainHand) ? - GeneralMethods.getRightSide(player.getLocation(), .55) : - GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); - } - - private void displayFireBalls() { - playFirebendingParticles(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0); - ParticleEffect.SMOKE_NORMAL.display(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0, 0.01); - JCMethods.emitLight(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld())); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - List list = shots.stream().map(shot -> shot.location).collect(Collectors.toList()); - list.add(getRightHandPos()); - return list; - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); - - collidedShot.ifPresent(shots::remove); - } else { - CoreAbility second = collision.getAbilitySecond(); - if (second instanceof AirShield) { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - boolean reflect = config.getBoolean("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); - - if (reflect) { - Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); - - if (collidedShot.isPresent()) { - FireShot fireShot = collidedShot.get(); - AirShield shield = (AirShield) second; - - fireShot.direction = player.getLocation().getDirection().clone(); - AirShieldReflector.reflect(shield, fireShot.location, fireShot.direction); - } - } - } - } - } - - @Override - public String getName() { - return "FireShots"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireShots.Description"); - } - - public List getShots() { - return shots; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public int getStartAmount() { - return startAmount; - } - - public void setStartAmount(int startAmount) { - this.startAmount = startAmount; - } - - public int getFireticks() { - return fireticks; - } - - public void setFireticks(int fireticks) { - this.fireticks = fireticks; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - @Override - public double getCollisionRadius() { - return collisionRadius; - } - - public void setCollisionRadius(double collisionRadius) { - this.collisionRadius = collisionRadius; - } - - public int getAmount() { - return amount; - } - - public void setAmount(int amount) { - this.amount = amount; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FireShots.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/FireSki.java b/src/com/jedk1/jedcore/ability/firebending/FireSki.java deleted file mode 100644 index d43de8a..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/FireSki.java +++ /dev/null @@ -1,332 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.FireTick; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class FireSki extends FireAbility implements AddonAbility { - - private Location location; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.SPEED) - private double speed; - private boolean ignite; - @Attribute(Attribute.FIRE_TICK) - private int fireTicks; - private double requiredHeight; - - public FireSki(Player player) { - super(player); - if (!isEnabled()) { - return; - } - - if (hasAbility(player, FireSki.class)) { - FireSki fs = getAbility(player, FireSki.class); - fs.remove(); - return; - } - - if (!bPlayer.canBend(getAbility("FireJet"))) { - return; - } - - setFields(); - - if (CollisionDetector.isOnGround(player) || CollisionDetector.distanceAboveGround(player) < requiredHeight) { - return; - } - - this.flightHandler.createInstance(player, this.getName()); - - location = player.getLocation(); - player.setAllowFlight(true); - player.setFlying(true); - - bPlayer.addCooldown(getAbility("FireJet"), getCooldown()); - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.FireSki.Cooldown"); - duration = config.getLong("Abilities.Fire.FireSki.Duration"); - speed = config.getDouble("Abilities.Fire.FireSki.Speed"); - ignite = config.getBoolean("Abilities.Fire.FireSki.IgniteEntities"); - fireTicks = config.getInt("Abilities.Fire.FireSki.FireTicks"); - requiredHeight = config.getDouble("Abilities.Fire.FireSki.RequiredHeight"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); - } - - if (isDay(player.getWorld())) { - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - } - } - - private void allowFlight() { - player.setAllowFlight(true); - player.setFlying(true); - } - - private void removeFlight() { - player.setAllowFlight(false); - player.setFlying(false); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(getAbility("FireJet"))) { - remove(); - return; - } - if (!collision()) { - movePlayer(); - if (System.currentTimeMillis() > getStartTime() + duration || isWater(player.getLocation().getBlock())) { - remove(); - } - } else { - remove(); - } - } - - private void movePlayer() { - location = player.getEyeLocation(); - location.setPitch(0); - Vector dV = location.getDirection().normalize(); - Vector travel; - - if (getPlayerDistance() > 1.8) { - removeFlight(); - travel = new Vector(dV.getX() * speed, -0.09, dV.getZ() * speed); - } else if (getPlayerDistance() < 1.7) { - allowFlight(); - travel = new Vector(dV.getX() * speed, 0.2, dV.getZ() * speed); - } else { - travel = new Vector(dV.getX() * speed, 0, dV.getZ() * speed); - } - - playFirebendingSound(player.getLocation()); - createBeam(); - - if (ignite) { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(player.getLocation().clone().add(0, -1, 0), 2.0)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - FireTick.set(entity, this.fireTicks); - } - } - } - - GeneralMethods.setVelocity(this, player, travel); - player.setFallDistance(0); - } - - private double getPlayerDistance() { - Location l = player.getLocation().clone(); - while (l.getBlockY() > l.getWorld().getMinHeight() && !GeneralMethods.isSolid(l.getBlock())) { - l.add(0, -0.1, 0); - } - return player.getLocation().getY() - l.getY(); - } - - private void createBeam() { - Location right = player.getEyeLocation().add(getRightHeadDirection(player).multiply(1.75)); - right.setPitch(-15); - Location right1 = right.subtract(right.getDirection().multiply(4)).add(0, -1.5, 0); - - Location left = player.getEyeLocation().add(getLeftHeadDirection(player).multiply(1.75)); - left.setPitch(-15); - Location left1 = left.subtract(left.getDirection().multiply(4)).add(0, -1.5, 0); - - double size = 0; - - for (Location l : JCMethods.getLinePoints(player.getEyeLocation().add(0, -0.5, 0).add(getRightHeadDirection(player).multiply(0.2)), right1, 6)) { - size += 0.05; - playFirebendingParticles(l, 4, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01)); - ParticleEffect.SMOKE_NORMAL.display(l, 1, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01), 0.08); - JCMethods.emitLight(l); - } - - size = 0; - for (Location l : JCMethods.getLinePoints(player.getEyeLocation().add(0, -0.5, 0).add(getLeftHeadDirection(player).multiply(0.2)), left1, 6)) { - size += 0.05; - playFirebendingParticles(l, 4, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01)); - ParticleEffect.SMOKE_NORMAL.display(l, 1, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01), 0.08); - JCMethods.emitLight(l); - } - } - - public Vector getRightHeadDirection(Player player) { - Vector direction = player.getLocation().getDirection().normalize(); - return new Vector(-direction.getZ(), 0.0, direction.getX()).normalize(); - } - - public Vector getLeftHeadDirection(Player player) { - Vector direction = player.getLocation().getDirection().normalize(); - return new Vector(direction.getZ(), 0.0, -direction.getX()).normalize(); - } - - private boolean collision() { - Location l = player.getEyeLocation(); - l.setPitch(0); - Vector dV = l.getDirection().normalize(); - l.add(new Vector(dV.getX() * 0.8, 0, dV.getZ() * 0.8)); - - if (l.getBlock().getType().isSolid()) { - return true; - } - if (l.clone().add(0, -1, 0).getBlock().getType().isSolid()) { - return true; - } - return l.clone().add(0, -2, 0).getBlock().getType().isSolid(); - } - - @Override - public void remove() { - removeFlight(); - - this.flightHandler.removeInstance(player, this.getName()); - - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "FireSki"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public void setLocation(Location location) { - this.location = location; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - } - - public boolean isIgnite() { - return ignite; - } - - public void setIgnite(boolean ignite) { - this.ignite = ignite; - } - - public int getFireTicks() { - return fireTicks; - } - - public void setFireTicks(int fireTicks) { - this.fireTicks = fireTicks; - } - - public double getRequiredHeight() { - return requiredHeight; - } - - public void setRequiredHeight(double requiredHeight) { - this.requiredHeight = requiredHeight; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FireSki.Enabled"); - } - - public static boolean isPunchActivated(World world) { - ConfigurationSection config = JedCoreConfig.getConfig(world); - return config.getBoolean("Abilities.Fire.FireSki.PunchActivated"); - } -} diff --git a/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java b/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java deleted file mode 100644 index 2227761..0000000 --- a/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java +++ /dev/null @@ -1,370 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LightningAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; - -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; - -public class LightningBurst extends LightningAbility implements AddonAbility { - - private static final ConcurrentHashMap BOLTS = new ConcurrentHashMap<>(); - - Random rand = new Random(); - @Attribute(Attribute.COOLDOWN) - private long cooldown, avatarCooldown; - @Attribute(Attribute.CHARGE_DURATION) - private long chargeUp, avatarChargeup; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.RADIUS) - private double radius; - - private boolean charged; - private static int ID = Integer.MIN_VALUE; - - private float soundVolume; - private int soundInterval; - - public LightningBurst(Player player) { - super(player); - if (!bPlayer.canBend(this) || hasAbility(player, LightningBurst.class)) { - return; - } - - setFields(); - if (bPlayer.isAvatarState() || JCMethods.isSozinsComet(player.getWorld())) { - chargeUp = avatarChargeup; - cooldown = avatarCooldown; - } - - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.LightningBurst.Cooldown"); - chargeUp = config.getLong("Abilities.Fire.LightningBurst.ChargeUp"); - avatarCooldown = config.getLong("Abilities.Fire.LightningBurst.AvatarCooldown"); - avatarChargeup = config.getLong("Abilities.Fire.LightningBurst.AvatarChargeUp"); - damage = config.getDouble("Abilities.Fire.LightningBurst.Damage"); - radius = config.getDouble("Abilities.Fire.LightningBurst.Radius"); - - soundVolume = (float) config.getDouble("Abilities.Fire.LightningBurst.Sound.Volume"); - soundInterval = config.getInt("Abilities.Fire.LightningBurst.Sound.Interval"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - if (RegionProtection.isRegionProtected(player, player.getLocation(), this)) { - remove(); - return; - } - if (!player.isSneaking()) { - if (!isCharging()) { - Location fake = player.getLocation().add(0, -2, 0); - fake.setPitch(0); - for (int i = -180; i < 180; i += 55) { - fake.setYaw(i); - for (double j = -180; j <= 180; j += 55) { - Location temp = fake.clone(); - Vector dir = fake.getDirection().clone().multiply(2 * Math.cos(Math.toRadians(j))); - temp.add(dir); - temp.setY(temp.getY() + 2 + (2 * Math.sin(Math.toRadians(j)))); - dir = GeneralMethods.getDirection(player.getLocation().add(0, 0, 0), temp); - spawnBolt(player.getLocation().clone().add(0, 1, 0).setDirection(dir), radius, 1, 20, true); - } - } - bPlayer.addCooldown(this); - } - remove(); - } else if (System.currentTimeMillis() > getStartTime() + chargeUp){ - setCharging(false); - displayCharging(); - } - } - - private void spawnBolt(Location location, double max, double gap, int arc, boolean doDamage) { - int id = ID; - BOLTS.put(id, new Bolt(this, location, id, max, gap, arc, doDamage)); - if (ID == Integer.MAX_VALUE) - ID = Integer.MIN_VALUE; - ID++; - } - - private void displayCharging() { - Location fake = player.getLocation().add(0, 0, 0); - fake.setPitch(0); - for (int i = -180; i < 180; i += 55) { - fake.setYaw(i); - for (double j = -180; j <= 180; j += 55) { - if (rand.nextInt(100) == 0) { - Location temp = fake.clone(); - Vector dir = fake.getDirection().clone().multiply(1.2 * Math.cos(Math.toRadians(j))); - temp.add(dir); - temp.setY(temp.getY() + 1.2 + (1.2 * Math.sin(Math.toRadians(j)))); - dir = GeneralMethods.getDirection(temp, player.getLocation().add(0, 1, 0)); - spawnBolt(temp.setDirection(dir), 1, 0.2, 20, false); - } - } - } - } - - public static void progressAll() { - BOLTS.values().forEach(Bolt::progress); - } - - public boolean isCharging() { - return !charged; - } - - public void setCharging(boolean charging) { - this.charged = !charging; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "LightningBurst"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.LightningBurst.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getAvatarCooldown() { - return avatarCooldown; - } - - public void setAvatarCooldown(long avatarCooldown) { - this.avatarCooldown = avatarCooldown; - } - - public long getChargeUp() { - return chargeUp; - } - - public void setChargeUp(long chargeUp) { - this.chargeUp = chargeUp; - } - - public long getAvatarChargeup() { - return avatarChargeup; - } - - public void setAvatarChargeup(long avatarChargeup) { - this.avatarChargeup = avatarChargeup; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getRadius() { - return radius; - } - - public void setRadius(double radius) { - this.radius = radius; - } - - public boolean isCharged() { - return charged; - } - - public void setCharged(boolean charged) { - this.charged = charged; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.LightningBurst.Enabled"); - } - - public class Bolt { - - private final LightningBurst ability; - private Location location; - private final float initYaw; - private final float initPitch; - private double step; - private final double max; - private final double gap; - private final int id; - private final int arc; - private final boolean doDamage; - - public Bolt(LightningBurst ability, Location location, int id, double max, double gap, int arc, boolean doDamage) { - this.ability = ability; - this.location = location; - this.id = id; - this.max = max; - this.arc = arc; - this.gap = gap; - this.doDamage = doDamage; - initYaw = location.getYaw(); - initPitch = location.getPitch(); - } - - private void progress() { - if (this.step >= max) { - BOLTS.remove(id); - return; - } - if (RegionProtection.isRegionProtected(player, location, LightningBurst.this) || !isTransparent(location.getBlock())) { - BOLTS.remove(id); - return; - } - double step = 0.2; - for (double i = 0; i < gap; i+= step) { - this.step += step; - location = location.add(location.getDirection().clone().multiply(step)); - - playLightningbendingParticle(location, 0f, 0f, 0f); - JCMethods.emitLight(location); - } - switch (rand.nextInt(3)) { - case 0: - location.setYaw(initYaw - arc); - break; - case 1: - location.setYaw(initYaw + arc); - break; - default: - location.setYaw(initYaw); - break; - } - switch (rand.nextInt(3)) { - case 0: - location.setPitch(initPitch - arc); - break; - case 1: - location.setPitch(initPitch + arc); - break; - default: - location.setPitch(initPitch); - break; - } - - if (rand.nextInt(soundInterval) == 0) { - location.getWorld().playSound(location, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); - } - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && doDamage) { - DamageHandler.damageEntity(entity, damage, ability); - } - } - } - - public LightningBurst getAbility() { - return ability; - } - - public Location getLocation() { - return location; - } - - public float getInitYaw() { - return initYaw; - } - - public float getInitPitch() { - return initPitch; - } - - public double getStep() { - return step; - } - - public double getMax() { - return max; - } - - public double getGap() { - return gap; - } - - public int getId() { - return id; - } - - public int getArc() { - return arc; - } - - public boolean isDoDamage() { - return doDamage; - } - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/passive/WallRun.java b/src/com/jedk1/jedcore/ability/passive/WallRun.java deleted file mode 100644 index 816dab9..0000000 --- a/src/com/jedk1/jedcore/ability/passive/WallRun.java +++ /dev/null @@ -1,264 +0,0 @@ -package com.jedk1.jedcore.ability.passive; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.List; - -public class WallRun extends ChiAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - - private boolean enabled; - - private boolean particles; - private boolean air; - private boolean earth; - private boolean water; - private boolean fire; - private boolean chi; - - private List invalid; - - public WallRun(Player player) { - super(player); - - setFields(); - if (!enabled) return; - - if (bPlayer.isOnCooldown("WallRun")) return; - - if (hasAbility(player, WallRun.class)) { - getAbility(player, WallRun.class).remove(); - return; - } - - if (player.getGameMode().equals(GameMode.SPECTATOR)) { - return; - } - - if (isEligible() && !JCMethods.isDisabledWorld(player.getWorld())) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - enabled = config.getBoolean("Abilities.Passives.WallRun.Enabled"); - cooldown = config.getLong("Abilities.Passives.WallRun.Cooldown"); - duration = config.getLong("Abilities.Passives.WallRun.Duration"); - particles = config.getBoolean("Abilities.Passives.WallRun.Particles"); - air = config.getBoolean("Abilities.Passives.WallRun.Air"); - earth = config.getBoolean("Abilities.Passives.WallRun.Earth"); - water = config.getBoolean("Abilities.Passives.WallRun.Water"); - fire = config.getBoolean("Abilities.Passives.WallRun.Fire"); - chi = config.getBoolean("Abilities.Passives.WallRun.Chi"); - invalid = config.getStringList("Abilities.Passives.WallRun.InvalidBlocks"); - } - - private boolean isEligible() { - if (!player.isSprinting()) - return false; - - if (!bPlayer.isToggled()) { - return false; - } - - if (bPlayer.getElements().contains(Element.AIR) && air) { - return true; - } else if (bPlayer.getElements().contains(Element.EARTH) && earth) { - return true; - } else if (bPlayer.getElements().contains(Element.WATER) && water) { - return true; - } else if (bPlayer.getElements().contains(Element.FIRE) && fire) { - return true; - } else return bPlayer.getElements().contains(Element.CHI) && chi; - } - - private boolean isAgainstWall() { - Location location = player.getLocation(); - if (location.getBlock().getRelative(BlockFace.NORTH).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.NORTH).getType().name())) { - return true; - } else if (location.getBlock().getRelative(BlockFace.SOUTH).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.SOUTH).getType().name())) { - return true; - } else if (location.getBlock().getRelative(BlockFace.WEST).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.WEST).getType().name())) { - return true; - } else return location.getBlock().getRelative(BlockFace.EAST).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.EAST).getType().name()); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline() || player.isOnGround()) { - remove(); - return; - } - if (!isAgainstWall()) { - remove(); - return; - } - if (System.currentTimeMillis() > getStartTime() + duration) { - remove(); - return; - } - - if (System.currentTimeMillis() - getStartTime() > 50L) { - bPlayer.addCooldown("WallRun", getCooldown()); - } - - if (particles) { - ParticleEffect.CRIT.display(player.getLocation(), 4, Math.random(), Math.random(), Math.random(), 0); - ParticleEffect.BLOCK_CRACK.display(player.getLocation(), 3, Math.random(), Math.random(), Math.random(), 0.1, Material.STONE.createBlockData()); - AirAbility.playAirbendingParticles(player.getLocation(), 5); - } - - Vector dir = player.getLocation().getDirection(); - dir.multiply(1.15); - GeneralMethods.setVelocity(this, player, dir); - } - - public long getCooldown() { - return cooldown; - } - - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "WallRun"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return "To use WallRun, sprint towards a wall, jump, then rapidly click to activate. You don't have to bind this ability to use it. It is a passive."; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public boolean hasParticles() { - return particles; - } - - public void setHasParticles(boolean particles) { - this.particles = particles; - } - - public boolean allowsAir() { - return air; - } - - public void setAllowsAir(boolean air) { - this.air = air; - } - - public boolean allowsEarth() { - return earth; - } - - public void setAllowsEarth(boolean earth) { - this.earth = earth; - } - - public boolean allowsWater() { - return water; - } - - public void setAllowsWater(boolean water) { - this.water = water; - } - - public boolean allowsFire() { - return fire; - } - - public void setAllowsFire(boolean fire) { - this.fire = fire; - } - - public boolean allowsChi() { - return chi; - } - - public void setAllowsChi(boolean chi) { - this.chi = chi; - } - - public List getInvalid() { - return invalid; - } - - public void setInvalid(List invalid) { - this.invalid = invalid; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Passives.WallRun.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java b/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java deleted file mode 100644 index 52e2078..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java +++ /dev/null @@ -1,523 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.BloodAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.Blaze; -import org.bukkit.entity.Creature; -import org.bukkit.entity.Creeper; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Fireball; -import org.bukkit.entity.Ghast; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Skeleton; -import org.bukkit.entity.ThrownPotion; -import org.bukkit.entity.Witch; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class BloodPuppet extends BloodAbility implements AddonAbility { - - private boolean nightOnly; - private boolean fullMoonOnly; - private boolean undeadMobs; - private boolean bloodPuppetThroughBlocks; - private boolean requireBound; - private int distance; - @Attribute(Attribute.DURATION) - private long holdTime; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - private long endTime; - - public LivingEntity puppet; - private long lastDamageTime = 0; - - Random rand = new Random(); - - public BloodPuppet(Player player) { - super(player); - if (!isEligible(player, true)) { - return; - } - - setFields(); - endTime = System.currentTimeMillis() + holdTime; - - if (grab()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - nightOnly = config.getBoolean("Abilities.Water.BloodPuppet.NightOnly"); - fullMoonOnly = config.getBoolean("Abilities.Water.BloodPuppet.FullMoonOnly"); - undeadMobs = config.getBoolean("Abilities.Water.BloodPuppet.UndeadMobs"); - bloodPuppetThroughBlocks = config.getBoolean("Abilities.Water.BloodPuppet.IgnoreWalls"); - requireBound = config.getBoolean("Abilities.Water.BloodPuppet.RequireBound"); - distance = config.getInt("Abilities.Water.BloodPuppet.Distance"); - holdTime = config.getLong("Abilities.Water.BloodPuppet.HoldTime"); - cooldown = config.getLong("Abilities.Water.BloodPuppet.Cooldown"); - } - - public boolean isEligible(Player player, boolean hasAbility) { - if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, BloodPuppet.class))) { - return false; - } - if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { - return false; - } - return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); - } - - private boolean canAttack() { - switch (puppet.getType()) { - case SKELETON: - case SPIDER: - case GIANT: - case ZOMBIE: - case SLIME: - case GHAST: - case PIGLIN: - case ZOMBIFIED_PIGLIN: - case ENDERMAN: - case CAVE_SPIDER: - case SILVERFISH: - case BLAZE: - case MAGMA_CUBE: - case WITCH: - case ENDERMITE: - case DROWNED: - case PLAYER: - return true; - default: - return false; - } - } - - private boolean grab() { - List entities = new ArrayList<>(); - for (int i = 1; i < distance; i++) { - Location location; - if (bloodPuppetThroughBlocks) { - location = player.getTargetBlock(null, i).getLocation(); - } else { - location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); - } - entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); - entities.remove(player); - if (!entities.isEmpty() && !entities.contains(player)) { - break; - } - } - if (entities.isEmpty()) { - return false; - } - Entity e = entities.get(0); - - if (e == null) - return false; - - if (!(e instanceof LivingEntity)) - return false; - - if (!undeadMobs && GeneralMethods.isUndead(e)) - return false; - - if ((e instanceof Player) && !canBeBloodbent((Player) e)) { - return false; - } - if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { - return false; - } - - for (BloodPuppet bb : getAbilities(BloodPuppet.class)) { - if (bb.puppet.getEntityId() == e.getEntityId()) { - return false; - } - } - - puppet = (LivingEntity) e; - DamageHandler.damageEntity(puppet, 0, this); - if (puppet instanceof Creature) - ((Creature) puppet).setTarget(null); - - if (e instanceof Player && BendingPlayer.getBendingPlayer((Player) e) != null) { - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer((Player) e); - bPlayer.blockChi(); - } - - return true; - } - - private boolean canBeBloodbent(Player player) { - if (Commands.invincible.contains(player.getName())) { - return false; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (requireBound) { - if (bPlayer.getAbilities().containsValue("Bloodbending")) { - return false; - } - return !bPlayer.getAbilities().containsValue("BloodPuppet"); - } else { - if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { - return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); - } - } - return true; - } - - public static void attack(Player player) { - if (hasAbility(player, BloodPuppet.class)) { - getAbility(player, BloodPuppet.class).attack(); - } - } - - private void attack() { - if (!canAttack()) - return; - - long damageCd = 0; - if (System.currentTimeMillis() > lastDamageTime + damageCd) { - lastDamageTime = System.currentTimeMillis(); - - if (puppet instanceof Skeleton) { - Skeleton skelly = (Skeleton) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(skelly.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); - Arrow a = puppet.getWorld().spawnArrow(loc, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()), 0.6f, 12); - a.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else if (puppet instanceof Creeper) { - Creeper creep = (Creeper) puppet; - creep.setPowered(true); - } - - else if (puppet instanceof Ghast) { - Ghast gaga = (Ghast) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(gaga.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); - Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); - fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.25)); - fb.setIsIncendiary(true); - fb.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else if (puppet instanceof Blaze) { - Blaze balawalaze = (Blaze) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(balawalaze.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); - Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); - fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.5)); - fb.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else if (puppet instanceof Witch) { - Witch missmagus = (Witch) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(missmagus.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - ThrownPotion tp = missmagus.launchProjectile(ThrownPotion.class, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation())); - ItemStack potionItem = new ItemStack(Material.SPLASH_POTION, 1); - PotionMeta potion = (PotionMeta) potionItem.getItemMeta(); - potion.setBasePotionType(JedCore.plugin.getPotionEffectAdapter().getHarmingPotionType()); - potionItem.setItemMeta(potion); - tp.setItem(potionItem); - tp.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.125)); - tp.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(puppet.getLocation(), 2)) { - if (e.getEntityId() == puppet.getEntityId()) - continue; - - if (e instanceof LivingEntity) { - int damage = 2; - if (puppet instanceof Player) { - Player p = (Player) puppet; - - switch (p.getInventory().getItemInMainHand().getType()) { - case WOODEN_SWORD: - case GOLDEN_SWORD: - damage = 5; - break; - case STONE_SWORD: - damage = 6; - break; - case IRON_SWORD: - damage = 7; - break; - case DIAMOND_SWORD: - damage = 8; - break; - default: - break; - } - } - ((LivingEntity) e).damage(damage, puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - } - } - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - if (!isEligible(player, false)) { - remove(); - return; - } - - if (!player.isSneaking()) { - remove(); - return; - } - - if (System.currentTimeMillis() > endTime) { - remove(); - return; - } - - if ((puppet instanceof Player && !((Player) puppet).isOnline()) || puppet.isDead()) { - remove(); - return; - } - - Location newLocation = puppet.getLocation(); - - Location location = GeneralMethods.getTargetedLocation(player, distance + 1); - double distance = location.distance(newLocation); - double dx, dy, dz; - dx = location.getX() - newLocation.getX(); - dy = location.getY() - newLocation.getY(); - dz = location.getZ() - newLocation.getZ(); - Vector vector = new Vector(dx, dy, dz); - if (distance > .5) { - puppet.setVelocity(vector.normalize().multiply(.5)); - } else { - puppet.setVelocity(new Vector(0, 0, 0)); - } - puppet.setFallDistance(0); - if (puppet instanceof Creature) { - ((Creature) puppet).setTarget(null); - } - AirAbility.breakBreathbendingHold(puppet); - } - - @Override - public void remove() { - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - if (puppet instanceof Player && ((Player) puppet).isOnline()) { - BendingPlayer.getBendingPlayer((Player) puppet).unblockChi(); - } - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "BloodPuppet"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.BloodPuppet.Description"); - } - - public boolean isNightOnly() { - return nightOnly; - } - - public void setNightOnly(boolean nightOnly) { - this.nightOnly = nightOnly; - } - - public boolean isFullMoonOnly() { - return fullMoonOnly; - } - - public void setFullMoonOnly(boolean fullMoonOnly) { - this.fullMoonOnly = fullMoonOnly; - } - - public boolean isUndeadMobs() { - return undeadMobs; - } - - public void setUndeadMobs(boolean undeadMobs) { - this.undeadMobs = undeadMobs; - } - - public boolean canBloodPuppetThroughBlocks() { - return bloodPuppetThroughBlocks; - } - - public void setCanBloodPuppetThroughBlocks(boolean bloodPuppetThroughBlocks) { - this.bloodPuppetThroughBlocks = bloodPuppetThroughBlocks; - } - - public boolean requiresBound() { - return requireBound; - } - - public void setRequireBound(boolean requireBound) { - this.requireBound = requireBound; - } - - public int getDistance() { - return distance; - } - - public void setDistance(int distance) { - this.distance = distance; - } - - public long getHoldTime() { - return holdTime; - } - - public void setHoldTime(long holdTime) { - this.holdTime = holdTime; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; - } - - public LivingEntity getPuppet() { - return puppet; - } - - public void setPuppet(LivingEntity puppet) { - this.puppet = puppet; - } - - public long getLastDamageTime() { - return lastDamageTime; - } - - public void setLastDamageTime(long lastDamageTime) { - this.lastDamageTime = lastDamageTime; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.BloodPuppet.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java b/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java deleted file mode 100644 index d19cabb..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java +++ /dev/null @@ -1,380 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.ThrownEntityTracker; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.BloodAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Creature; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class Bloodbending extends BloodAbility implements AddonAbility { - - private boolean nightOnly; - private boolean fullMoonOnly; - private boolean undeadMobs; - private boolean bloodbendingThroughBlocks; - private boolean requireBound; - private int distance; - @Attribute(Attribute.DURATION) - private long holdTime; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - private long time; - public LivingEntity victim; - private BendingPlayer victimBPlayer; - private boolean grabbed; - - public Bloodbending(Player player) { - super(player); - if (this.player == null || !isEligible(player, true)) { - return; - } - setFields(); - time = System.currentTimeMillis() + holdTime; - if (grab()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - nightOnly = config.getBoolean("Abilities.Water.Bloodbending.NightOnly"); - fullMoonOnly = config.getBoolean("Abilities.Water.Bloodbending.FullMoonOnly"); - undeadMobs = config.getBoolean("Abilities.Water.Bloodbending.UndeadMobs"); - bloodbendingThroughBlocks = config.getBoolean("Abilities.Water.Bloodbending.IgnoreWalls"); - requireBound = config.getBoolean("Abilities.Water.Bloodbending.RequireBound"); - distance = config.getInt("Abilities.Water.Bloodbending.Distance"); - holdTime = config.getLong("Abilities.Water.Bloodbending.HoldTime"); - cooldown = config.getLong("Abilities.Water.Bloodbending.Cooldown"); - } - - public boolean isEligible(Player player, boolean hasAbility) { - if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, Bloodbending.class))) { - return false; - } - if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { - return false; - } - return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); - } - - public static void launch(Player player) { - if (hasAbility(player, Bloodbending.class)) { - getAbility(player, Bloodbending.class).launch(); - } - } - - private void launch() { - if (Arrays.asList(ElementalAbility.getTransparentMaterials()).contains(player.getEyeLocation().getBlock().getType())) { - Vector direction = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, 20, ElementalAbility.getTransparentMaterials())).normalize().multiply(3); - if (!victim.isDead()) { - victim.setVelocity(direction); - - new HorizontalVelocityTracker(victim, player, 200L, this); - new ThrownEntityTracker(this, victim, player, 200L); - } - remove(); - } - } - - private boolean grab() { - List entities = new ArrayList<>(); - for (int i = 1; i < distance; i++) { - Location location; - if (bloodbendingThroughBlocks) { - location = player.getTargetBlock(null, i).getLocation(); - } else { - location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); - } - entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); - entities.remove(player); - - if (!entities.isEmpty() && !entities.contains(player)) { - break; - } - } - if (entities.isEmpty()) { - return false; - } - Entity e = entities.get(0); - if (e == null) { - return false; - } - if (!(e instanceof LivingEntity)) { - return false; - } - if (e instanceof ArmorStand) { - return false; - } - if (!undeadMobs && GeneralMethods.isUndead(e)) { - return false; - } - if ((e instanceof Player) && !canBeBloodbent((Player) e)) { - return false; - } - if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { - return false; - } - for (Bloodbending bb : getAbilities(Bloodbending.class)) { - if (bb.victim.getEntityId() == e.getEntityId()) { - return false; - } - } - - victim = (LivingEntity) e; - DamageHandler.damageEntity(victim, 0, this); - HorizontalVelocityTracker.remove(victim); - if (victim instanceof Creature) { - ((Creature) victim).setTarget(null); - } - if ((e instanceof Player) && BendingPlayer.getBendingPlayer((Player) e) != null) { - victimBPlayer = BendingPlayer.getBendingPlayer((Player) e); - } - return true; - } - - private boolean canBeBloodbent(Player player) { - if (Commands.invincible.contains(player.getName())) { - return false; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (requireBound) { - if (bPlayer.getAbilities().containsValue("Bloodbending")) { - return false; - } - return !bPlayer.getAbilities().containsValue("BloodPuppet"); - } else { - if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { - return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); - } - } - return true; - } - - @Override - public void progress() { - if (!isEligible(player, false)) { - remove(); - return; - } - if (!grabbed) { - if (victim instanceof Player && victimBPlayer != null) { - victimBPlayer.blockChi(); - grabbed = true; - } - } - - if (!player.isSneaking()) { - remove(); - return; - } - if (!player.isOnline() || player.isDead()) { - remove(); - return; - } - if (System.currentTimeMillis() > time) { - remove(); - return; - } - if (victim.isDead()) { - remove(); - return; - } - if ((victim instanceof Player) && !((Player) victim).isOnline()) { - remove(); - return; - } - Location oldLocation = victim.getLocation(); - Location loc = GeneralMethods.getTargetedLocation(player, (int) player.getLocation().distance(oldLocation)); - double distance = loc.distance(oldLocation); - Vector v = GeneralMethods.getDirection(oldLocation, GeneralMethods.getTargetedLocation(player, 10)); - if (distance > 1.2D) { - victim.setVelocity(v.normalize().multiply(0.8D)); - } else { - victim.setVelocity(new Vector(0, 0, 0)); - } - victim.setFallDistance(0.0F); - if (victim instanceof Creature) { - ((Creature) victim).setTarget(null); - } - AirAbility.breakBreathbendingHold(victim); - } - - @Override - public void remove() { - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - if (victim instanceof Player && victimBPlayer != null) { - victimBPlayer.unblockChi(); - } - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "Bloodbending"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.Bloodbending.Description"); - } - - public boolean isNightOnly() { - return nightOnly; - } - - public void setNightOnly(boolean nightOnly) { - this.nightOnly = nightOnly; - } - - public boolean isFullMoonOnly() { - return fullMoonOnly; - } - - public void setFullMoonOnly(boolean fullMoonOnly) { - this.fullMoonOnly = fullMoonOnly; - } - - public boolean isUndeadMobs() { - return undeadMobs; - } - - public void setUndeadMobs(boolean undeadMobs) { - this.undeadMobs = undeadMobs; - } - - public boolean isBloodbendingThroughBlocks() { - return bloodbendingThroughBlocks; - } - - public void setBloodbendingThroughBlocks(boolean bloodbendingThroughBlocks) { - this.bloodbendingThroughBlocks = bloodbendingThroughBlocks; - } - - public boolean isRequireBound() { - return requireBound; - } - - public void setRequireBound(boolean requireBound) { - this.requireBound = requireBound; - } - - public int getDistance() { - return distance; - } - - public void setDistance(int distance) { - this.distance = distance; - } - - public long getHoldTime() { - return holdTime; - } - - public void setHoldTime(long holdTime) { - this.holdTime = holdTime; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public LivingEntity getVictim() { - return victim; - } - - public void setVictim(LivingEntity victim) { - this.victim = victim; - } - - public BendingPlayer getVictimBPlayer() { - return victimBPlayer; - } - - public void setVictimBPlayer(BendingPlayer victimBPlayer) { - this.victimBPlayer = victimBPlayer; - } - - public boolean isGrabbed() { - return grabbed; - } - - public void setGrabbed(boolean grabbed) { - this.grabbed = grabbed; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.Bloodbending.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/Drain.java b/src/com/jedk1/jedcore/ability/waterbending/Drain.java deleted file mode 100644 index 8be1480..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/Drain.java +++ /dev/null @@ -1,604 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.util.WaterReturn; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.block.data.Waterlogged; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; - -public class Drain extends WaterAbility implements AddonAbility { - - private final List locations = new ArrayList<>(); - static final Set WATER_TEMPS = new HashSet<>(); - - //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. - private static float MAX_TEMP = 1.0F; - private static float MIN_HUMIDITY = 0.01F; - - private long regenDelay; - @Attribute(Attribute.DURATION) - private long duration; // 2000 - @Attribute(Attribute.COOLDOWN) - private long cooldown; // 2000 - private double absorbSpeed; // 0.1 - @Attribute(Attribute.RADIUS) - private int radius; // 6 - @Attribute("Chance") - private int chance; // 20 - private int absorbRate; // 6 - private int holdRange; // 2 - private boolean blastsEnabled; // true - private int maxBlasts; - private boolean keepSrc; // false - private boolean useRain; - private boolean usePlants; - - private double blastRange; // 20 - private double blastDamage; // 1.5 - private double blastSpeed; // 2 - - private boolean drainTemps; - - private long endTime; - private int absorbed = 0; - private int charge = 7; - private boolean noFill; - private int blasts; - private boolean hasCharge; - private final Material[] fillables = { Material.GLASS_BOTTLE, Material.BUCKET }; - - Random rand = new Random(); - - public Drain(Player player) { - super(player); - if (!bPlayer.canBend(this) || hasAbility(player, Drain.class)) { - return; - } - setFields(); - this.usePlants = bPlayer.canPlantbend(); - endTime = System.currentTimeMillis() + duration; - if (!canFill()) { - if (!blastsEnabled) - return; - noFill = true; - } - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - regenDelay = config.getLong("Abilities.Water.Drain.RegenDelay"); - duration = config.getLong("Abilities.Water.Drain.Duration"); - cooldown = config.getLong("Abilities.Water.Drain.Cooldown"); - absorbSpeed = config.getDouble("Abilities.Water.Drain.AbsorbSpeed"); - radius = config.getInt("Abilities.Water.Drain.Radius"); - chance = config.getInt("Abilities.Water.Drain.AbsorbChance"); - absorbRate = config.getInt("Abilities.Water.Drain.AbsorbRate"); - holdRange = config.getInt("Abilities.Water.Drain.HoldRange"); - blastsEnabled = config.getBoolean("Abilities.Water.Drain.BlastsEnabled"); - maxBlasts = config.getInt("Abilities.Water.Drain.MaxBlasts"); - keepSrc = config.getBoolean("Abilities.Water.Drain.KeepSource"); - blastRange = config.getDouble("Abilities.Water.Drain.BlastRange"); - blastDamage = config.getDouble("Abilities.Water.Drain.BlastDamage"); - blastSpeed = config.getDouble("Abilities.Water.Drain.BlastSpeed"); - useRain = config.getBoolean("Abilities.Water.Drain.AllowRainSource"); - drainTemps = config.getBoolean("Abilities.Water.Drain.DrainTempBlocks"); - - applyModifiers(); - } - - private void applyModifiers() { - if (isNight(player.getWorld())) { - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - blastRange = getNightFactor(blastRange); - blastDamage = getNightFactor(blastDamage); - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (!noFill) { - if (!player.isSneaking()) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (!canFill()) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (System.currentTimeMillis() > endTime) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (absorbed >= absorbRate) { - fill(); - absorbed = 0; - } - checkForValidSource(); - } else { - if (blasts >= maxBlasts) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (player.isSneaking()) { - if (charge >= 2) { - checkForValidSource(); - } - if (absorbed >= absorbRate) { - hasCharge = true; - absorbed = 0; - if (charge >= 3) { - charge -= 2; - } - } - } else if (!hasCharge || !keepSrc) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (hasCharge) { - displayWaterSource(); - } - } - dragWater(); - } - - public static void fireBlast(Player player) { - if (hasAbility(player, Drain.class)) { - getAbility(player, Drain.class).fireBlast(); - } - } - - private void fireBlast() { - if (charge <= 1) { - hasCharge = false; - charge = 7; - blasts++; - new DrainBlast(player, blastRange, blastDamage, blastSpeed, holdRange); - } - } - - private void displayWaterSource() { - Location location = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)); - Block block = location.getBlock(); - if (!GeneralMethods.isSolid(block) || isTransparent(block)) { - TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(charge)), 100L); - WATER_TEMPS.add(tb); - tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); - } - } - - private boolean canFill() { - for (ItemStack items : player.getInventory()) { - if (items != null && Arrays.asList(fillables).contains(items.getType())) { - return true; - } - } - return false; - } - - private void fill() { - for (int x = 0; x < absorbed; x++) { - for (Material fillable : fillables) { - int slot = player.getInventory().first(fillable); - if (slot == -1){ - continue; - } - if (player.getInventory().getItem(slot).getAmount() > 1) { - player.getInventory().getItem(slot).setAmount(player.getInventory().getItem(slot).getAmount() - 1); - - ItemStack filled = getFilled(fillable); - HashMap cantfit = player.getInventory().addItem(filled); - for (int id : cantfit.keySet()) { - player.getWorld().dropItem(player.getEyeLocation(), cantfit.get(id)); - } - } else { - player.getInventory().setItem(slot, getFilled(fillable)); - } - break; - } - } - } - - private ItemStack getFilled(Material type) { - ItemStack filled = null; - if (type == Material.GLASS_BOTTLE) { - filled = WaterReturn.waterBottleItem(); - } else if (type == Material.BUCKET) { - filled = new ItemStack(Material.WATER_BUCKET, 1); - } - - return filled; - } - - private void checkForValidSource() { - List locs = GeneralMethods.getCircle(player.getLocation(), radius, radius, false, true, 0); - for (int i = 0; i < locs.size(); i++) { - Block block = locs.get(rand.nextInt(locs.size()-1)).getBlock(); - if (rand.nextInt(chance) == 0) { - Location pLoc = player.getLocation(); - World world = pLoc.getWorld(); - double temp = world.getTemperature(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); - double humidity = world.getHumidity(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); - if (block.getY() > world.getMinHeight() && block.getY() < world.getMaxHeight()) { - Location bLoc = block.getLocation(); - if (useRain && world.hasStorm() && !(temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { - if (pLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { - if (bLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { - locations.add(bLoc.clone().add(.5, .5, .5)); - return; - } - } - } - if (usePlants && JCMethods.isSmallPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { - drainPlant(block); - } else if (usePlants && ElementalAbility.isPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { - locations.add(bLoc.clone().add(.5, .5, .5)); - new TempBlock(block, Material.AIR.createBlockData(), regenDelay); - } else if (isWater(block)) { - TempBlock tb = TempBlock.get(block); - if ((tb == null || (drainTemps && !WATER_TEMPS.contains(tb)))) { - drainWater(block); - } - } - } - } - } - } - - private boolean isObstructed(Location location1, Location location2) { - Vector loc1 = location1.toVector(); - Vector loc2 = location2.toVector(); - - Vector direction = loc2.subtract(loc1); - direction.normalize(); - - Location loc; - - double max = location1.distance(location2); - - for (double i = 1; i <= max; i++) { - loc = location1.clone().add(direction.clone().multiply(i)); - if (!isTransparent(loc.getBlock())) - return true; - } - - return false; - } - - private void drainPlant(Block block) { - if (JCMethods.isSmallPlant(block)) { - if (JCMethods.isSmallPlant(block.getRelative(BlockFace.DOWN))) { - if (JCMethods.isDoublePlant(block.getType())) { - block = block.getRelative(BlockFace.DOWN); - locations.add(block.getLocation().clone().add(.5, .5, .5)); - new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); - return; - } - block = block.getRelative(BlockFace.DOWN); - } - locations.add(block.getLocation().clone().add(.5, .5, .5)); - new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); - } - } - - private void drainWater(Block block) { - if (isTransparent(block.getRelative(BlockFace.UP)) && !isWater(block.getRelative(BlockFace.UP))) { - locations.add(block.getLocation().clone().add(.5, .5, .5)); - if (block.getBlockData() instanceof Waterlogged) { - new TempBlock(block, block.getType().createBlockData(bd -> ((Waterlogged) bd).setWaterlogged(false)), regenDelay); - } else { - TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(1)), regenDelay); - WATER_TEMPS.add(tb); - tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); - } - } - } - - private void dragWater() { - List toRemove = new ArrayList<>(); - if (!locations.isEmpty()) { - for (Location l : locations) { - Location playerLoc = player.getLocation().add(0, 1, 0); - if (noFill) - playerLoc = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)).subtract(0, .8, 0); - Vector dir = GeneralMethods.getDirection(l, playerLoc); - l = l.add(dir.multiply(absorbSpeed)); - ParticleEffect.WATER_SPLASH.display(l, 1, 0, 0, 0, 0); - GeneralMethods.displayColoredParticle("0099FF", l); - if (l.distance(playerLoc) < 1) { - toRemove.add(locations.indexOf(l)); - absorbed++; - } - } - } - if (!toRemove.isEmpty()) { - for (int i : toRemove) { - if (i < locations.size()) - locations.remove(i); - } - toRemove.clear(); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "Drain"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.Drain.Description"); - } - - @Override - public List getLocations() { - return locations; - } - - public long getRegenDelay() { - return regenDelay; - } - - public void setRegenDelay(long regenDelay) { - this.regenDelay = regenDelay; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public double getAbsorbSpeed() { - return absorbSpeed; - } - - public void setAbsorbSpeed(double absorbSpeed) { - this.absorbSpeed = absorbSpeed; - } - - public int getRadius() { - return radius; - } - - public void setRadius(int radius) { - this.radius = radius; - } - - public int getChance() { - return chance; - } - - public void setChance(int chance) { - this.chance = chance; - } - - public int getAbsorbRate() { - return absorbRate; - } - - public void setAbsorbRate(int absorbRate) { - this.absorbRate = absorbRate; - } - - public int getHoldRange() { - return holdRange; - } - - public void setHoldRange(int holdRange) { - this.holdRange = holdRange; - } - - public boolean isBlastsEnabled() { - return blastsEnabled; - } - - public void setBlastsEnabled(boolean blastsEnabled) { - this.blastsEnabled = blastsEnabled; - } - - public int getMaxBlasts() { - return maxBlasts; - } - - public void setMaxBlasts(int maxBlasts) { - this.maxBlasts = maxBlasts; - } - - public boolean isKeepSrc() { - return keepSrc; - } - - public void setKeepSrc(boolean keepSrc) { - this.keepSrc = keepSrc; - } - - public boolean isUseRain() { - return useRain; - } - - public void setUseRain(boolean useRain) { - this.useRain = useRain; - } - - public boolean isUsePlants() { - return usePlants; - } - - public void setUsePlants(boolean usePlants) { - this.usePlants = usePlants; - } - - public double getBlastRange() { - return blastRange; - } - - public void setBlastRange(double blastRange) { - this.blastRange = blastRange; - } - - public double getBlastDamage() { - return blastDamage; - } - - public void setBlastDamage(double blastDamage) { - this.blastDamage = blastDamage; - } - - public double getBlastSpeed() { - return blastSpeed; - } - - public void setBlastSpeed(double blastSpeed) { - this.blastSpeed = blastSpeed; - } - - public boolean isDrainTemps() { - return drainTemps; - } - - public void setDrainTemps(boolean drainTemps) { - this.drainTemps = drainTemps; - } - - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; - } - - public int getAbsorbed() { - return absorbed; - } - - public void setAbsorbed(int absorbed) { - this.absorbed = absorbed; - } - - public int getCharge() { - return charge; - } - - public void setCharge(int charge) { - this.charge = charge; - } - - public boolean isNoFill() { - return noFill; - } - - public void setNoFill(boolean noFill) { - this.noFill = noFill; - } - - public int getBlasts() { - return blasts; - } - - public void setBlasts(int blasts) { - this.blasts = blasts; - } - - public boolean isHasCharge() { - return hasCharge; - } - - public void setHasCharge(boolean hasCharge) { - this.hasCharge = hasCharge; - } - - public Material[] getFillables() { - return fillables; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.Drain.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java b/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java deleted file mode 100644 index 1912d14..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class DrainBlast extends WaterAbility implements AddonAbility { - - private Location location; - private Vector direction; - private double travelled; - - @Attribute(Attribute.RANGE) - private final double blastRange; // 20 - @Attribute(Attribute.DAMAGE) - private final double blastDamage; // 1.5 - @Attribute(Attribute.SPEED) - private final double blastSpeed; // 2 - - public DrainBlast(Player player, double range, double damage, double speed, int holdrange) { - super(player); - this.blastRange = range; - this.blastDamage = damage; - this.blastSpeed = speed; - location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(holdrange)); - start(); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (travelled >= blastRange) { - remove(); - return; - } - advanceAttack(); - } - - private void advanceAttack() { - for (int i = 0; i < blastSpeed; i++) { - travelled++; - if (travelled >= blastRange) - return; - - if (!player.isDead()) - direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, blastRange, Material.WATER)).normalize(); - location = location.add(direction.clone().multiply(1)); - if (GeneralMethods.isSolid(location.getBlock()) || !isTransparent(location.getBlock())) { - travelled = blastRange; - return; - } - - playWaterbendingSound(location); - TempBlock tb = new TempBlock(location.getBlock(), Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 100L); - Drain.WATER_TEMPS.add(tb); - tb.setRevertTask(() -> Drain.WATER_TEMPS.remove(tb)); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { - DamageHandler.damageEntity(entity, blastDamage, this); - travelled = blastRange; - } - } - } - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "Drain"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.Drain.Description"); - } - - public void setLocation(Location location) { - this.location = location; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getDistanceTravelled() { - return travelled; - } - - public void setDistanceTravelled(double travelled) { - this.travelled = travelled; - } - - public double getBlastRange() { - return blastRange; - } - - public double getBlastDamage() { - return blastDamage; - } - - public double getBlastSpeed() { - return blastSpeed; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.Drain.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java b/src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java deleted file mode 100644 index 9a2ab0f..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java +++ /dev/null @@ -1,440 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.IceAbility; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -public class FrostBreath extends IceAbility implements AddonAbility { - - private static final List INVALID_MATERIALS = new ArrayList(){{ - addAll(Arrays.asList( - Material.ICE, - Material.LAVA, - Material.AIR, - Material.VOID_AIR, - Material.CAVE_AIR)); - if (GeneralMethods.getMCVersion() >= 1170) { - add(Material.getMaterial("LIGHT")); - } - }}; - - //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. - private static float MAX_TEMP = 1.0F; - private static float MIN_HUMIDITY = 0.01F; - - public Config config; - - private State state; - private final List frozenBlocks = new ArrayList<>(); - - public FrostBreath(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { - return; - } - - this.config = new Config(player); - this.state = new BeamState(); - - double temp = player.getLocation().getWorld().getTemperature(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); - double humidity = player.getLocation().getWorld().getHumidity(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); - - if (config.restrictBiomes && (temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { - return; - } - - start(); - } - - @Override - public void progress() { - if (!state.update()) { - remove(); - } - - long time = System.currentTimeMillis(); - - frozenBlocks.removeIf(frozen -> { - if (time >= frozen.endTime) { - removeFrozenBlock(frozen.tempBlock); - frozen.tempBlock.revertBlock(); - return true; - } - - return false; - }); - } - - @Override - public void remove() { - super.remove(); - - frozenBlocks.forEach(fb -> { - removeFrozenBlock(fb.tempBlock); - fb.tempBlock.revertBlock(); - }); - frozenBlocks.clear(); - } - - @Override - public long getCooldown() { - return config.cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "FrostBreath"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.FrostBreath.Description"); - } - - public static List getInvalidMaterials() { - return INVALID_MATERIALS; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - public List getFrozenBlocks() { - return frozenBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.FrostBreath.Enabled"); - } - - private void addFrozenBlock(TempBlock tempBlock) { - PhaseChange.getFrozenBlocksMap().put(tempBlock, player); - } - - private void removeFrozenBlock(TempBlock tempBlock) { - PhaseChange.getFrozenBlocksMap().remove(tempBlock); - } - - private interface State { - boolean update(); - } - - private class BeamState implements State { - @Override - public boolean update() { - if (player == null || !player.isOnline()) { - return transition(); - } - - if (!bPlayer.canBendIgnoreCooldowns(FrostBreath.this)) { - return transition(); - } - - if (!player.isSneaking() || player.isDead()) { - return transition(); - } - - if (System.currentTimeMillis() >= getStartTime() + config.duration) { - return transition(); - } - - createBeam(); - - return true; - } - - private boolean transition() { - state = new SnowMeltingState(); - - return true; - } - - private boolean isLocationSafe(Location loc) { - Block block = loc.getBlock(); - - if (RegionProtection.isRegionProtected(player, loc, FrostBreath.this)) { - return false; - } - - return isTransparent(block); - } - - private boolean isFreezable(Location location, Entity entity) { - if (RegionProtection.isRegionProtected(FrostBreath.this, location)) { - return false; - } - - if (entity instanceof Player && Commands.invincible.contains(entity.getName())) { - return false; - } - - return !location.getBlock().getType().isSolid(); - } - - private void createBeam() { - Location loc = player.getEyeLocation(); - Vector dir = player.getLocation().getDirection(); - double step = 1; - double size = 0; - double offset = 0; - double damageRegion = 1.5; - - for (double i = 0; i < config.range; i += step) { - loc = loc.add(dir.clone().multiply(step)); - size += 0.005; - offset += 0.3; - damageRegion += 0.01; - - if (!isLocationSafe(loc)) - return; - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - for (Location cageLocation : createCage(entity.getLocation())) { - if (isFreezable(cageLocation, entity)) { - Block block = cageLocation.getBlock(); - - updateFrozenBlock(block, Material.ICE, config.freezeDuration); - } - } - - if (config.slowEnabled) { - ((LivingEntity) entity).addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect((int) config.slowDuration, 5)); - } - - if (config.damageEnabled) { - if (entity instanceof Player) { - DamageHandler.damageEntity(entity, config.playerDamage, FrostBreath.this); - } else { - DamageHandler.damageEntity(entity, config.mobDamage, FrostBreath.this); - } - } - } - } - - if (config.snowEnabled) { - freezeGround(loc); - } - - ParticleEffect.SNOW_SHOVEL.display(loc, config.particles, Math.random(), Math.random(), Math.random(), size); - - JCMethods.displayColoredParticles("#DCDCDC", loc, 1, Math.random(), Math.random(), Math.random(), 0.003f); - JCMethods.displayColoredParticles("#9696FF", loc, 1, Math.random(), Math.random(), Math.random(), 0.0035f); - } - } - - private Location getOffsetLocation(Location loc, double offset) { - return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); - } - - private void freezeGround(Location loc) { - for (Location l : GeneralMethods.getCircle(loc, 2, 2, false, true, 0)) { - if (!RegionProtection.isRegionProtected(player, l, FrostBreath.this)) { - Block block = l.getBlock(); - - if (isWater(l.getBlock())) { - updateFrozenBlock(block, Material.ICE, config.frozenWaterDuration); - } else if (isTransparent(l.getBlock()) && l.clone().add(0, -1, 0).getBlock().getType().isSolid() && !INVALID_MATERIALS.contains(l.clone().add(0, -1, 0).getBlock().getType())) { - if (config.bendSnow) { - updateFrozenBlock(block, Material.SNOW, config.snowDuration); - } else { - TempBlock current = TempBlock.get(block); - - // Refresh any existing TempBlock so the timer resets. - if (current != null) { - current.revertBlock(); - } - - TempBlock tempBlock = new TempBlock(block, Material.SNOW.createBlockData()); - tempBlock.setRevertTime(config.snowDuration); - } - } - } - } - } - - private void updateFrozenBlock(Block block, Material type, long duration) { - // Store the TempBlock as a FrozenBlock block so it can be reverted later. - for (FrozenBlock fb : frozenBlocks) { - if (fb.tempBlock.getBlock().equals(block)) { - if (fb.tempBlock.getBlockData().getMaterial() != type) { - // Completely overwrite this FrozenBlock if the new type doesn't match the old one. - removeFrozenBlock(fb.tempBlock); - fb.tempBlock.revertBlock(); - frozenBlocks.remove(fb); - break; - } - - fb.endTime = System.currentTimeMillis() + duration; - return; - } - } - - TempBlock tempBlock = new TempBlock(block, type.createBlockData()); - - frozenBlocks.add(new FrozenBlock(tempBlock, System.currentTimeMillis() + duration)); - - // Add the TempBlock to a ProjectKorra block list so it can be used as a water source. - // I don't believe there exists a way to make a TempBlock water bendable right now, so this - // is a hack to make it work. - addFrozenBlock(tempBlock); - } - - private List createCage(Location centerBlock) { - List selectedBlocks = new ArrayList<>(); - - int bX = centerBlock.getBlockX(); - int bY = centerBlock.getBlockY(); - int bZ = centerBlock.getBlockZ(); - - for (int x = bX - 1; x <= bX + 1; x++) { - for (int y = bY - 1; y <= bY + 1; y++) { - Location l = new Location(centerBlock.getWorld(), x, y, bZ); - selectedBlocks.add(l); - } - } - - for (int y = bY - 1; y <= bY + 2; y++) { - Location l = new Location(centerBlock.getWorld(), bX, y, bZ); - selectedBlocks.add(l); - } - - for (int z = bZ - 1; z <= bZ + 1; z++) { - for (int y = bY - 1; y <= bY + 1; y++) { - Location l = new Location(centerBlock.getWorld(), bX, y, z); - selectedBlocks.add(l); - } - } - - for (int x = bX - 1; x <= bX + 1; x++) { - for (int z = bZ - 1; z <= bZ + 1; z++) { - Location l = new Location(centerBlock.getWorld(), x, bY, z); - selectedBlocks.add(l); - } - } - - return selectedBlocks; - } - } - - // Wait for the frozen blocks to melt and remove it from bendable water list. - private class SnowMeltingState implements State { - SnowMeltingState() { - bPlayer.addCooldown(FrostBreath.this); - } - - @Override - public boolean update() { - return !frozenBlocks.isEmpty(); - } - } - - private static class FrozenBlock { - TempBlock tempBlock; - long endTime; - - FrozenBlock(TempBlock tempBlock, long endTime) { - this.tempBlock = tempBlock; - this.endTime = endTime; - } - } - - public static class Config { - long cooldown; - long duration; - int particles; - int freezeDuration; - int snowDuration; - int frozenWaterDuration; - int range; - boolean snowEnabled; - boolean bendSnow; - boolean damageEnabled; - double playerDamage; - double mobDamage; - boolean slowEnabled; - long slowDuration; - boolean restrictBiomes; - - Config(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - - cooldown = config.getLong("Abilities.Water.FrostBreath.Cooldown"); - duration = config.getLong("Abilities.Water.FrostBreath.Duration"); - particles = config.getInt("Abilities.Water.FrostBreath.Particles"); - freezeDuration = config.getInt("Abilities.Water.FrostBreath.FrostDuration"); - snowDuration = config.getInt("Abilities.Water.FrostBreath.SnowDuration"); - frozenWaterDuration = config.getInt("Abilities.Water.FrostBreath.FrozenWaterDuration"); - range = config.getInt("Abilities.Water.FrostBreath.Range"); - snowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Snow"); - bendSnow = config.getBoolean("Abilities.Water.FrostBreath.BendableSnow"); - damageEnabled = config.getBoolean("Abilities.Water.FrostBreath.Damage.Enabled"); - playerDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Player"); - mobDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Mob"); - slowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Slow.Enabled"); - slowDuration = config.getLong("Abilities.Water.FrostBreath.Slow.Duration"); - restrictBiomes = config.getBoolean("Abilities.Water.FrostBreath.RestrictBiomes"); - } - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java b/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java deleted file mode 100644 index 861c2d9..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java +++ /dev/null @@ -1,268 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.LightManager; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.HealingAbility; -import com.projectkorra.projectkorra.chiblocking.Smokescreen; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.util.WaterReturn; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Server; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Damageable; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Random; - -public class HealingWaters extends HealingAbility implements AddonAbility { - - private static long time = 0; - private static boolean enabled = true; - - public HealingWaters(Player player) { - super(player); - } - - public static void heal(Server server) { - if (enabled) { - if (System.currentTimeMillis() - time >= 1000) { - time = System.currentTimeMillis(); - for (Player player : server.getOnlinePlayers()) { - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer != null && bPlayer.canBend(getAbility("HealingWaters"))) { - heal(player); - } - } - } - } - } - - @SuppressWarnings("deprecation") - private static void heal(Player player) { - if (inWater(player)) { - if (player.isSneaking()) { - Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); - if (entity instanceof LivingEntity && inWater(entity)) { - Location playerLoc = entity.getLocation(); - playerLoc.add(0, 1, 0); - JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHPToEntity((LivingEntity) entity); - emitLight(playerLoc); - emitLight(entity.getLocation()); - } - } else { - Location playerLoc = player.getLocation(); - playerLoc.add(0, 1, 0); - JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHP(player); - emitLight(playerLoc); - } - - } else if(hasWaterSupply(player) && player.isSneaking()) { - Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); - if (entity != null) { - if (entity instanceof LivingEntity) { - Damageable dLe = (Damageable) entity; - if (dLe.getHealth() < dLe.getMaxHealth()) { - Location playerLoc = entity.getLocation(); - playerLoc.add(0, 1, 0); - JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHPToEntity((LivingEntity) entity); - entity.setFireTicks(0); - Random rand = new Random(); - if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); - emitLight(playerLoc); - emitLight(entity.getLocation()); - } - } - } else { - Location playerLoc = player.getLocation(); - playerLoc.add(0, 1, 0); - - JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f); - - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHP(player); - player.setFireTicks(0); - Random rand = new Random(); - if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); - emitLight(playerLoc); - } - } - } - - @SuppressWarnings("deprecation") - private static void giveHPToEntity(LivingEntity le) { - if (!le.isDead() && le.getHealth() < le.getMaxHealth()) { - applyHealingToEntity(le); - } - for (PotionEffect effect : le.getActivePotionEffects()) { - if (isNegativeEffect(effect.getType())) { - le.removePotionEffect(effect.getType()); - } - } - } - - private static void giveHP(Player player){ - if (!player.isDead() && player.getHealth() < 20) { - applyHealing(player); - } - for(PotionEffect effect : player.getActivePotionEffects()) { - if(isNegativeEffect(effect.getType())) { - if((effect.getType() == PotionEffectType.BLINDNESS) && Smokescreen.getBlindedTimes().containsKey(player.getName())) { - return; - } - player.removePotionEffect(effect.getType()); - } - } - } - - - - private static boolean inWater(Entity entity) { - Block block = entity.getLocation().getBlock(); - return isWater(block) && !TempBlock.isTempBlock(block); - } - - private static boolean hasWaterSupply(Player player){ - ItemStack heldItem = player.getInventory().getItemInMainHand(); - return (heldItem.isSimilar(WaterReturn.waterBottleItem()) || heldItem.getType() == Material.WATER_BUCKET); - - } - - private static void drainWaterSupply(Player player){ - ItemStack heldItem = player.getInventory().getItemInMainHand(); - ItemStack emptyBottle = new ItemStack(Material.GLASS_BOTTLE, 1); - if (heldItem.isSimilar(WaterReturn.waterBottleItem())) { - if (heldItem.getAmount() > 1) { - heldItem.setAmount(heldItem.getAmount() - 1); - HashMap cantFit = player.getInventory().addItem(emptyBottle); - for (int id : cantFit.keySet()) { - player.getWorld().dropItem(player.getEyeLocation(), cantFit.get(id)); - } - } else { - player.getInventory().setItemInMainHand(emptyBottle); - } - } - } - - @SuppressWarnings("deprecation") - private static void applyHealing(Player player) { - if (!RegionProtection.isRegionProtected(player, player.getLocation(), "HealingWaters")) - if(player.getHealth() < player.getMaxHealth()) { - player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, getPower(player))); - AirAbility.breakBreathbendingHold(player); - } - } - - @SuppressWarnings("deprecation") - private static void applyHealingToEntity(LivingEntity le) { - if (le.getHealth() < le.getMaxHealth()) { - le.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, 1)); - AirAbility.breakBreathbendingHold(le); - } - } - - public static int getPower(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - return config.getInt("Abilities.Water.HealingWaters.Power"); - } - - public static double getRange(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - return config.getDouble("Abilities.Water.HealingWaters.Range"); - } - - public static int getDrainChance(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - return config.getInt("Abilities.Water.HealingWaters.DrainChance"); - } - - public static void emitLight(Location loc) { - ConfigurationSection config = JedCoreConfig.getConfig((Player)null); - if (config.getBoolean("Abilities.Water.HealingWaters.DynamicLight.Enabled")) { - int brightness = config.getInt("Abilities.Water.HealingWaters.DynamicLight.Brightness"); - long keepAlive = config.getLong("Abilities.Water.HealingWaters.DynamicLight.KeepAlive"); - - LightManager.createLight(loc).brightness(brightness).timeUntilFadeout(keepAlive).emit(); - } - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "HealingWaters"; - } - - @Override - public boolean isHarmlessAbility() { - return true; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.HealingWaters.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - enabled = config.getBoolean("Abilities.Water.HealingWaters.Enabled"); - return enabled; - } - - @Override - public void progress() {} -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java b/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java deleted file mode 100644 index c32736d..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java +++ /dev/null @@ -1,332 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.ability.firebending.FirePunch; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.IceAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; - -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.MainHand; -import org.bukkit.potion.PotionEffectType; - -public class IceClaws extends IceAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long punchCooldown; - @Attribute(Attribute.COOLDOWN) - private long throwCooldown; - @Attribute(Attribute.CHARGE_DURATION) - private long chargeUp; - private int punchSlowDur; - private int throwSlowDur; - private int punchSlownessLevel; - private int throwSlownessLevel; - @Attribute(Attribute.DAMAGE) - private double punchDamage; - @Attribute(Attribute.DAMAGE) - private double throwDamage; - @Attribute(Attribute.RANGE) - private double range; - private boolean throwable; - private double throwSpeed; - - private Location head; - private Location origin; - private boolean launched; - - private Boolean iceInMainHand = null; - - public IceClaws(Player player) { - super(player); - if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { - return; - } - - if (hasAbility(player, IceClaws.class)) { - IceClaws ic = getAbility(player, IceClaws.class); - if (!ic.throwable) { - ic.remove(); - } - return; - } - - setFields(); - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - punchCooldown = config.getLong("Abilities.Water.IceClaws.Punch.Cooldown", 4000); - punchDamage = config.getDouble("Abilities.Water.IceClaws.Punch.Damage", 2.0); - punchSlownessLevel = config.getInt("Abilities.Water.IceClaws.Punch.Slowness", 3); - punchSlowDur = config.getInt("Abilities.Water.IceClaws.Punch.SlowDuration", 5000); - - throwCooldown = config.getLong("Abilities.Water.IceClaws.Throw.Cooldown", 4000); - throwDamage = config.getDouble("Abilities.Water.IceClaws.Throw.Damage", 2.0); - throwSlownessLevel = config.getInt("Abilities.Water.IceClaws.Throw.Slowness", 3); - throwSlowDur = config.getInt("Abilities.Water.IceClaws.Throw.SlowDuration", 5000); - throwSpeed = config.getDouble("Abilities.Water.IceClaws.Throw.Speed", 1.0); - - chargeUp = config.getLong("Abilities.Water.IceClaws.ChargeTime", 1000); - range = config.getDouble("Abilities.Water.IceClaws.Range", 10); - throwable = config.getBoolean("Abilities.Water.IceClaws.Throwable", true); - - applyModifiers(); - } - - private void applyModifiers() { - punchCooldown -= ((long) getNightFactor(punchCooldown) - punchCooldown); - throwCooldown -= ((long) getNightFactor(throwCooldown) - throwCooldown); - punchDamage = getNightFactor(punchDamage); - throwDamage = getNightFactor(throwDamage); - range = getNightFactor(range); - } - - @Override - public void progress() { - if (player == null || player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - if (System.currentTimeMillis() > getStartTime() + chargeUp) { - if (!launched && throwable) { - displayClaws(); - } else { - if (!shoot()) { - remove(); - } - } - } else if (player.isSneaking()) { - displayChargeUp(); - } else { - remove(); - } - } - - - public static void swapHands(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - if (!config.getBoolean("Abilities.Water.IceClaws.AllowHandSwap", true)) return; - IceClaws ic = getAbility(player, IceClaws.class); - if (ic == null) - return; - if (ic.iceInMainHand == null) - ic.iceInMainHand = true; - else ic.iceInMainHand = !ic.iceInMainHand; - } - - public Location getRightHandPos() { - return (player.getMainHand() == MainHand.RIGHT == ((iceInMainHand == null) || iceInMainHand) ? - GeneralMethods.getRightSide(player.getLocation(), .55) : - GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); - } - - public boolean shoot() { - for (double i = 0; i < 1; i += throwSpeed) { - head.add(origin.clone().getDirection().multiply(throwSpeed)); - if (origin.distance(head) >= range) return false; - if (!isTransparent(head.getBlock())) return false; - GeneralMethods.displayColoredParticle("66FFFF", head); - GeneralMethods.displayColoredParticle("CCFFFF", head); - ParticleEffect.SNOW_SHOVEL.display(head, 1, 0, 0, 0, 0); - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(head, 1.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { - freezeEntity((LivingEntity) entity, false); - return false; - } - } - } - return true; - } - - public static void throwClaws(Player player) { - if (hasAbility(player, IceClaws.class)) { - IceClaws ic = getAbility(player, IceClaws.class); - if (!ic.launched && player.isSneaking()) { - ic.launched = true; - ic.origin = ic.player.getEyeLocation(); - ic.head = ic.origin.clone(); - } - } - } - - private void displayClaws() { - Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); - GeneralMethods.displayColoredParticle("66FFFF", location); - GeneralMethods.displayColoredParticle("CCFFFF", location); - } - - private void displayChargeUp() { - Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); - ParticleEffect.WATER_SPLASH.display(location, 1, Math.random()/3, Math.random()/3, Math.random()/3, 0.0); - } - - public static boolean freezeEntity(Player player, LivingEntity entity) { - if (hasAbility(player, IceClaws.class)) { - getAbility(player, IceClaws.class).freezeEntity(entity); - return true; - } - return false; - } - - private void freezeEntity(LivingEntity entity) { - freezeEntity(entity, true); - } - - private void freezeEntity(LivingEntity entity, boolean isPunch) { - if (entity.hasPotionEffect(PotionEffectType.SPEED)) { - entity.removePotionEffect(PotionEffectType.SPEED); - } - int duration = isPunch ? punchSlowDur : throwSlowDur; - int level = isPunch ? punchSlownessLevel : throwSlownessLevel; - entity.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect(duration, level)); - bPlayer.addCooldown(this); - remove(); - DamageHandler.damageEntity(entity, isPunch ? punchDamage : throwDamage, this); - } - - @Override - public long getCooldown() { - return launched ? throwCooldown : punchCooldown; - } - - @Override - public Location getLocation() { - return head; - } - - @Override - public String getName() { - return "IceClaws"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.IceClaws.Description"); - } - - public void setPunchCooldown(long punchCooldown) { this.punchCooldown = punchCooldown; } - public long getPunchCooldown() { return punchCooldown; } - public void setThrowCooldown(long throwCooldown) { this.throwCooldown = throwCooldown; } - public long getThrowCooldown() { return throwCooldown; } - public void setPunchDamage(double punchDamage) { this.punchDamage = punchDamage; } - public double getPunchDamage() { return punchDamage; } - public void setThrowDamage(double throwDamage) { this.throwDamage = throwDamage; } - public double getThrowDamage() { return throwDamage; } - public void setPunchSlowDur(int punchSlowDur) { this.punchSlowDur = punchSlowDur; } - public int getPunchSlowDur() { return punchSlowDur; } - public void setThrowSlowDur(int throwSlowDur) { this.throwSlowDur = throwSlowDur; } - public int getThrowSlowDur() { return throwSlowDur; } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public boolean isThrowable() { - return throwable; - } - - public void setThrowable(boolean throwable) { - this.throwable = throwable; - } - - public Location getHead() { - return head; - } - - public void setHead(Location head) { - this.head = head; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public boolean isLaunched() { - return launched; - } - - public void setLaunched(boolean launched) { - this.launched = launched; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.IceClaws.Enabled"); - } - - public int getPunchSlownessLevel() { - return punchSlownessLevel; - } - - public void setPunchSlownessLevel(int punchSlownessLevel) { - this.punchSlownessLevel = punchSlownessLevel; - } - - public int getThrowSlownessLevel() { - return throwSlownessLevel; - } - - public void setThrowSlownessLevel(int throwSlownessLevel) { - this.throwSlownessLevel = throwSlownessLevel; - } - - public double getThrowSpeed() { - return throwSpeed; - } - - public void setThrowSpeed(double throwSpeed) { - this.throwSpeed = throwSpeed; - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java deleted file mode 100644 index 794225a..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.ability.IceAbility; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -import java.util.HashMap; -import java.util.Map; - -public class IcePassive { - - public static void handleSkating() { - Map> resultCache = new HashMap<>(); - - for (Player player: Bukkit.getServer().getOnlinePlayers()) { - Pair result = resultCache.get(player.getWorld()); - if (result == null) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - - boolean enabled = config.getBoolean("Abilities.Water.Ice.Passive.Skate.Enabled"); - int speedFactor = config.getInt("Abilities.Water.Ice.Passive.Skate.SpeedFactor"); - - result = new Pair<>(enabled, speedFactor); - resultCache.put(player.getWorld(), result); - } - - boolean enabled = result.first; - int speedFactor = result.second; - - if (!enabled) continue; - if (JCMethods.isDisabledWorld(player.getWorld())) continue; - if (!player.isOnGround()) continue; - if (!player.isSprinting()) continue; - if (!IceAbility.isIce(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) continue; - - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - - if (bPlayer == null) continue; - if (!bPlayer.canIcebend()) continue; - if (!bPlayer.isPassiveToggled(Element.WATER)) continue; - - if (!player.hasPermission("bending.ability.IceSkate")) continue; - - ParticleEffect.SNOW_SHOVEL.display(player.getLocation().clone().add(0, 0.2, 0), 15, Math.random()/2, Math.random()/2, Math.random()/2, 0); - player.removePotionEffect(PotionEffectType.SPEED); - player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 60, speedFactor)); - } - } - - private static class Pair { - T first; - U second; - - Pair(T first, U second) { - this.first = first; - this.second = second; - } - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceWall.java b/src/com/jedk1/jedcore/ability/waterbending/IceWall.java deleted file mode 100644 index b41793d..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/IceWall.java +++ /dev/null @@ -1,609 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.*; -import com.projectkorra.projectkorra.attribute.Attribute; -import org.bukkit.*; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.earthbending.EarthSmash; -import com.projectkorra.projectkorra.firebending.FireBlast; -import com.projectkorra.projectkorra.firebending.FireBlastCharged; -import com.projectkorra.projectkorra.firebending.lightning.Lightning; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.Torrent; -import com.projectkorra.projectkorra.waterbending.ice.IceBlast; - -public class IceWall extends IceAbility implements AddonAbility { - public static List instances = new ArrayList<>(); - - @Attribute(Attribute.HEIGHT) - private int maxHeight; - private int minHeight; - - @Attribute(Attribute.WIDTH) - private int width; - - @Attribute(Attribute.RANGE) - private int range; - - @Attribute("Health") - private int maxHealth; - private int minHealth; - - @Attribute(Attribute.DAMAGE) - private double damage; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - public static boolean stackable; - - public static boolean lifetimeEnabled; - public static long lifetimeTime; - - public int torrentDamage; - public int torrentFreezeDamage; - public int iceBlastDamage; - public int fireBlastDamage; - public int fireBlastChargedDamage; - public int lightningDamage; - public int combustionDamage; - public int earthSmashDamage; - public int airBlastDamage; - - public boolean isWallDoneFor = false; - public List affectedBlocks = new ArrayList<>(); - - private boolean rising = false; - private long lastDamageTime = 0; - private long lifetime = 0; - private int wallHealth; - private int tankedDamage; - - private final List lastBlocks = new ArrayList<>(); - private final List tempBlocks = new ArrayList<>(); - - Random rand = new Random(); - - public IceWall(Player player) { - super(player); - if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canIcebend()) { - return; - } - - setFields(); - Block b = getSourceBlock(player, (int) (range * getNightFactor(player.getWorld()))); - if (b == null) return; - - for (IceWall iw : instances) { - if (iw.affectedBlocks.contains(b)) { - iw.collapse(player, false); - return; - } - } - - if (!bPlayer.canBend(this) || !isWaterbendable(b)) return; - - wallHealth = (int) (((rand.nextInt((maxHealth - minHealth) + 1)) + minHealth) * getNightFactor(player.getWorld())); - loadAffectedBlocks(player, b); - lifetime = System.currentTimeMillis() + lifetimeTime; - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - maxHeight = (config.getInt("Abilities.Water.IceWall.MaxHeight")); - minHeight = (config.getInt("Abilities.Water.IceWall.MinHeight")); - width = (config.getInt("Abilities.Water.IceWall.Width")); - range = config.getInt("Abilities.Water.IceWall.Range"); - maxHealth = config.getInt("Abilities.Water.IceWall.MaxWallHealth"); - minHealth = config.getInt("Abilities.Water.IceWall.MinWallHealth"); - damage = config.getDouble("Abilities.Water.IceWall.Damage"); - cooldown = config.getLong("Abilities.Water.IceWall.Cooldown"); - stackable = config.getBoolean("Abilities.Water.IceWall.Stackable"); - lifetimeEnabled = config.getBoolean("Abilities.Water.IceWall.LifeTime.Enabled"); - lifetimeTime = config.getLong("Abilities.Water.IceWall.LifeTime.Duration"); - torrentDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Torrent"); - torrentFreezeDamage = config.getInt("Abilities.Water.IceWall.WallDamage.TorrentFreeze"); - iceBlastDamage = config.getInt("Abilities.Water.IceWall.WallDamage.IceBlast"); - fireBlastDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Fireblast"); - fireBlastChargedDamage = config.getInt("Abilities.Water.IceWall.WallDamage.FireblastCharged"); - lightningDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Lightning"); - combustionDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Combustion"); - earthSmashDamage = config.getInt("Abilities.Water.IceWall.WallDamage.EarthSmash"); - airBlastDamage = config.getInt("Abilities.Water.IceWall.WallDamage.AirBlast"); - } - - public Block getSourceBlock(Player player, int range) { - Vector direction = player.getEyeLocation().getDirection().normalize(); - - for (int i = 0; i <= range; i++) { - Block b = player.getEyeLocation().add(direction.clone().multiply((double) i)).getBlock(); - - if (isBendable(b)) return b; - } - - return null; - } - - public boolean isBendable(Block b) { - return isWater(b) || isIce(b.getType()) || isSnow(b.getType()); - } - - public void loadAffectedBlocks(Player player, Block block) { - Vector direction = player.getEyeLocation().getDirection().normalize(); - - double ox, oy, oz; - ox = -direction.getZ(); - oy = 0; - oz = direction.getX(); - - Vector orth = new Vector(ox, oy, oz); - orth = orth.normalize(); - - Location origin = block.getLocation(); - - World world = origin.getWorld(); - - int width = (int) (getWidth() * getNightFactor(world)); - int minHeight = (int) (getMinHeight() * getNightFactor(world)); - int maxHeight = (int) (getMaxHeight() * getNightFactor(world)); - - int height = minHeight; - boolean increasingHeight = true; - for (int i = -(width / 2); i < width / 2; i++) { - Block b = world.getBlockAt(origin.clone().add(orth.clone().multiply((double) i))); - - if (ElementalAbility.isAir(b.getType())) { - while (ElementalAbility.isAir(b.getType())) { - if (b.getY() < world.getMinHeight()) - return; - - b = b.getRelative(BlockFace.DOWN); - } - } - - if (!ElementalAbility.isAir(b.getRelative(BlockFace.UP).getType())) { - while (!ElementalAbility.isAir(b.getRelative(BlockFace.UP).getType())) { - if (b.getY() > b.getWorld().getMaxHeight()) - return; - - b = b.getRelative(BlockFace.UP); - } - } - - if (!stackable && isIceWallBlock(b)) { - continue; - } - - if (isBendable(b)) { - affectedBlocks.add(b); - for (int h = 1; h <= height; h++) { - Block up = b.getRelative(BlockFace.UP, h); - if (ElementalAbility.isAir(up.getType())) { - affectedBlocks.add(up); - } - } - - if (height < maxHeight && increasingHeight) - height++; - - if (i == 0) - increasingHeight = false; - - if (!increasingHeight && height > minHeight) - height--; - - lastBlocks.add(b); - } - - } - - bPlayer.addCooldown(this); - rising = true; - instances.add(this); - } - - @Override - public void progress() { - if (rising) { - if (lastBlocks.isEmpty()) { - rising = false; - } else { - List theseBlocks = new ArrayList<>(lastBlocks); - lastBlocks.clear(); - - for (Block b : theseBlocks) { - TempBlock tb = new TempBlock(b, Material.ICE.createBlockData()); - tempBlocks.add(tb); - - playIcebendingSound(b.getLocation()); - - Block up = b.getRelative(BlockFace.UP); - - if (affectedBlocks.contains(up)) - lastBlocks.add(up); - } - } - } - - if (System.currentTimeMillis() > lifetime && lifetimeEnabled) { - collapse(player, false); - } - } - - public void damageWall(Player player, int damage) { - long noDamageTicks = 1000; - if (System.currentTimeMillis() < lastDamageTime + noDamageTicks) - return; - - lastDamageTime = System.currentTimeMillis(); - tankedDamage += damage; - - if (tankedDamage >= wallHealth) { - collapse(player, true); - } - } - - public void collapse(Player player, boolean forceful) { - if (rising) return; - - for (TempBlock tb : tempBlocks) { - tb.revertBlock(); - tb.getLocation().getWorld().spawnParticle(Particle.BLOCK_CRACK, tb.getLocation(), 5, 0, 0, 0, 0, Material.PACKED_ICE.createBlockData()); - tb.getLocation().getWorld().playSound(tb.getLocation(), Sound.BLOCK_GLASS_BREAK, 5f, 5f); - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 2.5)) { - if (e.getEntityId() != player.getEntityId() && e instanceof LivingEntity) { - DamageHandler.damageEntity(e, damage * getNightFactor(player.getWorld()), this); - if (forceful) { - ((LivingEntity) e).setNoDamageTicks(0); - } - } - } - } - - tempBlocks.clear(); - isWallDoneFor = true; - } - - @Override - public void remove() { - super.remove(); - } - - public static void collisionDamage(Entity entity, double travelledDistance, Vector difference, Player instigator) { - for (IceWall iw : IceWall.instances) { - for (Block b : iw.affectedBlocks) { - if (entity.getLocation().getWorld() == b.getLocation().getWorld() && entity.getLocation().distance(b.getLocation()) < 2) { - double damage = ((travelledDistance - 5.0) < 0 ? 0 : travelledDistance - 5.0) / (difference.length()); - iw.damageWall(instigator, (int) damage); - } - } - } - } - - public static boolean checkExplosions(Location location, Entity entity) { - for (IceWall iw : IceWall.instances) { - for (Block b : iw.affectedBlocks) { - if (location.getWorld() == b.getLocation().getWorld() && location.distance(b.getLocation()) < 2) { - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, 3)) { - if (e instanceof LivingEntity) { - ((LivingEntity) e).damage(7, entity); - } - } - return true; - } - } - } - return false; - } - - public static boolean isIceWallBlock(Block block) { - for (IceWall iw : IceWall.instances) { - if (iw.affectedBlocks.contains(block)) { - return true; - } - } - return false; - } - - public static void progressAll() { - for (IceWall iw : new ArrayList<>(instances)) { - if (iw.isWallDoneFor) continue; // Skip already collapsed walls - for (Torrent t : getAbilities(Torrent.class)) { - if (t.getLocation() == null) continue; - for (int i = 0; i < t.getLaunchedBlocks().size(); i++) { - TempBlock tb = t.getLaunchedBlocks().get(i); - - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == tb.getLocation().getWorld() && ice.getLocation().distance(tb.getLocation()) <= 2) { - if (t.isFreeze()) - iw.damageWall(t.getPlayer(), (int) (iw.torrentFreezeDamage * getNightFactor(ice.getWorld()))); - else - iw.damageWall(t.getPlayer(), (int) (iw.torrentDamage * getNightFactor(ice.getWorld()))); - - if (!iw.isWallDoneFor) - t.setFreeze(false); - } - } - } - } - - for (IceBlast ib : getAbilities(IceBlast.class)) { - if (ib.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ib.source == null) - break; - - if (ice.getLocation().getWorld() == ib.source.getLocation().getWorld() && ice.getLocation().distance(ib.source.getLocation()) <= 2) { - iw.damageWall(ib.getPlayer(), (int) (iw.iceBlastDamage * getNightFactor(ice.getWorld()))); - - if (!iw.isWallDoneFor) - ib.remove(); - } - } - } - - for (FireBlastCharged fb : getAbilities(FireBlastCharged.class)) { - if (fb.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { - iw.damageWall(fb.getPlayer(), iw.fireBlastChargedDamage); - - if (!iw.isWallDoneFor) - fb.remove(); - } - } - } - - for (FireBlast fb : getAbilities(FireBlast.class)) { - if (fb.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { - iw.damageWall(fb.getPlayer(), iw.fireBlastDamage); - - if (!iw.isWallDoneFor) - fb.remove(); - } - } - } - - for (EarthSmash es : getAbilities(EarthSmash.class)) { - if (es.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (es.getState() == EarthSmash.State.SHOT) { - for (int j = 0; j < es.getBlocks().size(); j++) { - Block b = es.getBlocks().get(j); - if (ice.getLocation().getWorld() == b.getLocation().getWorld() && b.getLocation().distance(ice.getLocation()) <= 2) { - iw.damageWall(es.getPlayer(), iw.earthSmashDamage); - - if (!iw.isWallDoneFor) { - for (Block block : es.getBlocksIncludingInner()) { - if (block != null && !ElementalAbility.isAir(block.getType())) { - ParticleEffect.BLOCK_CRACK.display(block.getLocation(), 5, 0, 0, 0, 0, block.getBlockData().clone()); - } - } - es.remove(); - } - } - } - } - } - } - - for (Lightning l : getAbilities(Lightning.class)) { - for (Lightning.Arc arc : l.getArcs()) { - for (Block ice : iw.affectedBlocks) { - for (Location loc : arc.getPoints()) { - if (ice.getLocation().getWorld() == loc.getWorld() && loc.distance(ice.getLocation()) <= 1.5) { - iw.damageWall(l.getPlayer(), (int) (FireAbility.getDayFactor(iw.lightningDamage, ice.getWorld()))); - - if (!iw.isWallDoneFor) - l.remove(); - } - } - } - } - } - - for (CoreAbility ca : getAbilities(getAbility("Combustion").getClass())) { - if (ca.getLocation() == null) continue; - for (Block ice : iw.affectedBlocks) { - if (ice.getLocation().getWorld() == ca.getLocation().getWorld() && ca.getLocation().distance(ice.getLocation()) <= 1.5) { - iw.damageWall(ca.getPlayer(), iw.combustionDamage); - if (!iw.isWallDoneFor) ca.remove(); - } - } - } - } - - Iterator it = instances.iterator(); - while (it.hasNext()) { - IceWall iw = it.next(); - if (iw.isWallDoneFor) { - iw.affectedBlocks.clear(); - it.remove(); - } - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "IceWall"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.IceWall.Description"); - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public int getMaxHealth() { - return maxHealth; - } - - public void setMaxHealth(int maxHealth) { - this.maxHealth = maxHealth; - } - - public int getMinHealth() { - return minHealth; - } - - public void setMinHealth(int minHealth) { - this.minHealth = minHealth; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public boolean isRising() { - return rising; - } - - public void setRising(boolean rising) { - this.rising = rising; - } - - public long getLastDamageTime() { - return lastDamageTime; - } - - public void setLastDamageTime(long lastDamageTime) { - this.lastDamageTime = lastDamageTime; - } - - public long getLifetime() { - return lifetime; - } - - public void setLifetime(long lifetime) { - this.lifetime = lifetime; - } - - public int getWallHealth() { - return wallHealth; - } - - public void setWallHealth(int wallHealth) { - this.wallHealth = wallHealth; - } - - public int getTankedDamage() { - return tankedDamage; - } - - public void setTankedDamage(int tankedDamage) { - this.tankedDamage = tankedDamage; - } - - public List getLastBlocks() { - return lastBlocks; - } - - public List getTempBlocks() { - return tempBlocks; - } - - public int getMaxHeight() { - return maxHeight; - } - - public void setMaxHeight(int maxHeight) { - this.maxHeight = maxHeight; - } - - public int getMinHeight() { - return minHeight; - } - - public void setMinHeight(int minHeight) { - this.minHeight = minHeight; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.IceWall.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java b/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java deleted file mode 100644 index 6cf92d3..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Item; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class WakeFishing extends WaterAbility implements AddonAbility { - - private final static Material[] FISH_TYPES = { - Material.COD, Material.PUFFERFISH, Material.TROPICAL_FISH, Material.SALMON - }; - - private Block focusedBlock; - private Location location; - private int point; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.RANGE) - private long range; - - Random rand = new Random(); - - public WakeFishing(Player player) { - super(player); - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - if (prepare()) - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Water.WakeFishing.Cooldown"); - duration = config.getLong("Abilities.Water.WakeFishing.Duration"); - range = config.getLong("Abilities.Water.WakeFishing.Range"); - - applyModifiers(); - } - - private void applyModifiers() { - if (isNight(player.getWorld())) { - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - range = (long) getNightFactor(range); - } - } - - private boolean prepare() { - Block block = BlockSource.getWaterSourceBlock(player, range, ClickType.SHIFT_DOWN, true, false, false); - if (isWater(block)) { - focusedBlock = block; - location = focusedBlock.getLocation(); - return true; - } - return false; - } - - private boolean isFocused() { - Block block = BlockSource.getWaterSourceBlock(player, range, ClickType.SHIFT_DOWN, true, false, false); - return block != null && block.equals(focusedBlock); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline() || !player.isSneaking()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this) || !isFocused()) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (System.currentTimeMillis() > getStartTime() + duration) { - bPlayer.addCooldown(this); - remove(); - return; - } - displayParticles(); - spawnFishRandom(); - } - - private void displayParticles() { - point++; - if (point == 32) - point = 0; - for (int i = 0; i < 4; i++) { - ParticleEffect.WATER_SPLASH.display(getCirclePoints(focusedBlock.getLocation().clone().add(0.5, 0, 0.5), 32, (i * 90), 1).get(point), 3, 0, 0, 0, 0.05); - ParticleEffect.WATER_WAKE.display(getCirclePoints(focusedBlock.getLocation().clone().add(0.5, -0.6, 0.5), 32, (i * 90), 1).get(point), 1, 0, 0, 0, 0.02); - } - - ParticleEffect.SMOKE_NORMAL.display(focusedBlock.getLocation().clone().add(.5, .5, .5), 2, 0, 0, 0, 0.001); - } - - private void spawnFishRandom() { - if (rand.nextInt(50) == 0) { - Material fishType = FISH_TYPES[rand.nextInt(FISH_TYPES.length)]; - ItemStack fish = new ItemStack(fishType, 1); - - Item item = player.getWorld().dropItemNaturally(focusedBlock.getLocation().clone().add(.5, 1.5, .5), fish); - Vector v = player.getEyeLocation().toVector().subtract(focusedBlock.getLocation().clone().add(.5, 1.5, .5).toVector()); - item.setVelocity(v.multiply(.15)); - } - } - - private List getCirclePoints(Location location, int points, int startAngle, double size) { - List locations = new ArrayList(); - for (int i = 0; i < 360; i += 360 / points) { - double angle = (i * Math.PI / 180); - double x = size * Math.cos(angle + startAngle); - double z = size * Math.sin(angle + startAngle); - Location loc = location.clone(); - loc.add(x, 1, z); - locations.add(loc); - } - return locations; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "WakeFishing"; - } - - @Override - public boolean isHarmlessAbility() { - return true; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.WakeFishing.Description"); - } - - public Block getFocusedBlock() { - return focusedBlock; - } - - public void setFocusedBlock(Block focusedBlock) { - this.focusedBlock = focusedBlock; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getPoint() { - return point; - } - - public void setPoint(int point) { - this.point = point; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public long getRange() { - return range; - } - - public void setRange(long range) { - this.range = range; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.WakeFishing.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java b/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java deleted file mode 100644 index bd562ea..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java +++ /dev/null @@ -1,244 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.AABB; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.util.CollisionInitializer; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.Ability; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class WaterBlast extends WaterAbility implements AddonAbility { - - private Location location; - private Vector direction; - private final Ability ability; - private double travelled; - - @Attribute(Attribute.RANGE) - private final double range; - @Attribute(Attribute.DAMAGE) - private final double damage; - @Attribute(Attribute.SPEED) - private final double speed; - @Attribute("CollisionRadius") - private final double entityCollisionRadius; - @Attribute("CollisionRadius") - private final double abilityCollisionRadius; - - static { - CollisionInitializer.abilityMap.put("WaterBlast", "WaterGimbal"); - } - - public WaterBlast(Player player, Location origin, double range, double damage, double speed, double entityCollisionRadius, double abilityCollisionRadius, Ability ability) { - super(player); - - this.range = range; - this.damage = damage; - this.speed = speed; - this.ability = ability; - this.location = origin; - this.entityCollisionRadius = entityCollisionRadius; - this.abilityCollisionRadius = abilityCollisionRadius; - - start(); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (travelled >= range) { - remove(); - return; - } - - if (!advanceAttack()) { - remove(); - } - } - - private boolean advanceAttack() { - int steps = (int)Math.ceil(speed); - // This is how much the last step should move by. - double remainder = speed - Math.floor(speed); - - // Move in discrete steps so each block can be checked for collisions. - for (int i = 0; i < steps; i++) { - double stepSpeed = 1.0; - - if (remainder > 0 && i == steps - 1) { - // The last step should only move by the remainder because there are Math.ceil(speed) steps. - stepSpeed = remainder; - } - - travelled += stepSpeed; - - if (travelled >= range) { - return false; - } - - if (!player.isDead()) { - Location target = GeneralMethods.getTargetedLocation(player, range, Material.WATER); - if (location.distanceSquared(target) <= 1) { - // Make sure the WaterBlast moves in to the solid block. - target = target.add(player.getLocation().getDirection()); - } - direction = GeneralMethods.getDirection(location, target).normalize(); - } - - location = location.add(direction.clone().multiply(stepSpeed)); - - if (GeneralMethods.isSolid(location.getBlock())) { - if (!GeneralMethods.isSolid(location.getBlock().getRelative(BlockFace.UP))) { - location.add(0, 1, 0); - } else { - return false; - } - } - - if (!isTransparent(location.getBlock()) || RegionProtection.isRegionProtected(this, location)) { - return false; - } - - playWaterbendingSound(location); - - new RegenTempBlock(location.getBlock(), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 250); - - // Only damage entities that are more than 3 blocks away. - if (travelled >= 3) { - AABB collider = AABB.BlockBounds.at(location).scale(entityCollisionRadius * 2); - - boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { - DamageHandler.damageEntity(entity, damage, ability); - return true; - }); - - if (hit) { - return false; - } - } - } - - return true; - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public double getCollisionRadius() { - return abilityCollisionRadius; - } - - @Override - public String getName() { - return "WaterBlast"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public void setLocation(Location location) { - this.location = location; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public Ability getAbility() { - return ability; - } - - public double getTravelled() { - return travelled; - } - - public void setTravelled(double travelled) { - this.travelled = travelled; - } - - public double getRange() { - return range; - } - - public double getDamage() { - return damage; - } - - public double getSpeed() { - return speed; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public double getAbilityCollisionRadius() { - return abilityCollisionRadius; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - return true; - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java b/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java deleted file mode 100644 index 55c0a35..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java +++ /dev/null @@ -1,330 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending.combo; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.waterbending.Torrent; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; - -public class Maelstrom extends WaterAbility implements AddonAbility, ComboAbility { - - private int depth; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - - private final List pool = new ArrayList<>(); - private final List wave = new ArrayList<>(); - private Location origin; - private int step; - private int levelStep; - private int angle; - private boolean canRemove; - - public Maelstrom(Player player) { - super(player); - if (!bPlayer.canBendIgnoreBinds(this) || hasAbility(player, Maelstrom.class)) { - return; - } - setFields(); - if (setOrigin()) { - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - Torrent t = getAbility(player, Torrent.class); - if (t != null) { - t.remove(); - } - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Water.WaterCombo.Maelstrom.Cooldown"); - duration = config.getLong("Abilities.Water.WaterCombo.Maelstrom.Duration"); - depth = config.getInt("Abilities.Water.WaterCombo.Maelstrom.MaxDepth"); - range = config.getInt("Abilities.Water.WaterCombo.Maelstrom.Range"); - canRemove = true; - - applyModifiers(); - } - - private void applyModifiers() { - if (isNight(player.getWorld())) { - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - range = (int) getNightFactor(range); - } - } - - public boolean setOrigin() { - Block block = BlockSource.getWaterSourceBlock(player, range, ClickType.LEFT_CLICK, true, false, false); - if (block != null) { - if (!isTransparent(block.getRelative(BlockFace.UP))) { - return false; - } - for (int i = 0; i < depth; i++) { - if (!isWater(block.getRelative(BlockFace.DOWN, i))) { - setDepth(i - 1); - break; - } - } - if (getDepth() < 3) { - return false; - } - origin = block.getLocation().clone(); - for (Location l : GeneralMethods.getCircle(origin, getDepth(), 1, false, false, 0)) { - if (!isWater(l.getBlock())) { - return false; - } - } - return true; - } - return false; - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.getWorld() != origin.getWorld()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - remove(); - return; - } - if (System.currentTimeMillis() > getStartTime() + duration) { - remove(); - return; - } - removeWater(false); - playAnimation(); - dragEntities(); - if (canRemove && (step == 0 || step % 20 == 0)) { - if (levelStep < getDepth()) { - levelStep++; - removeWater(true); - } - if (step == 20) { - step = 0; - } - } - step++; - } - - public void removeWater(boolean increase) { - if (increase) { - pool.clear(); - for (int i = 0; i < levelStep; i++) { - for (Location l : GeneralMethods.getCircle(origin.clone().subtract(0, i, 0), levelStep - i, 1, false, false, 0)) { - if (!isWater(l.getBlock()) && !isTransparent(l.getBlock())) { - canRemove = false; - break; - } - if (!pool.contains(l.getBlock())) { - pool.add(l.getBlock()); - } - } - } - } - for (Block b : pool) { - if (wave.contains(b)) continue; - new RegenTempBlock(b, Material.AIR, Material.AIR.createBlockData(), 100); - } - } - - public void dragEntities(){ - for(Block b : pool){ - if (pool.indexOf(b) % 3 == 0) { - Location l = b.getLocation(); - for(Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 1.5D)){ - Vector direction = GeneralMethods.getDirection(entity.getLocation(), origin.clone().subtract(-0.5, (levelStep - 1), -0.5)); - entity.setVelocity(direction.multiply(0.2)); - } - } - } - } - - public void playAnimation() { - wave.clear(); - int waves = 5; - int newAngle = this.angle; - for (int i = 0; i < levelStep; i++) { - for (int degree = 0; degree < waves; degree++) { - double size = (levelStep - i) - 1; - double angle = ((newAngle + (degree * (360F / waves))) * Math.PI / 180); - double x = size * Math.cos(angle); - double z = size * Math.sin(angle); - Location loc = origin.clone(); - loc.add(x + 0.5, -(i - 0.5), z + 0.5); - Block b = loc.getBlock(); - for (int j = 0; j < 2; j++) { - wave.add(b.getRelative(BlockFace.DOWN, j)); - new RegenTempBlock(b.getRelative(BlockFace.DOWN, j), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(1)), 0); - ParticleEffect.WATER_SPLASH.display(loc, 3, Math.random(), Math.random(), Math.random(), 0); - } - } - newAngle += 15; - } - this.angle+=(levelStep * 2); - - } - - public void setDepth(int depth) { - this.depth = depth; - } - - public int getDepth() { - return depth; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return origin; - } - - @Override - public String getName() { - return "Maelstrom"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public Object createNewComboInstance(Player player) { - return new Maelstrom(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.Maelstrom.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Water.WaterCombo.Maelstrom.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.WaterCombo.Maelstrom.Description"); - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public List getPool() { - return pool; - } - - public List getWave() { - return wave; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public int getAngle() { - return angle; - } - - public void setAngle(int angle) { - this.angle = angle; - } - - public boolean canRemove() { - return canRemove; - } - - public void setCanRemove(boolean canRemove) { - this.canRemove = canRemove; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.WaterCombo.Maelstrom.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java deleted file mode 100644 index c1adb24..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java +++ /dev/null @@ -1,730 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending.combo; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.MaterialUtil; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.airbending.AirSpout; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.earthbending.Catapult; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.WaterManipulation; -import com.projectkorra.projectkorra.waterbending.WaterSpout; -import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; -import com.projectkorra.projectkorra.waterbending.util.WaterReturn; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; - -public class WaterFlow extends WaterAbility implements AddonAbility, ComboAbility { - - @Attribute(Attribute.SELECT_RANGE) - private int sourceRange; //10 - @Attribute(Attribute.RANGE) - private int maxRange; //40 - private int minRange; //8 - @Attribute(Attribute.DURATION) - private long duration; //10000 - @Attribute(Attribute.COOLDOWN) - private long cooldown; //15000 - private long meltDelay; //5000 - @Attribute("Length") - private long trail; //80 - private boolean avatar; //true - private boolean stayAtSource; //true - private int stayRange; //100 - private boolean fullMoonEnabled; - private int fullMoonCooldown; - private int fullMoonDuration; - private boolean playerRideOwnFlow; - private int size; //1; - private int avatarSize; //3; - private int fullMoonSizeSmall; //2; - private int fullMoonSizeLarge; //3; - private long avatarDuration; //60000; - private boolean canUseBottle; - private boolean canUsePlants; - private boolean removeOnAnyDamage; - - private long time; - private Location origin; - private Location head; - private int range; - private Block sourceBlock; - private boolean frozen; - private double prevHealth; - private int headSize; - private boolean usingBottle; - private final ConcurrentHashMap directions = new ConcurrentHashMap<>(); - private final List blocks = new ArrayList<>(); - - Random rand = new Random(); - - public WaterFlow(Player player) { - super(player); - if (!bPlayer.canBendIgnoreBinds(this)) { - return; - } - if (JCMethods.isLunarEclipse(player.getWorld())) { - return; - } - if (hasAbility(player, WaterFlow.class)) { - getAbility(player, WaterFlow.class).remove(); - return; - } - setFields(); - - usingBottle = false; - - if (prepare()) { - headSize = size; - trail = trail * size; - range = maxRange; - prevHealth = player.getHealth(); - time = System.currentTimeMillis(); - - int augment = (int) Math.round(getNightFactor(player.getWorld())); - if (isFullMoon(player.getWorld()) && fullMoonEnabled && sourceBlock != null) { - List sources = getNearbySources(sourceBlock, 3); - if (sources.size() > 9) { - headSize = fullMoonSizeSmall; - } - if (sources.size() > 36) { - headSize = fullMoonSizeLarge; - } - trail = trail * augment; - range = range - (range / 3); - maxRange = range; - duration = duration * fullMoonDuration; - cooldown = cooldown * fullMoonCooldown; - } - if (bPlayer.isAvatarState()) { - headSize = avatarSize; - if (avatar) { - duration = 0; - } else { - duration = avatarDuration; - } - } - start(); - if (hasAbility(player, WaterManipulation.class)) { - WaterManipulation manip = getAbility(player, WaterManipulation.class); - manip.remove(); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - sourceRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.SourceRange"); - maxRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MaxRange"); - minRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MinRange"); - duration = config.getLong("Abilities.Water.WaterCombo.WaterFlow.Duration"); - cooldown = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Cooldown"); - meltDelay = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MeltDelay"); - trail = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Trail"); - avatar = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.IsAvatarStateToggle"); - avatarDuration = config.getLong("Abilities.Water.WaterCombo.WaterFlow.AvatarStateDuration"); - stayAtSource = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.PlayerStayNearSource"); - stayRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MaxDistanceFromSource"); - canUseBottle = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.BottleSource"); - canUsePlants = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.PlantSource"); - removeOnAnyDamage = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.RemoveOnAnyDamage"); - fullMoonCooldown = config.getInt("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Cooldown"); - fullMoonDuration = config.getInt("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Duration"); - fullMoonEnabled = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Enabled"); - playerRideOwnFlow = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.PlayerRideOwnFlow"); - size = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.Normal"); - avatarSize = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.AvatarState"); - fullMoonSizeSmall = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonSmall"); - fullMoonSizeLarge = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonLarge"); - - applyModifiers(); - } - - private void applyModifiers() { - if (isNight(player.getWorld())) { - maxRange = (int) getNightFactor(maxRange); - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - } - } - - public static List getNearbySources(Block block, int searchRange) { - List sources = new ArrayList<>(); - for (Location l : GeneralMethods.getCircle(block.getLocation(), searchRange, 2, false, false, -1)) { - Block blockI = l.getBlock(); - if (isWater(block)) { - if (blockI.getType() == Material.WATER && JCMethods.isLiquidSource(blockI) && WaterManipulation.canPhysicsChange(blockI)) { - sources.add(blockI); - } - } - if (isLava(block)) { - if (blockI.getType() == Material.LAVA && JCMethods.isLiquidSource(blockI) && WaterManipulation.canPhysicsChange(blockI)) { - sources.add(blockI); - } - } - } - return sources; - } - - private boolean prepare() { - sourceBlock = BlockSource.getWaterSourceBlock(player, sourceRange, ClickType.SHIFT_DOWN, true, bPlayer.canIcebend(), canUsePlants); - if (sourceBlock != null) { - boolean isGoodSource = GeneralMethods.isAdjacentToThreeOrMoreSources(sourceBlock, false) || (TempBlock.isTempBlock(sourceBlock) && WaterAbility.isBendableWaterTempBlock(sourceBlock)); - - // canUsePlants needs to be checked here due to a bug with PK dynamic source caching. - // getWaterSourceBlock can return a plant even if canUsePlants is passed as false. - if (isGoodSource || (canUsePlants && isPlant(sourceBlock))) { - head = sourceBlock.getLocation().clone(); - origin = sourceBlock.getLocation().clone(); - if (isPlant(sourceBlock)) { - new PlantRegrowth(player, sourceBlock); - } - return true; - } - } - - if (canUseBottle && WaterReturn.hasWaterBottle(player)){ - Location eye = player.getEyeLocation(); - Location forward = eye.clone().add(eye.getDirection()); - - if (isTransparent(eye.getBlock()) && isTransparent(forward.getBlock())) { - head = forward.clone(); - origin = forward.clone(); - usingBottle = true; - WaterReturn.emptyWaterBottle(player); - return true; - } - } - return false; - } - - @SuppressWarnings("deprecation") - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreBinds(this) || !bPlayer.canBendIgnoreCooldowns(getAbility("WaterManipulation"))) { - remove(); - return; - } - if (duration > 0 && System.currentTimeMillis() > time + duration) { - remove(); - return; - } - if ((stayAtSource && player.getLocation().distance(origin) >= stayRange) || head.getY() > head.getWorld().getMaxHeight() || head.getY() < head.getWorld().getMinHeight()) { - remove(); - return; - } - if (RegionProtection.isRegionProtected(player, head, this)) { - remove(); - return; - } - if (AirAbility.isWithinAirShield(head)) { - remove(); - return; - } - if (prevHealth > player.getHealth()) { - remove(); - return; - } - - if (removeOnAnyDamage) { - // Only update the previous health if any damage should remove it. - prevHealth = player.getHealth(); - } - - if (!frozen) { - if (player.isSneaking()) { - if (range >= minRange) { - range -= 2; - } - //BlockSource.update(player, sourceRange, ClickType.RIGHT_CLICK); - } else { - if (range < maxRange) { - range += 2; - } - } - moveWater(); - //updateBlocks(); - manageLength(); - } - } - - private void manageLength() { - int pos = 0; - int ids = 0; - List tempList = new ArrayList<>(blocks); - for (Block block : tempList) { - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(block.getLocation(), 2.8)) { - if (entity.getEntityId() == player.getEntityId() && !playerRideOwnFlow) { - continue; - } - boolean isPlayer = entity instanceof Player; - if (isPlayer) { - if (getPlayers(AirSpout.class).contains(entity)) { - continue; - } else if (getPlayers(WaterSpout.class).contains(entity)) { - continue; - } else if (getPlayers(Catapult.class).contains(entity)) { - continue; - } - } - if (RegionProtection.isRegionProtected(this, entity.getLocation()) || (isPlayer && Commands.invincible.contains(entity.getName()))) { - continue; - } - Location temp = directions.get(block); - Vector dir = GeneralMethods.getDirection(entity.getLocation(), directions.get(block).add(temp.getDirection().multiply(1.5))); - GeneralMethods.setVelocity(this, entity, dir.clone().normalize().multiply(1)); - entity.setFallDistance(0f); - } - - if (!MaterialUtil.isTransparent(block) || RegionProtection.isRegionProtected(player, block.getLocation(), "Torrent")) { - blocks.remove(block); - directions.remove(block); - if (TempBlock.isTempBlock(block)) { - TempBlock.revertBlock(block, Material.AIR); - } - } else { - if (!isWater(block)) { - new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0))); - } - } - pos++; - if (pos > trail) { - ids++; - } - } - for (int i = 0; i < ids; i++) { - if (i >= blocks.size()) { - break; - } - Block block = blocks.get(i); - blocks.remove(block); - directions.remove(block); - if (TempBlock.isTempBlock(block)) { - TempBlock.revertBlock(block, Material.AIR); - } - } - tempList.clear(); - } - - private void moveWater() { - if (!MaterialUtil.isTransparent(head.getBlock()) || RegionProtection.isRegionProtected(player, head, "Torrent")) { - range -= 2; - } - Vector direction = GeneralMethods.getDirection(head, GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); - head = head.add(direction.clone().multiply(1)); - head.setDirection(direction); - playWaterbendingSound(head); - for (Block block : GeneralMethods.getBlocksAroundPoint(head, headSize)) { - if (directions.containsKey(block)) { - directions.replace(block, head.clone()); - } else { - directions.put(block, head.clone()); - blocks.add(block); - } - } - } - - private void removeBlocks() { - for (Block block : directions.keySet()) { - if (TempBlock.isTempBlock(block)) { - TempBlock.revertBlock(block, Material.AIR); - } - } - } - - public static void freeze(Player player) { - if (hasAbility(player, WaterFlow.class)) { - WaterFlow wf = getAbility(player, WaterFlow.class); - if (!wf.bPlayer.canIcebend()) return; - if (!wf.frozen) { - wf.bPlayer.addCooldown(wf); - wf.freeze(); - } - } - } - - private void freeze() { - frozen = true; - for (Block block : directions.keySet()) { - if (TempBlock.isTempBlock(block)) { - if (rand.nextInt(5) == 0) { - playIcebendingSound(block.getLocation()); - } - new RegenTempBlock(block, Material.ICE, Material.ICE.createBlockData(), randInt((int) meltDelay - 250, (int) meltDelay + 250)); - } - } - } - - public int randInt(int min, int max) { - return rand.nextInt(max - min) + min; - } - - @Override - public void remove() { - if (player.isOnline() && cooldown > 0) { - bPlayer.addCooldown(this); - } - if (!frozen) { - removeBlocks(); - } - - if (usingBottle) { - new WaterReturn(player, head.getBlock()); - } - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return head; - } - - @Override - public String getName() { - return "WaterFlow"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public Object createNewComboInstance(Player player) { - return new WaterFlow(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.WaterFlow.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Water.WaterCombo.WaterFlow.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.WaterCombo.WaterFlow.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public int getSourceRange() { - return sourceRange; - } - - public void setSourceRange(int sourceRange) { - this.sourceRange = sourceRange; - } - - public int getMaxRange() { - return maxRange; - } - - public void setMaxRange(int maxRange) { - this.maxRange = maxRange; - } - - public int getMinRange() { - return minRange; - } - - public void setMinRange(int minRange) { - this.minRange = minRange; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getMeltDelay() { - return meltDelay; - } - - public void setMeltDelay(long meltDelay) { - this.meltDelay = meltDelay; - } - - public long getTrail() { - return trail; - } - - public void setTrail(long trail) { - this.trail = trail; - } - - public boolean isAvatar() { - return avatar; - } - - public void setAvatar(boolean avatar) { - this.avatar = avatar; - } - - public boolean isStayAtSource() { - return stayAtSource; - } - - public void setStayAtSource(boolean stayAtSource) { - this.stayAtSource = stayAtSource; - } - - public int getStayRange() { - return stayRange; - } - - public void setStayRange(int stayRange) { - this.stayRange = stayRange; - } - - public boolean isFullMoonEnabled() { - return fullMoonEnabled; - } - - public void setFullMoonEnabled(boolean fullMoonEnabled) { - this.fullMoonEnabled = fullMoonEnabled; - } - - public int getFullMoonCooldown() { - return fullMoonCooldown; - } - - public void setFullMoonCooldown(int fullMoonCooldown) { - this.fullMoonCooldown = fullMoonCooldown; - } - - public int getFullMoonDuration() { - return fullMoonDuration; - } - - public void setFullMoonDuration(int fullMoonDuration) { - this.fullMoonDuration = fullMoonDuration; - } - - public boolean isPlayerRideOwnFlow() { - return playerRideOwnFlow; - } - - public void setPlayerRideOwnFlow(boolean playerRideOwnFlow) { - this.playerRideOwnFlow = playerRideOwnFlow; - } - - public int getSize() { - return size; - } - - public void setSize(int size) { - this.size = size; - } - - public int getAvatarSize() { - return avatarSize; - } - - public void setAvatarSize(int avatarSize) { - this.avatarSize = avatarSize; - } - - public int getFullMoonSizeSmall() { - return fullMoonSizeSmall; - } - - public void setFullMoonSizeSmall(int fullMoonSizeSmall) { - this.fullMoonSizeSmall = fullMoonSizeSmall; - } - - public int getFullMoonSizeLarge() { - return fullMoonSizeLarge; - } - - public void setFullMoonSizeLarge(int fullMoonSizeLarge) { - this.fullMoonSizeLarge = fullMoonSizeLarge; - } - - public long getAvatarDuration() { - return avatarDuration; - } - - public void setAvatarDuration(long avatarDuration) { - this.avatarDuration = avatarDuration; - } - - public boolean isCanUseBottle() { - return canUseBottle; - } - - public void setCanUseBottle(boolean canUseBottle) { - this.canUseBottle = canUseBottle; - } - - public boolean isCanUsePlants() { - return canUsePlants; - } - - public void setCanUsePlants(boolean canUsePlants) { - this.canUsePlants = canUsePlants; - } - - public boolean isRemoveOnAnyDamage() { - return removeOnAnyDamage; - } - - public void setRemoveOnAnyDamage(boolean removeOnAnyDamage) { - this.removeOnAnyDamage = removeOnAnyDamage; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public Location getHead() { - return head; - } - - public void setHead(Location head) { - this.head = head; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public Block getSourceBlock() { - return sourceBlock; - } - - public void setSourceBlock(Block sourceBlock) { - this.sourceBlock = sourceBlock; - } - - public boolean isFrozen() { - return frozen; - } - - public void setFrozen(boolean frozen) { - this.frozen = frozen; - } - - public double getPrevHealth() { - return prevHealth; - } - - public void setPrevHealth(double prevHealth) { - this.prevHealth = prevHealth; - } - - public int getHeadSize() { - return headSize; - } - - public void setHeadSize(int headSize) { - this.headSize = headSize; - } - - public boolean isUsingBottle() { - return usingBottle; - } - - public void setUsingBottle(boolean usingBottle) { - this.usingBottle = usingBottle; - } - - public ConcurrentHashMap getDirections() { - return directions; - } - - public List getBlocks() { - return blocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java deleted file mode 100644 index 9fed934..0000000 --- a/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java +++ /dev/null @@ -1,648 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending.combo; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.ability.waterbending.WaterBlast; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.CollisionInitializer; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.Torrent; -import com.projectkorra.projectkorra.waterbending.WaterManipulation; -import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; -import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; -import com.projectkorra.projectkorra.waterbending.util.WaterReturn; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -public class WaterGimbal extends WaterAbility implements AddonAbility, ComboAbility { - - @Attribute(Attribute.SELECT_RANGE) - private int sourceRange; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("Width") - private double ringSize; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.SPEED) - private double speed; - private int animSpeed; - private boolean plantSourcing; - private boolean snowSourcing; - private boolean requireAdjacentPlants; - private boolean canUseBottle; - private double abilityCollisionRadius; - private double entityCollisionRadius; - - private int step; - private boolean initializing; - private boolean leftVisible = true; - private boolean rightVisible = true; - private boolean rightConsumed = false; - private boolean leftConsumed = false; - private Block sourceBlock; - private TempBlock source; - private Location sourceLoc; - private Location origin1; - private Location origin2; - private boolean usingBottle; - - private final Random rand = new Random(); - - static { - CollisionInitializer.abilityMap.put("WaterGimbal", ""); - } - - public WaterGimbal(Player player) { - super(player); - if (!bPlayer.canBendIgnoreBinds(this)) { - return; - } - if (JCMethods.isLunarEclipse(player.getWorld())) { - return; - } - if (hasAbility(player, WaterGimbal.class)) { - return; - } - setFields(); - usingBottle = false; - if (grabSource()) { - start(); - initializing = true; - if (hasAbility(player, Torrent.class)) { - getAbility(player, Torrent.class).remove(); - } - if (hasAbility(player, WaterManipulation.class)) { - getAbility(player, WaterManipulation.class).remove(); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - sourceRange = config.getInt("Abilities.Water.WaterCombo.WaterGimbal.SourceRange"); - cooldown = config.getLong("Abilities.Water.WaterCombo.WaterGimbal.Cooldown"); - ringSize = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.RingSize"); - range = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.Range"); - damage = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.Damage"); - speed = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.Speed"); - animSpeed = config.getInt("Abilities.Water.WaterCombo.WaterGimbal.AnimationSpeed"); - plantSourcing = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.PlantSource"); - snowSourcing = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.SnowSource"); - requireAdjacentPlants = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.RequireAdjacentPlants"); - canUseBottle = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.BottleSource"); - abilityCollisionRadius = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.AbilityCollisionRadius"); - entityCollisionRadius = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.EntityCollisionRadius"); - - applyModifiers(); - } - - private void applyModifiers() { - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - range = getNightFactor(range); - damage = getNightFactor(damage); - } - - @Override - public void progress() { - if (player == null || player.isDead() || !player.isOnline() || !player.isSneaking()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreBinds(this) || !bPlayer.canBendIgnoreCooldowns(getAbility("WaterManipulation"))) { - remove(); - return; - } - if (hasAbility(player, WaterManipulation.class)) { - getAbility(player, WaterManipulation.class).remove(); - } - if (leftConsumed && rightConsumed) { - remove(); - return; - } - if (!initializing) { - getGimbalBlocks(player.getLocation()); - if (!leftVisible && !leftConsumed && origin1 != null) { - if (origin1.getBlockY() <= player.getEyeLocation().getBlockY()) { - new WaterBlast(player, origin1, range, damage, speed, entityCollisionRadius, abilityCollisionRadius, this); - leftConsumed = true; - } - } - - if (!rightVisible && !rightConsumed && origin2 != null) { - if (origin2.getBlockY() <= player.getEyeLocation().getBlockY()) { - new WaterBlast(player, origin2, range, damage, speed, entityCollisionRadius, abilityCollisionRadius, this); - rightConsumed = true; - } - } - } else { - Vector direction = GeneralMethods.getDirection(sourceLoc, player.getEyeLocation()); - sourceLoc = sourceLoc.add(direction.multiply(1).normalize()); - - if (source == null || !sourceLoc.getBlock().getLocation().equals(source.getLocation())) { - if (source != null) { - source.revertBlock(); - } - if (isTransparent(sourceLoc.getBlock())) { - source = new TempBlock(sourceLoc.getBlock(), Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0))); - } - } - - if (source != null && source.getLocation().distance(player.getLocation()) < 2.5) { - source.revertBlock(); - initializing = false; - } - } - } - - private boolean grabSource() { - sourceBlock = BlockSource.getWaterSourceBlock(player, sourceRange, ClickType.SHIFT_DOWN, true, true, plantSourcing, snowSourcing, false); - if (sourceBlock != null) { - // All of these extra checks need to be done because PK sourcing system is buggy. - boolean usingSnow = snowSourcing && (sourceBlock.getType() == Material.SNOW_BLOCK || sourceBlock.getType() == Material.SNOW); - - if (isPlant(sourceBlock) || usingSnow) { - if (usingSnow || !requireAdjacentPlants || JCMethods.isAdjacentToThreeOrMoreSources(sourceBlock, sourceBlock.getType())) { - playFocusWaterEffect(sourceBlock); - sourceLoc = sourceBlock.getLocation(); - - new PlantRegrowth(this.player, sourceBlock); - sourceBlock.setType(Material.AIR); - - return true; - } - } else if (!ElementalAbility.isSnow(sourceBlock)) { - boolean isTempBlock = TempBlock.isTempBlock(sourceBlock); - - if (GeneralMethods.isAdjacentToThreeOrMoreSources(sourceBlock, false) || (isTempBlock && WaterAbility.isBendableWaterTempBlock(sourceBlock))) { - playFocusWaterEffect(sourceBlock); - sourceLoc = sourceBlock.getLocation(); - - if (isTempBlock) { - PhaseChange.thaw(sourceBlock); - } - - return true; - } - } - } - - // Try to use bottles if no source blocks nearby. - // todo: works the first time, requires actual sources and still consumes water bottle afterwards - if (canUseBottle && hasWaterBottle(player)){ - Location eye = player.getEyeLocation(); - Location forward = eye.clone().add(eye.getDirection()); - - if (isTransparent(eye.getBlock()) && isTransparent(forward.getBlock())) { - sourceLoc = forward; - sourceBlock = sourceLoc.getBlock(); - usingBottle = true; - WaterReturn.emptyWaterBottle(player); - return true; - } - } - return false; - } - - // Custom function to see if player has bottle. - // This is to get around the WaterReturn limitation since OctopusForm will currently be using the bottle. - private boolean hasWaterBottle(Player player) { - PlayerInventory inventory = player.getInventory(); - return JedCore.plugin.getPotionEffectAdapter().hasWaterPotion(inventory); - } - - public static void prepareBlast(Player player) { - if (hasAbility(player, WaterGimbal.class)) { - getAbility(player, WaterGimbal.class).prepareBlast(); - if (hasAbility(player, WaterManipulation.class)) { - getAbility(player, WaterManipulation.class).remove(); - } - } - } - - public void prepareBlast() { - if (leftVisible) { - leftVisible = false; - return; - } - if (rightVisible) { - rightVisible = false; - } - } - - private void getGimbalBlocks(Location location) { - List ring1 = new ArrayList<>(); - List ring2 = new ArrayList<>(); - Location l = location.clone().add(0, 1, 0); - int count = 0; - - while (count < animSpeed) { - boolean completed = false; - double velocity = 0.15; - double angle = 3.0 + this.step * velocity; - double xRotation = Math.PI / 2.82 * 2.1; - Vector v1 = new Vector(Math.cos(angle), Math.sin(angle), 0.0D).multiply(ringSize); - Vector v2 = new Vector(Math.cos(angle), Math.sin(angle), 0.0D).multiply(ringSize); - rotateAroundAxisX(v1, xRotation); - rotateAroundAxisX(v2, -xRotation); - rotateAroundAxisY(v1, -((location.getYaw() * Math.PI / 180) - 1.575)); - rotateAroundAxisY(v2, -((location.getYaw() * Math.PI / 180) - 1.575)); - - if (!ring1.contains(l.clone().add(v1).getBlock()) && !leftConsumed) { - completed = true; - Block block = l.clone().add(v1).getBlock(); - if (isTransparent(block)) { - ring1.add(block); - } else { - for (int i = 0; i < 4; i++) { - if (isTransparent(block.getRelative(BlockFace.UP, i))) { - ring1.add(block.getRelative(BlockFace.UP, i)); - break; - } - } - } - } - - if (!ring2.contains(l.clone().add(v2).getBlock()) && !rightConsumed) { - completed = true; - Block block = l.clone().add(v2).getBlock(); - if (isTransparent(block)) { - ring2.add(block); - } else { - for (int i = 0; i < 4; i++) { - if (isTransparent(block.getRelative(BlockFace.UP, i))) { - ring2.add(block.getRelative(BlockFace.UP, i)); - break; - } - } - } - } - - if (completed) { - count++; - } - - if (leftConsumed && rightConsumed) { - break; - } - - this.step++; - } - - if (!leftConsumed) { - if (!ring1.isEmpty()) { - Collections.reverse(ring1); - origin1 = ring1.get(0).getLocation(); - } - for (Block block : ring1) { - new RegenTempBlock(block, Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 150L); - if (rand.nextInt(10) == 0) { - playWaterbendingSound(block.getLocation()); - } - } - } - - if (!rightConsumed) { - if (!ring2.isEmpty()) { - Collections.reverse(ring2); - origin2 = ring2.get(0).getLocation(); - } - for (Block block : ring2) { - new RegenTempBlock(block, Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 150L); - if (rand.nextInt(10) == 0) { - playWaterbendingSound(block.getLocation()); - } - } - } - } - - private void rotateAroundAxisX(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double y = v.getY() * cos - v.getZ() * sin; - double z = v.getY() * sin + v.getZ() * cos; - v.setY(y).setZ(z); - } - - private void rotateAroundAxisY(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double x = v.getX() * cos + v.getZ() * sin; - double z = v.getX() * -sin + v.getZ() * cos; - v.setX(x).setZ(z); - } - - @Override - public void remove() { - if (source != null) { - source.revertBlock(); - } - if (player.isOnline() && !initializing) { - bPlayer.addCooldown(this); - } - - if (usingBottle) { - new WaterReturn(player, sourceBlock); - } - super.remove(); - } - - public Player getPlayer() { - return player; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "WaterGimbal"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public Object createNewComboInstance(Player player) { - return new WaterGimbal(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.WaterGimbal.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Water.WaterCombo.WaterGimbal.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.WaterCombo.WaterGimbal.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public int getSourceRange() { - return sourceRange; - } - - public void setSourceRange(int sourceRange) { - this.sourceRange = sourceRange; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public double getRingSize() { - return ringSize; - } - - public void setRingSize(double ringSize) { - this.ringSize = ringSize; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - } - - public int getAnimSpeed() { - return animSpeed; - } - - public void setAnimSpeed(int animSpeed) { - this.animSpeed = animSpeed; - } - - public boolean isPlantSourcing() { - return plantSourcing; - } - - public void setPlantSourcing(boolean plantSourcing) { - this.plantSourcing = plantSourcing; - } - - public boolean isSnowSourcing() { - return snowSourcing; - } - - public void setSnowSourcing(boolean snowSourcing) { - this.snowSourcing = snowSourcing; - } - - public boolean isRequireAdjacentPlants() { - return requireAdjacentPlants; - } - - public void setRequireAdjacentPlants(boolean requireAdjacentPlants) { - this.requireAdjacentPlants = requireAdjacentPlants; - } - - public boolean isCanUseBottle() { - return canUseBottle; - } - - public void setCanUseBottle(boolean canUseBottle) { - this.canUseBottle = canUseBottle; - } - - public double getAbilityCollisionRadius() { - return abilityCollisionRadius; - } - - public void setAbilityCollisionRadius(double abilityCollisionRadius) { - this.abilityCollisionRadius = abilityCollisionRadius; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - public int getStep() { - return step; - } - - public void setStep(int step) { - this.step = step; - } - - public boolean isInitializing() { - return initializing; - } - - public void setInitializing(boolean initializing) { - this.initializing = initializing; - } - - public boolean isLeftVisible() { - return leftVisible; - } - - public void setLeftVisible(boolean leftVisible) { - this.leftVisible = leftVisible; - } - - public boolean isRightVisible() { - return rightVisible; - } - - public void setRightVisible(boolean rightVisible) { - this.rightVisible = rightVisible; - } - - public boolean isRightConsumed() { - return rightConsumed; - } - - public void setRightConsumed(boolean rightConsumed) { - this.rightConsumed = rightConsumed; - } - - public boolean isLeftConsumed() { - return leftConsumed; - } - - public void setLeftConsumed(boolean leftConsumed) { - this.leftConsumed = leftConsumed; - } - - public Block getSourceBlock() { - return sourceBlock; - } - - public void setSourceBlock(Block sourceBlock) { - this.sourceBlock = sourceBlock; - } - - public TempBlock getSource() { - return source; - } - - public void setSource(TempBlock source) { - this.source = source; - } - - public Location getSourceLoc() { - return sourceLoc; - } - - public void setSourceLoc(Location sourceLoc) { - this.sourceLoc = sourceLoc; - } - - public Location getOrigin1() { - return origin1; - } - - public void setOrigin1(Location origin1) { - this.origin1 = origin1; - } - - public Location getOrigin2() { - return origin2; - } - - public void setOrigin2(Location origin2) { - this.origin2 = origin2; - } - - public boolean isUsingBottle() { - return usingBottle; - } - - public void setUsingBottle(boolean usingBottle) { - this.usingBottle = usingBottle; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.Enabled"); - } -} diff --git a/src/com/jedk1/jedcore/collision/AABB.java b/src/com/jedk1/jedcore/collision/AABB.java deleted file mode 100644 index 35df188..0000000 --- a/src/com/jedk1/jedcore/collision/AABB.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.jedk1.jedcore.collision; - -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.util.Vector; - -import java.util.Optional; - -public class AABB implements Collider { - public static AABB PlayerBounds = new AABB(new Vector(-0.3, 0.0, -0.3), new Vector(0.3, 1.8, 0.3)); - public static AABB BlockBounds = new AABB(new Vector(0.0, 0.0, 0.0), new Vector(1.0, 1.0, 1.0)); - - private Vector min; - private Vector max; - private boolean hasVolume; - - public AABB(Block block) { - this.min = min(block); - this.max = max(block); - - this.hasVolume = max.clone().subtract(min).lengthSquared() > 0; - } - - public AABB(Entity entity) { - this.min = min(entity); - this.max = max(entity); - - this.hasVolume = max.clone().subtract(min).lengthSquared() > 0; - } - - public AABB(Vector min, Vector max) { - this.min = min; - this.max = max; - - if (min != null && max != null) { - this.hasVolume = max.clone().subtract(min).lengthSquared() > 0; - } - } - - public boolean hasVolume() { - return this.hasVolume; - } - - public AABB at(Vector pos) { - if (min == null || max == null) return new AABB(null, null); - - return new AABB(min.clone().add(pos), max.clone().add(pos)); - } - - public AABB at(Location location) { - if (min == null || max == null) return new AABB(null, null); - - return at(location.toVector()); - } - - public AABB grow(double x, double y, double z) { - Vector change = new Vector(x, y, z); - - return new AABB(min.clone().subtract(change), max.clone().add(change)); - } - - public AABB scale(double x, double y, double z) { - Vector extents = getHalfExtents(); - Vector newExtents = extents.clone().multiply(new Vector(x, y, z)); - - Vector diff = newExtents.clone().subtract(extents); - return grow(diff.getX(), diff.getY(), diff.getZ()); - } - - public AABB scale(double amount) { - Vector extents = getHalfExtents(); - Vector newExtents = extents.clone().multiply(amount); - - Vector diff = newExtents.clone().subtract(extents); - return grow(diff.getX(), diff.getY(), diff.getZ()); - } - - public Vector min() { - return this.min; - } - - public Vector max() { - return this.max; - } - - public Vector mid() { - return this.min.clone().add(this.max().clone().subtract(this.min()).multiply(0.5)); - } - - public boolean contains(Vector test) { - if (min == null || max == null || !hasVolume) return false; - - return (test.getX() >= min.getX() && test.getX() <= max.getX()) && - (test.getY() >= min.getY() && test.getY() <= max.getY()) && - (test.getZ() >= min.getZ() && test.getZ() <= max.getZ()); - } - - public Optional intersects(Ray ray) { - if (min == null || max == null || !hasVolume) return Optional.empty(); - - double t1 = (min.getX() - ray.origin.getX()) * ray.directionReciprocal.getX(); - double t2 = (max.getX() - ray.origin.getX()) * ray.directionReciprocal.getX(); - - double t3 = (min.getY() - ray.origin.getY()) * ray.directionReciprocal.getY(); - double t4 = (max.getY() - ray.origin.getY()) * ray.directionReciprocal.getY(); - - double t5 = (min.getZ() - ray.origin.getZ()) * ray.directionReciprocal.getZ(); - double t6 = (max.getZ() - ray.origin.getZ()) * ray.directionReciprocal.getZ(); - - double tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6)); - double tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6)); - - if (tmax < 0 || tmin > tmax) { - return Optional.empty(); - } - - return Optional.of(tmin); - } - - public boolean intersects(AABB other) { - if (min == null || max == null || other.min == null || other.max == null || !hasVolume || !other.hasVolume) { - return false; - } - - return (max.getX() > other.min.getX() && - min.getX() < other.max.getX() && - max.getY() > other.min.getY() && - min.getY() < other.max.getY() && - max.getZ() > other.min.getZ() && - min.getZ() < other.max.getZ()); - } - - public boolean intersects(Sphere sphere) { - if (!this.hasVolume) return false; - - return sphere.intersects(this); - } - - @Override - public Vector getPosition() { - return mid(); - } - - @Override - public Vector getHalfExtents() { - Vector half = max.clone().subtract(min).multiply(0.5); - // Return a vector of half extents that reach from mid to box sides. - return new Vector(Math.abs(half.getX()), Math.abs(half.getY()), Math.abs(half.getZ())); - } - - private Vector min(Entity entity) { - Vector worldMin = entity.getBoundingBox().getMin(); - - return worldMin.clone().subtract(entity.getLocation().toVector()); - } - - private Vector max(Entity entity) { - Vector worldMax = entity.getBoundingBox().getMax(); - - return worldMax.clone().subtract(entity.getLocation().toVector()); - } - - private Vector min(Block block) { - if (block.isPassable()) { - return new Vector(0, 0, 0); - } - - Vector worldMin = block.getBoundingBox().getMin(); - - return worldMin.clone().subtract(block.getLocation().toVector()); - } - - private Vector max(Block block) { - if (block.isPassable()) { - return new Vector(0, 0, 0); - } - - Vector worldMax = block.getBoundingBox().getMax(); - - return worldMax.clone().subtract(block.getLocation().toVector()); - } -} diff --git a/src/com/jedk1/jedcore/collision/Collider.java b/src/com/jedk1/jedcore/collision/Collider.java deleted file mode 100644 index 03cedca..0000000 --- a/src/com/jedk1/jedcore/collision/Collider.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.jedk1.jedcore.collision; - -import org.bukkit.util.Vector; - -public interface Collider { - boolean intersects(AABB aabb); - boolean intersects(Sphere sphere); - Vector getPosition(); - Vector getHalfExtents(); - - boolean contains(Vector point); -} diff --git a/src/com/jedk1/jedcore/collision/CollisionDetector.java b/src/com/jedk1/jedcore/collision/CollisionDetector.java deleted file mode 100644 index 95440c1..0000000 --- a/src/com/jedk1/jedcore/collision/CollisionDetector.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.jedk1.jedcore.collision; - -import com.projectkorra.projectkorra.ability.ElementalAbility; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.Collections; -import java.util.Optional; -import java.util.Set; - -public class CollisionDetector { - public static boolean checkEntityCollisions(Player player, Collider collider, CollisionCallback function) { - return checkEntityCollisions(player, collider, function, true); - } - - // Checks a collider to see if it's hitting any entities near it. - // Calls the CollisionCallback when hitting a target. - // Returns true if it hits a target. - public static boolean checkEntityCollisions(Player player, Collider collider, CollisionCallback callback, boolean livingOnly) { - // This is used to increase the lookup volume for nearby entities. - // Entity locations can be out of the collider volume while still intersecting. - final double ExtentBuffer = 4.0; - - // Create the extent vector to use as size of bounding box to find nearby entities. - Vector extent = collider.getHalfExtents().add(new Vector(ExtentBuffer, ExtentBuffer, ExtentBuffer)); - - World world = player.getWorld(); - Vector pos = collider.getPosition(); - Location location = new Location(world, pos.getX(), pos.getY(), pos.getZ()); - - boolean hit = false; - - for (Entity entity : location.getWorld().getNearbyEntities(location, extent.getX(), extent.getY(), extent.getZ())) { - if (entity == player) continue; - if (entity instanceof ArmorStand) continue; - - if (entity instanceof Player && ((Player) entity).getGameMode().equals(GameMode.SPECTATOR)) { - continue; - } - - if (livingOnly && !(entity instanceof LivingEntity)) { - continue; - } - - AABB entityBounds = new AABB(entity).at(entity.getLocation()); - - if (collider.intersects(entityBounds)) { - if (callback.onCollision(entity)) { - return true; - } - - hit = true; - } - } - - return hit; - } - - // Checks if the entity is on the ground. Uses NMS bounding boxes for accuracy. - public static boolean isOnGround(Entity entity) { - final double epsilon = 0.01; - - Location location = entity.getLocation(); - AABB entityBounds = new AABB(entity).at(location.clone().subtract(0, epsilon, 0)); - - for (int x = -1; x <= 1; ++x) { - for (int z = -1; z <= 1; ++z) { - Block checkBlock = location.clone().add(x, -epsilon, z).getBlock(); - if (ElementalAbility.isAir(checkBlock.getType())) continue; - - AABB checkBounds = new AABB(checkBlock).at(checkBlock.getLocation()); - - if (entityBounds.intersects(checkBounds)) { - return true; - } - } - } - - return false; - } - - public static double distanceAboveGround(Entity entity) { - return distanceAboveGround(entity, Collections.emptySet()); - } - - // Cast a ray down to find how far above the ground this entity is. - public static double distanceAboveGround(Entity entity, Set groundMaterials) { - Location location = entity.getLocation().clone(); - Ray ray = new Ray(location, new Vector(0, -1, 0)); - - for (double y = location.getY() - 1; y >= 0; --y) { - location.setY(y); - - Block block = location.getBlock(); - AABB checkBounds; - - if (groundMaterials.contains(block.getType())) { - checkBounds = AABB.BlockBounds; - } else { - checkBounds = new AABB(block); - } - - checkBounds = checkBounds.at(block.getLocation()); - - Optional rayHit = checkBounds.intersects(ray); - - if (rayHit.isPresent()) { - return rayHit.get(); - } - } - - return Double.MAX_VALUE; - } - - public interface CollisionCallback { - // return true to break out of the loop - boolean onCollision(Entity e); - } -} diff --git a/src/com/jedk1/jedcore/collision/CollisionUtil.java b/src/com/jedk1/jedcore/collision/CollisionUtil.java deleted file mode 100644 index 1095edf..0000000 --- a/src/com/jedk1/jedcore/collision/CollisionUtil.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.jedk1.jedcore.collision; - -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; - -import java.util.Iterator; -import java.util.List; - -public final class CollisionUtil { - private CollisionUtil() { - - } - - public static void handleFallingBlockCollisions(Collision collision, List fallingBlocks) { - if (collision.isRemovingFirst()) { - Location location = collision.getLocationSecond(); - double firstRadius = collision.getAbilityFirst().getCollisionRadius(); - double secondRadius = collision.getAbilitySecond().getCollisionRadius(); - double collisionRadiusSq = (firstRadius + secondRadius) * (firstRadius + secondRadius); - - // Loop through all falling blocks because the collision system stops on the first collision. - for (Iterator iterator = fallingBlocks.iterator(); iterator.hasNext();) { - TempFallingBlock tfb = iterator.next(); - - // Check if this falling block is within collision radius - if (tfb.getLocation().distanceSquared(location) <= collisionRadiusSq) { - tfb.remove(); - iterator.remove(); - } - } - } - } -} diff --git a/src/com/jedk1/jedcore/collision/Ray.java b/src/com/jedk1/jedcore/collision/Ray.java deleted file mode 100644 index 6ecf860..0000000 --- a/src/com/jedk1/jedcore/collision/Ray.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.jedk1.jedcore.collision; - -import org.bukkit.Location; -import org.bukkit.util.Vector; - -public class Ray { - public Vector origin; - public Vector direction; - public Vector directionReciprocal; - - public Ray(Vector origin, Vector direction) { - this.direction = direction; - this.origin = origin; - this.directionReciprocal = new Vector(0, 0, 0); - - if (direction.getX() == 0.0) { - directionReciprocal.setX(Double.MAX_VALUE); - } else { - directionReciprocal.setX(1.0 / direction.getX()); - } - - if (direction.getY() == 0.0) { - directionReciprocal.setY(Double.MAX_VALUE); - } else { - directionReciprocal.setY(1.0 / direction.getY()); - } - - if (direction.getZ() == 0.0) { - directionReciprocal.setZ(Double.MAX_VALUE); - } else { - directionReciprocal.setZ(1.0 / direction.getZ()); - } - } - - public Ray(Location origin, Vector direction) { - this(origin.toVector(), direction); - } -} diff --git a/src/com/jedk1/jedcore/collision/Sphere.java b/src/com/jedk1/jedcore/collision/Sphere.java deleted file mode 100644 index d0514a0..0000000 --- a/src/com/jedk1/jedcore/collision/Sphere.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.jedk1.jedcore.collision; - -import org.bukkit.util.Vector; - -public class Sphere implements Collider { - public Vector center; - public double radius; - - public Sphere(Vector center, double radius) { - this.center = center; - this.radius = radius; - } - - public Sphere at(Vector newCenter) { - return new Sphere(newCenter, radius); - } - - public boolean intersects(AABB aabb) { - Vector min = aabb.min(); - Vector max = aabb.max(); - - // Get the point closest to sphere center on the aabb. - double x = Math.max(min.getX(), Math.min(center.getX(), max.getX())); - double y = Math.max(min.getY(), Math.min(center.getY(), max.getY())); - double z = Math.max(min.getZ(), Math.min(center.getZ(), max.getZ())); - - // Check if that point is inside of the sphere. - return contains(new Vector(x, y, z)); - } - - public boolean intersects(Sphere other) { - double distSq = other.center.distanceSquared(center); - double rsum = radius + other.radius; - - // Spheres will be colliding if their distance apart is less than the sum of the radii. - return distSq <= rsum * rsum; - } - - @Override - public Vector getPosition() { - return center.clone(); - } - - @Override - public Vector getHalfExtents() { - return new Vector(radius, radius, radius); - } - - public boolean contains(Vector point) { - double distSq = center.distanceSquared(point); - return distSq <= radius * radius; - } -} diff --git a/src/com/jedk1/jedcore/command/Commands.java b/src/com/jedk1/jedcore/command/Commands.java deleted file mode 100644 index 1c23a38..0000000 --- a/src/com/jedk1/jedcore/command/Commands.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.jedk1.jedcore.command; - - -public class Commands { - - public Commands() { - new JedCoreCommand(); - } -} diff --git a/src/com/jedk1/jedcore/command/JedCoreCommand.java b/src/com/jedk1/jedcore/command/JedCoreCommand.java deleted file mode 100644 index 1db12e9..0000000 --- a/src/com/jedk1/jedcore/command/JedCoreCommand.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.jedk1.jedcore.command; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.command.PKCommand; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -public class JedCoreCommand extends PKCommand { - private static final String DOWNLOAD_URL = "https://github.com/CozmycDev/JedCore"; - - public JedCoreCommand() { - super("jedcore", "/bending jedcore", "This command will show the statistics and version of JedCore.", new String[] { "jedcore", "jc" }); - } - - @Override - public void execute(CommandSender sender, List args) { - if (!correctLength(sender, args.size(), 0, 1) || (!hasPermission(sender) && !isSenderJedCoreDev(sender))) { - return; - } - if (args.size() == 0) { - sendBuildInfo(sender); - } else if (args.size() == 1 && (hasPermission(sender, "debug") || isSenderJedCoreDev(sender))) { - //Dev commands for debugging etc. - if (args.get(0).equalsIgnoreCase("refresh")) { - sender.sendMessage(ChatColor.AQUA + "Jedcore refreshed."); - } - } else { - help(sender, false); - } - } - - public static void sendBuildInfo(CommandSender sender) { - sender.sendMessage(ChatColor.GRAY + "Running JedCore Build: " + ChatColor.RED + JedCore.plugin.getDescription().getVersion()); - sender.sendMessage(ChatColor.GRAY + "Developed by: " + ChatColor.RED + JedCore.plugin.getDescription().getAuthors().toString().replace("[", "").replace("]", "")); - sender.sendMessage(ChatColor.GRAY + "Modified by: " + ChatColor.RED + "plushmonkey"); - sender.sendMessage(ChatColor.GRAY + "Maintained by: " + ChatColor.RED + "Cozmyc"); - sender.sendMessage(ChatColor.GRAY + "URL: " + ChatColor.RED + ChatColor.ITALIC + DOWNLOAD_URL); - } - - private boolean isSenderJedCoreDev(CommandSender sender) { - UUID[] devs = { - UUID.fromString("4eb6315e-9dd1-49f7-b582-c1170e497ab0"), - UUID.fromString("d57565a5-e6b0-44e3-a026-979d5de10c4d"), - UUID.fromString("e98a2f7d-d571-4900-a625-483cbe6774fe") - }; - if (sender instanceof Player) { - Player player = (Player) sender; - if (Arrays.asList(devs).contains(player.getUniqueId())) { - return true; - } - } - return false; - } -} diff --git a/src/com/jedk1/jedcore/configuration/Config.java b/src/com/jedk1/jedcore/configuration/Config.java deleted file mode 100644 index 06355d5..0000000 --- a/src/com/jedk1/jedcore/configuration/Config.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.jedk1.jedcore.configuration; - -import com.jedk1.jedcore.JedCore; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; - -public class Config { - - JedCore plugin; - - private final File file; - public FileConfiguration config; - - public Config(File file) { - this.plugin = JedCore.plugin; - this.file = new File(plugin.getDataFolder() + File.separator + file); - this.config = YamlConfiguration.loadConfiguration(this.file); - reloadConfig(); - } - - public void createConfig() { - if (!file.getParentFile().exists()) { - try { - file.getParentFile().mkdir(); - plugin.getLogger().info("Generating new directory for " + file.getName() + "!"); - } catch (Exception e) { - plugin.getLogger().info("Failed to generate directory!"); - e.printStackTrace(); - } - } - - if (!file.exists()) { - try { - file.createNewFile(); - plugin.getLogger().info("Generating new " + file.getName() + "!"); - } catch (Exception e) { - plugin.getLogger().info("Failed to generate " + file.getName() + "!"); - e.printStackTrace(); - } - } - } - - public FileConfiguration getConfig() { - return config; - } - - public void reloadConfig() { - createConfig(); - try { - config.load(file); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void saveConfig() { - try { - config.options().copyDefaults(true); - config.save(file); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java deleted file mode 100644 index 710e78f..0000000 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ /dev/null @@ -1,1104 +0,0 @@ -package com.jedk1.jedcore.configuration; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.configuration.ConfigManager; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; - -public class JedCoreConfig { - - static JedCore plugin; - public static Config board; - - public JedCoreConfig(JedCore plugin) { - JedCoreConfig.plugin = plugin; - board = new Config(new File("board.yml")); - loadConfigBoard(); - loadConfigCore(); - addDeathMessages(); - setupElementSphereNames(); - } - - private void loadConfigBoard() { - FileConfiguration config; - config = board.getConfig(); - config.addDefault("Settings.Enabled", false); - config.options().copyDefaults(true); - board.saveConfig(); - } - - private void loadConfigCore() { - FileConfiguration config; - config = JedCore.plugin.getConfig(); - - config.addDefault("Settings.Updater.Check", true); - config.addDefault("Settings.Updater.Notify", true); - config.addDefault("Properties.MobCollisions.Enabled", true); - config.addDefault("Properties.AbilityCollisions.Enabled", true); - config.addDefault("Properties.PerWorldConfig", true); - config.addDefault("Properties.FireTickMethod", "larger"); - config.addDefault("Properties.LogDebug", false); - - config.addDefault("Properties.ChiRestrictor.Enabled", false); - config.addDefault("Properties.ChiRestrictor.ResetCooldown", true); - config.addDefault("Properties.ChiRestrictor.MeleeDistance", 7); - config.addDefault("Properties.ChiRestrictor.Whitelist", new ArrayList()); - - config.addDefault("Properties.Fire.DynamicLight.Enabled", true); - config.addDefault("Properties.Fire.DynamicLight.Brightness", 13); - config.addDefault("Properties.Fire.DynamicLight.KeepAlive", 600); - - config.addDefault("Abilities.Avatar.ElementSphere.Enabled", true); - config.addDefault("Abilities.Avatar.ElementSphere.Description", "ElementSphere is a very all round ability, being " - + "able to shoot attacks of each element, each with a " - + "different effect. To use, simply Left-Click. Once active, " - + "Sneak (Default: Shift) to fly around. Sneak and double " - + "Left-Click to disable the ability! " - + "To use each element, simply select hotbar slots 1-4 and Left-Click. " - + "Each element has limited uses! Once an element is used up, " - + "the element's ring will disappear!"); - config.addDefault("Abilities.Avatar.ElementSphere.Cooldown", 180000); - config.addDefault("Abilities.Avatar.ElementSphere.Duration", 60000); - config.addDefault("Abilities.Avatar.ElementSphere.MaxControlledHeight", 40); - config.addDefault("Abilities.Avatar.ElementSphere.FlySpeed", 1.5); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Knockback", 2); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Speed", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactRevert", 15000); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.BurnDuration", 3000); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Speed", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Controllable", false); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Speed", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Knockback", 2.0); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Damage", 12.0); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.RequiredUses", 10); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.EndAbility", true); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactCraterSize", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactRevert", 30000); - - config.addDefault("Abilities.Avatar.SpiritBeam.Enabled", true); - config.addDefault("Abilities.Avatar.SpiritBeam.Description", "An energybending ability usable by the Avatar. " - + "To use, one must enter the AvatarState and hold down Sneak (Default: Shift). " - + "This ability lasts only for a few seconds before requiring " - + "another activation."); - config.addDefault("Abilities.Avatar.SpiritBeam.Cooldown", 15000); - config.addDefault("Abilities.Avatar.SpiritBeam.Duration", 1000); - config.addDefault("Abilities.Avatar.SpiritBeam.Range", 40); - config.addDefault("Abilities.Avatar.SpiritBeam.Damage", 10.0); - config.addDefault("Abilities.Avatar.SpiritBeam.AvatarStateOnly", true); - config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Enabled", true); - config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Radius", 3); - config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Regen", 20000); - - config.addDefault("Abilities.Air.AirBlade.Enabled", true); - config.addDefault("Abilities.Air.AirBlade.Description", "With this ability bound, Left-Click to shoot " - + "a strong blade of air at your targets to deal some damage!"); - config.addDefault("Abilities.Air.AirBlade.Cooldown", 3000); - config.addDefault("Abilities.Air.AirBlade.Range", 30.0); - config.addDefault("Abilities.Air.AirBlade.Damage", 4.0); - config.addDefault("Abilities.Air.AirBlade.Speed", 1.0); - config.addDefault("Abilities.Air.AirBlade.Knockback", 0.0); - config.addDefault("Abilities.Air.AirBlade.EntityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirBlade.AbilityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.Enabled", true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveFirst", true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveSecond", true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.Enabled", true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveFirst", true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveSecond", false); - config.addDefault("Abilities.Air.AirBlade.BlockCutting.Enabled", true); - config.addDefault("Abilities.Air.AirBlade.BlockCutting.Revert", true); - config.addDefault("Abilities.Air.AirBlade.BlockCutting.RevertTime", 5000); - config.addDefault("Abilities.Air.AirBlade.BlockCutting.Materials", Arrays.asList( - "#small_flowers", - "#flowers", - "#crops", - "#saplings", - "BIG_DRIPLEAF_STEM", - "BIG_DRIPLEAF", - "CAVE_VINES", - "CAVE_VINES_PLANT", - "VINE", - "FERN", - "LARGE_FERN", - "SHORT_GRASS", - "TALL_GRASS", - "DEAD_BUSH", - "SEA_PICKLE", - "CACTUS_FLOWER", - "BERRY_BUSH", - "RED_MUSHROOM", - "BROWN_MUSHROOM" - )); - - config.addDefault("Abilities.Air.AirBreath.Enabled", true); - config.addDefault("Abilities.Air.AirBreath.Description", "To use, hold Sneak (Default: Shift) to release " - + "a strong breath of wind, knocking your opponents " - + "back. This ability also has a longer range and " - + "stronger knockback while in AvatarState!"); - config.addDefault("Abilities.Air.AirBreath.Cooldown", 3000); - config.addDefault("Abilities.Air.AirBreath.Duration", 3000); - config.addDefault("Abilities.Air.AirBreath.Particles", 3); - config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Lava", true); - config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Fire", true); - config.addDefault("Abilities.Air.AirBreath.ExtinguishEntities", true); - config.addDefault("Abilities.Air.AirBreath.Damage.Enabled", false); - config.addDefault("Abilities.Air.AirBreath.Damage.Player", 1.0); - config.addDefault("Abilities.Air.AirBreath.Damage.Mob", 2.0); - config.addDefault("Abilities.Air.AirBreath.Knockback", 0.8); - config.addDefault("Abilities.Air.AirBreath.Range", 10); - config.addDefault("Abilities.Air.AirBreath.LaunchPower", 1.0); - config.addDefault("Abilities.Air.AirBreath.RegenTargetOxygen", true); - config.addDefault("Abilities.Air.AirBreath.Avatar.Enabled", true); - config.addDefault("Abilities.Air.AirBreath.Avatar.Range", 20); - config.addDefault("Abilities.Air.AirBreath.Avatar.Knockback", 3.5); - - config.addDefault("Abilities.Air.AirGlide.Enabled", true); - config.addDefault("Abilities.Air.AirGlide.Description", "While falling, tap Sneak for a " - + "slow and steady descent. Tap Sneak again to stop gliding."); - config.addDefault("Abilities.Air.AirGlide.Speed", 0.5); - config.addDefault("Abilities.Air.AirGlide.FallSpeed", 0.1); - config.addDefault("Abilities.Air.AirGlide.Particles", 4); - config.addDefault("Abilities.Air.AirGlide.AllowAirSpout", false); - config.addDefault("Abilities.Air.AirGlide.Cooldown", 0); - config.addDefault("Abilities.Air.AirGlide.Duration", 0); - config.addDefault("Abilities.Air.AirGlide.RequireGround", false); - - config.addDefault("Abilities.Air.AirPunch.Enabled", true); - config.addDefault("Abilities.Air.AirPunch.Description", "Left-Click in rapid succession to punch high desnity packets of air " - + "at enemies to do slight damage. A few punches can be thrown before the ability goes on cooldown."); - config.addDefault("Abilities.Air.AirPunch.Cooldown", 5000); - config.addDefault("Abilities.Air.AirPunch.Threshold", 500); - config.addDefault("Abilities.Air.AirPunch.Shots", 4); - config.addDefault("Abilities.Air.AirPunch.Range", 30); - config.addDefault("Abilities.Air.AirPunch.Damage", 1.0); - config.addDefault("Abilities.Air.AirPunch.Speed", 1.0); - config.addDefault("Abilities.Air.AirPunch.EntityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirPunch.AbilityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.Enabled", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveFirst", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveSecond", false); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.Enabled",true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveFirst",true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveSecond",false); - config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.Enabled", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveFirst", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveSecond", false); - - config.addDefault("Abilities.Air.Meditate.Enabled", true); - config.addDefault("Abilities.Air.Meditate.Description", "Hold Sneak (Default: Shift) to start meditating. " - + "After you have focused your energy, you will obtain several buffs."); - config.addDefault("Abilities.Air.Meditate.UnfocusMessage", "You have become unfocused due to taking damage!"); - config.addDefault("Abilities.Air.Meditate.LossFocusMessage", true); - config.addDefault("Abilities.Air.Meditate.ChargeTime", 5000); - config.addDefault("Abilities.Air.Meditate.Cooldown", 60000); - config.addDefault("Abilities.Air.Meditate.BoostDuration", 20000); - config.addDefault("Abilities.Air.Meditate.ParticleDensity", 5); - config.addDefault("Abilities.Air.Meditate.AbsorptionBoost", 2); - config.addDefault("Abilities.Air.Meditate.SpeedBoost", 3); - config.addDefault("Abilities.Air.Meditate.JumpBoost", 3); - - config.addDefault("Abilities.Air.SonicBlast.Enabled", true); - config.addDefault("Abilities.Air.SonicBlast.Description", "SonicBlast is a soundbending ability, known by very few airbenders. " - + "It allows the airbender to stun and deafen an opponent by creating a sonic blast. " - + "This is achieved by creating two regions of high and low pressure and bringing them together. " - + "To use, hold Sneak (Default: Shift) in the direction of the target. Once particles appear " - + "around you, let go of Sneak to shoot a SonicBlast at your target! The technique is very powerful, " - + "even if it doesn't seem it, and comes with a short cooldown."); - config.addDefault("Abilities.Air.SonicBlast.ChargeTime", 2000); - config.addDefault("Abilities.Air.SonicBlast.Damage", 4.0); - config.addDefault("Abilities.Air.SonicBlast.Effects.BlindnessDuration", 5000); - config.addDefault("Abilities.Air.SonicBlast.Effects.NauseaDuration", 5000); - config.addDefault("Abilities.Air.SonicBlast.Cooldown", 6000); - config.addDefault("Abilities.Air.SonicBlast.EntityCollisionRadius", 1.3); - config.addDefault("Abilities.Air.SonicBlast.AbilityCollisionRadius", 1.3); - config.addDefault("Abilities.Air.SonicBlast.Range", 20); - config.addDefault("Abilities.Air.SonicBlast.ChargeSwapping", true); - - config.addDefault("Abilities.Air.AirCombo.AirSlam.Enabled", true); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Description", "Kick your enemy up into the air then blast them away!"); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Cooldown", 8000); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Power", 5.0); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Range", 8); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Combination", Arrays.asList("AirSwipe:SHIFT_DOWN", "AirBlast:SHIFT_UP", "AirBlast:SHIFT_DOWN")); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Instructions", "AirSwipe (Hold sneak) > AirBlast (Release sneak) > AirBlast (Hold sneak)"); - - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Enabled", true); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Description", "Create a stream of air as you fly which causes nearby " - + "entities to be thrown in your direction."); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.DragFactor", 1.5); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Duration", 2000); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Cooldown", 6000); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Combination", Arrays.asList("Flight:SHIFT_DOWN", "Flight:SHIFT_UP", "Flight:SHIFT_DOWN", "Flight:SHIFT_UP")); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Instructions", "Flight (Double tap sneak)"); - - config.addDefault("Abilities.Earth.EarthArmor.Enabled", true); - config.addDefault("Abilities.Earth.EarthArmor.Description", "If the block is metal, then you will get metal armor!"); - config.addDefault("Abilities.Earth.EarthArmor.Resistance.Strength", 2); - config.addDefault("Abilities.Earth.EarthArmor.Resistance.Duration", 4000); - config.addDefault("Abilities.Earth.EarthArmor.UseIronArmor", false); - - config.addDefault("Abilities.Earth.EarthKick.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Description", "This move enables an earthbender to create a " - + "large earthen cover, ideal for defense. " - + "To use, Sneak (Default: Shift) at an earth " - + "source and it will raise and launch towards " - + "your foe!"); - config.addDefault("Abilities.Earth.EarthKick.Cooldown", 2000); - config.addDefault("Abilities.Earth.EarthKick.EarthBlocks", 10); - - double oldDamage = 0.0; - if (config.contains("Abilities.Earth.EarthKick.Damage")) { - oldDamage = config.getDouble("Abilities.Earth.EarthKick.Damage"); - config.set("Abilities.Earth.EarthKick.Damage", null); - } - - config.addDefault("Abilities.Earth.EarthKick.Damage.Normal", oldDamage > 0.0 ? oldDamage : 2.0); - config.addDefault("Abilities.Earth.EarthKick.Damage.Metal", 3.0); - config.addDefault("Abilities.Earth.EarthKick.EntityCollisionRadius", 1.5); - config.addDefault("Abilities.Earth.EarthKick.AbilityCollisionRadius", 1.5); - config.addDefault("Abilities.Earth.EarthKick.MultipleHits", true); - config.addDefault("Abilities.Earth.EarthKick.SourceRange", 2.0); - config.addDefault("Abilities.Earth.EarthKick.Spread", 20); - config.addDefault("Abilities.Earth.EarthKick.Velocity", 0.7); - config.addDefault("Abilities.Earth.EarthKick.AllowMetal", true); - config.addDefault("Abilities.Earth.EarthKick.ReplaceSource", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveSecond", true); - - - config.addDefault("Abilities.Earth.EarthLine.Enabled", true); - config.addDefault("Abilities.Earth.EarthLine.Description", "To use, place your cursor over an earth-bendable block on the ground, " - + "then Sneak (Default: Shift) to select the block. After selecting the block you may release Sneak. " - + "If you then Left-Click at an object or player, a small piece of earth will come up " - + "from the ground and move towards your target to deal damage and knock them back. " - + "Additionally, hold Sneak to control the flow of the line!"); - config.addDefault("Abilities.Earth.EarthLine.Cooldown", 3000); - config.addDefault("Abilities.Earth.EarthLine.PrepareCooldown", 0); - config.addDefault("Abilities.Earth.EarthLine.Range", 30); - config.addDefault("Abilities.Earth.EarthLine.PrepareRange", 3); - config.addDefault("Abilities.Earth.EarthLine.SourceKeepRange", 7); - config.addDefault("Abilities.Earth.EarthLine.AffectingRadius", 2); - config.addDefault("Abilities.Earth.EarthLine.AllowChangeDirection", true); - config.addDefault("Abilities.Earth.EarthLine.MaxDuration", 2500); - config.addDefault("Abilities.Earth.EarthLine.Damage", 3.0); - config.addDefault("Abilities.Earth.EarthLine.RemovalPolicy.SwappedSlots.Enabled", false); - - config.addDefault("Abilities.Earth.EarthPillar.Enabled", true); - config.addDefault("Abilities.Earth.EarthPillar.Description", "With this ability bound, tap Sneak (Default: Shift) on any Earthbendable " - + "surface to create pillar of earth in the direction of the block face!"); - config.addDefault("Abilities.Earth.EarthPillar.Height", 6); - config.addDefault("Abilities.Earth.EarthPillar.Range", 10); - - config.addDefault("Abilities.Earth.EarthShard.Enabled", true); - config.addDefault("Abilities.Earth.EarthShard.Description", "EarthShard is a variation of EarthBlast " - + "which the earthbender may use to hit a target. This " - + "ability deals a fair amount of damage and is easy to " - + "rapid-fire. To use, simply shift at an earthbendable block, " - + "and it will ascend to your eye height. Then, click towards your " - + "target and the block will launch itself towards it."); - config.addDefault("Abilities.Earth.EarthShard.Cooldown", 1000); - config.addDefault("Abilities.Earth.EarthShard.Damage.Normal", 1.0); - config.addDefault("Abilities.Earth.EarthShard.Damage.Metal", 1.5); - config.addDefault("Abilities.Earth.EarthShard.PrepareRange", 5); - config.addDefault("Abilities.Earth.EarthShard.AbilityRange", 30); - config.addDefault("Abilities.Earth.EarthShard.MaxShards", 3); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Allow", true); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Velocity", 1.0); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Range", 1.5); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Allow", true); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Velocity", 1.0); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Range", 1.5); -// config.addDefault("Abilities.Earth.EarthShard.KnockUp.Allow", true); -// config.addDefault("Abilities.Earth.EarthShard.KnockUp.Velocity", 1.0); - config.addDefault("Abilities.Earth.EarthShard.AbilityCollisionRadius", 2.0); - config.addDefault("Abilities.Earth.EarthShard.EntityCollisionRadius", 1.4); - - config.addDefault("Abilities.Earth.EarthSurf.Enabled", true); - config.addDefault("Abilities.Earth.EarthSurf.Description", "This ability allows an earth bender to " - + "ride up on a wave of earth, allowing them to travel a little faster than " - + "normal. To use, simply be in the air just above " - + "the ground, and Left Click! Additionally, if an entity just so happens to get caught in " - + "the wave, they will be moved with the wave."); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Cooldown", 3000); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown", 2000); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Scaled", true); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Enabled", false); - config.addDefault("Abilities.Earth.EarthSurf.Duration.Duration", 7000); - config.addDefault("Abilities.Earth.EarthSurf.Duration.Enabled", false); - config.addDefault("Abilities.Earth.EarthSurf.RelaxedCollisions", true); - config.addDefault("Abilities.Earth.EarthSurf.RemoveOnAnyDamage", false); - config.addDefault("Abilities.Earth.EarthSurf.Speed", 0.55); - config.addDefault("Abilities.Earth.EarthSurf.HeightTolerance", 3); - config.addDefault("Abilities.Earth.EarthSurf.SpringStiffness", 0.35); - - config.addDefault("Abilities.Earth.Fissure.Enabled", true); - config.addDefault("Abilities.Earth.Fissure.Description", "Fissure is an advanced Lavabending " - + "ability enabling a lavabender to tear up the ground, " - + "swallowing up any enemies. To use, simply swing at an enemy " - + "and a line of lava will crack open. " - + "Then, tap Sneak (Default: Shift) to expand the crevice. " - + "The crevice has a maximum width and depth. Once the crevice has reached it's maximum " - + "width, Sneak while looking at the crevice to close it!"); - config.addDefault("Abilities.Earth.Fissure.Cooldown", 20000); - config.addDefault("Abilities.Earth.Fissure.Duration", 15000); - config.addDefault("Abilities.Earth.Fissure.MaxWidth", 3); - config.addDefault("Abilities.Earth.Fissure.SlapRange", 12); - config.addDefault("Abilities.Earth.Fissure.SlapDelay", 50); - - config.addDefault("Abilities.Earth.LavaDisc.Enabled", true); - config.addDefault("Abilities.Earth.LavaDisc.Description", "Hold Sneak (Default: Shift) on a lava source " - + "block to generate a disc of lava at your finger tips. Releasing " - + "Sneak will shoot the disc off in the direction " - + "you are looking! If you tap or hold Sneak again, " - + "the disc will attempt to return to you!"); - String[] meltable = { - Material.COBBLESTONE.name(), Material.OAK_LOG.name(), Material.SPRUCE_LOG.name(), - Material.JUNGLE_LOG.name(), Material.DARK_OAK_LOG.name(), Material.BIRCH_LOG.name(), - Material.ACACIA_LOG.name() - }; - config.addDefault("Abilities.Earth.LavaDisc.Cooldown", 7000); - config.addDefault("Abilities.Earth.LavaDisc.Duration", 1000); - config.addDefault("Abilities.Earth.LavaDisc.Damage", 4.0); - config.addDefault("Abilities.Earth.LavaDisc.Particles", 3); - config.addDefault("Abilities.Earth.LavaDisc.ContinueAfterEntityHit", false); - config.addDefault("Abilities.Earth.LavaDisc.RecallLimit", 3); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.RegenTime", 5000); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.BlockDamage", true); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks", meltable); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.LavaTrail", true); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.TrailFlow", false); - config.addDefault("Abilities.Earth.LavaDisc.Source.RegenTime", 10000); - config.addDefault("Abilities.Earth.LavaDisc.Source.LavaOnly", false); - config.addDefault("Abilities.Earth.LavaDisc.Source.Range", 4.0); - config.addDefault("Abilities.Earth.LavaDisc.RemovalPolicy.SwappedSlots.Enabled", true); - - config.addDefault("Abilities.Earth.LavaFlux.Enabled", true); - config.addDefault("Abilities.Earth.LavaFlux.Description", "This offensive ability enables a Lavabender to create a wave of lava, " - + "swiftly progressing forward and hurting/burning anything in its way. To use, " - + "simply swing your arm towards a target and the ability will activate."); - config.addDefault("Abilities.Earth.LavaFlux.Range", 12); - config.addDefault("Abilities.Earth.LavaFlux.Cooldown", 8000); - config.addDefault("Abilities.Earth.LavaFlux.Duration", 4000); - config.addDefault("Abilities.Earth.LavaFlux.Cleanup", 1000); - config.addDefault("Abilities.Earth.LavaFlux.Damage", 1.0); - config.addDefault("Abilities.Earth.LavaFlux.Speed", 1); - config.addDefault("Abilities.Earth.LavaFlux.Wave", true); - config.addDefault("Abilities.Earth.LavaFlux.KnockUp", 1.0); - config.addDefault("Abilities.Earth.LavaFlux.KnockBack", 1.0); - - config.addDefault("Abilities.Earth.LavaThrow.Enabled", true); - config.addDefault("Abilities.Earth.LavaThrow.Description", "Throwing lava is a fundamental technique for the rare subskill. " - + "Use Sneak(Deafult: Shift) while looking at a pool of lava infront of you, then " - + "Left-Click to splash the lava at your target. " - + "It can be used in rapid succession to create multiple streams of lava!"); - config.addDefault("Abilities.Earth.LavaThrow.Cooldown", 7000); - config.addDefault("Abilities.Earth.LavaThrow.MaxShots", 6); - config.addDefault("Abilities.Earth.LavaThrow.Range", 20); - config.addDefault("Abilities.Earth.LavaThrow.Damage", 1.0); - config.addDefault("Abilities.Earth.LavaThrow.SourceGrabRange", 4); - config.addDefault("Abilities.Earth.LavaThrow.SourceRegenDelay", 10000); - config.addDefault("Abilities.Earth.LavaThrow.FireTicks", 80); - config.addDefault("Abilities.Earth.LavaThrow.CurveFactor", 0.5); - - config.addDefault("Abilities.Earth.MagnetShield.Enabled", true); - config.addDefault("Abilities.Earth.MagnetShield.Description", "Repel any metal projectiles using a strong magnetic shield. " - + "To activate, simply hold sneak with this ability bound."); - config.addDefault("Abilities.Earth.MagnetShield.Materials", Arrays.asList( - "IRON_INGOT", - "IRON_HELMET", - "IRON_CHESTPLATE", - "IRON_LEGGINGS", - "IRON_BOOTS", - "IRON_BLOCK", - "IRON_AXE", - "IRON_PICKAXE", - "IRON_SWORD", - "IRON_HOE", - "IRON_SHOVEL", - "IRON_DOOR", - "IRON_NUGGET", - "IRON_BARS", - "IRON_HORSE_ARMOR", - "IRON_TRAPDOOR", - "HEAVY_WEIGHTED_PRESSURE_PLATE", - "GOLD_INGOT", - "GOLDEN_HELMET", - "GOLDEN_CHESTPLATE", - "GOLDEN_LEGGINGS", - "GOLDEN_BOOTS", - "GOLD_BLOCK", - "GOLD_NUGGET", - "GOLDEN_AXE", - "GOLDEN_PICKAXE", - "GOLDEN_SHOVEL", - "GOLDEN_SWORD", - "GOLDEN_HOE", - "GOLDEN_HORSE_ARMOR", - "LIGHT_WEIGHTED_PRESSURE_PLATE", - "CLOCK", - "COMPASS", - "RAW_GOLD_BLOCK", - "RAW_IRON_BLOCK", - "RAW_IRON", - "RAW_GOLD", - "ANVIL", - "CHIPPED_ANVIL", - "DAMAGED_ANVIL", - "IRON_ORE", - "GOLD_ORE", - "DEEPSLATE_IRON_ORE", - "DEEPSLATE_GOLD_ORE", - "SHIELD" - )); - config.addDefault("Abilities.Earth.MagnetShield.Duration", 6000); - config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Shift", 5000); - config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Click", 5000); - config.addDefault("Abilities.Earth.MagnetShield.Range", 5.0); - config.addDefault("Abilities.Earth.MagnetShield.RepelArrows", true); - config.addDefault("Abilities.Earth.MagnetShield.RepelLivingEntities", true); - config.addDefault("Abilities.Earth.MagnetShield.Velocity", 0.1); - - config.addDefault("Abilities.Earth.MetalFragments.Enabled", true); - config.addDefault("Abilities.Earth.MetalFragments.Description", "MetalFragments allows you to select a source and shoot " - + "multiple fragments of metal out of that source " - + "block towards your target, injuring them on impact. " - + "To use, tap Sneak (Default: Shift) at a metal " - + "source block and it will float up. Then, turn around " - + "and click at your target to fling metal fragments at them."); - config.addDefault("Abilities.Earth.MetalFragments.Cooldown", 5000); - config.addDefault("Abilities.Earth.MetalFragments.MaxSources", 3); - config.addDefault("Abilities.Earth.MetalFragments.SourceRange", 5); - config.addDefault("Abilities.Earth.MetalFragments.MaxFragments", 10); - config.addDefault("Abilities.Earth.MetalFragments.Damage", 4.0); - config.addDefault("Abilities.Earth.MetalFragments.Velocity", 2.0); - - config.addDefault("Abilities.Earth.MetalHook.Enabled", true); - config.addDefault("Abilities.Earth.MetalHook.Description", "This ability lets a Metalbender bend metal into " - + "grappling hooks, allowing them to easily manouver terrain. " - + "To use this ability, the user must either have Iron in their inventory " - + "or be wearing an Iron/Chainmail Chestplate. Left-Click in the direction " - + "you are looking to fire a grappling hook, several hooks can be active at once, " - + "allowing the bender to 'hang' in locations. To disengage the hooks, hold Shift (Default: Sneak) or Sprint."); - config.addDefault("Abilities.Earth.MetalHook.Cooldown", 3000); - config.addDefault("Abilities.Earth.MetalHook.Range", 30); - config.addDefault("Abilities.Earth.MetalHook.MaxHooks", 3); - config.addDefault("Abilities.Earth.MetalHook.TotalHooks", 0); - config.addDefault("Abilities.Earth.MetalHook.RequireItems", true); - config.addDefault("Abilities.Earth.MetalHook.BarrierHooking", true); - - config.addDefault("Abilities.Earth.MetalShred.Enabled", true); - config.addDefault("Abilities.Earth.MetalShred.Description", "MetalShred allows you to tear a metal surface allowing you to sneak in to the other side." - + "To use, you must find a flat metal surface. Then, Sneak(Default: Shift) " - + "at a piece of metal on that surface, and two pieces of metal " - + "will be pulled toward you. Finally, run alongside the surface to coil " - + "the metal around those two pieces. The way will be open, and the blocks " - + "will not reset until you either select a new source or you switch " - + "abilities. If you click after having torn a hole in a vertical surface, " - + "you can Left-Click in any direction and the metal will unfold in that " - + "direction. If you are fast and precise enough, the metal can bend in " - + "any shape. The length of this sheet of metal depends on how much was " - + "coiled in the first place."); - config.addDefault("Abilities.Earth.MetalShred.SourceRange", 5); - config.addDefault("Abilities.Earth.MetalShred.ExtendTick", 80); - config.addDefault("Abilities.Earth.MetalShred.Damage", 6.0); - - config.addDefault("Abilities.Earth.MudSurge.Enabled", true); - config.addDefault("Abilities.Earth.MudSurge.Description", "This ability lets an earthbender send a surge of mud " - + "in any direction, knocking back enemies and " - + "dealing moderate damage. This ability has a chance " - + "of blinding the target. To use, select " - + "a source of earth and click in any direction."); - config.addDefault("Abilities.Earth.MudSurge.Cooldown", 6000); - config.addDefault("Abilities.Earth.MudSurge.Damage", 1.0); - config.addDefault("Abilities.Earth.MudSurge.Waves", 5); - config.addDefault("Abilities.Earth.MudSurge.SourceRange", 7); - config.addDefault("Abilities.Earth.MudSurge.BlindChance", 10); - config.addDefault("Abilities.Earth.MudSurge.WetSourceOnly", false); - config.addDefault("Abilities.Earth.MudSurge.WaterSearchRadius", 5); - config.addDefault("Abilities.Earth.MudSurge.BlindTicks", 60); - config.addDefault("Abilities.Earth.MudSurge.CollisionRadius", 2.0); - config.addDefault("Abilities.Earth.MudSurge.MultipleHits", true); - config.addDefault("Abilities.Earth.MudSurge.AllowFallDamage", false); - config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.SwappedSlots.Enabled", true); - config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Enabled", true); - config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Range", 25.0); - - config.addDefault("Abilities.Earth.SandBlast.Enabled", true); - config.addDefault("Abilities.Earth.SandBlast.Description", "This ability lets an earthbender blast a bunch of sand at an enemy " - + "damaging them and temporarily blinding them! Just Sneak (Default: Shift) " - + "on a sand bendable block, then Left-Click in a direction to shoot a " - + "blast of sand!"); - config.addDefault("Abilities.Earth.SandBlast.Cooldown", 3000); - config.addDefault("Abilities.Earth.SandBlast.Damage", 3.0); - config.addDefault("Abilities.Earth.SandBlast.SourceRange", 8); - config.addDefault("Abilities.Earth.SandBlast.Range", 30); - config.addDefault("Abilities.Earth.SandBlast.MaxSandBlocks", 10); - - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Enabled", true); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Description", "Create a Crevice in the ground! Once opened, " - + "anyone can Tap Sneak with Shockwave to close the Crevice!"); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Range", 50); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.RevertDelay", 7500); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Depth", 5); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth", 8); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Cooldown", 10000); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Combination", Arrays.asList("Collapse:RIGHT_CLICK_BLOCK", "Shockwave:SHIFT_DOWN", "Shockwave:SHIFT_UP", "Shockwave:SHIFT_DOWN")); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Instructions", "Collapse (Right-click a block) > Shockwave (Tap sneak) > Shockwave (Tap sneak)"); - - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Enabled", true); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Description", "Fire balls of magma at your enemy!"); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots", 3); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage", 2.0); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange", 4); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown", 6000); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown", 1500); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow", false); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions", true); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection", true); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange", 30.0); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius", 2.0); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed", 1.5); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration", 15000); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources", 15); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Combination", Arrays.asList("EarthBlast:SHIFT_DOWN", "LavaFlow:SHIFT_UP", "LavaFlow:SHIFT_DOWN", "LavaFlow:RIGHT_CLICK_BLOCK")); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Instructions", "EarthBlast (Hold sneak) > LavaFlow (Release sneak) > LavaFlow (Hold sneak) > LavaFlow (Right-click a block) > LavaFlow (Left-click multiple times)"); - - ArrayList combustionSkipMaterials = new ArrayList<>(); - combustionSkipMaterials.add("#bee_growables"); - combustionSkipMaterials.add("#cave_vines"); - combustionSkipMaterials.add("#crops"); - combustionSkipMaterials.add("#flowers"); - combustionSkipMaterials.add("vine"); - combustionSkipMaterials.add("pale_hanging_moss"); - - config.addDefault("Abilities.Fire.Combustion.Enabled", true); - config.addDefault("Abilities.Fire.Combustion.Description", "Hold Shift to focus large amounts of energy into your body, " - + "Release Shift to fire Combustion. Move your mouse to " - + "direct where the beam travels. Left-Click to detonate " - + "the beam manually"); - config.addDefault("Abilities.Fire.Combustion.Damage", 4.0); - config.addDefault("Abilities.Fire.Combustion.FireTick", 100); - config.addDefault("Abilities.Fire.Combustion.MisfireModifier", -1); - config.addDefault("Abilities.Fire.Combustion.Power", 3); - config.addDefault("Abilities.Fire.Combustion.Range", 100); - config.addDefault("Abilities.Fire.Combustion.Speed", 0.65); - config.addDefault("Abilities.Fire.Combustion.Warmup", 1500); - config.addDefault("Abilities.Fire.Combustion.Cooldown", 5000); - config.addDefault("Abilities.Fire.Combustion.RegenTime", 10000); - config.addDefault("Abilities.Fire.Combustion.EntityCollisionRadius", 1.3); - config.addDefault("Abilities.Fire.Combustion.AbilityCollisionRadius", 1.3); - config.addDefault("Abilities.Fire.Combustion.DamageBlocks", true); - config.addDefault("Abilities.Fire.Combustion.RegenBlocks", true); - config.addDefault("Abilities.Fire.Combustion.WaitForRegen", true); - config.addDefault("Abilities.Fire.Combustion.InstantExplodeIfHit", true); - config.addDefault("Abilities.Fire.Combustion.ExplodeOnDeath", true); - config.addDefault("Abilities.Fire.Combustion.RemovalPolicy.SwappedSlots.Enabled", false); - config.addDefault("Abilities.Fire.Combustion.SkipMaterials", combustionSkipMaterials); - - config.addDefault("Abilities.Fire.Discharge.Enabled", true); - config.addDefault("Abilities.Fire.Discharge.Description", "Left-Click to shoot bolts of electricity out " - + "of your fingertips zapping what ever it hits!"); - config.addDefault("Abilities.Fire.Discharge.Damage", 3.0); - config.addDefault("Abilities.Fire.Discharge.Cooldown", 5000); - config.addDefault("Abilities.Fire.Discharge.AvatarCooldown", 500); - config.addDefault("Abilities.Fire.Discharge.Duration", 1000); - config.addDefault("Abilities.Fire.Discharge.SlotSwapping", false); - config.addDefault("Abilities.Fire.Discharge.EntityCollisionRadius", 1.0); - config.addDefault("Abilities.Fire.Discharge.AbilityCollisionRadius", 1.0); - config.addDefault("Abilities.Fire.Discharge.Sound.Volume", 0.6); - config.addDefault("Abilities.Fire.Discharge.Sound.Interval", 6); - - config.addDefault("Abilities.Fire.FireBall.Enabled", true); - config.addDefault("Abilities.Fire.FireBall.Description", "To use, simply Left-Click to shoot a fireball at your target!"); - config.addDefault("Abilities.Fire.FireBall.Cooldown", 3000); - config.addDefault("Abilities.Fire.FireBall.Range", 50); - config.addDefault("Abilities.Fire.FireBall.Damage", 3.0); - config.addDefault("Abilities.Fire.FireBall.FireDuration", 2000); - config.addDefault("Abilities.Fire.FireBall.Controllable", false); - config.addDefault("Abilities.Fire.FireBall.FireTrail", true); - config.addDefault("Abilities.Fire.FireBall.CollisionRadius", 1.1); - config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.Enabled", true); - config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveFirst", true); - config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Enabled", true); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveFirst", false); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Reflect", true); - - config.addDefault("Abilities.Fire.FireBreath.Enabled", true); - config.addDefault("Abilities.Fire.FireBreath.Description", "To use, hold Sneak (Default: Shift) to start breathing " - + "fire! Some Firebenders possess the power to infuse color " - + "when they breathe, it's unclear how they do this, but some suggest " - + "it can be obtained by saying \"Bring fire and light together as one and allow the breath of color\" " - + "and can be brought back to normal by saying \"Split the bond of fire " - + "and light and set the color free\"."); - config.addDefault("Abilities.Fire.FireBreath.Cooldown", 5000); - config.addDefault("Abilities.Fire.FireBreath.Duration", 3000); - config.addDefault("Abilities.Fire.FireBreath.Particles", 3); - config.addDefault("Abilities.Fire.FireBreath.Damage.Player", 1.0); - config.addDefault("Abilities.Fire.FireBreath.Damage.Mob", 2.0); - config.addDefault("Abilities.Fire.FireBreath.FireDuration", 3000); - config.addDefault("Abilities.Fire.FireBreath.Range", 10); - config.addDefault("Abilities.Fire.FireBreath.Avatar.FireEnabled", true); - config.addDefault("Abilities.Fire.FireBreath.Melt.Enabled", true); - config.addDefault("Abilities.Fire.FireBreath.Melt.Chance", 3); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.Enabled", true); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "You have bonded fire with light and can now breathe pure color."); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "You have split your bond of color and light."); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "You don't possess the power to bond light with fire."); - - config.addDefault("Abilities.Fire.FireComet.Enabled", true); - config.addDefault("Abilities.Fire.FireComet.Description", "Harnessing the power of Sozin's Comet, a firebender can create a great " - + "ball of fire, with much destructive power. Only useable during Sozin's Comet or while in the AvatarState, hold Sneak (Default: Shift) " - + "to start charging the ability up. Once the ability is charged, a large mass of particles will follow your cursor, until you release sneak, " - + "launching the great ball of fire in the direction you are looking."); - config.addDefault("Abilities.Fire.FireComet.Cooldown", 45000); - config.addDefault("Abilities.Fire.FireComet.ChargeUp", 7000); - config.addDefault("Abilities.Fire.FireComet.Damage", 6.0); - config.addDefault("Abilities.Fire.FireComet.BlastRadius", 3.0); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.Cooldown", 30000); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.ChargeUp", 5000); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.Damage", 12.0); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.BlastRadius", 5.0); - config.addDefault("Abilities.Fire.FireComet.Range", 50); - config.addDefault("Abilities.Fire.FireComet.RegenDelay", 15000); - config.addDefault("Abilities.Fire.FireComet.SozinsCometOnly", true); - config.addDefault("Abilities.Fire.FireComet.AvatarStateBypassComet", true); - - config.addDefault("Abilities.Fire.FirePunch.Enabled", true); - config.addDefault("Abilities.Fire.FirePunch.Description", "This basic ability allows a Firebender to channel their energies into a " - + "single punch, igniting and damaging the victim."); - config.addDefault("Abilities.Fire.FirePunch.Cooldown", 4000); - config.addDefault("Abilities.Fire.FirePunch.FireTicks", 2000); - config.addDefault("Abilities.Fire.FirePunch.Damage", 2.0); - config.addDefault("Abilities.Fire.FirePunch.BurnsDroppedItems", true); - - config.addDefault("Abilities.Fire.FireShots.Enabled", true); - config.addDefault("Abilities.Fire.FireShots.Description", "To use, tap Sneak (Default: Shift) to summon a " - + "FireBalls at your hand, then Left Click to shoot off each ball! " - + "Each shot will follow the cursor until it runs out or hits something! " - + "Tap Sneak again to switch your main hand."); - config.addDefault("Abilities.Fire.FireShots.Cooldown", 3000); - config.addDefault("Abilities.Fire.FireShots.Range", 50); - config.addDefault("Abilities.Fire.FireShots.FireBalls", 4); - config.addDefault("Abilities.Fire.FireShots.FireDuration", 3000); - config.addDefault("Abilities.Fire.FireShots.Damage", 2.0); - config.addDefault("Abilities.Fire.FireShots.CollisionRadius", 0.9); - config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.Enabled", true); - config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveFirst", true); - config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Enabled", true); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveFirst", false); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); - - config.addDefault("Abilities.Fire.FireSki.Enabled", true); - config.addDefault("Abilities.Fire.FireSki.Cooldown", 6000); - config.addDefault("Abilities.Fire.FireSki.Duration", 6000); - config.addDefault("Abilities.Fire.FireSki.Speed", 0.7); - config.addDefault("Abilities.Fire.FireSki.IgniteEntities", true); - config.addDefault("Abilities.Fire.FireSki.FireTicks", 60); - config.addDefault("Abilities.Fire.FireSki.RequiredHeight", 0.7); - config.addDefault("Abilities.Fire.FireSki.PunchActivated", false); - - config.addDefault("Abilities.Fire.LightningBurst.Enabled", true); - config.addDefault("Abilities.Fire.LightningBurst.Description", "To use the most explosive lightning move available to a firebender, hold " - + "Sneak (Default: Shift) until blue sparks appear in front of you. Upon releasing, " - + "you will unleash an electrical sphere, shocking anyone who gets too close"); - config.addDefault("Abilities.Fire.LightningBurst.Cooldown", 25000); - config.addDefault("Abilities.Fire.LightningBurst.ChargeUp", 4000); - config.addDefault("Abilities.Fire.LightningBurst.AvatarCooldown", 1000); - config.addDefault("Abilities.Fire.LightningBurst.AvatarChargeUp", 1000); - config.addDefault("Abilities.Fire.LightningBurst.Radius", 12); - config.addDefault("Abilities.Fire.LightningBurst.Damage", 9.0); - config.addDefault("Abilities.Fire.LightningBurst.Sound.Volume", 0.6); - config.addDefault("Abilities.Fire.LightningBurst.Sound.Interval", 6); - - config.addDefault("Abilities.Water.Bloodbending.Enabled", true); - config.addDefault("Abilities.Water.Bloodbending.Description", "This ability allows a skilled waterbender " - + "to bend the water within an enemy's blood, granting them full " - + "control over the enemy's limbs. This ability is extremely dangerous " - + "and is to be used carefully. To use, sneak while looking at an entity " - + "and its body will follow your movement. If you click, you will launch " - + "the entity towards whatever you were looking at when you clicked. The " - + "entity may collide with others, injuring them and the other one further."); - config.addDefault("Abilities.Water.Bloodbending.NightOnly", false); - config.addDefault("Abilities.Water.Bloodbending.FullMoonOnly", false); - config.addDefault("Abilities.Water.Bloodbending.UndeadMobs", true); - config.addDefault("Abilities.Water.Bloodbending.IgnoreWalls", false); - config.addDefault("Abilities.Water.Bloodbending.RequireBound", false); - config.addDefault("Abilities.Water.Bloodbending.Distance", 6); - config.addDefault("Abilities.Water.Bloodbending.HoldTime", 10000); - config.addDefault("Abilities.Water.Bloodbending.Cooldown", 4000); - - config.addDefault("Abilities.Water.BloodPuppet.Enabled", true); - config.addDefault("Abilities.Water.BloodPuppet.Description", "This very high-level bloodbending ability lets " - + "a master control entities' limbs, forcing them to " - + "attack the master's target. To use this ability, you must " - + "be a bloodbender. Next, sneak while targeting " - + "a mob or player and you will start controlling them. To " - + "make the entity hit another, click. To release your " - + "target, stop sneaking. This ability has NO cooldown, but " - + "may only be usable during the night depending on the " - + "server configuration."); - config.addDefault("Abilities.Water.BloodPuppet.NightOnly", false); - config.addDefault("Abilities.Water.BloodPuppet.FullMoonOnly", false); - config.addDefault("Abilities.Water.BloodPuppet.UndeadMobs", true); - config.addDefault("Abilities.Water.BloodPuppet.IgnoreWalls", false); - config.addDefault("Abilities.Water.BloodPuppet.RequireBound", false); - config.addDefault("Abilities.Water.BloodPuppet.Distance", 6); - config.addDefault("Abilities.Water.BloodPuppet.HoldTime", 10000); - config.addDefault("Abilities.Water.BloodPuppet.Cooldown", 4000); - - config.addDefault("Abilities.Water.Drain.Enabled", true); - config.addDefault("Abilities.Water.Drain.Description", "Inspired by how Hama drained water from the fire lilies, many benders " - + "have practiced in the skill of draining water from plants! With this ability bound, " - + "Sneak (Default: Shift) near/around plant sources to drain the water out of them to fill up any " - + "bottles/buckets in your inventory! Alternatively, if you have nothing to fill" - + " and blasts are enabled in the config, you will be able to create mini blasts " - + "of water to shoot at your targets! Aleternatively, this ability can also be used to quickly fill up " - + "bottles from straight water sources or from falling rain!"); - config.addDefault("Abilities.Water.Drain.RegenDelay", 15000); - config.addDefault("Abilities.Water.Drain.Duration", 2000); - config.addDefault("Abilities.Water.Drain.Cooldown", 2000); - config.addDefault("Abilities.Water.Drain.AbsorbSpeed", 0.1); - config.addDefault("Abilities.Water.Drain.AbsorbChance", 20); - config.addDefault("Abilities.Water.Drain.AbsorbRate", 6); - config.addDefault("Abilities.Water.Drain.Radius", 6); - config.addDefault("Abilities.Water.Drain.HoldRange", 2); - config.addDefault("Abilities.Water.Drain.AllowRainSource", true); - config.addDefault("Abilities.Water.Drain.BlastsEnabled", true); - config.addDefault("Abilities.Water.Drain.KeepSource", false); - config.addDefault("Abilities.Water.Drain.BlastSpeed", 1); - config.addDefault("Abilities.Water.Drain.BlastDamage", 1.5); - config.addDefault("Abilities.Water.Drain.BlastRange", 20); - config.addDefault("Abilities.Water.Drain.MaxBlasts", 4); - config.addDefault("Abilities.Water.Drain.DrainTempBlocks", true); - - config.addDefault("Abilities.Water.FrostBreath.Enabled", true); - config.addDefault("Abilities.Water.FrostBreath.Description", "As demonstrated by Katara, a Waterbender is able to freeze their breath, " - + "causing anything it touches to be frozen! With this ability bound, simply hold " - + "Sneak (Default: Shift) to start breathing frost!"); - config.addDefault("Abilities.Water.FrostBreath.Cooldown", 15000); - config.addDefault("Abilities.Water.FrostBreath.Duration", 3000); - config.addDefault("Abilities.Water.FrostBreath.Particles", 3); - config.addDefault("Abilities.Water.FrostBreath.FrostDuration", 5000); - config.addDefault("Abilities.Water.FrostBreath.FrozenWaterDuration", 10000); - config.addDefault("Abilities.Water.FrostBreath.Range", 10); - config.addDefault("Abilities.Water.FrostBreath.Snow", true); - config.addDefault("Abilities.Water.FrostBreath.SnowDuration", 5000); - config.addDefault("Abilities.Water.FrostBreath.BendableSnow", false); - config.addDefault("Abilities.Water.FrostBreath.Damage.Enabled", false); - config.addDefault("Abilities.Water.FrostBreath.Damage.Player", 1.0); - config.addDefault("Abilities.Water.FrostBreath.Damage.Mob", 2.0); - config.addDefault("Abilities.Water.FrostBreath.Slow.Enabled", true); - config.addDefault("Abilities.Water.FrostBreath.Slow.Duration", 4000); - config.addDefault("Abilities.Water.FrostBreath.RestrictBiomes", true); - - config.addDefault("Abilities.Water.HealingWaters.Enabled", true); - config.addDefault("Abilities.Water.HealingWaters.Description", "To use this ability, the bender has to be partially submerged " - + "in water, OR be holding either a bottle of water or a water bucket." - + " This move will heal the player automatically if they have it equipped " - + "and are standing in water. If the player sneaks while in water and is targeting" - + " another entity, the bender will heal the targeted entity. The alternate " - + "healing method requires the bender to be holding a bottle of water or a water" - + " bucket. To start healing simply sneak, however if the bender is targeting " - + "a mob while sneaking, the bender will heal the targeted mob."); - config.addDefault("Abilities.Water.HealingWaters.Power", 1); - config.addDefault("Abilities.Water.HealingWaters.Range", 5); - config.addDefault("Abilities.Water.HealingWaters.DrainChance", 5); - config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Enabled", true); - config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Brightness", 10); - config.addDefault("Abilities.Water.HealingWaters.DynamicLight.KeepAlive", 1500); - - config.addDefault("Abilities.Water.IceClaws.Enabled", true); - config.addDefault("Abilities.Water.IceClaws.Description", "As demonstrated by Hama, a Waterbender can pull water out of thin air to create claws " - + "at the tips of their fingers. With IceClaws bound, hold Sneak (Default: Shift) to " - + "start pulling water out the air until you form claws at your finger " - + "tips, then attack an enemy to slow them down and do a bit of damage!"); - config.addDefault("Abilities.Water.IceClaws.Cooldown", 6000); - config.addDefault("Abilities.Water.IceClaws.ChargeTime", 1000); - config.addDefault("Abilities.Water.IceClaws.Range", 10); - config.addDefault("Abilities.Water.IceClaws.Throwable", true); - config.addDefault("Abilities.Water.IceClaws.Punch.Cooldown", 4000); - config.addDefault("Abilities.Water.IceClaws.Punch.Damage", 2.0); - config.addDefault("Abilities.Water.IceClaws.Punch.Slowness", 3); - config.addDefault("Abilities.Water.IceClaws.Punch.SlowDuration", 5000); - config.addDefault("Abilities.Water.IceClaws.Throw.Cooldown", 4000); - config.addDefault("Abilities.Water.IceClaws.Throw.Damage", 2.0); - config.addDefault("Abilities.Water.IceClaws.Throw.Slowness", 3); - config.addDefault("Abilities.Water.IceClaws.Throw.SlowDuration", 5000); - config.addDefault("Abilities.Water.IceClaws.Throw.Speed", 1.0); - config.addDefault("Abilities.Water.IceClaws.AllowHandSwap", true); - - config.addDefault("Abilities.Water.IceWall.Enabled", true); - config.addDefault("Abilities.Water.IceWall.Description", "IceWall allows an icebender to create a wall of ice, similar to " - + "raiseearth. To use, simply sneak while targeting either water, ice, or snow. " - + "To break the wall, you must sneak again while targeting it. Be aware that " - + "other icebenders can break your own shields, and if you are too close you " - + "can get hurt by the shards."); - config.addDefault("Abilities.Water.IceWall.Cooldown", 4000); - config.addDefault("Abilities.Water.IceWall.Width", 6); - config.addDefault("Abilities.Water.IceWall.MaxHeight", 5); - config.addDefault("Abilities.Water.IceWall.MinHeight", 3); - config.addDefault("Abilities.Water.IceWall.MaxWallHealth", 12); - config.addDefault("Abilities.Water.IceWall.MinWallHealth", 8); - config.addDefault("Abilities.Water.IceWall.Range", 8); - config.addDefault("Abilities.Water.IceWall.Damage", 4.0); - config.addDefault("Abilities.Water.IceWall.CanBreak", true); - config.addDefault("Abilities.Water.IceWall.Stackable", false); - config.addDefault("Abilities.Water.IceWall.LifeTime.Enabled", false); - config.addDefault("Abilities.Water.IceWall.LifeTime.Duration", 10000); - config.addDefault("Abilities.Water.IceWall.WallDamage", true); - config.addDefault("Abilities.Water.IceWall.WallDamage.Torrent", 5); - config.addDefault("Abilities.Water.IceWall.WallDamage.TorrentFreeze", 9); - config.addDefault("Abilities.Water.IceWall.WallDamage.IceBlast", 8); - config.addDefault("Abilities.Water.IceWall.WallDamage.Fireblast", 3); - config.addDefault("Abilities.Water.IceWall.WallDamage.FireblastCharged", 5); - config.addDefault("Abilities.Water.IceWall.WallDamage.Lightning", 12); - config.addDefault("Abilities.Water.IceWall.WallDamage.Combustion", 12); - config.addDefault("Abilities.Water.IceWall.WallDamage.EarthSmash", 8); - config.addDefault("Abilities.Water.IceWall.WallDamage.AirBlast", 2); - - config.addDefault("Abilities.Water.WakeFishing.Enabled", true); - config.addDefault("Abilities.Water.WakeFishing.Description", "With this ability bound, hold Sneak (Default: Shift) at a water block and " - + "don't lose focus of that block. Eventually some fish will investigate " - + "the wake and swim out at you!"); - config.addDefault("Abilities.Water.WakeFishing.Cooldown", 10000); - config.addDefault("Abilities.Water.WakeFishing.Duration", 20000); - config.addDefault("Abilities.Water.WakeFishing.Range", 5); - - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Description", "Create a swirling mass of water that drags any entity that enters it to the bottom " - + "of the whirlpool."); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Cooldown", 25000); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Duration", 15000); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.MaxDepth", 5); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Range", 10); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Combination", Arrays.asList("PhaseChange:SHIFT_DOWN", "Torrent:LEFT_CLICK", "Torrent:LEFT_CLICK")); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Instructions", "PhaseChange (Hold sneak) > Torrent (Left-click) > Torrent (Left-click)"); - - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Description", "Some Waterbenders have managed to create torrents of water much stronger than a regular torrent, " - + "that can carry them selves and others, as well as being able to freeze the entire stream whenever. The bender must stay focused on the flow or else the flow will stop." - + " If you Sneak (Default: Shift) while controlling the stream, the stream will return to you."); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Cooldown", 8000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Duration", 8000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MeltDelay", 5000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.SourceRange", 10); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxRange", 40); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MinRange", 8); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Trail", 80); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.BottleSource", false); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlantSource", false); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.RemoveOnAnyDamage", false); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.Normal", 1); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.AvatarState", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonSmall", 2); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonLarge", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.IsAvatarStateToggle", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.AvatarStateDuration", 60000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerStayNearSource", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxDistanceFromSource", 100); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Cooldown", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Duration", 2); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerRideOwnFlow", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Combination", Arrays.asList("WaterManipulation:SHIFT_DOWN", "WaterManipulation:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "WaterManipulation:SHIFT_UP")); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Instructions", "WaterManipulation (Tap sneak) > Torrent (Tap sneak) > Torrent (Hold sneak) > WaterManipulation (Release sneak)"); - - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Description", "Skilled Waterbenders are able to create two spinning rings of water around their bodies, " - + "which can be used as a defensive ability or for an offensive attack."); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Cooldown", 7000); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Damage", 3.0); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RingSize", 3.5); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Range", 40); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SourceRange", 10); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Speed", 2); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AnimationSpeed", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.PlantSource", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SnowSource", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RequireAdjacentPlants", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.BottleSource", false); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AbilityCollisionRadius", 1.6); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.EntityCollisionRadius", 1.6); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.Enabled", false); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveFirst", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveSecond", false); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Combination", Arrays.asList("Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "WaterManipulation:SHIFT_DOWN")); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Instructions", "Torrent (Tap sneak) > Torrent (Tap sneak) > WaterManipulation (Hold sneak) > WaterManipulation (Left-click multiple times)"); - - config.addDefault("Abilities.Water.Ice.Passive.Skate.Enabled", true); - config.addDefault("Abilities.Water.Ice.Passive.Skate.SpeedFactor", 4); - - config.addDefault("Abilities.Chi.Backstab.Enabled", true); - config.addDefault("Abilities.Chi.Backstab.Description", "Strike your foe in the back with a hard jab, temporariliy blocking their Chi, and " - + "inflicting a lot of damage! This ability has a long cooldown. You must hit the target in the back or this ability won't work!"); - config.addDefault("Abilities.Chi.Backstab.Cooldown", 8500); - config.addDefault("Abilities.Chi.Backstab.Damage", 6.0); - config.addDefault("Abilities.Chi.Backstab.MaxActivationAngle", 90); - - config.addDefault("Abilities.Chi.DaggerThrow.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.Description", "With this ability bound, Left-Click in " - + "rapid succession to shoot arrows out of your inventory at your target!"); - config.addDefault("Abilities.Chi.DaggerThrow.Cooldown", 3000); - config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Amount", 6); - config.addDefault("Abilities.Chi.DaggerThrow.Damage", 1.0); - config.addDefault("Abilities.Chi.DaggerThrow.ParticleTrail", true); - config.addDefault("Abilities.Chi.DaggerThrow.RequireArrows", false); - config.addDefault("Abilities.Chi.DaggerThrow.AllowPickup", false); - config.addDefault("Abilities.Chi.DaggerThrow.AbilityCollisionRadius", 0.5); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Cooldown", 1000); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.HitsRequired", 1); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Cooldown", 1000); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.HitsRequired", 1); - - String[] invalidWallRun = {Material.BARRIER.name()}; - config.addDefault("Abilities.Passives.WallRun.Enabled", true); - config.addDefault("Abilities.Passives.WallRun.Cooldown", 6000); - config.addDefault("Abilities.Passives.WallRun.Duration", 20000); - config.addDefault("Abilities.Passives.WallRun.Particles", true); - config.addDefault("Abilities.Passives.WallRun.Air", true); - config.addDefault("Abilities.Passives.WallRun.Earth", false); - config.addDefault("Abilities.Passives.WallRun.Water", false); - config.addDefault("Abilities.Passives.WallRun.Fire", true); - config.addDefault("Abilities.Passives.WallRun.Chi", true); - config.addDefault("Abilities.Passives.WallRun.InvalidBlocks", invalidWallRun); - - config.options().copyDefaults(true); - plugin.saveConfig(); - } - - private void addDeathMessages() { - FileConfiguration lang = ConfigManager.languageConfig.get(); - - //Fire - lang.addDefault("Abilities.Fire.FireComet.DeathMessage", "{victim} was squashed under the pressure of {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FireBall.DeathMessage", "{victim} burst from {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FireBreath.DeathMessage", "{victim} was consumed {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.Discharge.DeathMessage", "{victim} couldn't take {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FirePunch.DeathMessage", "{victim} punched out from {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FireShots.DeathMessage", "{victim} was shot by {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.LightningBurst.DeathMessage", "{victim} crackled out of existence from {attacker}'s {ability}"); - - //Water - lang.addDefault("Abilities.Water.Drain.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.FrostBreath.DeathMessage", "{victim} shattered from {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.IceClaws.DeathMessage", "{victim} was ripped to shreds by {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.IceWall.DeathMessage", "{victim} was collateral to {attacker}'s exploding {ability}"); - lang.addDefault("Abilities.Water.WaterBlast.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.Combo.WaterGimbal.DeathMessage", "{victim} was ripped apart by {attacker}'s {ability}"); - - //Earth - lang.addDefault("Abilities.Earth.EarthKick.DeathMessage", "{victim} got too much dirt in their eye from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.EarthLine.DeathMessage", "{victim} lost their footing from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.EarthShard.DeathMessage", "{victim} got blasted apart {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.LavaDisc.DeathMessage", "{victim} sliced in half by {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.LavaFlux.DeathMessage", "{victim} couldn't take the heat from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.LavaThrow.DeathMessage", "{victim} melted from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.MetalFragments.DeathMessage", "{victim} was shredded apart from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.MetalShred.DeathMessage", "{victim} was in the way of {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.MudSurge.DeathMessage", "{victim} drowned in mud from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.SandBlast.DeathMessage", "{victim} was sandblasted to oblivion from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.Combo.MagmaBlast.DeathMessage", "{victim} was obliterated by {attacker}'s {ability}"); - - //Air - lang.addDefault("Abilities.Air.AirBlade.DeathMessage", "{victim} was sliced in two by {attacker}'s {ability}"); - lang.addDefault("Abilities.Air.AirPunch.DeathMessage", "{victim} was exploded by {attacker}'s {ability}"); - lang.addDefault("Abilities.Air.SonicBlast.DeathMessage", "{victim}'s ears burst after {attacker}'s {ability}"); - - //Chi - lang.addDefault("Abilities.Chi.DaggerThrow.DeathMessage", "{victim} got stabbed too many times from {attacker}'s {ability}"); - lang.addDefault("Abilities.Chi.Backstab.DeathMessage", "{victim} fell victim to {attacker}'s {ability}"); - - //Avatar - lang.addDefault("Abilities.Avatar.SpiritBeam.DeathMessage", "{victim} was erased from existence by {attacker}'s {ability}"); - lang.addDefault("Abilities.Avatar.ElementSphereAir.DeathMessage", "{victim} was blasted apart by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereFire.DeathMessage", "{victim} was burnt to cinders by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereEarth.DeathMessage", "{victim} was crushed by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereWater.DeathMessage", "{victim} was sliced apart by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereStream.DeathMessage", "{victim} took the full force of {attacker}'s \u00A75ElementSphere"); - - ConfigManager.languageConfig.save(); - } - - private void setupElementSphereNames() { - FileConfiguration lang = ConfigManager.languageConfig.get(); - - lang.addDefault("Abilities.Avatar.ElementSphereAir.Name", "Air"); - lang.addDefault("Abilities.Avatar.ElementSphereFire.Name", "Fire"); - lang.addDefault("Abilities.Avatar.ElementSphereEarth.Name", "Earth"); - lang.addDefault("Abilities.Avatar.ElementSphereWater.Name", "Water"); - lang.addDefault("Abilities.Avatar.ElementSphereStream.Name", "Stream"); - - ConfigManager.languageConfig.save(); - } - - public static ConfigurationSection getConfig(Player player) { - if (player == null) - return getConfig((World)null); - return getConfig(player.getWorld()); - } - - public static ConfigurationSection getConfig(World world) { - boolean perWorldConfig = plugin.getConfig().getBoolean("Properties.PerWorldConfig"); - - if (world == null || !perWorldConfig) { - return plugin.getConfig(); - } - - String prefix = "Worlds." + world.getName(); - return new SubsectionConfigurationDecorator(plugin.getConfig(), prefix); - } -} diff --git a/src/com/jedk1/jedcore/configuration/SubsectionConfigurationDecorator.java b/src/com/jedk1/jedcore/configuration/SubsectionConfigurationDecorator.java deleted file mode 100644 index a3b76ca..0000000 --- a/src/com/jedk1/jedcore/configuration/SubsectionConfigurationDecorator.java +++ /dev/null @@ -1,668 +0,0 @@ -package com.jedk1.jedcore.configuration; - -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.Configuration; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.serialization.ConfigurationSerializable; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -// ConfigurationSection decorator that tries to fetch with a prefix prepended to the path. -// If that section doesn't exist, then it falls back to the parent. -public class SubsectionConfigurationDecorator implements ConfigurationSection { - private ConfigurationSection parent; - private String prefix; - - public SubsectionConfigurationDecorator(ConfigurationSection parent, String prefix) { - this.parent = parent; - this.prefix = prefix; - - if (!this.prefix.endsWith(".")) { - this.prefix += "."; - } - } - - public String getPrefix() { - return this.prefix; - } - - @Override - public Set getKeys(boolean deep) { - return parent.getKeys(deep); - } - - @Override - public Map getValues(boolean deep) { - return parent.getValues(deep); - } - - @Override - public boolean contains(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return true; - } - - return parent.contains(path); - } - - @Override - public boolean contains(String path, boolean ignoreDefault) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath, ignoreDefault)) { - return true; - } - - return parent.contains(path, ignoreDefault); - } - - @Override - public boolean isSet(String path) { - String newPath = getPrefix() + path; - - if (parent.isSet(newPath)) { - return true; - } - - return parent.isSet(path); - } - - @Override - public String getCurrentPath() { - return parent.getCurrentPath(); - } - - @Override - public String getName() { - return parent.getName(); - } - - @Override - public Configuration getRoot() { - return parent.getRoot(); - } - - @Override - public ConfigurationSection getParent() { - return parent.getParent(); - } - - @Override - public Object get(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.get(newPath); - } - - return parent.get(path); - } - - @Override - public Object get(String path, Object def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.get(newPath, def); - } - - return parent.get(path, def); - } - - @Override - public void set(String path, Object value) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - parent.set(newPath, value); - return; - } - - parent.set(path, value); - } - - @Override - public ConfigurationSection createSection(String path) { - return parent.createSection(getPrefix() + path); - } - - @Override - public ConfigurationSection createSection(String path, Map map) { - return parent.createSection(getPrefix() + path, map); - } - - @Override - public String getString(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getString(newPath); - } - - return parent.getString(path); - } - - @Override - public String getString(String path, String def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getString(newPath, def); - } - - return parent.getString(path, def); - } - - @Override - public boolean isString(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isString(newPath); - } - - return parent.isString(path); - } - - @Override - public int getInt(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getInt(newPath); - } - - return parent.getInt(path); - } - - @Override - public int getInt(String path, int def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getInt(newPath, def); - } - - return parent.getInt(path, def); - } - - @Override - public boolean isInt(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isInt(newPath); - } - - return parent.isInt(path); - } - - @Override - public boolean getBoolean(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getBoolean(newPath); - } - - return parent.getBoolean(path); - } - - @Override - public boolean getBoolean(String path, boolean def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getBoolean(newPath, def); - } - - return parent.getBoolean(path, def); - } - - @Override - public boolean isBoolean(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isBoolean(newPath); - } - - return parent.isBoolean(path); - } - - @Override - public double getDouble(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getDouble(newPath); - } - - return parent.getDouble(path); - } - - @Override - public double getDouble(String path, double def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getDouble(newPath, def); - } - - return parent.getDouble(path, def); - } - - @Override - public boolean isDouble(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isDouble(newPath); - } - - return parent.isDouble(path); - } - - @Override - public long getLong(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getLong(newPath); - } - - return parent.getLong(path); - } - - @Override - public long getLong(String path, long def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getLong(newPath, def); - } - - return parent.getLong(path, def); - } - - @Override - public boolean isLong(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isLong(newPath); - } - - return parent.isLong(path); - } - - @Override - public List getList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getList(newPath); - } - - return parent.getList(path); - } - - @Override - public List getList(String path, List def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getList(newPath, def); - } - - return parent.getList(path, def); - } - - @Override - public boolean isList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isList(newPath); - } - - return parent.isList(path); - } - - @Override - public List getStringList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getStringList(newPath); - } - - return parent.getStringList(path); - } - - @Override - public List getIntegerList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getIntegerList(newPath); - } - - return parent.getIntegerList(path); - } - - @Override - public List getBooleanList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getBooleanList(newPath); - } - - return parent.getBooleanList(path); - } - - @Override - public List getDoubleList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getDoubleList(newPath); - } - - return parent.getDoubleList(path); - } - - @Override - public List getFloatList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getFloatList(newPath); - } - - return parent.getFloatList(path); - } - - @Override - public List getLongList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getLongList(newPath); - } - - return parent.getLongList(path); - } - - @Override - public List getByteList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getByteList(newPath); - } - - return parent.getByteList(path); - } - - @Override - public List getCharacterList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getCharacterList(newPath); - } - - return parent.getCharacterList(path); - } - - @Override - public List getShortList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getShortList(newPath); - } - - return parent.getShortList(path); - } - - @Override - public List> getMapList(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getMapList(newPath); - } - - return parent.getMapList(path); - } - - @Override - public T getSerializable(String s, Class aClass) { - return parent.getSerializable(s, aClass); - } - - @Override - public T getSerializable(String s, Class aClass, T t) { - return parent.getSerializable(s, aClass, t); - } - - @Override - public T getObject(String s, Class aClass) { - return parent.getObject(s, aClass); - } - - @Override - public T getObject(String s, Class aClass, T t) { - return parent.getObject(s, aClass, t); - } - - @Override - public Vector getVector(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getVector(newPath); - } - - return parent.getVector(path); - } - - @Override - public Vector getVector(String path, Vector def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getVector(newPath, def); - } - - return parent.getVector(path, def); - } - - @Override - public boolean isVector(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isVector(newPath); - } - - return parent.isVector(path); - } - - @Override - public OfflinePlayer getOfflinePlayer(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getOfflinePlayer(newPath); - } - - return parent.getOfflinePlayer(path); - } - - @Override - public OfflinePlayer getOfflinePlayer(String path, OfflinePlayer def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getOfflinePlayer(newPath, def); - } - - return parent.getOfflinePlayer(path, def); - } - - @Override - public boolean isOfflinePlayer(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isOfflinePlayer(newPath); - } - - return parent.isOfflinePlayer(path); - } - - @Override - public ItemStack getItemStack(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getItemStack(newPath); - } - - return parent.getItemStack(path); - } - - @Override - public ItemStack getItemStack(String path, ItemStack def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getItemStack(newPath, def); - } - - return parent.getItemStack(path, def); - } - - @Override - public boolean isItemStack(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isItemStack(newPath); - } - - return parent.isItemStack(path); - } - - @Override - public Color getColor(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getColor(newPath); - } - - return parent.getColor(path); - } - - @Override - public Color getColor(String path, Color def) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getColor(newPath, def); - } - - return parent.getColor(path, def); - } - - @Override - public boolean isColor(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isColor(newPath); - } - - return parent.isColor(path); - } - - @Override - public Location getLocation(String s) { - return parent.getLocation(s); - } - - @Override - public Location getLocation(String s, Location location) { - return parent.getLocation(s, location); - } - - @Override - public boolean isLocation(String s) { - return parent.isLocation(s); - } - - @Override - public ConfigurationSection getConfigurationSection(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.getConfigurationSection(newPath); - } - - return parent.getConfigurationSection(path); - } - - @Override - public boolean isConfigurationSection(String path) { - String newPath = getPrefix() + path; - - if (parent.contains(newPath)) { - return parent.isConfigurationSection(newPath); - } - - return parent.isConfigurationSection(path); - } - - @Override - public ConfigurationSection getDefaultSection() { - return parent.getDefaultSection(); - } - - @Override - public void addDefault(String path, Object value) { - parent.addDefault(path, value); - } - - @Override - public List getComments(String s) { - return List.of(); - } - - @Override - public List getInlineComments(String s) { - return List.of(); - } - - @Override - public void setComments(String s, List list) { - - } - - @Override - public void setInlineComments(String s, List list) { - - } -} diff --git a/src/com/jedk1/jedcore/event/PKCommandEvent.java b/src/com/jedk1/jedcore/event/PKCommandEvent.java deleted file mode 100644 index 3886951..0000000 --- a/src/com/jedk1/jedcore/event/PKCommandEvent.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.jedk1.jedcore.event; - -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -public class PKCommandEvent extends Event{ - - public enum CommandType { - ADD, - BIND, - CHECK, - CHOOSE, - CLEAR, - DISPLAY, - GIVE, - HELP, - IMPORT, - INVINCIBLE, - PERMREMOVE, - PRESET, - RELOAD, - REMOVE, - TOGGLE, - VERSION, - WHO, - JEDCORE; - - public static CommandType getType(String string) { - for (CommandType element : CommandType.values()) { - if (element.toString().equalsIgnoreCase(string)) { - return element; - } - } - return null; - } - } - - public static final HandlerList handlers = new HandlerList(); - private Player sender; - private CommandType type; - private String[] args; - - public PKCommandEvent(Player sender, String[] args, CommandType type) { - this.sender = sender; - this.type = type; - this.args = args; - } - - public Player getSender() { - return sender; - } - - public CommandType getType() { - return type; - } - - public String[] getArgs() { - return args; - } - - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java deleted file mode 100644 index 9373862..0000000 --- a/src/com/jedk1/jedcore/listener/AbilityListener.java +++ /dev/null @@ -1,584 +0,0 @@ -package com.jedk1.jedcore.listener; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.ability.airbending.AirBlade; -import com.jedk1.jedcore.ability.airbending.AirBreath; -import com.jedk1.jedcore.ability.airbending.AirGlide; -import com.jedk1.jedcore.ability.airbending.AirPunch; -import com.jedk1.jedcore.ability.airbending.Meditate; -import com.jedk1.jedcore.ability.airbending.SonicBlast; -import com.jedk1.jedcore.ability.avatar.SpiritBeam; -import com.jedk1.jedcore.ability.avatar.elementsphere.ElementSphere; -import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; -import com.jedk1.jedcore.ability.earthbending.EarthKick; -import com.jedk1.jedcore.ability.earthbending.EarthLine; -import com.jedk1.jedcore.ability.earthbending.EarthPillar; -import com.jedk1.jedcore.ability.earthbending.EarthShard; -import com.jedk1.jedcore.ability.earthbending.EarthSurf; -import com.jedk1.jedcore.ability.earthbending.Fissure; -import com.jedk1.jedcore.ability.earthbending.LavaDisc; -import com.jedk1.jedcore.ability.earthbending.LavaFlux; -import com.jedk1.jedcore.ability.earthbending.LavaThrow; -import com.jedk1.jedcore.ability.earthbending.MagnetShield; -import com.jedk1.jedcore.ability.earthbending.MetalArmor; -import com.jedk1.jedcore.ability.earthbending.MetalFragments; -import com.jedk1.jedcore.ability.earthbending.MetalHook; -import com.jedk1.jedcore.ability.earthbending.MetalShred; -import com.jedk1.jedcore.ability.earthbending.MudSurge; -import com.jedk1.jedcore.ability.earthbending.SandBlast; -import com.jedk1.jedcore.ability.earthbending.combo.Crevice; -import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; -import com.jedk1.jedcore.ability.firebending.Combustion; -import com.jedk1.jedcore.ability.firebending.Discharge; -import com.jedk1.jedcore.ability.firebending.FireBall; -import com.jedk1.jedcore.ability.firebending.FireBreath; -import com.jedk1.jedcore.ability.firebending.FireComet; -import com.jedk1.jedcore.ability.firebending.FirePunch; -import com.jedk1.jedcore.ability.firebending.FireShots; -import com.jedk1.jedcore.ability.firebending.FireSki; -import com.jedk1.jedcore.ability.firebending.LightningBurst; -import com.jedk1.jedcore.ability.passive.WallRun; -import com.jedk1.jedcore.ability.waterbending.BloodPuppet; -import com.jedk1.jedcore.ability.waterbending.Drain; -import com.jedk1.jedcore.ability.waterbending.FrostBreath; -import com.jedk1.jedcore.ability.waterbending.IceClaws; -import com.jedk1.jedcore.ability.waterbending.IceWall; -import com.jedk1.jedcore.ability.waterbending.WakeFishing; -import com.jedk1.jedcore.ability.waterbending.combo.WaterFlow; -import com.jedk1.jedcore.ability.waterbending.combo.WaterGimbal; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ProjectKorra; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; -import com.projectkorra.projectkorra.airbending.Suffocate; -import com.projectkorra.projectkorra.earthbending.EarthArmor; -import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; -import com.projectkorra.projectkorra.firebending.FireJet; -import com.projectkorra.projectkorra.util.MovementHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.waterbending.blood.Bloodbending; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerToggleSneakEvent; -import org.bukkit.inventory.EquipmentSlot; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class AbilityListener implements Listener { - - JedCore plugin; - - public AbilityListener(JedCore plugin) { - this.plugin = plugin; - } - - private final List recentlyDropped = new ArrayList<>(); - - @EventHandler(priority = EventPriority.LOWEST) - // Abilities that should bypass punch cancels should be handled here. - public void onPlayerSwingBypassCancel(PlayerInteractEvent event) { - Player player = event.getPlayer(); - if (event.getHand() != EquipmentSlot.HAND) { - return; - } - if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { - return; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null) { - return; - } - - if (Suffocate.isBreathbent(player) || bPlayer.isChiBlocked()) { - return; - } - - if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { - return; - } - - CoreAbility coreAbil = bPlayer.getBoundAbility(); - if (coreAbil == null) { - return; - } - - if (!bPlayer.canBendIgnoreCooldowns(coreAbil)) { - return; - } - - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { - return; - } - - // FireSki bypasses punch cancel because the normal version is activated from sneaking alone. - // The punch activation exists just so people don't accidentally activate it, so they should have the same - // requirements for activation. - if (coreAbil instanceof FireJet && FireSki.isPunchActivated(player.getWorld())) { - if (player.isSneaking()) { - FireSki ski = new FireSki(player); - if (ski.isStarted() && !bPlayer.isOnCooldown("FireJet")) { - // The event only needs to be cancelled when FireSki is set to have no cooldown. - // This is to prevent FireJet from activating from the same swing event. - event.setCancelled(true); - } - } - } - } - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerDropItemEvent(PlayerDropItemEvent event) { - recentlyDropped.add(event.getPlayer().getUniqueId()); - - // FirePunch item burn effect - Player player = event.getPlayer(); - FirePunch fp = FirePunch.getAbility(player, FirePunch.class); - boolean burnEnabled = com.jedk1.jedcore.configuration.JedCoreConfig.getConfig((Player)null).getBoolean("Abilities.Fire.FirePunch.BurnsDroppedItems", true); - if (fp != null && burnEnabled) { - var item = event.getItemDrop(); - var loc = fp.getRightHandPos(); - ParticleEffect.LAVA.display(loc, 5, 0.1, 0.1, 0.1, 0.05); - ParticleEffect.FLAME.display(loc, 3, 0.1, 0.1, 0.1, 0.01); - ParticleEffect.SMOKE_NORMAL.display(loc, 2, 0.05, 0.05, 0.05, 0.01); - loc.getWorld().playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, 0.3f, 1.4f); - item.remove(); - } - - Bukkit.getScheduler().runTaskLater(ProjectKorra.plugin, () -> recentlyDropped.remove(event.getPlayer().getUniqueId()), 2L); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerInventoryInteract(InventoryClickEvent event) { - InventoryAction action = event.getAction(); - if (action == InventoryAction.DROP_ALL_CURSOR || - action == InventoryAction.DROP_ALL_SLOT || - action == InventoryAction.DROP_ONE_CURSOR || - action == InventoryAction.DROP_ONE_SLOT || - action == InventoryAction.UNKNOWN) { - - recentlyDropped.add(event.getWhoClicked().getUniqueId()); - - Bukkit.getScheduler().runTaskLater(ProjectKorra.plugin, () -> { - recentlyDropped.remove(event.getWhoClicked().getUniqueId()); - }, 2L); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerSwing(PlayerInteractEvent event) { - Player player = event.getPlayer(); - - if (recentlyDropped.contains(player.getUniqueId())) return; - - if (event.getHand() != EquipmentSlot.HAND) { - return; - } - if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { - return; - } - if (event.getAction() == Action.LEFT_CLICK_BLOCK && event.isCancelled()){ - return; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null) { - return; - } - - if (Suffocate.isBreathbent(player)) { - event.setCancelled(true); - return; - } else if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { - event.setCancelled(true); - return; - } else if (bPlayer.isChiBlocked()) { - event.setCancelled(true); - return; - } else if (GeneralMethods.isInteractable(player.getTargetBlock((Set)null, 5))) { - return; - } - - if (bPlayer.isToggled()) { - new WallRun(player); - } - - CoreAbility coreAbil = bPlayer.getBoundAbility(); - if (coreAbil == null) { - if (MultiAbilityManager.hasMultiAbilityBound(player)){ - String abil = MultiAbilityManager.getBoundMultiAbility(player); - if (abil.equalsIgnoreCase("elementsphere")) { - new ElementSphere(player); - } - } - return; - } - - String abilName = bPlayer.getBoundAbilityName(); - Class abilClass = coreAbil.getClass(); - - if (bPlayer.canBendIgnoreCooldowns(coreAbil)) { - - if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(AirBlade.class)) { - new AirBlade(player); - } - if (abilClass.equals(AirPunch.class)) { - new AirPunch(player); - } - } - - if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(EarthArmor.class)) { - new MetalArmor(player); - } - if (abilClass.equals(EarthLine.class)) { - EarthLine.shootLine(player); - } - if (abilClass.equals(EarthShard.class)) { - EarthShard.throwShard(player); - } - if (abilClass.equals(EarthSurf.class)) { - new EarthSurf(player); - } - if (abilClass.equals(Fissure.class)) { - new Fissure(player); - } - if (abilClass.equals(LavaFlux.class)) { - new LavaFlux(player); - } - if (abilClass.equals(LavaThrow.class)) { - LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); - if (lt != null) { - lt.createBlast(); - } - } - if (abilClass.equals(MetalFragments.class)) { - MetalFragments.shootFragment(player); - } - if (abilClass.equals(MetalHook.class)) { - new MetalHook(player); - } - if (abilClass.equals(MetalShred.class)) { - MetalShred.extend(player); - } - if (abilClass.equals(MudSurge.class)) { - MudSurge.mudSurge(player); - } - if (abilClass.equals(SandBlast.class)) { - SandBlast.blastSand(player); - } - if (abilClass.equals(LavaFlow.class)) { - MagmaBlast.performAction(player); - } - if (abilClass.equals(MagnetShield.class)) { - new MagnetShield(player, true); - } - } - - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(Combustion.class)) { - Combustion.combust(player); - } - if (abilClass.equals(Discharge.class)) { - new Discharge(player); - } - if (abilClass.equals(FireBall.class)) { - new FireBall(player); - } - if (abilClass.equals(FirePunch.class)) { - new FirePunch(player); - } - if (abilClass.equals(FireShots.class)) { - FireShots.fireShot(player); - } - } - - if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.WATER.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { - com.jedk1.jedcore.ability.waterbending.Bloodbending.launch(player); - } - if (abilClass.equals(BloodPuppet.class)) { - BloodPuppet.attack(player); - } - if (abilClass.equals(IceClaws.class)) { - IceClaws.throwClaws(player); - } - if (abilName.equals("Drain")) { - Drain.fireBlast(player); - } - if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { - WaterGimbal.prepareBlast(player); - } - if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { - WaterFlow.freeze(player); - } - } - if (coreAbil instanceof ChiAbility && bPlayer.isElementToggled(Element.CHI)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Chi.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(DaggerThrow.class)) { - new DaggerThrow(player); - } - } - - if (coreAbil instanceof AvatarAbility) { - if (abilClass.equals(ElementSphere.class)) { - new ElementSphere(player); - } - } - } - } - - public static ConcurrentHashMap recent = new ConcurrentHashMap(); - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerSneak(PlayerToggleSneakEvent event) { - Player player = event.getPlayer(); - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - - if (event.isCancelled() || bPlayer == null) { - return; - } - - String abilName = bPlayer.getBoundAbilityName(); - if (Suffocate.isBreathbent(player)) { - if (!abilName.equalsIgnoreCase("AirSwipe") - && !abilName.equalsIgnoreCase("FireBlast") - && !abilName.equalsIgnoreCase("EarthBlast") - && !abilName.equalsIgnoreCase("WaterManipulation")) { - if(!player.isSneaking()) { - event.setCancelled(true); - } - } - } - - if (MovementHandler.isStopped(player) || Bloodbending.isBloodbent(player)) { - event.setCancelled(true); - return; - } - - CoreAbility coreAbil = bPlayer.getBoundAbility(); - if (coreAbil == null) { - return; - } - - Class abilClass = coreAbil.getClass(); - - if (bPlayer.isChiBlocked()) { - event.setCancelled(true); - return; - } - - if (player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (abilClass.equals(FireShots.class)) { - FireShots.swapHands(player); - } - - if (abilClass.equals(FirePunch.class)) { - FirePunch.swapHands(player); - } - } - } - - if (!player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { - if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(AirBreath.class)) { - new AirBreath(player); - } - if (abilClass.equals(AirGlide.class)) { - new AirGlide(player); - } - if (abilClass.equals(Meditate.class)) { - new Meditate(player); - } - if (abilClass.equals(SonicBlast.class)) { - new SonicBlast(player); - } - } - - if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(EarthKick.class)) { - new EarthKick(player); - } - if (abilClass.equals(EarthLine.class)) { - new EarthLine(player); - } - if (abilClass.equals(EarthPillar.class)) { - new EarthPillar(player); - } - if (abilClass.equals(EarthShard.class)) { - new EarthShard(player); - } - if (abilClass.equals(Fissure.class)) { - Fissure.performAction(player); - } - if (abilClass.equals(LavaDisc.class)) { - new LavaDisc(player); - } - if (abilClass.equals(MagnetShield.class)) { - new MagnetShield(player, false); - } - if (abilClass.equals(MetalFragments.class)) { - new MetalFragments(player); - } - if (abilClass.equals(MetalShred.class)) { - new MetalShred(player); - } - if (abilClass.equals(MudSurge.class)) { - new MudSurge(player); - } - if (abilClass.equals(SandBlast.class)) { - new SandBlast(player); - } - if (abilClass.equals(Crevice.class)) { - Crevice.closeCrevice(player); - } - if (abilClass.equals(LavaThrow.class)) { - LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); - if (lt == null) { - new LavaThrow(player); - } - } - } - - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(Combustion.class)) { - new Combustion(event.getPlayer()); - } - if (abilClass.equals(FireBreath.class)) { - new FireBreath(player); - } - if (abilClass.equals(FireComet.class)) { - new FireComet(player); - } - if (abilClass.equals(FireJet.class)) { - if (FireSki.isPunchActivated(player.getWorld())) { - FireSki fs = CoreAbility.getAbility(player, FireSki.class); - - if (fs != null) { - fs.remove(); - } - } else { - new FireSki(player); - } - } - if (abilClass.equals(FireShots.class)) { - new FireShots(player); - } - if (abilClass.equals(LightningBurst.class)) { - new LightningBurst(player); - } - } - - if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Water.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { - new com.jedk1.jedcore.ability.waterbending.Bloodbending(player); - } - if (abilClass.equals(BloodPuppet.class)) { - new BloodPuppet(player); - } - if (abilClass.equals(FrostBreath.class)) { - new FrostBreath(player); - } - if (abilClass.equals(IceClaws.class)) { - new IceClaws(player); - IceClaws.swapHands(player); - } - if (abilClass.equals(IceWall.class)) { - new IceWall(player); - } - if (abilName.equals("Drain")) { - new Drain(player); - } - if (abilClass.equals(WakeFishing.class)) { - new WakeFishing(player); - } - } - - if (coreAbil instanceof AvatarAbility) { - if (abilClass.equals(SpiritBeam.class)) { - new SpiritBeam(player); - } - } - } - } - - @EventHandler - public void onArrowHit(EntityDamageByEntityEvent event) { - if (event.getDamager().getType() == EntityType.ARROW) { - Arrow arrow = (Arrow) event.getDamager(); - if (arrow.getShooter() instanceof Player && arrow.hasMetadata("daggerthrow")) { - Player player = (Player) arrow.getShooter(); - event.setDamage(0.0D); - player.playSound(player.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 1.0f); - } - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerInteraction(PlayerInteractEvent event) { - if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { - MetalFragments.shootFragment(event.getPlayer()); - } - } - - @EventHandler - public void onChange(EntityChangeBlockEvent event) { - if (event.getEntity() instanceof FallingBlock) { - if (event.getEntity().hasMetadata("magmablast")) event.setCancelled(true); - } - } -} diff --git a/src/com/jedk1/jedcore/listener/CommandListener.java b/src/com/jedk1/jedcore/listener/CommandListener.java deleted file mode 100644 index 5b296c8..0000000 --- a/src/com/jedk1/jedcore/listener/CommandListener.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.jedk1.jedcore.listener; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.command.JedCoreCommand; -import com.jedk1.jedcore.event.PKCommandEvent; -import com.jedk1.jedcore.event.PKCommandEvent.CommandType; -import com.projectkorra.projectkorra.command.PKCommand; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.Arrays; -import java.util.UUID; - -public class CommandListener implements Listener { - - JedCore plugin; - String[] cmdaliases = {"/bending", "/bend", "/b", "/pk", "/projectkorra", "/korra", "/mtla", "/tla"}; - public static String[] developers = { - "4eb6315e-9dd1-49f7-b582-c1170e497ab0", //jedk1 - "d57565a5-e6b0-44e3-a026-979d5de10c4d", //s3xi - "e98a2f7d-d571-4900-a625-483cbe6774fe", //Aztl - "b6bd2ceb-4922-4707-9173-8a02044e9069" //Cozmyc - }; - - public CommandListener(JedCore plugin) { - this.plugin = plugin; - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerCommand(PlayerCommandPreprocessEvent event) { - String cmd = event.getMessage().toLowerCase(); - String[] args = cmd.split("\\s+"); - if (Arrays.asList(cmdaliases).contains(args[0]) && args.length >= 2) { - PKCommandEvent new_event = new PKCommandEvent(event.getPlayer(), args, null); - for (PKCommand command : PKCommand.instances.values()) { - if (Arrays.asList(command.getAliases()).contains(args[1].toLowerCase())) { - new_event = new PKCommandEvent(event.getPlayer(), args, CommandType.getType(command.getName())); - } - } - Bukkit.getServer().getPluginManager().callEvent(new_event); - } - } - - CommandType[] types = {CommandType.ADD, CommandType.BIND, CommandType.CHOOSE, CommandType.CLEAR, CommandType.PRESET, CommandType.REMOVE}; - - @EventHandler(priority = EventPriority.NORMAL) - public void onPKCommand(final PKCommandEvent event) { - new BukkitRunnable() { - public void run() { - if (event.getType() != null) { - if (event.getType().equals(CommandType.WHO) && event.getSender().hasPermission("bending.command.who")) { - if (event.getArgs().length == 3) { - if (Bukkit.getPlayer(event.getArgs()[2]) != null) { - UUID uuid = Bukkit.getPlayer(event.getArgs()[2]).getUniqueId(); - if (Arrays.asList(developers).contains(uuid.toString())) { - event.getSender().sendMessage(ChatColor.DARK_AQUA + "JedCore Developer"); - } - } - } - return; - } - if (event.getType().equals(CommandType.VERSION) && event.getSender().hasPermission("bending.command.version")) { - JedCoreCommand.sendBuildInfo(event.getSender()); - } - } - } - }.runTaskLater(JedCore.plugin, 1); - } -} diff --git a/src/com/jedk1/jedcore/listener/JCListener.java b/src/com/jedk1/jedcore/listener/JCListener.java deleted file mode 100644 index ac3868c..0000000 --- a/src/com/jedk1/jedcore/listener/JCListener.java +++ /dev/null @@ -1,245 +0,0 @@ -package com.jedk1.jedcore.listener; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.ability.chiblocking.Backstab; -import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; -import com.jedk1.jedcore.ability.earthbending.EarthSurf; -import com.jedk1.jedcore.ability.earthbending.LavaDisc; -import com.jedk1.jedcore.ability.earthbending.MetalFragments; -import com.jedk1.jedcore.ability.earthbending.MetalShred; -import com.jedk1.jedcore.ability.earthbending.MudSurge; -import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; -import com.jedk1.jedcore.ability.firebending.FireBreath; -import com.jedk1.jedcore.ability.firebending.FirePunch; -import com.jedk1.jedcore.ability.firebending.FireSki; -import com.jedk1.jedcore.ability.waterbending.IceClaws; -import com.jedk1.jedcore.ability.waterbending.IceWall; -import com.jedk1.jedcore.util.LightManager; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.ProjectKorra; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.IceAbility; -import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; -import com.projectkorra.projectkorra.event.AbilityStartEvent; -import com.projectkorra.projectkorra.event.BendingReloadEvent; -import com.projectkorra.projectkorra.event.HorizontalVelocityChangeEvent; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.inventory.InventoryPickupItemEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.event.player.PlayerToggleSprintEvent; -import org.bukkit.scheduler.BukkitRunnable; - -public class JCListener implements Listener { - - JedCore plugin; - - public JCListener(JedCore plugin) { - this.plugin = plugin; - } - - @EventHandler - public void onAbilityStart(AbilityStartEvent event) { - if (event.isCancelled()) return; - - if (event.getAbility() instanceof LavaFlow) { - Player player = event.getAbility().getPlayer(); - MagmaBlast mb = CoreAbility.getAbility(player, MagmaBlast.class); - - if (mb != null && (mb.hasBlocks() || mb.shouldBlockLavaFlow())) { - event.setCancelled(true); - LavaFlow flow = (LavaFlow) event.getAbility(); - - // Reset the cooldown of LavaFlow that was set before the call to start(). - flow.getBendingPlayer().removeCooldown(flow); - } - } else if (event.getAbility() instanceof PlantRegrowth) { - PlantRegrowth regrowth = (PlantRegrowth)event.getAbility(); - - // Stop PlantRegrowth from creating permanent snow when used against FrostBreath snow. - if (regrowth.getType() == Material.SNOW && TempBlock.isTempBlock(regrowth.getBlock())) { - event.setCancelled(true); - } - } - } - - @EventHandler - public void onFlow(BlockFromToEvent event) { - if (!LavaDisc.canFlowFrom(event.getBlock())) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.LOW) - public void onPlayerFallDamage(EntityDamageEvent event) { - if (event.isCancelled() || event.getCause() != DamageCause.FALL || !(event.getEntity() instanceof Player)) { - return; - } - - Player player = (Player)event.getEntity(); - - if (MudSurge.onFallDamage(player)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onEntityDamage(EntityDamageEvent event) { - if (event.getCause().equals(DamageCause.SUFFOCATION)) { - if (event.getEntity() instanceof LivingEntity) { - LivingEntity entity = (LivingEntity) event.getEntity(); - Block block = entity.getEyeLocation().getBlock(); - if (RegenTempBlock.blocks.containsKey(block) && IceAbility.isIce(block)) { - event.setCancelled(true); - return; - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { - if (event.getDamager() instanceof Player && event.getEntity() instanceof LivingEntity) { - if (event.getCause() == DamageCause.ENTITY_ATTACK && event.getDamager().getWorld().equals(event.getEntity().getWorld())) { - double distSq = event.getDamager().getLocation().distanceSquared(event.getEntity().getLocation()); - - // Only activate these in melee range - if (distSq <= 5 * 5) { - FirePunch fp = CoreAbility.getAbility((Player) event.getDamager(), FirePunch.class); - if (fp != null) { - fp.punch((LivingEntity) event.getEntity()); - event.setCancelled(true); - return; - } - - if (Backstab.punch((Player) event.getDamager(), (LivingEntity) event.getEntity())) { - event.setCancelled(true); - double damage = Backstab.getDamage(event.getDamager().getWorld()); - DamageHandler.damageEntity(event.getEntity(), (Player) event.getDamager(), damage, CoreAbility.getAbility("BackStab")); - return; - } - } - } - - if (IceClaws.freezeEntity((Player) event.getDamager(), (LivingEntity) event.getEntity())) { - event.setCancelled(true); - return; - } - } - - if (event.getDamager() instanceof Arrow arrow) { - if (event.getEntity() instanceof LivingEntity) { - if (arrow.hasMetadata("daggerthrow")) { - event.setDamage(0); - if (!(arrow.getShooter() instanceof Player shooter)) return; - if (!CoreAbility.hasAbility(shooter, DaggerThrow.class)) return; - DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); - if (daggerThrow != null) { - daggerThrow.damageEntityFromArrow(((LivingEntity) event.getEntity()), arrow); - arrow.remove(); - event.setCancelled(true); - } - } - if (arrow.hasMetadata("metalhook")) { - event.setDamage(0); - arrow.remove(); - event.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onBlockBreak(BlockBreakEvent event) { - MetalFragments.remove(event.getPlayer(), event.getBlock()); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onEntityExplode(EntityExplodeEvent event){ - if (IceWall.checkExplosions(event.getLocation(), event.getEntity())) { - event.blockList().clear(); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onCollisionWithEntity(HorizontalVelocityChangeEvent event) { - if (event.getEntity().getWorld() != event.getInstigator().getWorld()) { - return; - } - IceWall.collisionDamage(event.getEntity(), event.getDistanceTraveled(), event.getDifference(), event.getInstigator()); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerSprint(PlayerToggleSprintEvent event) { - if (!event.isSprinting()) - return; - - if (CoreAbility.hasAbility(event.getPlayer(), EarthSurf.class)) { - event.setCancelled(true); - return; - } - - if (CoreAbility.hasAbility(event.getPlayer(), FireSki.class)) { - event.setCancelled(true); - return; - } - - MetalShred.startShred(event.getPlayer()); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void projectKorraReload(BendingReloadEvent event) { - final CommandSender sender = event.getSender(); - LightManager.get().restart(); - // There's a PK bug where a new collision manager is set on reload without stopping the old task. - ProjectKorra.getCollisionManager().stopCollisionDetection(); - new BukkitRunnable() { - public void run() { - JCMethods.reload(); - sender.sendMessage(ChatColor.DARK_AQUA + "JedCore config reloaded."); - } - }.runTaskLater(JedCore.plugin, 1); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onChat(AsyncPlayerChatEvent event){ - Player player = event.getPlayer(); - String msg = event.getMessage(); - - if (msg.toLowerCase().contains("bring fire and light together as one and allow the breath of color")) { - FireBreath.toggleRainbowBreath(player, true); - event.setCancelled(true); - } - - if (msg.toLowerCase().contains("split the bond of fire and light and set the color free")) { - FireBreath.toggleRainbowBreath(player, false); - event.setCancelled(true); - } - - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onItemPickup(InventoryPickupItemEvent event) { - if (event.getItem().getPickupDelay() >= Short.MAX_VALUE) { - event.setCancelled(true); - } - } -} diff --git a/src/com/jedk1/jedcore/policies/removal/CannotBendRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/CannotBendRemovalPolicy.java deleted file mode 100644 index 270037c..0000000 --- a/src/com/jedk1/jedcore/policies/removal/CannotBendRemovalPolicy.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.jedk1.jedcore.policies.removal; - -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.CoreAbility; - -public class CannotBendRemovalPolicy implements RemovalPolicy { - private BendingPlayer bPlayer; - private boolean ignoreBinds; - private boolean ignoreCooldowns; - private CoreAbility ability; - - public CannotBendRemovalPolicy(BendingPlayer bPlayer, CoreAbility ability) { - this(bPlayer, ability, false, false); - } - - public CannotBendRemovalPolicy(BendingPlayer bPlayer, CoreAbility ability, boolean ignoreBinds, boolean ignoreCooldowns) { - this.bPlayer = bPlayer; - this.ability = ability; - this.ignoreBinds = ignoreBinds; - this.ignoreCooldowns = ignoreCooldowns; - } - - @Override - public boolean shouldRemove() { - if (this.ignoreBinds && this.ignoreCooldowns) { - return !this.bPlayer.canBendIgnoreBindsCooldowns(ability); - } - - if (this.ignoreBinds) { - return !this.bPlayer.canBendIgnoreBinds(ability); - } - - if (this.ignoreCooldowns) { - return !this.bPlayer.canBendIgnoreCooldowns(ability); - } - - return !this.bPlayer.canBend(ability); - } - - @Override - public String getName() { - return "CannotBend"; - } -} diff --git a/src/com/jedk1/jedcore/policies/removal/CompositeRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/CompositeRemovalPolicy.java deleted file mode 100644 index 77eb59b..0000000 --- a/src/com/jedk1/jedcore/policies/removal/CompositeRemovalPolicy.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.jedk1.jedcore.policies.removal; - -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.ability.CoreAbility; -import org.bukkit.configuration.ConfigurationSection; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -public class CompositeRemovalPolicy implements RemovalPolicy { - private List policies = new ArrayList<>(); - private CoreAbility ability; - - public CompositeRemovalPolicy(CoreAbility ability, List policies) { - this.policies = policies; - this.ability = ability; - } - - public CompositeRemovalPolicy(CoreAbility ability, RemovalPolicy... policies) { - // Create as an ArrayList instead of fixed-sized so policies can be added/removed. - this.policies = new ArrayList<>(Arrays.asList(policies)); - this.ability = ability; - } - - @Override - public boolean shouldRemove() { - if (policies.isEmpty()) return false; - - for (RemovalPolicy policy : policies) { - if (policy.shouldRemove()) { - return true; - } - } - return false; - } - - public void load(ConfigurationSection config, String prefix) { - if (this.policies.isEmpty()) return; - - String pathPrefix = prefix + ".RemovalPolicy."; - - // Load the configuration section for each policy and pass it to the load method. - for (Iterator iterator = policies.iterator(); iterator.hasNext(); ) { - RemovalPolicy policy = iterator.next(); - ConfigurationSection section = config.getConfigurationSection(pathPrefix + policy.getName()); - - if (section != null) { - boolean enabled = section.getBoolean("Enabled"); - - if (!enabled) { - iterator.remove(); - continue; - } - - policy.load(section); - } - } - } - - @Override - public void load(ConfigurationSection config) { - if (this.policies.isEmpty()) return; - - Element element = ability.getElement(); - if (element instanceof Element.SubElement) { - element = ((Element.SubElement) element).getParentElement(); - } - - String abilityName = ability.getName(); - load(config, "Abilities." + element.getName() + "." + abilityName); - } - - public void addPolicy(RemovalPolicy policy) { - this.policies.add(policy); - } - - public void removePolicyType(Class type) { - policies.removeIf((policy) -> type.isAssignableFrom(policy.getClass())); - } - - @Override - public String getName() { - return "Composite"; - } -} diff --git a/src/com/jedk1/jedcore/policies/removal/IsDeadRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/IsDeadRemovalPolicy.java deleted file mode 100644 index 81c98cb..0000000 --- a/src/com/jedk1/jedcore/policies/removal/IsDeadRemovalPolicy.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.jedk1.jedcore.policies.removal; - -import org.bukkit.entity.Player; - -public class IsDeadRemovalPolicy implements RemovalPolicy { - private Player player; - - public IsDeadRemovalPolicy(Player player) { - this.player = player; - } - - @Override - public boolean shouldRemove() { - return this.player == null || !this.player.isOnline() || this.player.isDead(); - } - - @Override - public String getName() { - return "IsDead"; - } -} diff --git a/src/com/jedk1/jedcore/policies/removal/IsOfflineRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/IsOfflineRemovalPolicy.java deleted file mode 100644 index 9443215..0000000 --- a/src/com/jedk1/jedcore/policies/removal/IsOfflineRemovalPolicy.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.jedk1.jedcore.policies.removal; - -import org.bukkit.entity.Player; - -public class IsOfflineRemovalPolicy implements RemovalPolicy { - private Player player; - - public IsOfflineRemovalPolicy(Player player) { - this.player = player; - } - - @Override - public boolean shouldRemove() { - return this.player == null || !this.player.isOnline(); - } - - @Override - public String getName() { - return "IsOffline"; - } -} diff --git a/src/com/jedk1/jedcore/policies/removal/OutOfRangeRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/OutOfRangeRemovalPolicy.java deleted file mode 100644 index ee5c394..0000000 --- a/src/com/jedk1/jedcore/policies/removal/OutOfRangeRemovalPolicy.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.jedk1.jedcore.policies.removal; - -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; - -import java.util.function.Supplier; - -public class OutOfRangeRemovalPolicy implements RemovalPolicy { - private Supplier fromSupplier; - private Player player; - private double range; - - public OutOfRangeRemovalPolicy(Player player, double range, Supplier from) { - this.player = player; - this.range = range; - this.fromSupplier = from; - } - - @Override - public boolean shouldRemove() { - if (this.range == 0) return false; - - Location from = this.fromSupplier.get(); - return from.distanceSquared(this.player.getLocation()) >= (this.range * this.range); - } - - @Override - public void load(ConfigurationSection config) { - this.range = config.getDouble("Range"); - } - - @Override - public String getName() { - return "OutOfRange"; - } -} diff --git a/src/com/jedk1/jedcore/policies/removal/RemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/RemovalPolicy.java deleted file mode 100644 index d240687..0000000 --- a/src/com/jedk1/jedcore/policies/removal/RemovalPolicy.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.jedk1.jedcore.policies.removal; - -import org.bukkit.configuration.ConfigurationSection; - -public interface RemovalPolicy { - boolean shouldRemove(); - - default void load(ConfigurationSection config) { } - String getName(); -} - diff --git a/src/com/jedk1/jedcore/policies/removal/SwappedSlotsRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/SwappedSlotsRemovalPolicy.java deleted file mode 100644 index e822dd1..0000000 --- a/src/com/jedk1/jedcore/policies/removal/SwappedSlotsRemovalPolicy.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.jedk1.jedcore.policies.removal; - -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.CoreAbility; - -public class SwappedSlotsRemovalPolicy implements RemovalPolicy { - private BendingPlayer bPlayer; - private Class type; - - public SwappedSlotsRemovalPolicy(BendingPlayer bPlayer, Class type) { - this.bPlayer = bPlayer; - this.type = type; - } - - @Override - public boolean shouldRemove() { - CoreAbility bound = this.bPlayer.getBoundAbility(); - - return bound == null || !bound.getClass().isAssignableFrom(type); - } - - @Override - public String getName() { - return "SwappedSlots"; - } -} diff --git a/src/com/jedk1/jedcore/util/AbilitySelector.java b/src/com/jedk1/jedcore/util/AbilitySelector.java deleted file mode 100644 index 62fe6f6..0000000 --- a/src/com/jedk1/jedcore/util/AbilitySelector.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.ability.waterbending.WaterBlast; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.earthbending.Collapse; -import com.projectkorra.projectkorra.earthbending.CollapseWall; -import com.projectkorra.projectkorra.earthbending.RaiseEarth; -import com.projectkorra.projectkorra.earthbending.RaiseEarthWall; -import com.projectkorra.projectkorra.earthbending.Ripple; -import com.projectkorra.projectkorra.earthbending.Shockwave; -import com.projectkorra.projectkorra.firebending.Blaze; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.firebending.BlazeRing; -import com.projectkorra.projectkorra.firebending.FireBlast; -import com.projectkorra.projectkorra.firebending.FireBlastCharged; -import com.projectkorra.projectkorra.waterbending.SurgeWall; -import com.projectkorra.projectkorra.waterbending.SurgeWave; -import com.projectkorra.projectkorra.waterbending.Torrent; -import com.projectkorra.projectkorra.waterbending.TorrentWave; -import com.projectkorra.projectkorra.waterbending.WaterSpout; -import com.projectkorra.projectkorra.waterbending.WaterSpoutWave; -import com.projectkorra.projectkorra.waterbending.ice.IceSpikeBlast; -import com.projectkorra.projectkorra.waterbending.ice.IceSpikePillar; -import com.projectkorra.projectkorra.waterbending.ice.IceSpikePillarField; - -import java.util.HashMap; -import java.util.Map; - -public class AbilitySelector { - private static Map specialAbilities = new HashMap<>(); - - static { - specialAbilities.put("FireBlast", CoreAbility.getAbility(FireBlast.class)); - specialAbilities.put("FireBlastCharged", CoreAbility.getAbility(FireBlastCharged.class)); - specialAbilities.put("Blaze", CoreAbility.getAbility(Blaze.class)); - specialAbilities.put("BlazeArc", CoreAbility.getAbility(BlazeArc.class)); - specialAbilities.put("BlazeRing", CoreAbility.getAbility(BlazeRing.class)); - - specialAbilities.put("WaterSpout", CoreAbility.getAbility(WaterSpout.class)); - specialAbilities.put("WaterSpoutWave", CoreAbility.getAbility(WaterSpoutWave.class)); - specialAbilities.put("Torrent", CoreAbility.getAbility(Torrent.class)); - specialAbilities.put("TorrentWave", CoreAbility.getAbility(TorrentWave.class)); - specialAbilities.put("SurgeWall", CoreAbility.getAbility(SurgeWall.class)); - specialAbilities.put("SurgeWave", CoreAbility.getAbility(SurgeWave.class)); - specialAbilities.put("IceSpike", CoreAbility.getAbility(IceSpikeBlast.class)); - specialAbilities.put("IceSpikeBlast", CoreAbility.getAbility(IceSpikeBlast.class)); - specialAbilities.put("IceSpikePillar", CoreAbility.getAbility(IceSpikePillar.class)); - specialAbilities.put("IceSpikePillarField", CoreAbility.getAbility(IceSpikePillarField.class)); - - specialAbilities.put("Shockwave", CoreAbility.getAbility(Shockwave.class)); - specialAbilities.put("Ripple", CoreAbility.getAbility(Ripple.class)); - specialAbilities.put("RaiseEarth", CoreAbility.getAbility(RaiseEarth.class)); - specialAbilities.put("RaiseEarthWall", CoreAbility.getAbility(RaiseEarthWall.class)); - specialAbilities.put("Collapse", CoreAbility.getAbility(Collapse.class)); - specialAbilities.put("CollapseWall", CoreAbility.getAbility(CollapseWall.class)); - - specialAbilities.put("WaterGimbal", CoreAbility.getAbility(WaterBlast.class)); - } - - public static CoreAbility getAbility(String abilityName) { - CoreAbility ability = specialAbilities.get(abilityName); - - if (ability != null) - return ability; - - return CoreAbility.getAbility(abilityName); - } -} diff --git a/src/com/jedk1/jedcore/util/AirShieldReflector.java b/src/com/jedk1/jedcore/util/AirShieldReflector.java deleted file mode 100644 index 5b589a3..0000000 --- a/src/com/jedk1/jedcore/util/AirShieldReflector.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.projectkorra.projectkorra.airbending.AirShield; -import org.bukkit.Location; -import org.bukkit.util.Vector; - -public class AirShieldReflector { - public static void reflect(AirShield shield, Location location, Vector direction) { - Location shieldLocation = shield.getPlayer().getEyeLocation().clone(); - double radius = shield.getRadius(); - - if (shieldLocation.distanceSquared(location) > radius * radius) - return; - - Vector normal = location.toVector().subtract(shieldLocation.toVector()).normalize(); - // Move this instance so it's at the edge of the shield. - Location newLocation = shieldLocation.clone().add(normal.clone().multiply(radius)); - - location.setX(newLocation.getX()); - location.setY(newLocation.getY()); - location.setZ(newLocation.getZ()); - - // Reflect the direction about the normal. - direction.subtract(normal.clone().multiply(2 * direction.dot(normal))).normalize(); - } - - private AirShieldReflector() { } -} diff --git a/src/com/jedk1/jedcore/util/BlockUtil.java b/src/com/jedk1/jedcore/util/BlockUtil.java deleted file mode 100644 index 8a34f6f..0000000 --- a/src/com/jedk1/jedcore/util/BlockUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.collision.AABB; -import org.bukkit.Location; -import org.bukkit.entity.FallingBlock; - -public final class BlockUtil { - private BlockUtil() { - - } - - public static AABB getFallingBlockBoundsFull(FallingBlock fb) { - Location loc = fb.getLocation(); - - // Subtract to line the bounding box up with the corner of the box. - // The FallingBlock#getLocation returns the center of the block at the bottom. - return AABB.BlockBounds.at(loc.subtract(0.5, 0, 0.5)); - } -} diff --git a/src/com/jedk1/jedcore/util/ChiRestrictor.java b/src/com/jedk1/jedcore/util/ChiRestrictor.java deleted file mode 100644 index 8869cc8..0000000 --- a/src/com/jedk1/jedcore/util/ChiRestrictor.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.event.AbilityStartEvent; -import com.projectkorra.projectkorra.event.BendingReloadEvent; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.scheduler.BukkitRunnable; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -// Stops chi abilities from being activated from ranged attacks. -// Only works on Chi abilities that have a public method with the signature "Entity getTarget()". -public class ChiRestrictor implements Listener { - private static Map, Method> cache = new HashMap<>(); - private static Set whitelist = new HashSet<>(); - - private static boolean enabled; - private static boolean resetCooldown; - private static double meleeDistanceSq; - - static { - reloadConfig(); - } - - @EventHandler - public void onBendingReload(BendingReloadEvent event) { - new BukkitRunnable() { - public void run() { - reloadConfig(); - } - }.runTaskLater(JedCore.plugin, 1); - } - - public static void reloadConfig() { - whitelist.clear(); - - ConfigurationSection config = JedCoreConfig.getConfig((Player)null); - - enabled = config.getBoolean("Properties.ChiRestrictor.Enabled"); - resetCooldown = config.getBoolean("Properties.ChiRestrictor.ResetCooldown"); - double meleeDistance = config.getDouble("Properties.ChiRestrictor.MeleeDistance"); - - meleeDistanceSq = meleeDistance * meleeDistance; - - for (String abilityName : config.getStringList("Properties.ChiRestrictor.Whitelist")) { - whitelist.add(abilityName.toLowerCase()); - } - } - - @EventHandler - public void onAbilityStart(AbilityStartEvent event) { - if (!enabled || event.isCancelled() || !(event.getAbility() instanceof ChiAbility)) { - return; - } - - ChiAbility ability = (ChiAbility)event.getAbility(); - if (isWhitelisted(ability.getName())) { - return; - } - - Entity target = getTarget(ability); - if (target == null) { - return; - } - - Player player = event.getAbility().getPlayer(); - - if (player.getWorld() != target.getWorld()) { - return; - } - - double distanceSq = target.getLocation().distanceSquared(player.getLocation()); - if (distanceSq > meleeDistanceSq) { - event.setCancelled(true); - - if (resetCooldown) { - ability.getBendingPlayer().removeCooldown(ability); - } - } - } - - private static boolean isWhitelisted(String name) { - return whitelist.contains(name.toLowerCase()); - } - - private static Entity getTarget(ChiAbility ability) { - Class clazz = ability.getClass(); - - Method method; - - // Check to see if this class was stored in cache to minimize reflection usage. - if (cache.containsKey(clazz)) { - method = cache.get(clazz); - - // method will be null when the class has already been checked and didn't have getTarget. - if (method == null) { - return null; - } - } else { - // Use reflection to see if the ability has getTarget method. - // Store this in a map to minimize reflection usage. - try { - method = clazz.getDeclaredMethod("getTarget"); - - cache.put(clazz, method); - } catch (NoSuchMethodException e) { - cache.put(clazz, null); - return null; - } - } - - // Call the getTarget method if it exists and return the Entity. - try { - Object entity = method.invoke(ability); - - if (entity instanceof Entity) { - return (Entity)entity; - } - - return null; - } catch (IllegalAccessException|InvocationTargetException e) { - return null; - } - } -} diff --git a/src/com/jedk1/jedcore/util/CollisionInitializer.java b/src/com/jedk1/jedcore/util/CollisionInitializer.java deleted file mode 100644 index 403baf9..0000000 --- a/src/com/jedk1/jedcore/util/CollisionInitializer.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.ProjectKorra; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import org.bukkit.configuration.ConfigurationSection; - -import java.util.HashMap; -import java.util.Map; - -public class CollisionInitializer { - // This is used for special mappings where collisions are stored in a separate place. - public static Map abilityMap = new HashMap<>(); - private Class type; - - public CollisionInitializer(Class type) { - this.type = type; - } - - public boolean initialize() { - CoreAbility ability = CoreAbility.getAbility(type); - - if (ability == null) return false; - - String abilityName = ability.getName(); - - Element element = ability.getElement(); - if (element instanceof Element.SubElement) { - element = ((Element.SubElement) element).getParentElement(); - if (element == null) { - element = ability.getElement(); - } - } - - if (abilityMap.containsKey(abilityName)) { - abilityName = abilityMap.get(abilityName); - } - - String collisionPath = getCollisionPath(abilityName, element); - - ConfigurationSection section = JedCore.plugin.getConfig().getConfigurationSection(collisionPath); - for (String key : section.getKeys(false)) { - ConfigurationSection abilityConfig = section.getConfigurationSection(key); - - boolean enabled = abilityConfig.getBoolean("Enabled"); - if (!enabled) continue; - - if (key.equalsIgnoreCase("-small-")) { - JedCore.logDebug("Initializing small collision for " + abilityName + "."); - ProjectKorra.getCollisionInitializer().addSmallAbility(ability); - - continue; - } else if (key.equalsIgnoreCase("-large-")) { - JedCore.logDebug("Initializing large collision for " + abilityName + "."); - ProjectKorra.getCollisionInitializer().addLargeAbility(ability); - - continue; - } - - boolean removeFirst = abilityConfig.getBoolean("RemoveFirst"); - boolean removeSecond = abilityConfig.getBoolean("RemoveSecond"); - - CoreAbility secondAbility = AbilitySelector.getAbility(key); - - if (secondAbility != null) { - JedCore.logDebug("Initializing collision for " + abilityName + " => " + key); - - ProjectKorra.getCollisionManager().addCollision(new Collision(ability, secondAbility, removeFirst, removeSecond)); - } - } - - return true; - } - - private String getCollisionPath(String abilityName, Element element) { - CoreAbility ability = CoreAbility.getAbility(abilityName); - if (ability == null) { - return ""; - } - - StringBuilder sb = new StringBuilder(); - - sb.append("Abilities.").append(element.getName()).append("."); - - if (ability instanceof ComboAbility) { - sb.append(element.getName()).append("Combo."); - } - - sb.append(abilityName).append(".Collisions"); - - return sb.toString(); - } -} diff --git a/src/com/jedk1/jedcore/util/FireTick.java b/src/com/jedk1/jedcore/util/FireTick.java deleted file mode 100644 index adb9e53..0000000 --- a/src/com/jedk1/jedcore/util/FireTick.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.JedCore; -import org.bukkit.entity.Entity; - -import java.util.HashMap; -import java.util.Map; - -public class FireTick { - private static Map methods = new HashMap<>(); - private static FireTickMethod method = new OverwriteFireTickMethod(); - - static { - methods.put("overwrite", new OverwriteFireTickMethod()); - methods.put("larger", new LargerFireTickMethod()); - methods.put("accumulate", new AccumulateFireTickMethod()); - } - - public static void set(Entity target, int amount) { - method.set(target, amount); - } - - public static void loadMethod() { - String methodName = JedCore.plugin.getConfig().getString("Properties.FireTickMethod"); - - FireTickMethod newMethod = methods.get(methodName.toLowerCase()); - if (newMethod != null) { - JedCore.logDebug("Using " + methodName + " as FireTickMethod."); - method = newMethod; - } else { - JedCore.plugin.getLogger().warning(methodName + " not a known FireTickMethod. Defaulting to larger method."); - method = new LargerFireTickMethod(); - } - } - - private interface FireTickMethod { - void set(Entity entity, int amount); - } - - // Always set the target's fire tick to the new amount. - private static class OverwriteFireTickMethod implements FireTickMethod { - @Override - public void set(Entity entity, int amount) { - entity.setFireTicks(amount); - } - } - - // Only overwrite target's fire tick if the new fire tick is larger. - private static class LargerFireTickMethod implements FireTickMethod { - @Override - public void set(Entity entity, int amount) { - if (entity.getFireTicks() < amount) { - entity.setFireTicks(amount); - } - } - } - - // Increase the target's fire tick instead of overwriting. - private static class AccumulateFireTickMethod implements FireTickMethod { - @Override - public void set(Entity entity, int amount) { - entity.setFireTicks(entity.getFireTicks() + amount); - } - } -} diff --git a/src/com/jedk1/jedcore/util/LightManager.java b/src/com/jedk1/jedcore/util/LightManager.java deleted file mode 100644 index 2a44fce..0000000 --- a/src/com/jedk1/jedcore/util/LightManager.java +++ /dev/null @@ -1,454 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ProjectKorra; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Levelled; -import org.bukkit.block.data.Waterlogged; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -public class LightManager { - - // Our LightManager instance - private static final LightManager INSTANCE = new LightManager(); - // If the MC version is pre-LIGHT (< 1.17) this class basically does nothing - private final boolean modern; - // Striped Lock set at number of processors * 2 - private final Object[] locks; - // A map containing all active lights - private final ConcurrentHashMap> lightMap = new ConcurrentHashMap<>(); - // A queue for handling individual reversions - private final ConcurrentLinkedQueue blockChangeQueue = new ConcurrentLinkedQueue<>(); - - // Default LIGHT BlockData - private final Map lightDataMap = new HashMap<>(); - private final Map waterloggedLightDataMap = new HashMap<>(); - - // Scheduler with threads equal to the number of available processors, this handles reverting expired lights - private ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors()); - - /** - * Creates a new LightManager instance. Initializes default BlockData for LIGHT and waterlogged LIGHT, - * sets up locks based on the number of available processors * 2, and schedules the reverter task to run periodically - * using a ScheduledThreadPoolExecutor. - */ - private LightManager() { - modern = GeneralMethods.getMCVersion() >= 1170; - - int numLocks = Runtime.getRuntime().availableProcessors() * 2; - locks = new Object[numLocks]; - for (int i = 0; i < numLocks; i++) { - locks[i] = new Object(); - } - - if (modern) { - precomputeLightData(); - startLightReverter(); - } - } - - /** - * Retrieves the current time and iterates over all light data in the light map. If the current time is greater - * than or equal to the expiry time of a light data, it fades the light out and removes the light data from the map. - * This is running periodically, or every 50ms, via the scheduled thread pool executor. - */ - private void revertExpiredLights() { - long currentTime = System.currentTimeMillis(); - List lightsToRevert = new ArrayList<>(); - - lightMap.forEach((location, lightDataSet) -> { - Iterator iterator = lightDataSet.iterator(); - while (iterator.hasNext()) { - LightData lightData = iterator.next(); - if (currentTime >= lightData.expiryTime) { - lightsToRevert.add(lightData); - iterator.remove(); - } - } - if (lightDataSet.isEmpty()) { - lightMap.remove(location); - } - }); - - for (LightData lightData : lightsToRevert) { - fadeLight(lightData); - } - } - - /** - * Precomputes light data for levels 1 through 15 by creating a BlockData object for each level - * with the "LIGHT" material and setting the level using the Levelled interface. It also - * creates a waterlogged version of each light data object using the Waterlogged interface. - * The resulting objects are stored in the lightDataMap and waterloggedLightDataMap maps - * respectively. This cuts down on computation time constantly manipulating BlockData. - */ - private void precomputeLightData() { - BlockData lightData = Bukkit.createBlockData(Material.valueOf("LIGHT")); - - for (int level = 1; level <= 15; level++) { - ((Levelled) lightData).setLevel(level); - lightDataMap.put(level, lightData.clone()); - - BlockData waterloggedLightData = lightData.clone(); - ((Waterlogged) waterloggedLightData).setWaterlogged(true); - waterloggedLightDataMap.put(level, waterloggedLightData); - } - } - - /** - * Starts the light reverter task by scheduling it to run at a fixed rate of 50 milliseconds, or 1 tick. - * If the scheduler is already shut down, a new ScheduledThreadPoolExecutor is created with the number of available processors. - */ - private void startLightReverter() { - if (scheduler.isShutdown()) { - scheduler = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors()); - } - - scheduler.scheduleAtFixedRate(this::revertExpiredLights, 0, 50, TimeUnit.MILLISECONDS); - scheduler.scheduleAtFixedRate(this::processBlockChanges, 0, 50, TimeUnit.MILLISECONDS); - } - - /** - * Fades out a light by decrementing its brightness by 1. The light will stop fading when its brightness - * reaches 0. The fade process is scheduled to run every 50 milliseconds, or 1 tick. - * - * @param lightData the LightData object containing the light's brightness, location, UUID, and ephemeral flag - */ - private void fadeLight(LightData lightData) { - int brightness = lightData.brightness; - - class TaskHolder { - ScheduledFuture future; - } - TaskHolder taskHolder = new TaskHolder(); - - Runnable task = new Runnable() { - private int currentBrightness = brightness; - - @Override - public void run() { - currentBrightness--; - if (currentBrightness > 0) { - sendLightChange(lightData.location, currentBrightness, lightData.observers); - } else { - revertLight(lightData); - taskHolder.future.cancel(false); - } - } - }; - - taskHolder.future = scheduler.scheduleAtFixedRate(task, 0, 50, TimeUnit.MILLISECONDS); - } - - /** - * Sends a block change to the specified location. Brightness of 0 indicates that the light should be reverted. - * - * @param location the location where the light change is to be sent - * @param brightness the brightness level of the light - * @param observers the list of players who can see the light - */ - private void sendLightChange(Location location, int brightness, Collection observers) { - BlockData lightData = brightness > 0 ? getLightData(location, brightness) : getCurrentBlockData(location); - World targetWorld = location.getWorld(); - double maxDistanceSquared = Math.pow(Bukkit.getServer().getViewDistance() * 16, 2); - - observers.stream() - .filter(player -> player != null && player.isOnline() && !player.isDead() && player.getWorld().equals(targetWorld)) - .filter(player -> player.getLocation().distanceSquared(location) <= maxDistanceSquared) - .forEach(player -> blockChangeQueue.add(new BlockChange(player, location, lightData))); - } - - private void processBlockChanges() { - BlockChange blockChange; - while ((blockChange = blockChangeQueue.poll()) != null) { - Player player = blockChange.getPlayer(); - BlockChange finalBlockChange = blockChange; - Bukkit.getScheduler().runTaskAsynchronously(ProjectKorra.plugin, () -> { - player.sendBlockChange(finalBlockChange.getLocation(), finalBlockChange.getBlockData()); - }); - } - } - - /** - * Helper method to revert a light at the specified location by calling sendLightChange with a brightness of 0. - * - * @param lightData the LightData object containing the location, brightness, UUID, and ephemeral flag of the light to be reverted - */ - private void revertLight(LightData lightData) { - sendLightChange(lightData.location, 0, lightData.observers); - } - - /** - * Returns the BlockData as light for the given Location, based on whether the block is water or air. - * - * @param location the Location to get the BlockData for - * @param lightLevel the light level to set for the BlockData - * @return the BlockData for the given Location - */ - private BlockData getLightData(Location location, int lightLevel) { - if (location.getBlock().getType() == Material.WATER) { - return waterloggedLightDataMap.get(lightLevel); - } else { - return lightDataMap.get(lightLevel); - } - } - - /** - * Returns the BlockData for the given Location, based on the current state of the block. - * Used to revert lights that have expired. - * - * @param location the Location to get the BlockData for - * @return the BlockData for the given Location - */ - private BlockData getCurrentBlockData(Location location) { - return location.getBlock().getBlockData(); - } - - public static LightManager get() { - return INSTANCE; - } - - /** - * Creates a new LightBuilder instance with the given location. - * - * @param location the location where the light will be created - * @return a new LightBuilder instance - */ - public static LightBuilder createLight(Location location) { - return new LightBuilder(location); - } - - /** - * Adds a light at the specified location with the given brightness and expiry. - * Visible for the specified observers. - * Subsequent calls to a location with an active light extends the expiration time for the relevant observers. - * - * @param location the location where the light should be added - * @param brightness the brightness of the light, 1-15 - * @param expiry the time in milliseconds before the light fades out - * @param observers the list of players who can see the light - */ - private void addLight(Location location, int brightness, long expiry, Collection observers) { - if (!modern) return; - - location = location.getBlock().getLocation(); - long expiryTime = System.currentTimeMillis() + expiry; - - if (location.getBlock().getLightLevel() >= brightness || - (!location.getBlock().isEmpty() && !location.getBlock().getType().equals(Material.WATER))) return; - - LightData newLightData = new LightData(location, brightness, observers, expiryTime); - - Object lock = getLockForLocation(location); - synchronized (lock) { - ConcurrentSkipListSet existingSet = lightMap.computeIfAbsent(location, loc -> new ConcurrentSkipListSet<>()); - existingSet.removeIf(lightData -> lightData.observers.equals(observers)); - existingSet.add(newLightData); - } - - sendLightChange(location, brightness, observers); - } - - /** - * Returns the lock object associated with the given location. The lock object - * is used to synchronize access to the light data for the location. The - * function calculates the hash code of the location and uses it to determine - * the index of the lock object in the locks array. The locks array is - * initialized with a fixed number of objects based on the number of available - * processors * 2. - * - * @param location the location for which the lock object is requested - * @return the lock object associated with the location - */ - private Object getLockForLocation(Location location) { - return locks[(location.hashCode() & 0x7FFFFFFF) % locks.length]; - } - - /** - * Reverts all active lights immediately with no fade-out, then restarts the revert scheduler. - * This does not normally need to be used as it's already called when ProjectKorra is reloaded. - */ - public void restart() { - if (!modern) return; - - lightMap.values().forEach(set -> set.forEach(this::revertLight)); - lightMap.clear(); - - scheduler.shutdown(); - - try { - if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { - scheduler.shutdownNow(); - } - } catch (InterruptedException e) { - scheduler.shutdownNow(); - Thread.currentThread().interrupt(); - } - - startLightReverter(); - } - - private static class LightData implements Comparable { - private final Location location; - private final int brightness; - private final Collection observers; - private final long expiryTime; - - private LightData(Location location, int brightness, Collection observers, long expiryTime) { - this.location = location; - this.brightness = brightness; - this.observers = observers; - this.expiryTime = expiryTime; - } - - /** - * Calculates the hash code for this object. The hash code is based on the - * values of the location, brightness, observers, and expiryTime fields. - * - * @return the hash code of this object - */ - @Override - public int hashCode() { - return Objects.hash(location, brightness, observers, expiryTime); - } - - /** - * Checks if this LightData object is equal to another object. Two LightData objects are considered - * equal if they have the same brightness, expiryTime, location, and observers. - * - * @param obj the object to compare this LightData object to - * @return true if the objects are equal, false otherwise - */ - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - LightData that = (LightData) obj; - return brightness == that.brightness && - expiryTime == that.expiryTime && - location.equals(that.location) && - observers.equals(that.observers); - } - - /** - * Returns a string representation of the LightData object. - * - * @return a string in the format "LightData{location=..., brightness=..., observers=..., expiryTime=...}" - */ - @Override - public String toString() { - return "LightData{" + - "location=" + location + - ", brightness=" + brightness + - ", observers=" + observers + - ", expiryTime=" + expiryTime + - '}'; - } - - /** - * Compares this LightData object with another LightData object based on their expiryTime. - * - * @param other the LightData object to compare to - * @return a negative integer, zero, or a positive integer as this object's - * expiryTime is less than, equal to, or greater than the other object's - * expiryTime. - */ - @Override - public int compareTo(LightData other) { - return Long.compare(this.expiryTime, other.expiryTime); - } - } - - public static class LightBuilder { - private final Location location; - private int brightness = 15; // default brightness - private long timeUntilFade = 50; // default expiry time in ms - private Collection observers = Bukkit.getOnlinePlayers(); // default to all players - - public LightBuilder(Location location) { - this.location = location; - } - - /** - * Sets the brightness value, 1-15, for this light. - * - * @param brightness the new brightness value, a value 1-15. - * @return the current instance of the LightBuilder - */ - public LightBuilder brightness(int brightness) { - this.brightness = Math.max(1, Math.min(15, brightness)); - return this; - } - - /** - * Sets the expiry time in ms for this light, defaults to 50ms. - * - * @param expiry the new expiry time in milliseconds - * @return the current instance of the LightBuilder - */ - public LightBuilder timeUntilFadeout(long expiry) { - this.timeUntilFade = expiry; - return this; - } - - /** - * Sets the collection of observers for this light, defaults to everybody. - * - * @param observers the collection of observers to set - * @return the current instance of the LightBuilder - */ - public LightBuilder observers(Collection observers) { - this.observers = observers; - return this; - } - - /** - * Emits this light at the specified location with the given brightness, expiry time, and observers. - */ - public void emit() { - LightManager.get().addLight(location, brightness, timeUntilFade, observers); - } - } - - private static class BlockChange { - private final Player player; - private final Location location; - private final BlockData blockData; - - public BlockChange(Player player, Location location, BlockData blockData) { - this.player = player; - this.location = location; - this.blockData = blockData; - } - - public Player getPlayer() { - return player; - } - - public Location getLocation() { - return location; - } - - public BlockData getBlockData() { - return blockData; - } - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/util/MaterialUtil.java b/src/com/jedk1/jedcore/util/MaterialUtil.java deleted file mode 100644 index 1180a2f..0000000 --- a/src/com/jedk1/jedcore/util/MaterialUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.projectkorra.projectkorra.GeneralMethods; -import org.bukkit.Material; -import org.bukkit.Tag; -import org.bukkit.block.Block; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class MaterialUtil { - - // todo: use the registry/tags (with config) or grab directly from PKs config maybe? - private static final List TRANSPARENT_MATERIALS = new ArrayList<>() {{ - addAll(Arrays.asList( - Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.OAK_SAPLING, Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, - Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING, Material.WATER, - Material.LAVA, Material.COBWEB, Material.TALL_GRASS, Material.GRASS, Material.FERN, Material.DEAD_BUSH, - Material.DANDELION, Material.POPPY, Material.BLUE_ORCHID, Material.ALLIUM, - Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, - Material.OXEYE_DAISY, Material.BROWN_MUSHROOM, Material.RED_MUSHROOM, Material.TORCH, Material.FIRE, - Material.WHEAT, Material.SNOW, Material.SUGAR_CANE, Material.VINE, Material.SUNFLOWER, Material.LILAC, - Material.LARGE_FERN, Material.ROSE_BUSH, Material.PEONY)); - if (GeneralMethods.getMCVersion() >= 1170) { - add(Material.getMaterial("LIGHT")); - } - }}; - - public static boolean isSign(Material material) { - return Tag.SIGNS.isTagged(material); - } - - public static boolean isSign(Block block) { - return isSign(block.getType()); - } - - // Do a fast lookup by avoiding the region protection check. - public static boolean isTransparent(Block block) { - return isTransparent(block.getType()); - } - - // Do a fast lookup by avoiding the region protection check. - public static boolean isTransparent(Material material) { - return TRANSPARENT_MATERIALS.contains(material); - } -} diff --git a/src/com/jedk1/jedcore/util/MetricsLite.java b/src/com/jedk1/jedcore/util/MetricsLite.java deleted file mode 100644 index b93fb90..0000000 --- a/src/com/jedk1/jedcore/util/MetricsLite.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright 2011-2013 Tyler Blair. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and contributors and should not be interpreted as representing official policies, - * either expressed or implied, of anybody else. - */ - -package com.jedk1.jedcore.util; - -import org.bukkit.Bukkit; -import org.bukkit.Server; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.scheduler.BukkitTask; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Method; -import java.net.Proxy; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.UUID; -import java.util.logging.Level; -import java.util.zip.GZIPOutputStream; - -public class MetricsLite { - - /** - * The current revision number - */ - private final static int REVISION = 7; - - /** - * The base url of the metrics domain - */ - private static final String BASE_URL = "http://report.mcstats.org"; - - /** - * The url used to report a server's status - */ - private static final String REPORT_URL = "/plugin/%s"; - - /** - * Interval of time to ping (in minutes) - */ - private final static int PING_INTERVAL = 15; - - /** - * The plugin this metrics submits for - */ - private final Plugin plugin; - - /** - * The plugin configuration file - */ - private final YamlConfiguration configuration; - - /** - * The plugin configuration file - */ - private final File configurationFile; - - /** - * Unique server id - */ - private final String guid; - - /** - * Debug mode - */ - private final boolean debug; - - /** - * Lock for synchronization - */ - private final Object optOutLock = new Object(); - - /** - * Id of the scheduled task - */ - private volatile BukkitTask task = null; - - public MetricsLite(Plugin plugin) throws IOException { - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } - - this.plugin = plugin; - - // load the config - configurationFile = getConfigFile(); - configuration = YamlConfiguration.loadConfiguration(configurationFile); - - // add some defaults - configuration.addDefault("opt-out", false); - configuration.addDefault("guid", UUID.randomUUID().toString()); - configuration.addDefault("debug", false); - - // Do we need to create the file? - if (configuration.get("guid", null) == null) { - configuration.options().header("http://mcstats.org").copyDefaults(true); - configuration.save(configurationFile); - } - - // Load the guid then - guid = configuration.getString("guid"); - debug = configuration.getBoolean("debug", false); - } - - /** - * Start measuring statistics. This will immediately create an async repeating task as the plugin and send - * the initial data to the metrics backend, and then after that it will post in increments of - * PING_INTERVAL * 1200 ticks. - * - * @return True if statistics measuring is running, otherwise false. - */ - public boolean start() { - synchronized (optOutLock) { - // Did we opt out? - if (isOptOut()) { - return false; - } - - // Is metrics already running? - if (task != null) { - return true; - } - - // Begin hitting the server with glorious data - task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { - - private boolean firstPost = true; - - public void run() { - try { - // This has to be synchronized or it can collide with the disable method. - synchronized (optOutLock) { - // Disable Task, if it is running and the server owner decided to opt-out - if (isOptOut() && task != null) { - task.cancel(); - task = null; - } - } - - // We use the inverse of firstPost because if it is the first time we are posting, - // it is not a interval ping, so it evaluates to FALSE - // Each time thereafter it will evaluate to TRUE, i.e PING! - postPlugin(!firstPost); - - // After the first post we set firstPost to false - // Each post thereafter will be a ping - firstPost = false; - } catch (IOException e) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); - } - } - } - }, 0, PING_INTERVAL * 1200); - - return true; - } - } - - /** - * Has the server owner denied plugin metrics? - * - * @return true if metrics should be opted out of it - */ - public boolean isOptOut() { - synchronized (optOutLock) { - try { - // Reload the metrics file - configuration.load(getConfigFile()); - } catch (IOException | InvalidConfigurationException ex) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); - } - return true; - } - return configuration.getBoolean("opt-out", false); - } - } - - /** - * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. - * - * @throws java.io.IOException - */ - public void enable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (isOptOut()) { - configuration.set("opt-out", false); - configuration.save(configurationFile); - } - - // Enable Task, if it is not running - if (task == null) { - start(); - } - } - } - - /** - * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. - * - * @throws java.io.IOException - */ - public void disable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (!isOptOut()) { - configuration.set("opt-out", true); - configuration.save(configurationFile); - } - - // Disable Task, if it is running - if (task != null) { - task.cancel(); - task = null; - } - } - } - - /** - * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status - * - * @return the File object for the config file - */ - public File getConfigFile() { - // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use - // is to abuse the plugin object we already have - // plugin.getDataFolder() => base/plugins/PluginA/ - // pluginsFolder => base/plugins/ - // The base is not necessarily relative to the startup directory. - File pluginsFolder = plugin.getDataFolder().getParentFile(); - - // return => base/plugins/PluginMetrics/config.yml - return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); - } - - /** - * Gets the online player (backwards compatibility) - * - * @return online player amount - */ - private int getOnlinePlayers() { - try { - Method onlinePlayerMethod = Server.class.getMethod("getOnlinePlayers"); - if(onlinePlayerMethod.getReturnType().equals(Collection.class)) { - return ((Collection)onlinePlayerMethod.invoke(Bukkit.getServer())).size(); - } else { - return ((Player[])onlinePlayerMethod.invoke(Bukkit.getServer())).length; - } - } catch (Exception ex) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); - } - } - - return 0; - } - - /** - * Generic method that posts a plugin to the metrics website - */ - private void postPlugin(boolean isPing) throws IOException { - // Server software specific section - PluginDescriptionFile description = plugin.getDescription(); - String pluginName = description.getName(); - boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled - String pluginVersion = description.getVersion(); - String serverVersion = Bukkit.getVersion(); - int playersOnline = this.getOnlinePlayers(); - - // END server software specific section -- all code below does not use any code outside of this class / Java - - // Construct the post data - StringBuilder json = new StringBuilder(1024); - json.append('{'); - - // The plugin's description file containg all of the plugin data such as name, version, author, etc - appendJSONPair(json, "guid", guid); - appendJSONPair(json, "plugin_version", pluginVersion); - appendJSONPair(json, "server_version", serverVersion); - appendJSONPair(json, "players_online", Integer.toString(playersOnline)); - - // New data as of R6 - String osname = System.getProperty("os.name"); - String osarch = System.getProperty("os.arch"); - String osversion = System.getProperty("os.version"); - String java_version = System.getProperty("java.version"); - int coreCount = Runtime.getRuntime().availableProcessors(); - - // normalize os arch .. amd64 -> x86_64 - if (osarch.equals("amd64")) { - osarch = "x86_64"; - } - - appendJSONPair(json, "osname", osname); - appendJSONPair(json, "osarch", osarch); - appendJSONPair(json, "osversion", osversion); - appendJSONPair(json, "cores", Integer.toString(coreCount)); - appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); - appendJSONPair(json, "java_version", java_version); - - // If we're pinging, append it - if (isPing) { - appendJSONPair(json, "ping", "1"); - } - - // close json - json.append('}'); - - // Create the url - URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); - - // Connect to the website - URLConnection connection; - - // Mineshafter creates a socks proxy, so we can safely bypass it - // It does not reroute POST requests so we need to go around it - if (isMineshafterPresent()) { - connection = url.openConnection(Proxy.NO_PROXY); - } else { - connection = url.openConnection(); - } - - - byte[] uncompressed = json.toString().getBytes(); - byte[] compressed = gzip(json.toString()); - - // Headers - connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); - connection.addRequestProperty("Content-Type", "application/json"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - - connection.setDoOutput(true); - - if (debug) { - System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); - } - - // Write the data - OutputStream os = connection.getOutputStream(); - os.write(compressed); - os.flush(); - - // Now read the response - final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); - String response = reader.readLine(); - - // close resources - os.close(); - reader.close(); - - if (response == null || response.startsWith("ERR") || response.startsWith("7")) { - if (response == null) { - response = "null"; - } else if (response.startsWith("7")) { - response = response.substring(response.startsWith("7,") ? 2 : 1); - } - - throw new IOException(response); - } - } - - /** - * GZip compress a string of bytes - * - * @param input - * @return - */ - public static byte[] gzip(String input) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gzos = null; - - try { - gzos = new GZIPOutputStream(baos); - gzos.write(input.getBytes(StandardCharsets.UTF_8)); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (gzos != null) try { - gzos.close(); - } catch (IOException ignore) { - } - } - - return baos.toByteArray(); - } - - /** - * Check if mineshafter is present. If it is, we need to bypass it to send POST requests - * - * @return true if mineshafter is installed on the server - */ - private boolean isMineshafterPresent() { - try { - Class.forName("mineshafter.MineServer"); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Appends a json encoded key/value pair to the given string builder. - * - * @param json - * @param key - * @param value - * @throws UnsupportedEncodingException - */ - private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { - boolean isValueNumeric = false; - - try { - if (value.equals("0") || !value.endsWith("0")) { - Double.parseDouble(value); - isValueNumeric = true; - } - } catch (NumberFormatException e) { - isValueNumeric = false; - } - - if (json.charAt(json.length() - 1) != '{') { - json.append(','); - } - - json.append(escapeJSON(key)); - json.append(':'); - - if (isValueNumeric) { - json.append(value); - } else { - json.append(escapeJSON(value)); - } - } - - /** - * Escape a string to create a valid JSON string - * - * @param text - * @return - */ - private static String escapeJSON(String text) { - StringBuilder builder = new StringBuilder(); - - builder.append('"'); - for (int index = 0; index < text.length(); index++) { - char chr = text.charAt(index); - - switch (chr) { - case '"': - case '\\': - builder.append('\\'); - builder.append(chr); - break; - case '\b': - builder.append("\\b"); - break; - case '\t': - builder.append("\\t"); - break; - case '\n': - builder.append("\\n"); - break; - case '\r': - builder.append("\\r"); - break; - default: - if (chr < ' ') { - String t = "000" + Integer.toHexString(chr); - builder.append("\\u" + t.substring(t.length() - 4)); - } else { - builder.append(chr); - } - break; - } - } - builder.append('"'); - - return builder.toString(); - } - - /** - * Encode text as UTF-8 - * - * @param text the text to encode - * @return the encoded text, as UTF-8 - */ - private static String urlEncode(final String text) throws UnsupportedEncodingException { - return URLEncoder.encode(text, "UTF-8"); - } - -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/util/RegenTempBlock.java b/src/com/jedk1/jedcore/util/RegenTempBlock.java deleted file mode 100644 index 3afa11d..0000000 --- a/src/com/jedk1/jedcore/util/RegenTempBlock.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockState; -import org.bukkit.block.data.BlockData; -import org.bukkit.inventory.InventoryHolder; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -public class RegenTempBlock { - - public static Map blocks = new HashMap<>(); - public static Map temps = new HashMap<>(); - public static Map states = new HashMap<>(); - - /** - * Creates a TempBlock that reverts after a delay. - * @param block Block to be updated/reverted. - * @param material Material to be changed. - * @param data Data to be changed. - * @param delay Delay until block regens. - */ - public RegenTempBlock(Block block, Material material, BlockData data, long delay) { - this(block, material, data, delay, true); - } - - /** - * Creates a TempBlock or a State of a block that reverts after a certain time. - * @param block Block to be updated/reverted. - * @param material Material to be changed. - * @param data Data to be changed. - * @param delay Delay until block regens. - * @param temp Use TempBlock or BlockState. - */ - public RegenTempBlock(Block block, Material material, BlockData data, long delay, boolean temp) { - this(block, material, data, delay, temp, null); - } - - public RegenTempBlock(Block block, Material material, BlockData data, long delay, boolean temp, RegenCallback callback) { - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - if (block.getState() instanceof InventoryHolder || block.getType() == Material.JUKEBOX) { - return; - } - if (blocks.containsKey(block)) { - blocks.replace(block, new RegenBlockData(System.currentTimeMillis() + delay, callback)); - block.setBlockData(data.clone()); - } else { - blocks.put(block, new RegenBlockData(System.currentTimeMillis() + delay, callback)); - if (TempBlock.isTempBlock(block)) { - TempBlock.get(block).revertBlock(); - } - if (temp) { - TempBlock tb = new TempBlock(block, data.clone()); - temps.put(block, tb); - } else { - states.put(block, block.getState()); - if (material != null) { - block.setBlockData(data.clone()); - } - } - } - } - - /** - * Manages blocks to be reverted. - */ - public static void manage() { - Iterator> iterator = blocks.entrySet().iterator(); - - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - - Block b = entry.getKey(); - RegenBlockData blockData = entry.getValue(); - - if (System.currentTimeMillis() >= blockData.endTime) { - TempBlock tb = temps.get(b); - if (tb != null) { - tb.revertBlock(); - temps.remove(b); - } - - BlockState bs = states.get(b); - if (bs != null) { - bs.update(true); - states.remove(b); - } - - iterator.remove(); - - if (blockData.callback != null) { - blockData.callback.onRegen(b); - } - } - } - } - - /** - * Reverts an individual block. - * @param block - */ - public static void revert(Block block) { - if (blocks.containsKey(block)) { - if (TempBlock.isTempBlock(block) && temps.containsKey(block)) { - TempBlock tb = TempBlock.get(block); - tb.revertBlock(); - temps.remove(block); - } - if (states.containsKey(block)) { - states.get(block).update(true); - states.remove(block); - } - blocks.remove(block); - } - } - - /** - * Reverts all blocks. - */ - public static void revertAll() { - for (Block b : blocks.keySet()) { - if (temps.containsKey(b)) { - TempBlock tb = temps.get(b); - tb.revertBlock(); - } - if (states.containsKey(b)) { - states.get(b).update(true); - } - } - temps.clear(); - states.clear(); - blocks.clear(); - } - - /** - * Returns true if the block is a RegenTempBlock. - * @param block - * @return - */ - public static boolean hasBlock(Block block) { - return blocks.containsKey(block); - } - - /** - * Returns true if the block is stored as a temp block. - * @param block - * @return - */ - public static boolean isTempBlock(Block block) { - return temps.containsKey(block); - } - - /** - * Returns true if the block is stored as a block state. - * @param block - * @return - */ - public static boolean isBlockState(Block block) { - return states.containsKey(block); - } - - private static class RegenBlockData { - long endTime; - RegenCallback callback; - - public RegenBlockData(long endTime, RegenCallback callback) { - this.endTime = endTime; - this.callback = callback; - } - } - - public interface RegenCallback { - void onRegen(Block block); - } -} diff --git a/src/com/jedk1/jedcore/util/TemporaryFallingBlock.java b/src/com/jedk1/jedcore/util/TemporaryFallingBlock.java deleted file mode 100644 index 55debfb..0000000 --- a/src/com/jedk1/jedcore/util/TemporaryFallingBlock.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.block.data.BlockData; -import org.bukkit.util.Vector; - -public class TemporaryFallingBlock extends TempFallingBlock { - - private final Location originalLocation; - - public TemporaryFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability) { - super(location, data, velocity, ability); - originalLocation = location.clone(); - } - - public Location getOriginalLocation() { - return originalLocation; - } - - public boolean hasMoved() { - Location currentLocation = getFallingBlock().getLocation(); - return currentLocation.getX() != originalLocation.getX() || currentLocation.getZ() != originalLocation.getZ(); - } - - public void resetToOriginalLocation() { - getFallingBlock().teleport(originalLocation); - } -} diff --git a/src/com/jedk1/jedcore/util/ThrownEntityTracker.java b/src/com/jedk1/jedcore/util/ThrownEntityTracker.java deleted file mode 100644 index 9c6fb7d..0000000 --- a/src/com/jedk1/jedcore/util/ThrownEntityTracker.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.Ability; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -public class ThrownEntityTracker { - - public static ConcurrentHashMap instances = new ConcurrentHashMap<>(); - public static boolean collisions = JedCore.plugin.getConfig().getBoolean("Properties.MobCollisions.Enabled"); - private long delay; - private final long fireTime; - private final Entity entity; - private final Player instigator; - private Vector thisVelocity; - private Ability ability; - - public ThrownEntityTracker(Ability ability, Entity e, Player instigator, long delay) { - entity = e; - this.instigator = instigator; - fireTime = System.currentTimeMillis(); - this.delay = delay; - thisVelocity = e.getVelocity(); - this.delay = delay; - instances.put(entity, this); - } - - public void update() { - if (System.currentTimeMillis() < fireTime + delay) { - return; - } - - if (!collisions || entity.isOnGround()) { - remove(); - return; - } - - thisVelocity = entity.getVelocity().clone(); - - List nearby = GeneralMethods.getEntitiesAroundPoint(entity.getLocation(), 2D); - nearby.remove(entity); - nearby.remove(instigator); - - if (nearby.size() != 0) { - entity.setVelocity(thisVelocity.multiply(0.5D)); - for(Entity e : nearby){ - e.setVelocity(entity.getVelocity().multiply(0.25D).add(GeneralMethods.getDirection(entity.getLocation(), e.getLocation()).multiply(2))); - if (e instanceof LivingEntity) { - DamageHandler.damageEntity(e, 2D, ability); - } - if (entity instanceof LivingEntity) { - DamageHandler.damageEntity(entity, 1D, ability); - ((LivingEntity) entity).setNoDamageTicks(0); - } - } - remove(); - } - } - - public static void updateAll() { - for (Entity entity : instances.keySet()) { - if (entity == null) { - instances.remove(entity); - continue; - } - instances.get(entity).update(); - } - } - - public void remove() { - remove(entity); - } - - public static void remove(Entity entity) { - if (instances.containsKey(entity)) { - instances.remove(entity); - } - } - - public static void removeAll() { - instances.clear(); - } - -} diff --git a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter.java deleted file mode 100644 index 45edae3..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import org.bukkit.Location; - -public interface ParticleAdapter { - void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha); - void displayMagneticParticles(Location location); -} diff --git a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapterFactory.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapterFactory.java deleted file mode 100644 index 50284b7..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapterFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import com.projectkorra.projectkorra.GeneralMethods; -import org.bukkit.Bukkit; - -public class ParticleAdapterFactory { - - private ParticleAdapter adapter; - - public ParticleAdapterFactory() { - int serverVersion = GeneralMethods.getMCVersion(); - - if (serverVersion >= 1205) { - Bukkit.getLogger().info("[JedCore] Using 1.20.5+ ParticleAdapter"); - adapter = new ParticleAdapter_1_20_5(); - } else { - Bukkit.getLogger().info("[JedCore] Using 1.20.4- ParticleAdapter"); - adapter = new ParticleAdapter_1_20_4(); - } - } - - public ParticleAdapter getAdapter() { - return adapter; - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_4.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_4.java deleted file mode 100644 index 4d29090..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_4.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import org.bukkit.*; - -public class ParticleAdapter_1_20_4 implements ParticleAdapter { - - @Override - public void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { - if (location.getWorld() == null) return; - int[] color = hexToRgb(hex); - if (alpha < 255) { - location.getWorld().spawnParticle(Particle.valueOf("SPELL_MOB_AMBIENT"), location, 0, color[0] / 255D, color[1] / 255D, color[2] / 255D, 1); - } else { - location.getWorld().spawnParticle(Particle.valueOf("SPELL_MOB"), location, 0, color[0] / 255D, color[1] / 255D, color[2] / 255D, 1); - } - } - - @Override - public void displayMagneticParticles(Location location) { - location.getWorld().spawnParticle(Particle.valueOf("ASH"), location, 1, 0, 0, 0, 0.03); - } - - private int[] hexToRgb(String hex) { - return new int[] { - Integer.valueOf(hex.substring(1, 3), 16), - Integer.valueOf(hex.substring(3, 5), 16), - Integer.valueOf(hex.substring(5, 7), 16) - }; - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_5.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_5.java deleted file mode 100644 index 0813924..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_5.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import org.bukkit.*; - -public class ParticleAdapter_1_20_5 implements ParticleAdapter { - - @Override - public void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { - if (location.getWorld() == null) return; - int[] color = hexToRgb(hex); - location.getWorld().spawnParticle(Particle.valueOf("ENTITY_EFFECT"), location, amount, extra, offsetX, offsetY, offsetZ, Color.fromARGB(alpha, color[0], color[1], color[2])); - } - - @Override - public void displayMagneticParticles(Location location) { - location.getWorld().spawnParticle(Particle.valueOf("MYCELIUM"), location, 1, 0, 0, 0, 0.01); - } - - private int[] hexToRgb(String hex) { - return new int[] { - Integer.valueOf(hex.substring(1, 3), 16), - Integer.valueOf(hex.substring(3, 5), 16), - Integer.valueOf(hex.substring(5, 7), 16) - }; - } -} diff --git a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter.java deleted file mode 100644 index f4fbb53..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionType; - -public interface PotionEffectAdapter { - PotionType getHarmingPotionType(); - PotionEffect getSlownessEffect(int duration, int strength); - PotionEffect getResistanceEffect(int duration, int strength); - PotionEffect getNauseaEffect(int duration); - void applyJumpBoost(Player player, int duration, int strength); - boolean hasWaterPotion(Inventory inventory); -} diff --git a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapterFactory.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapterFactory.java deleted file mode 100644 index e4b67c7..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapterFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import com.projectkorra.projectkorra.GeneralMethods; -import org.bukkit.Bukkit; - -public class PotionEffectAdapterFactory { - - private PotionEffectAdapter adapter; - - public PotionEffectAdapterFactory() { - int serverVersion = GeneralMethods.getMCVersion(); - - if (serverVersion >= 1205) { - Bukkit.getLogger().info("[JedCore] Using 1.20.5+ PotionEffectAdapter"); - adapter = new PotionEffectAdapter_1_20_5(); - } else { - Bukkit.getLogger().info("[JedCore] Using 1.20.4- PotionEffectAdapter"); - adapter = new PotionEffectAdapter_1_20_4(); - } - } - - public PotionEffectAdapter getAdapter() { - return adapter; - } -} diff --git a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_4.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_4.java deleted file mode 100644 index b79e91e..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_4.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.potion.PotionType; - -public class PotionEffectAdapter_1_20_4 implements PotionEffectAdapter { - - @Override - public PotionType getHarmingPotionType() { - return PotionType.valueOf("INSTANT_DAMAGE"); - } - - @Override - public PotionEffect getSlownessEffect(int duration, int strength) { - return new PotionEffect(PotionEffectType.getByName("SLOW"), duration / 50, strength); - } - - @Override - public PotionEffect getResistanceEffect(int duration, int strength) { - return new PotionEffect(PotionEffectType.getByName("DAMAGE_RESISTANCE"), duration / 50, strength - 1); - } - - @Override - public PotionEffect getNauseaEffect(int duration) { - return new PotionEffect(PotionEffectType.getByName("CONFUSION"), duration / 50, 1); - } - - @Override - public void applyJumpBoost(Player player, int duration, int strength) { - if (player.hasPotionEffect(PotionEffectType.getByName("JUMP"))) { - player.removePotionEffect(PotionEffectType.getByName("JUMP")); - } - player.addPotionEffect(new PotionEffect(PotionEffectType.getByName("JUMP"), duration / 50, strength - 1)); - } - - @Override - public boolean hasWaterPotion(Inventory inventory) { - if (inventory.contains(Material.POTION)) { - ItemStack item = inventory.getItem(inventory.first(Material.POTION)); - if (item == null) return false; - PotionMeta meta = (PotionMeta) item.getItemMeta(); - if (meta == null) return false; - - PotionType potionType = PotionMetaUtil.getPotionType(meta); - return potionType == PotionType.WATER; - } - return false; - } -} diff --git a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_5.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_5.java deleted file mode 100644 index 1ef51b1..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_5.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.potion.PotionType; - -public class PotionEffectAdapter_1_20_5 implements PotionEffectAdapter { - - @Override - public PotionType getHarmingPotionType() { - return PotionType.valueOf("HARMING"); - } - - @Override - public PotionEffect getSlownessEffect(int duration, int strength) { - return new PotionEffect(PotionEffectType.getByName("SLOWNESS"), duration / 50, strength - 1); - } - - @Override - public PotionEffect getResistanceEffect(int duration, int strength) { - return new PotionEffect(PotionEffectType.getByName("RESISTANCE"), duration / 50, strength - 1); - } - - @Override - public PotionEffect getNauseaEffect(int duration) { - return new PotionEffect(PotionEffectType.getByName("NAUSEA"), duration / 50, 1); - } - - @Override - public void applyJumpBoost(Player player, int duration, int strength) { - if (player.hasPotionEffect(PotionEffectType.getByName("JUMP_BOOST"))) { - player.removePotionEffect(PotionEffectType.getByName("JUMP_BOOST")); - } - player.addPotionEffect(new PotionEffect(PotionEffectType.getByName("JUMP_BOOST"), duration / 50, strength - 1)); - } - - @Override - public boolean hasWaterPotion(Inventory inventory) { - if (inventory.contains(Material.POTION)) { - ItemStack item = inventory.getItem(inventory.first(Material.POTION)); - if (item == null) return false; - PotionMeta meta = (PotionMeta) item.getItemMeta(); - if (meta == null) return false; - - PotionType potionType = PotionMetaUtil.getPotionType(meta); - return potionType == PotionType.WATER; - } - return false; - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/util/versionadapter/PotionMetaUtil.java b/src/com/jedk1/jedcore/util/versionadapter/PotionMetaUtil.java deleted file mode 100644 index 1d82431..0000000 --- a/src/com/jedk1/jedcore/util/versionadapter/PotionMetaUtil.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.jedk1.jedcore.util.versionadapter; - -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.PotionType; - -import java.lang.reflect.Method; - -public class PotionMetaUtil { - - public static PotionType getPotionType(PotionMeta meta) { - try { - Method getBasePotionType = PotionMeta.class.getMethod("getBasePotionType"); - return (PotionType) getBasePotionType.invoke(meta); - } catch (NoSuchMethodException e) { - try { - Method getBasePotionData = PotionMeta.class.getMethod("getBasePotionData"); - Object basePotionData = getBasePotionData.invoke(meta); - - Method getType = basePotionData.getClass().getMethod("getType"); - return (PotionType) getType.invoke(basePotionData); - } catch (Exception ex) { - ex.printStackTrace(); - } - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } -} \ No newline at end of file From d9d4b8f88ae7b24eb9364df7e4372723f24c1c49 Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 3 Aug 2025 19:15:58 -0700 Subject: [PATCH 47/61] Manually added all of the src files --- src/JCManager.java | 27 + src/JCMethods.java | 356 ++++++ src/JedCore.java | 175 +++ src/ability/airbending/AirBlade.java | 276 +++++ src/ability/airbending/AirBreath.java | 395 ++++++ src/ability/airbending/AirGlide.java | 259 ++++ src/ability/airbending/AirPunch.java | 296 +++++ src/ability/airbending/Meditate.java | 234 ++++ src/ability/airbending/SonicBlast.java | 221 ++++ src/ability/airbending/combo/AirSlam.java | 188 +++ src/ability/airbending/combo/SwiftStream.java | 197 +++ src/ability/avatar/SpiritBeam.java | 279 +++++ src/ability/avatar/elementsphere/ESAir.java | 223 ++++ src/ability/avatar/elementsphere/ESEarth.java | 219 ++++ src/ability/avatar/elementsphere/ESFire.java | 299 +++++ .../avatar/elementsphere/ESStream.java | 406 +++++++ src/ability/avatar/elementsphere/ESWater.java | 256 ++++ .../avatar/elementsphere/ElementSphere.java | 523 ++++++++ src/ability/chiblocking/Backstab.java | 114 ++ src/ability/chiblocking/DaggerThrow.java | 348 ++++++ src/ability/earthbending/EarthKick.java | 336 ++++++ src/ability/earthbending/EarthLine.java | 492 ++++++++ src/ability/earthbending/EarthPillar.java | 216 ++++ src/ability/earthbending/EarthShard.java | 274 +++++ src/ability/earthbending/EarthSurf.java | 503 ++++++++ src/ability/earthbending/Fissure.java | 441 +++++++ src/ability/earthbending/LavaDisc.java | 553 +++++++++ src/ability/earthbending/LavaFlux.java | 451 +++++++ src/ability/earthbending/LavaThrow.java | 344 ++++++ src/ability/earthbending/MagnetShield.java | 281 +++++ src/ability/earthbending/MetalArmor.java | 212 ++++ src/ability/earthbending/MetalFragments.java | 430 +++++++ src/ability/earthbending/MetalHook.java | 396 ++++++ src/ability/earthbending/MetalShred.java | 483 ++++++++ src/ability/earthbending/MudSurge.java | 654 ++++++++++ src/ability/earthbending/SandBlast.java | 377 ++++++ src/ability/earthbending/combo/Crevice.java | 370 ++++++ .../earthbending/combo/MagmaBlast.java | 615 ++++++++++ src/ability/firebending/Combustion.java | 629 ++++++++++ src/ability/firebending/Discharge.java | 347 ++++++ src/ability/firebending/FireBall.java | 308 +++++ src/ability/firebending/FireBreath.java | 427 +++++++ src/ability/firebending/FireComet.java | 465 +++++++ src/ability/firebending/FirePunch.java | 180 +++ src/ability/firebending/FireShots.java | 416 +++++++ src/ability/firebending/FireSki.java | 333 +++++ src/ability/firebending/LightningBurst.java | 370 ++++++ src/ability/passive/WallRun.java | 265 ++++ src/ability/waterbending/BloodPuppet.java | 511 ++++++++ src/ability/waterbending/BloodShot.java | 131 ++ src/ability/waterbending/Bloodbending.java | 377 ++++++ src/ability/waterbending/Drain.java | 605 ++++++++++ src/ability/waterbending/DrainBlast.java | 169 +++ src/ability/waterbending/FrostBreath.java | 440 +++++++ src/ability/waterbending/HealingWaters.java | 267 ++++ src/ability/waterbending/IceClaws.java | 299 +++++ src/ability/waterbending/IcePassive.java | 71 ++ src/ability/waterbending/combo/Maelstrom.java | 331 +++++ src/ability/waterbending/combo/WaterFlow.java | 728 +++++++++++ .../waterbending/combo/WaterGimbal.java | 649 ++++++++++ src/command/Commands.java | 9 + src/command/JedCoreCommand.java | 65 + src/configuration/Config.java | 67 ++ src/configuration/JedCoreConfig.java | 1069 +++++++++++++++++ .../SubsectionConfigurationDecorator.java | 668 ++++++++++ src/event/PKCommandEvent.java | 69 ++ src/listener/AbilityListener.java | 569 +++++++++ src/listener/CommandListener.java | 76 ++ src/listener/JCListener.java | 237 ++++ .../removal/CannotBendRemovalPolicy.java | 44 + .../removal/CompositeRemovalPolicy.java | 102 ++ src/policies/removal/IsDeadRemovalPolicy.java | 21 + .../removal/IsOfflineRemovalPolicy.java | 21 + .../removal/OutOfRangeRemovalPolicy.java | 37 + src/policies/removal/RemovalPolicy.java | 11 + .../removal/SwappedSlotsRemovalPolicy.java | 26 + src/util/AbilitySelector.java | 54 + src/util/AirShieldReflector.java | 28 + src/util/BlockUtil.java | 19 + src/util/ChiRestrictor.java | 136 +++ src/util/CollisionInitializer.java | 96 ++ src/util/FireTick.java | 65 + src/util/LightManager.java | 443 +++++++ src/util/MaterialUtil.java | 48 + src/util/MetricsLite.java | 535 +++++++++ src/util/PaperLib.java | 96 ++ src/util/RegenTempBlock.java | 193 +++ src/util/TempFallingBlock.java | 151 +++ src/util/TemporaryFallingBlock.java | 29 + src/util/ThreadUtil.java | 209 ++++ src/util/ThrownEntityTracker.java | 93 ++ src/util/versionadapter/ParticleAdapter.java | 8 + .../ParticleAdapterFactory.java | 25 + .../ParticleAdapter_1_20_4.java | 30 + .../ParticleAdapter_1_20_5.java | 26 + .../versionadapter/PotionEffectAdapter.java | 15 + .../PotionEffectAdapterFactory.java | 25 + .../PotionEffectAdapter_1_20_4.java | 55 + .../PotionEffectAdapter_1_20_5.java | 55 + src/util/versionadapter/PotionMetaUtil.java | 29 + 100 files changed, 26591 insertions(+) create mode 100644 src/JCManager.java create mode 100644 src/JCMethods.java create mode 100644 src/JedCore.java create mode 100644 src/ability/airbending/AirBlade.java create mode 100644 src/ability/airbending/AirBreath.java create mode 100644 src/ability/airbending/AirGlide.java create mode 100644 src/ability/airbending/AirPunch.java create mode 100644 src/ability/airbending/Meditate.java create mode 100644 src/ability/airbending/SonicBlast.java create mode 100644 src/ability/airbending/combo/AirSlam.java create mode 100644 src/ability/airbending/combo/SwiftStream.java create mode 100644 src/ability/avatar/SpiritBeam.java create mode 100644 src/ability/avatar/elementsphere/ESAir.java create mode 100644 src/ability/avatar/elementsphere/ESEarth.java create mode 100644 src/ability/avatar/elementsphere/ESFire.java create mode 100644 src/ability/avatar/elementsphere/ESStream.java create mode 100644 src/ability/avatar/elementsphere/ESWater.java create mode 100644 src/ability/avatar/elementsphere/ElementSphere.java create mode 100644 src/ability/chiblocking/Backstab.java create mode 100644 src/ability/chiblocking/DaggerThrow.java create mode 100644 src/ability/earthbending/EarthKick.java create mode 100644 src/ability/earthbending/EarthLine.java create mode 100644 src/ability/earthbending/EarthPillar.java create mode 100644 src/ability/earthbending/EarthShard.java create mode 100644 src/ability/earthbending/EarthSurf.java create mode 100644 src/ability/earthbending/Fissure.java create mode 100644 src/ability/earthbending/LavaDisc.java create mode 100644 src/ability/earthbending/LavaFlux.java create mode 100644 src/ability/earthbending/LavaThrow.java create mode 100644 src/ability/earthbending/MagnetShield.java create mode 100644 src/ability/earthbending/MetalArmor.java create mode 100644 src/ability/earthbending/MetalFragments.java create mode 100644 src/ability/earthbending/MetalHook.java create mode 100644 src/ability/earthbending/MetalShred.java create mode 100644 src/ability/earthbending/MudSurge.java create mode 100644 src/ability/earthbending/SandBlast.java create mode 100644 src/ability/earthbending/combo/Crevice.java create mode 100644 src/ability/earthbending/combo/MagmaBlast.java create mode 100644 src/ability/firebending/Combustion.java create mode 100644 src/ability/firebending/Discharge.java create mode 100644 src/ability/firebending/FireBall.java create mode 100644 src/ability/firebending/FireBreath.java create mode 100644 src/ability/firebending/FireComet.java create mode 100644 src/ability/firebending/FirePunch.java create mode 100644 src/ability/firebending/FireShots.java create mode 100644 src/ability/firebending/FireSki.java create mode 100644 src/ability/firebending/LightningBurst.java create mode 100644 src/ability/passive/WallRun.java create mode 100644 src/ability/waterbending/BloodPuppet.java create mode 100644 src/ability/waterbending/BloodShot.java create mode 100644 src/ability/waterbending/Bloodbending.java create mode 100644 src/ability/waterbending/Drain.java create mode 100644 src/ability/waterbending/DrainBlast.java create mode 100644 src/ability/waterbending/FrostBreath.java create mode 100644 src/ability/waterbending/HealingWaters.java create mode 100644 src/ability/waterbending/IceClaws.java create mode 100644 src/ability/waterbending/IcePassive.java create mode 100644 src/ability/waterbending/combo/Maelstrom.java create mode 100644 src/ability/waterbending/combo/WaterFlow.java create mode 100644 src/ability/waterbending/combo/WaterGimbal.java create mode 100644 src/command/Commands.java create mode 100644 src/command/JedCoreCommand.java create mode 100644 src/configuration/Config.java create mode 100644 src/configuration/JedCoreConfig.java create mode 100644 src/configuration/SubsectionConfigurationDecorator.java create mode 100644 src/event/PKCommandEvent.java create mode 100644 src/listener/AbilityListener.java create mode 100644 src/listener/CommandListener.java create mode 100644 src/listener/JCListener.java create mode 100644 src/policies/removal/CannotBendRemovalPolicy.java create mode 100644 src/policies/removal/CompositeRemovalPolicy.java create mode 100644 src/policies/removal/IsDeadRemovalPolicy.java create mode 100644 src/policies/removal/IsOfflineRemovalPolicy.java create mode 100644 src/policies/removal/OutOfRangeRemovalPolicy.java create mode 100644 src/policies/removal/RemovalPolicy.java create mode 100644 src/policies/removal/SwappedSlotsRemovalPolicy.java create mode 100644 src/util/AbilitySelector.java create mode 100644 src/util/AirShieldReflector.java create mode 100644 src/util/BlockUtil.java create mode 100644 src/util/ChiRestrictor.java create mode 100644 src/util/CollisionInitializer.java create mode 100644 src/util/FireTick.java create mode 100644 src/util/LightManager.java create mode 100644 src/util/MaterialUtil.java create mode 100644 src/util/MetricsLite.java create mode 100644 src/util/PaperLib.java create mode 100644 src/util/RegenTempBlock.java create mode 100644 src/util/TempFallingBlock.java create mode 100644 src/util/TemporaryFallingBlock.java create mode 100644 src/util/ThreadUtil.java create mode 100644 src/util/ThrownEntityTracker.java create mode 100644 src/util/versionadapter/ParticleAdapter.java create mode 100644 src/util/versionadapter/ParticleAdapterFactory.java create mode 100644 src/util/versionadapter/ParticleAdapter_1_20_4.java create mode 100644 src/util/versionadapter/ParticleAdapter_1_20_5.java create mode 100644 src/util/versionadapter/PotionEffectAdapter.java create mode 100644 src/util/versionadapter/PotionEffectAdapterFactory.java create mode 100644 src/util/versionadapter/PotionEffectAdapter_1_20_4.java create mode 100644 src/util/versionadapter/PotionEffectAdapter_1_20_5.java create mode 100644 src/util/versionadapter/PotionMetaUtil.java diff --git a/src/JCManager.java b/src/JCManager.java new file mode 100644 index 0000000..5fda987 --- /dev/null +++ b/src/JCManager.java @@ -0,0 +1,27 @@ +package com.jedk1.jedcore; + +import org.bukkit.Bukkit; + + import com.jedk1.jedcore.ability.firebending.LightningBurst; + import com.jedk1.jedcore.ability.waterbending.HealingWaters; + import com.jedk1.jedcore.ability.waterbending.IcePassive; + import com.jedk1.jedcore.util.RegenTempBlock; + +public class JCManager implements Runnable { + + public JedCore plugin; + + public JCManager(JedCore plugin) { + this.plugin = plugin; + } + + public void run() { + LightningBurst.progressAll(); + + HealingWaters.heal(Bukkit.getServer()); + IcePassive.handleSkating(); +// IceWall.progressAll(); + + RegenTempBlock.manage(); + } +} \ No newline at end of file diff --git a/src/JCMethods.java b/src/JCMethods.java new file mode 100644 index 0000000..d1a802f --- /dev/null +++ b/src/JCMethods.java @@ -0,0 +1,356 @@ +package com.jedk1.jedcore; + +import java.util.*; + +import com.jedk1.jedcore.util.*; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.region.RegionProtection; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ProjectKorra; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager; +import com.projectkorra.projectkorra.util.TempBlock; + +public class JCMethods { + + // todo: either use PKs isPlant or the registry/tags (with config) + private static final ArrayList SMALL_PLANTS = new ArrayList(){{ + addAll(Arrays.asList(Material.GRASS, Material.FERN, Material.POPPY, Material.DANDELION, Material.OAK_SAPLING, + Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, + Material.DARK_OAK_SAPLING, Material.ALLIUM, Material.ORANGE_TULIP, Material.PINK_TULIP, Material.RED_TULIP, + Material.WHITE_TULIP, Material.ROSE_BUSH, Material.BLUE_ORCHID, Material.LILAC, Material.OXEYE_DAISY, + Material.AZURE_BLUET, Material.PEONY, Material.SUNFLOWER, Material.LARGE_FERN, Material.RED_MUSHROOM, + Material.BROWN_MUSHROOM, Material.PUMPKIN_STEM, Material.MELON_STEM, Material.WHEAT, Material.TALL_GRASS, + Material.BEETROOTS, Material.CARROTS, Material.POTATOES, Material.CRIMSON_FUNGUS, Material.WARPED_FUNGUS, + Material.BAMBOO, Material.BAMBOO_SAPLING)); + + int serverVersion = GeneralMethods.getMCVersion(); + if (serverVersion >= 1170) { + add(Material.getMaterial("AZALEA")); + add(Material.getMaterial("FLOWERING_AZALEA")); + add(Material.getMaterial("FLOWERING_AZALEA_LEAVES")); + add(Material.getMaterial("AZALEA_LEAVES")); + add(Material.getMaterial("BIG_DRIPLEAF")); + add(Material.getMaterial("BIG_DRIPLEAF_STEM")); + add(Material.getMaterial("SMALL_DRIPLEAF")); + add(Material.getMaterial("HANGING_ROOTS")); + add(Material.getMaterial("GLOW_LICHEN")); + add(Material.getMaterial("CAVE_VINES")); + add(Material.getMaterial("CAVE_VINES_PLANT")); + } + }}; + + private static List worlds = new ArrayList<>(); + private static List combos = new ArrayList<>(); + + public static List getDisabledWorlds() { + return JCMethods.worlds; + } + + public static void registerDisabledWorlds() { + worlds.clear(); + List registeredworlds = ProjectKorra.plugin.getConfig().getStringList("Properties.DisabledWorlds"); + if (!registeredworlds.isEmpty()) { + worlds.addAll(registeredworlds); + } + } + + public static boolean isDisabledWorld(World world) { + return getDisabledWorlds().contains(world.getName()); + } + + public static List getCombos() { + return JCMethods.combos; + } + + public static void registerCombos() { + combos.clear(); + combos.addAll(ComboManager.getComboAbilities().keySet()); + } + + /** + * Gets the points of a line between two points. + * @param startLoc + * @param endLoc + * @param points + * @return locations + */ + public static List getLinePoints(Location startLoc, Location endLoc, int points){ + List locations = new ArrayList(); + Location diff = endLoc.subtract(startLoc); + double diffX = diff.getX() / points; + double diffY = diff.getY() / points; + double diffZ = diff.getZ() / points; + Location loc = startLoc; + for(int i = 0; i < points; i++){ + loc.add(new Location(startLoc.getWorld(), diffX, diffY, diffZ)); + locations.add(loc.clone()); + } + return locations; + } + + public static List getCirclePoints(Location location, int points, double size) { + return getCirclePoints(location, points, size, 0); + } + + /** + * Gets points in a circle. + * @param location + * @param points + * @param size + * @return + */ + public static List getCirclePoints(Location location, int points, double size, double startangle){ + List locations = new ArrayList(); + for(int i = 0; i < 360; i += 360/points){ + double angle = (i * Math.PI / 180); + double x = size * Math.cos(angle + startangle); + double z = size * Math.sin(angle + startangle); + Location loc = location.clone(); + loc.add(x, 0, z); + locations.add(loc); + } + return locations; + } + + /** + * Gets points in a vertical circle. + * @param location + * @param points + * @param size + * @param yawOffset + * @return + */ + public static List getVerticalCirclePoints(Location location, int points, double size, float yawOffset) { + List locations = new ArrayList<>(); + Location fakeLoc = location.clone(); + fakeLoc.setPitch(0); + fakeLoc.setYaw(yawOffset); + Vector direction = fakeLoc.getDirection(); + + for(double j = -180; j <= 180; j += points){ + Location tempLoc = fakeLoc.clone(); + Vector newDir = direction.clone().multiply(size * Math.cos(Math.toRadians(j))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + size + (size * Math.sin(Math.toRadians(j)))); + locations.add(tempLoc.clone()); + } + return locations; + } + + /** + * Remove an item from a players inventory. + * @param player + * @param material + * @param amount + * @return + */ + public static boolean removeItemFromInventory(Player player, Material material, int amount) { + for (ItemStack item : player.getInventory().getContents()) { + if (item != null && item.getType() == material) { + if (item.getAmount() == amount) { + Map remaining = player.getInventory().removeItem(item); + + if (!remaining.isEmpty()) { + ItemStack offhand = player.getInventory().getItemInOffHand(); + + // Spigot seems to not handle offhand correctly with removeItem, so try to manually remove it. + if (offhand != null && offhand.getType() == material && offhand.getAmount() == amount) { + player.getInventory().setItemInOffHand(null); + } + } + } else if (item.getAmount() > amount) { + item.setAmount(item.getAmount() - amount); + } + + return true; + } + } + + return false; + } + + /** + * Gets points in a spiral shape. + * @param location + * @param points + * @param spiralCount + * @param startAngle + * @param startSize + * @param finalSize + * @param noClip + * @return + */ + public static List getSpiralPoints(Location location, int points, int spiralCount, int startAngle, double startSize, double finalSize, boolean noClip){ + return getSpiralPoints(location, points, spiralCount, 0.0D, startAngle, startSize, finalSize, noClip); + } + + /** + * Gets points in a vertical spiral shape, could be used for a tornado. + * @param location + * @param points + * @param spiralCount + * @param height + * @param startAngle + * @param startSize + * @param finalSize + * @param noClip + * @return + */ + public static List getSpiralPoints(Location location, int points, int spiralCount, double height, int startAngle, double startSize, double finalSize, boolean noClip){ + List locations = new ArrayList(); + + points = points/spiralCount; + double sizeIncr = ((finalSize - startSize) / points)/spiralCount; + double hightIncr = (height/points)/spiralCount; + double size = startSize; + for(int i = 0; i < spiralCount; i++){ + for(int j = 0; j < 360; j += 360/points){ + hightIncr = hightIncr + ((height/points)/spiralCount); + size = size + sizeIncr; + double angle = (j * Math.PI / 180); + double x = size * Math.cos(angle + startAngle); + double z = size * Math.sin(angle + startAngle); + Location loc = location.clone(); + loc.add(x, hightIncr, z); + if(!noClip && ElementalAbility.isAir(loc.getBlock().getType())) + locations.add(loc); + else if(noClip) + locations.add(loc); + } + } + + return locations; + } + + public static void extinguishBlocks(Player player, String ability, int range, int radius, boolean fire, boolean lava){ + for (Block block : GeneralMethods.getBlocksAroundPoint(player.getTargetBlock(null, range).getLocation(), radius)) { + Material mat = block.getType(); + if(mat != Material.FIRE && mat != Material.LAVA && mat != Material.SOUL_FIRE) + continue; + if (RegionProtection.isRegionProtected(player, block.getLocation(), ability)) + continue; + if (((mat == Material.FIRE || mat == Material.SOUL_FIRE) && fire)||(mat == Material.LAVA && lava)) { + block.setType(mat != Material.LAVA ? Material.AIR : isLiquidSource(block) ? Material.OBSIDIAN : Material.COBBLESTONE); + block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0); + } + } + } + + /** + * Checks if 3 blocks around the block are of the required type. + * @param block + * @param type + * @return + */ + public static boolean isAdjacentToThreeOrMoreSources(Block block, Material type) { + if (TempBlock.isTempBlock(block)) { + return false; + } + int sources = 0; + BlockFace[] faces = { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN }; + for (BlockFace face : faces) { + Block blocki = block.getRelative(face); + if ((blocki.getType() == type)) { + sources++; + } + } + if (sources >= 2) + return true; + return false; + } + + static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, + Material.NETHER_PORTAL, Material.END_PORTAL, + Material.END_PORTAL_FRAME, Material.OBSIDIAN}; + + public static boolean isUnbreakable(Block block) { + if (block.getState() instanceof InventoryHolder) { + return true; + } + if (Arrays.asList(unbreakables).contains(block.getType())) + return true; + return false; + } + + public static boolean isLiquidSource(Block block) { + if (!block.isLiquid()) { + return false; + } + + if (!(block.getBlockData() instanceof Levelled)) { + return false; + } + + Levelled levelData = (Levelled) block.getBlockData(); + + return levelData.getLevel() == 0; + } + + // TODO: Should this be reimplemented or has the rpg plugin been abandoned? + public static boolean isSozinsComet(World world) { + return false; + } + + // TODO: Should this be reimplemented or has the rpg plugin been abandoned? + public static boolean isLunarEclipse(World world) { + return false; + } + + // todo: see SMALL_PLANTS + public static boolean isDoublePlant(Material material) { + return material == Material.SUNFLOWER || material == Material.LILAC || material == Material.TALL_GRASS || + material == Material.LARGE_FERN || material == Material.ROSE_BUSH || material == Material.PEONY; + } + + public static boolean isSmallPlant(Block block) { + return isSmallPlant(block.getType()); + } + + public static boolean isSmallPlant(Material material) { + return WaterAbility.isPlant(material); + //return SMALL_PLANTS.contains(material); + } + + public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra) { + displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, 255); + } + + public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { + JedCore.plugin.getParticleAdapter().displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, alpha); + } + + public static void emitLight(Location loc) { + ConfigurationSection config = JedCoreConfig.getConfig((Player)null); + if (config.getBoolean("Properties.Fire.DynamicLight.Enabled")) { + int brightness = config.getInt("Properties.Fire.DynamicLight.Brightness"); + long keepAlive = config.getLong("Properties.Fire.DynamicLight.KeepAlive"); + + LightManager.createLight(loc).brightness(brightness).timeUntilFadeout(keepAlive).emit(); + } + } + + public static void reload() { + JedCore.log.info("JedCore Reloaded."); + JedCore.plugin.reloadConfig(); + JedCore.logDebug = JedCoreConfig.getConfig((World)null).getBoolean("Properties.LogDebug"); + CoreAbility.registerPluginAbilities(JedCore.plugin, "com.jedk1.jedcore.ability"); + registerDisabledWorlds(); + registerCombos(); + RegenTempBlock.revertAll(); + JedCore.plugin.initializeCollisions(); + FireTick.loadMethod(); + } +} diff --git a/src/JedCore.java b/src/JedCore.java new file mode 100644 index 0000000..dfebb83 --- /dev/null +++ b/src/JedCore.java @@ -0,0 +1,175 @@ +package com.jedk1.jedcore; + +import java.io.IOException; +import java.util.logging.*; + +import com.google.common.reflect.ClassPath; +import com.jedk1.jedcore.ability.waterbending.BloodShot; +import com.jedk1.jedcore.command.Commands; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.listener.AbilityListener; +import com.jedk1.jedcore.listener.CommandListener; +import com.jedk1.jedcore.listener.JCListener; +import com.jedk1.jedcore.util.*; +import com.jedk1.jedcore.util.versionadapter.ParticleAdapter; +import com.jedk1.jedcore.util.versionadapter.ParticleAdapterFactory; +import com.jedk1.jedcore.util.versionadapter.PotionEffectAdapter; +import com.jedk1.jedcore.util.versionadapter.PotionEffectAdapterFactory; +import com.projectkorra.projectkorra.ability.CoreAbility; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.plugin.java.JavaPlugin; + +public class JedCore extends JavaPlugin { + + public static JedCore plugin; + public static Logger log; + public static String dev; + public static String version; + public static boolean logDebug; + public static boolean isFolia; + public static boolean luminol; + public static boolean paper; + + private ParticleAdapter particleAdapter; + private PotionEffectAdapter potionEffectAdapter; + + @Override + public void onEnable() { + plugin = this; + log = this.getLogger(); + new JedCoreConfig(this); + + logDebug = JedCoreConfig.getConfig((World) null).getBoolean("Properties.LogDebug"); + + dev = this.getDescription().getAuthors().toString().replace("[", "").replace("]", ""); + version = this.getDescription().getVersion(); + + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + isFolia = true; + } catch (ClassNotFoundException ignored) {} + + try { + Class.forName("com.destroystokyo.paper.PaperConfig"); + paper = true; + } catch (ClassNotFoundException ignored) {} + + try { + Class.forName("me.earthme.luminol.api.ThreadedRegion"); + luminol = true; + } catch (ClassNotFoundException ignored) {} + + if (isFolia) { + if (Bukkit.getVersion().contains("Folia")) { + getLogger().info("Server is running on Folia"); + } + } + + if (paper) { + if (Bukkit.getVersion().contains("Paper")) { + getLogger().info("Server is running on Paper"); + } + } + + if (luminol) { + if (Bukkit.getVersion().contains("Luminol")) { + getLogger().info("Server is running on Luminol"); + } + } + + JCMethods.registerDisabledWorlds(); + CoreAbility.registerPluginAbilities(this, "com.jedk1.jedcore.ability"); + + getServer().getPluginManager().registerEvents(new AbilityListener(this), this); + getServer().getPluginManager().registerEvents(new CommandListener(this), this); + getServer().getPluginManager().registerEvents(new JCListener(this), this); + getServer().getPluginManager().registerEvents(new ChiRestrictor(), this); + + // Repeating logic task - uses ThreadUtil + ThreadUtil.runSyncTimer(new JCManager(this), 0L, 1L); + + new Commands(); + FireTick.loadMethod(); + + particleAdapter = new ParticleAdapterFactory().getAdapter(); + potionEffectAdapter = new PotionEffectAdapterFactory().getAdapter(); + + // Delayed combo/collision init + ThreadUtil.runSyncLater(() -> { + JCMethods.registerCombos(); + initializeCollisions(); + }, 1L); + + + // Optional Metrics - disabled on Folia-like servers + if (!isFolia) { + try { + MetricsLite metrics = new MetricsLite(this); + metrics.start(); + log.info("Initialized Metrics."); + } catch (IOException e) { + log.info("Failed to submit statistics for MetricsLite."); + } + } else { + log.info("Skipping MetricsLite: incompatible with Folia/Luminol."); + } + } + + public void initializeCollisions() { + boolean enabled = getConfig().getBoolean("Properties.AbilityCollisions.Enabled"); + if (!enabled) { + getLogger().info("Collisions disabled."); + return; + } + + try { + ClassPath cp = ClassPath.from(this.getClassLoader()); + + for (ClassPath.ClassInfo info : cp.getTopLevelClassesRecursive("com.jedk1.jedcore.ability")) { + try { + @SuppressWarnings("unchecked") + Class abilityClass = (Class) Class.forName(info.getName()); + if (abilityClass == null) continue; + + CollisionInitializer initializer = new CollisionInitializer<>(abilityClass); + initializer.initialize(); + } catch (Exception ignored) {} + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void onDisable() { + RegenTempBlock.revertAll(); + } + + public static void logDebug(String message) { + if (logDebug) { + plugin.getLogger().info(message); + } + } + + public ParticleAdapter getParticleAdapter() { + return particleAdapter; + } + + public PotionEffectAdapter getPotionEffectAdapter() { + return potionEffectAdapter; + } + + public static boolean isFolia() { + return isFolia; + } + + public static boolean isPaper() { + return paper; + } + + public static boolean isLuminol() { + return luminol; + } +} diff --git a/src/ability/airbending/AirBlade.java b/src/ability/airbending/AirBlade.java new file mode 100644 index 0000000..f0a6d9b --- /dev/null +++ b/src/ability/airbending/AirBlade.java @@ -0,0 +1,276 @@ +package com.jedk1.jedcore.ability.airbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + +public class AirBlade extends AirAbility implements AddonAbility { + + private Location location; + private Vector direction; + private double travelled; + + @Attribute("Growth") + private double growth = 1; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute("CollisionRadius") + private double entityCollisionRadius; + + public AirBlade(Player player) { + super(player); + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + this.location = player.getEyeLocation().clone(); + this.direction = player.getEyeLocation().getDirection().clone(); + + start(); + if (!isRemoved()) + bPlayer.addCooldown(this); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Air.AirBlade.Cooldown"); + range = config.getDouble("Abilities.Air.AirBlade.Range"); + damage = config.getDouble("Abilities.Air.AirBlade.Damage"); + entityCollisionRadius = config.getDouble("Abilities.Air.AirBlade.EntityCollisionRadius"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (travelled >= range) { + remove(); + return; + } + + progressBlade(); + } + + private void progressBlade() { + for (int j = 0; j < 2; j++) { + if (!moveAndCheckCollision()) { + return; + } + + double pitch = -location.getPitch(); + Location lastLoc = location.clone(); + + for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { + Location tempLoc = calculateParticleLocation(i); + playAirbendingParticles(tempLoc, 1, (float) Math.random() / 2, (float) Math.random() / 2, (float) Math.random() / 2); + + if (j == 0 && !lastLoc.getBlock().getLocation().equals(tempLoc.getBlock().getLocation())) { + if (handleEntityCollision(tempLoc)) { + return; + } + lastLoc = tempLoc; + } + } + } + } + + private boolean moveAndCheckCollision() { + location = location.add(direction.multiply(1)); + playAirbendingSound(location); + travelled++; + growth += 0.125; + + if (travelled >= range || + !isTransparent(location.getBlock()) || + RegionProtection.isRegionProtected(player, player.getLocation(), this)) { + remove(); + return false; + } + return true; + } + + private Location calculateParticleLocation(double angle) { + Location tempLoc = location.clone(); + tempLoc.setPitch(0); + Vector tempDir = tempLoc.getDirection().clone(); + tempDir.setY(0); + Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(angle))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(angle)))); + return tempLoc; + } + + private boolean handleEntityCollision(Location tempLoc) { + boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), entity -> { + DamageHandler.damageEntity(entity, damage, this); + remove(); + return true; + }); + if (hit) { + remove(); + return true; + } + return false; + } + + @Override + public Player getPlayer() { + return player; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public List getLocations() { + List locations = new ArrayList<>(); + + double pitch = -location.getPitch(); + + for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { + Location tempLoc = location.clone(); + tempLoc.setPitch(0); + + Vector tempDir = tempLoc.getDirection().clone(); + tempDir.setY(0); + + Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(i))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(i)))); + + locations.add(tempLoc); + } + + return locations; + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Air.AirBlade.AbilityCollisionRadius"); + } + + public long getCooldown() { + return cooldown; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + @Override + public String getName() { + return "AirBlade"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirBlade.Description"); + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getTravelled() { + return travelled; + } + + public void setTravelled(double travelled) { + this.travelled = travelled; + } + + public double getGrowth() { + return growth; + } + + public void setGrowth(double growth) { + this.growth = growth; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.AirBlade.Enabled"); + } +} diff --git a/src/ability/airbending/AirBreath.java b/src/ability/airbending/AirBreath.java new file mode 100644 index 0000000..497af20 --- /dev/null +++ b/src/ability/airbending/AirBreath.java @@ -0,0 +1,395 @@ +package com.jedk1.jedcore.ability.airbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +public class AirBreath extends AirAbility implements AddonAbility { + + private int particles; + private boolean coolLava; + private boolean extinguishFire; + private boolean extinguishMobs; + private boolean damageEnabled; + private double launch; + private boolean regenOxygen; + private boolean avatarAmplify; + private int avatarRange; + private double avatarKnockback; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.DAMAGE) + private double playerDamage; + @Attribute(Attribute.DAMAGE) + private double mobDamage; + @Attribute(Attribute.KNOCKBACK) + private double knockback; + @Attribute(Attribute.RANGE) + private int range; + + public AirBreath(Player player) { + super(player); + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + if (bPlayer.isAvatarState() && avatarAmplify) { + range = avatarRange; + knockback = avatarKnockback; + } + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Air.AirBreath.Cooldown"); + duration = config.getLong("Abilities.Air.AirBreath.Duration"); + particles = config.getInt("Abilities.Air.AirBreath.Particles"); + coolLava = config.getBoolean("Abilities.Air.AirBreath.AffectBlocks.Lava"); + extinguishFire = config.getBoolean("Abilities.Air.AirBreath.AffectBlocks.Fire"); + extinguishMobs = config.getBoolean("Abilities.Air.AirBreath.ExtinguishEntities"); + damageEnabled = config.getBoolean("Abilities.Air.AirBreath.Damage.Enabled"); + playerDamage = config.getDouble("Abilities.Air.AirBreath.Damage.Player"); + mobDamage = config.getDouble("Abilities.Air.AirBreath.Damage.Mob"); + knockback = config.getDouble("Abilities.Air.AirBreath.Knockback"); + range = config.getInt("Abilities.Air.AirBreath.Range"); + launch = config.getDouble("Abilities.Air.AirBreath.LaunchPower"); + regenOxygen = config.getBoolean("Abilities.Air.AirBreath.RegenTargetOxygen"); + avatarAmplify = config.getBoolean("Abilities.Air.AirBreath.Avatar.Enabled"); + avatarRange = config.getInt("Abilities.Air.AirBreath.Avatar.Range"); + avatarKnockback = config.getDouble("Abilities.Air.AirBreath.Avatar.Knockback"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!(bPlayer.getBoundAbility() instanceof AirBreath)) { + bPlayer.addCooldown(this); + remove(); + return; + } + + if (!player.isSneaking()) { + bPlayer.addCooldown(this); + remove(); + return; + } + + if (System.currentTimeMillis() < getStartTime() + duration) { + playAirbendingSound(player.getLocation()); + createBeam(); + } else { + bPlayer.addCooldown(this); + remove(); + } + } + + private boolean isLocationSafe(Location loc) { + Block block = loc.getBlock(); + + if (RegionProtection.isRegionProtected(player, loc, this)) { + return false; + } + + return isTransparent(block); + } + + private void createBeam() { + Location loc = player.getEyeLocation(); + Vector dir = player.getLocation().getDirection(); + double step = 1; + double size = 0; + double damageregion = 1.5; + + for (double i = 0; i < range; i += step) { + loc = loc.add(dir.clone().multiply(step)); + size += 0.005; + damageregion += 0.01; + + if (!handleLocationSafety(loc)) { + return; + } + + handleEntityCollisions(loc, dir, damageregion); + displayBeamParticles(loc, size); + handleBlockEffects(); + } + } + + private boolean handleLocationSafety(Location loc) { + if (!isLocationSafe(loc)) { + if (!isTransparent(loc.getBlock()) && player.getLocation().getPitch() > 30) { + GeneralMethods.setVelocity(this, player, player.getLocation().getDirection().multiply(-launch)); + } + return false; + } + return true; + } + + private void handleEntityCollisions(Location loc, Vector dir, double damageregion) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageregion)) { + if (isValidTarget(entity)) { + if (isEntityProtected(entity)) { + continue; + } + applyEntityEffects(entity, dir); + } + } + } + + private boolean isValidTarget(Entity entity) { + return entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand); + } + + private boolean isEntityProtected(Entity entity) { + return RegionProtection.isRegionProtected(this, entity.getLocation()) || (entity instanceof Player && Commands.invincible.contains(entity.getName())); + } + + private void applyEntityEffects(Entity entity, Vector dir) { + if (entity instanceof LivingEntity livingEntity) { + applyDamage(livingEntity); + applyOxygenRegen(livingEntity); + if (extinguishMobs) { + livingEntity.setFireTicks(0); + } + } + dir.multiply(knockback); + GeneralMethods.setVelocity(this, entity, dir); + } + + private void applyDamage(LivingEntity entity) { + if (damageEnabled) { + if (entity instanceof Player) { + DamageHandler.damageEntity(entity, playerDamage, this); + } else { + DamageHandler.damageEntity(entity, mobDamage, this); + } + } + } + + private void applyOxygenRegen(LivingEntity entity) { + if (regenOxygen && isWater(entity.getLocation().getBlock()) && !entity.hasPotionEffect(PotionEffectType.WATER_BREATHING)) { + entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 100, 2)); + } + } + + private void displayBeamParticles(Location loc, double size) { + if (isWater(loc.getBlock())) { + ParticleEffect.WATER_BUBBLE.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + } + + ParticleEffect mainParticle = getAirbendingParticles(); + if (mainParticle == ParticleEffect.CLOUD) { + ParticleEffect.CLOUD.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + JCMethods.displayColoredParticles("#FFFFFF", loc, particles, Math.random(), Math.random(), Math.random(), 0f); + JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particles, Math.random(), Math.random(), Math.random(), size, 50); + } else if (mainParticle != null) { + mainParticle.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + } + } + + private void handleBlockEffects() { + JCMethods.extinguishBlocks(player, "AirBreath", range, 2, extinguishFire, coolLava); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return player.getEyeLocation(); + } + + @Override + public String getName() { + return "AirBreath"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirBreath.Description"); + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public int getParticles() { + return particles; + } + + public void setParticles(int particles) { + this.particles = particles; + } + + public boolean isCoolLava() { + return coolLava; + } + + public void setCoolLava(boolean coolLava) { + this.coolLava = coolLava; + } + + public boolean canExtinguishFire() { + return extinguishFire; + } + + public void setExtinguishFire(boolean extinguishFire) { + this.extinguishFire = extinguishFire; + } + + public boolean canExtinguishMobs() { + return extinguishMobs; + } + + public void setExtinguishMobs(boolean extinguishMobs) { + this.extinguishMobs = extinguishMobs; + } + + public boolean isDamageEnabled() { + return damageEnabled; + } + + public void setDamageEnabled(boolean damageEnabled) { + this.damageEnabled = damageEnabled; + } + + public double getPlayerDamage() { + return playerDamage; + } + + public void setPlayerDamage(double playerDamage) { + this.playerDamage = playerDamage; + } + + public double getMobDamage() { + return mobDamage; + } + + public void setMobDamage(double mobDamage) { + this.mobDamage = mobDamage; + } + + public double getKnockback() { + return knockback; + } + + public void setKnockback(double knockback) { + this.knockback = knockback; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public double getLaunch() { + return launch; + } + + public void setLaunch(double launch) { + this.launch = launch; + } + + public boolean canRegenOxygen() { + return regenOxygen; + } + + public void setRegenOxygen(boolean regenOxygen) { + this.regenOxygen = regenOxygen; + } + + public boolean isAvatarAmplify() { + return avatarAmplify; + } + + public void setAvatarAmplify(boolean avatarAmplify) { + this.avatarAmplify = avatarAmplify; + } + + public int getAvatarRange() { + return avatarRange; + } + + public void setAvatarRange(int avatarRange) { + this.avatarRange = avatarRange; + } + + public double getAvatarKnockback() { + return avatarKnockback; + } + + public void setAvatarKnockback(double avatarKnockback) { + this.avatarKnockback = avatarKnockback; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.AirBreath.Enabled"); + } +} diff --git a/src/ability/airbending/AirGlide.java b/src/ability/airbending/AirGlide.java new file mode 100644 index 0000000..77c0b1d --- /dev/null +++ b/src/ability/airbending/AirGlide.java @@ -0,0 +1,259 @@ +package com.jedk1.jedcore.ability.airbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.airbending.AirSpout; +import com.projectkorra.projectkorra.attribute.Attribute; +import org.bukkit.Location; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class AirGlide extends AirAbility implements AddonAbility { + + private double fallSpeed; + private int particles; + private boolean airspout; + private long lastCooldown; + private boolean progressing; + // The player must touch the ground for the cooldown to start if this is true. + private boolean requireGround; + + @Attribute(Attribute.SPEED) + private double speed; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + + public AirGlide(Player player) { + super(player); + + if (hasAbility(player, AirGlide.class)) { + AirGlide ag = getAbility(player, AirGlide.class); + ag.remove(); + return; + } + + if (bPlayer.isOnCooldown(this) || CollisionDetector.isOnGround(player)) { + return; + } + + setFields(); + + this.progressing = true; + + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + speed = config.getDouble("Abilities.Air.AirGlide.Speed"); + fallSpeed = config.getDouble("Abilities.Air.AirGlide.FallSpeed"); + particles = config.getInt("Abilities.Air.AirGlide.Particles"); + airspout = config.getBoolean("Abilities.Air.AirGlide.AllowAirSpout"); + cooldown = config.getLong("Abilities.Air.AirGlide.Cooldown"); + duration = config.getLong("Abilities.Air.AirGlide.Duration"); + requireGround = config.getBoolean("Abilities.Air.AirGlide.RequireGround") && cooldown > 0; + } + + public void progress() { + long time = System.currentTimeMillis(); + + if (this.progressing) { + update(time); + } else { + if (player.isDead() || !player.isOnline()) { + this.requireGround = false; + remove(); + return; + } + + if (CollisionDetector.isOnGround(this.player)) { + this.requireGround = false; + remove(); + } else { + if (time > lastCooldown + cooldown / 2) { + bPlayer.addCooldown(this); + lastCooldown = time; + } + } + } + } + + @SuppressWarnings("deprecation") + private void update(long time) { + if (this.duration > 0 && time >= this.getStartTime() + this.duration) { + remove(); + return; + } + + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!hasAbility(player, AirGlide.class)) { + remove(); + return; + } + + if ((airspout && hasAbility(player, AirSpout.class)) || !hasAirGlide()) { + remove(); + return; + } + + if (!player.isOnGround()) { + Location firstLocation = player.getEyeLocation(); + + Vector directionVector = firstLocation.getDirection().normalize(); + double distanceFromPlayer = speed; + + Vector shootFromPlayer = new Vector(directionVector.getX() * distanceFromPlayer, -fallSpeed, directionVector.getZ() * distanceFromPlayer); + firstLocation.add(shootFromPlayer.getX(), shootFromPlayer.getY(), shootFromPlayer.getZ()); + + GeneralMethods.setVelocity(this, player, shootFromPlayer); + + playAirbendingParticles(player.getLocation(), particles); + } else if (!isTransparent(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) { + remove(); + } + } + + @Override + public void remove() { + this.progressing = false; + bPlayer.addCooldown(this); + + if (!this.requireGround) { + super.remove(); + } + } + + private boolean hasAirGlide() { + return bPlayer.getAbilities().containsValue("AirGlide"); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return player.getLocation(); + } + + @Override + public String getName() { + return "AirGlide"; + } + + @Override + public boolean isHarmlessAbility() { + return true; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirGlide.Description"); + } + + public boolean isRequireGround() { + return requireGround; + } + + public void setRequireGround(boolean requireGround) { + this.requireGround = requireGround; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public double getFallSpeed() { + return fallSpeed; + } + + public void setFallSpeed(double fallSpeed) { + this.fallSpeed = fallSpeed; + } + + public int getParticles() { + return particles; + } + + public void setParticles(int particles) { + this.particles = particles; + } + + public boolean allowsAirSpout() { + return airspout; + } + + public void setAllowAirSpout(boolean airspout) { + this.airspout = airspout; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public long getLastCooldown() { + return lastCooldown; + } + + public void setLastCooldown(long lastCooldown) { + this.lastCooldown = lastCooldown; + } + + public boolean isProgressing() { + return progressing; + } + + public void setProgressing(boolean progressing) { + this.progressing = progressing; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.AirGlide.Enabled"); + } +} diff --git a/src/ability/airbending/AirPunch.java b/src/ability/airbending/AirPunch.java new file mode 100644 index 0000000..eac83b2 --- /dev/null +++ b/src/ability/airbending/AirPunch.java @@ -0,0 +1,296 @@ +package com.jedk1.jedcore.ability.airbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class AirPunch extends AirAbility implements AddonAbility { + + private final Map locations = new ConcurrentHashMap<>(); + + private int shots; + private long lastShotTime; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private long threshold; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.COOLDOWN) + private double damage; + @Attribute("CollisionRadius") + private double entityCollisionRadius; + + public AirPunch(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, AirPunch.class)) { + AirPunch ap = getAbility(player, AirPunch.class); + ap.createShot(); + return; + } + + setFields(); + + start(); + + if (!isRemoved()) createShot(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Air.AirPunch.Cooldown"); + threshold = config.getLong("Abilities.Air.AirPunch.Threshold"); + shots = config.getInt("Abilities.Air.AirPunch.Shots"); + range = config.getDouble("Abilities.Air.AirPunch.Range"); + damage = config.getDouble("Abilities.Air.AirPunch.Damage"); + entityCollisionRadius = config.getDouble("Abilities.Air.AirPunch.EntityCollisionRadius"); + } + + @Override + public void progress() { + progressShots(); + + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + prepareRemove(); + return; + } + + if (shots == 0 || System.currentTimeMillis() > lastShotTime + threshold) { + prepareRemove(); + } + } + + private void prepareRemove() { + if (player.isOnline() && !bPlayer.isOnCooldown(this)) { + bPlayer.addCooldown(this); + } + + if (locations.isEmpty()) { + remove(); + } + } + + private void createShot() { + if (shots >= 1) { + lastShotTime = System.currentTimeMillis(); + shots--; + locations.put(player.getEyeLocation().add(player.getLocation().getDirection().multiply(1.5).normalize()), 0D); + } + } + + private void progressShots() { + Iterator> iterator = locations.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + Location originalLoc = entry.getKey(); + double dist = entry.getValue(); + ShotResult result = simulateShotProgression(originalLoc, dist); + + iterator.remove(); + + if (result.moved) { + locations.put(result.newLoc, result.newDist); + } + } + } + + private record ShotResult(Location newLoc, double newDist, boolean moved) {} + + private ShotResult simulateShotProgression(Location startLoc, double startDist) { + Location loc = startLoc.clone(); + double dist = startDist; + boolean shouldRemove = false; + boolean moved = false; + + for (int i = 0; i < 3 && !shouldRemove; i++) { + dist++; + if (dist >= range) { + shouldRemove = true; + } else { + Location nextLoc = calculateNextLocation(loc); + if (isPathBlocked(nextLoc)) { + shouldRemove = true; + } else { + applyShotEffects(nextLoc); + if (checkAndHandleCollision(nextLoc)) { + shouldRemove = true; + } else { + loc = nextLoc; + moved = true; + } + } + } + } + + return new ShotResult(loc, dist, moved); + } + + private Location calculateNextLocation(Location currentLocation) { + return currentLocation.add(currentLocation.getDirection().clone().multiply(1)); + } + + private boolean isPathBlocked(Location location) { + return GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock()) || RegionProtection.isRegionProtected(player, location, this); + } + + private void applyShotEffects(Location location) { + getAirbendingParticles().display(location, 2, Math.random() / 5, Math.random() / 5, Math.random() / 5, 0.0); + playAirbendingSound(location); + } + + private boolean checkAndHandleCollision(Location location) { + return CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), entityCollisionRadius), entity -> { + DamageHandler.damageEntity(entity, damage, this); + return true; + }); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Air.AirPunch.AbilityCollisionRadius"); + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + Location location = collision.getLocationFirst(); + + locations.remove(location); + } + } + + @Override + public List getLocations() { + return new ArrayList<>(locations.keySet()); + } + + @Override + public String getName() { + return "AirPunch"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirPunch.Description"); + } + + public long getThreshold() { + return threshold; + } + + public void setThreshold(long threshold) { + this.threshold = threshold; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + public int getShots() { + return shots; + } + + public void setShots(int shots) { + this.shots = shots; + } + + public long getLastShotTime() { + return lastShotTime; + } + + public void setLastShotTime(long lastShotTime) { + this.lastShotTime = lastShotTime; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.AirPunch.Enabled"); + } +} diff --git a/src/ability/airbending/Meditate.java b/src/ability/airbending/Meditate.java new file mode 100644 index 0000000..c240829 --- /dev/null +++ b/src/ability/airbending/Meditate.java @@ -0,0 +1,234 @@ +package com.jedk1.jedcore.ability.airbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.SpiritualAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class Meditate extends SpiritualAbility implements AddonAbility { + + private double startHealth; + private String unfocusMsg; + private long warmup; + private int particleDensity; + private boolean lossFocusMessage; + private int absorptionBoost; + private int speedBoost; + private int jumpBoost; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private int boostDuration; + + public Meditate(Player player) { + super(player); + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + unfocusMsg = config.getString("Abilities.Air.Meditate.UnfocusMessage"); + lossFocusMessage = config.getBoolean("Abilities.Air.Meditate.LossFocusMessage"); + warmup = config.getLong("Abilities.Air.Meditate.ChargeTime"); + cooldown = config.getLong("Abilities.Air.Meditate.Cooldown"); + boostDuration = config.getInt("Abilities.Air.Meditate.BoostDuration"); + particleDensity = config.getInt("Abilities.Air.Meditate.ParticleDensity"); + absorptionBoost = config.getInt("Abilities.Air.Meditate.AbsorptionBoost"); + speedBoost = config.getInt("Abilities.Air.Meditate.SpeedBoost"); + jumpBoost = config.getInt("Abilities.Air.Meditate.JumpBoost"); + + startHealth = player.getHealth(); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + + if (player.getHealth() < startHealth) { + if (lossFocusMessage) player.sendMessage(Element.SPIRITUAL.getColor() + unfocusMsg); + remove(); + return; + } + + if (System.currentTimeMillis() > getStartTime() + warmup) { + player.spawnParticle(Particle.ELECTRIC_SPARK, player.getLocation(), 3, 0.5, 0.5, 0.5, 0.003F); + + JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particleDensity, Math.random(), Math.random(), Math.random(), 0f); + + if (!player.isSneaking()) { + bPlayer.addCooldown(this); + givePlayerBuffs(); + remove(); + } + } else if (player.isSneaking()) { + JCMethods.displayColoredParticles("#FFFFFF", player.getLocation(), particleDensity, Math.random(), Math.random(), Math.random(), 0f, 50); + } else { + remove(); + } + } + + private void givePlayerBuffs() { + if (player.hasPotionEffect(PotionEffectType.SPEED)) { + player.removePotionEffect(PotionEffectType.SPEED); + } + + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, boostDuration/50, speedBoost - 1)); + + JedCore.plugin.getPotionEffectAdapter().applyJumpBoost(player, boostDuration, jumpBoost); + + if (player.hasPotionEffect(PotionEffectType.ABSORPTION)) { + player.removePotionEffect(PotionEffectType.ABSORPTION); + } + + player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, boostDuration/50, absorptionBoost - 1)); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return player.getLocation(); + } + + @Override + public String getName() { + return "Meditate"; + } + + @Override + public boolean isHarmlessAbility() { + return true; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.Meditate.Description"); + } + + public double getStartHealth() { + return startHealth; + } + + public void setStartHealth(double startHealth) { + this.startHealth = startHealth; + } + + public String getUnfocusMsg() { + return unfocusMsg; + } + + public void setUnfocusMsg(String unfocusMsg) { + this.unfocusMsg = unfocusMsg; + } + + public boolean hasUnfocusMessage() { + return lossFocusMessage; + } + + public void setHasUnfocusMessage(boolean hasUnfocusMessage) { + this.lossFocusMessage = hasUnfocusMessage; + } + + public long getWarmup() { + return warmup; + } + + public void setWarmup(long warmup) { + this.warmup = warmup; + } + + public int getBoostDuration() { + return boostDuration; + } + + public void setBoostDuration(int boostDuration) { + this.boostDuration = boostDuration; + } + + public int getParticleDensity() { + return particleDensity; + } + + public void setParticleDensity(int particleDensity) { + this.particleDensity = particleDensity; + } + + public int getAbsorptionBoost() { + return absorptionBoost; + } + + public void setAbsorptionBoost(int absorptionBoost) { + this.absorptionBoost = absorptionBoost; + } + + public int getSpeedBoost() { + return speedBoost; + } + + public void setSpeedBoost(int speedBoost) { + this.speedBoost = speedBoost; + } + + public int getJumpBoost() { + return jumpBoost; + } + + public void setJumpBoost(int jumpBoost) { + this.jumpBoost = jumpBoost; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.Meditate.Enabled"); + } +} diff --git a/src/ability/airbending/SonicBlast.java b/src/ability/airbending/SonicBlast.java new file mode 100644 index 0000000..5ae22f2 --- /dev/null +++ b/src/ability/airbending/SonicBlast.java @@ -0,0 +1,221 @@ +package com.jedk1.jedcore.ability.airbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +public class SonicBlast extends AirAbility implements AddonAbility { + + private Location location; + private Vector direction; + private boolean isCharged; + private int travelled; + private int nauseaDur; + private int blindDur; + private boolean chargeSwapping; + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.RANGE) + private double range; + @Attribute("CollisionRadius") + private double entityCollisionRadius; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("WarmUp") + private long warmup; + + public SonicBlast(Player player) { + super(player); + + if (hasAbility(player, SonicBlast.class) || bPlayer.isOnCooldown(this)) { + return; + } + + setFields(); + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + damage = config.getDouble("Abilities.Air.SonicBlast.Damage"); + range = config.getDouble("Abilities.Air.SonicBlast.Range"); + entityCollisionRadius = config.getDouble("Abilities.Air.SonicBlast.EntityCollisionRadius"); + cooldown = config.getLong("Abilities.Air.SonicBlast.Cooldown"); + warmup = config.getLong("Abilities.Air.SonicBlast.ChargeTime"); + chargeSwapping = config.getBoolean("Abilities.Air.SonicBlast.ChargeSwapping"); + nauseaDur = config.getInt("Abilities.Air.SonicBlast.Effects.NauseaDuration"); + blindDur = config.getInt("Abilities.Air.SonicBlast.Effects.BlindnessDuration"); + } + + @Override + public void progress() { + if (!checkPlayerState()) { + return; + } + + if (!canStartAbility()) { + remove(); + return; + } + + if (player.isSneaking() && travelled == 0) { + handleCharging(); + } else { + handleProgression(); + } + } + + private boolean checkPlayerState() { + return !player.isDead() && player.isOnline(); + } + + private boolean canStartAbility() { + CoreAbility boundAbility = bPlayer.getBoundAbility(); + return chargeSwapping || travelled > 0 || boundAbility instanceof SonicBlast; + } + + private void handleCharging() { + direction = player.getEyeLocation().getDirection().normalize(); + if (isCharged) { + playAirbendingParticles(player.getLocation().add(0, 1, 0), 5, (float) Math.random(), (float) Math.random(), (float) Math.random()); + } else if (System.currentTimeMillis() > getStartTime() + warmup) { + isCharged = true; + } + } + + private void handleProgression() { + if (isCharged) { + if (!bPlayer.isOnCooldown(this)) { + bPlayer.addCooldown(this); + } + if (travelled < range && isLocationSafe()) { + advanceLocation(); + } else { + remove(); + } + } else { + remove(); + } + } + + private boolean isLocationSafe() { + if (location == null) { + Location origin = player.getEyeLocation().clone(); + location = origin.clone(); + } + + return isTransparent(location.getBlock()); + } + + private void advanceLocation() { + travelled++; + + if (location == null) { + Location origin = player.getEyeLocation().clone(); + location = origin.clone(); + } + + for (int i = 0; i < 5; i++) { + for (int angle = 0; angle < 360; angle += 20) { + Location temp = location.clone(); + Vector dir = GeneralMethods.getOrthogonalVector(direction.clone(), angle, 1); + temp.add(dir); + playAirbendingParticles(temp, 1, 0, 0, 0); + } + + boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), entityCollisionRadius), entity -> { + DamageHandler.damageEntity(entity, damage, this); + LivingEntity lE = (LivingEntity) entity; + + lE.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getNauseaEffect(nauseaDur)); + lE.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindDur/50, 1)); + return true; + }); + + if (hit) { + remove(); + return; + } + + location = location.add(direction.clone().multiply(0.2)); + } + + location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 1, 0); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Air.SonicBlast.AbilityCollisionRadius"); + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "SonicBlast"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.SonicBlast.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.SonicBlast.Enabled"); + } +} diff --git a/src/ability/airbending/combo/AirSlam.java b/src/ability/airbending/combo/AirSlam.java new file mode 100644 index 0000000..f2f99b3 --- /dev/null +++ b/src/ability/airbending/combo/AirSlam.java @@ -0,0 +1,188 @@ +package com.jedk1.jedcore.ability.airbending.combo; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.ThrownEntityTracker; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; +import com.projectkorra.projectkorra.region.RegionProtection; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; + +public class AirSlam extends AirAbility implements AddonAbility, ComboAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.KNOCKBACK) + private double power; + @Attribute(Attribute.RANGE) + private int range; + + private LivingEntity target; + + public AirSlam(Player player) { + super(player); + + if (!bPlayer.canBendIgnoreBinds(this)) { + return; + } + + setFields(); + + Entity targetEntity = GeneralMethods.getTargetedEntity(player, range, new ArrayList<>()); + if (!(targetEntity instanceof LivingEntity) + || RegionProtection.isRegionProtected(this, targetEntity.getLocation()) + || ((targetEntity instanceof Player) && Commands.invincible.contains(targetEntity.getName()))) + return; + + this.target = (LivingEntity) targetEntity; + + start(); + + if (!isRemoved()) { + bPlayer.addCooldown(this); + GeneralMethods.setVelocity(this, target, new Vector(0, 2, 0)); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Air.AirCombo.AirSlam.Cooldown"); + power = config.getDouble("Abilities.Air.AirCombo.AirSlam.Power"); + range = config.getInt("Abilities.Air.AirCombo.AirSlam.Range"); + } + + @Override + public void progress() { + if (player == null || player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (System.currentTimeMillis() > getStartTime() + 50) { + Vector dir = player.getLocation().getDirection(); + GeneralMethods.setVelocity(this, target, new Vector(dir.getX(), 0.05, dir.getZ()).multiply(power)); + new HorizontalVelocityTracker(target, player, 0L, this); + new ThrownEntityTracker(this, target, player, 0L); + target.setFallDistance(0); + } + + if (System.currentTimeMillis() > getStartTime() + 400) { + remove(); + return; + } + + playAirbendingParticles(target.getLocation(), 10); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return target != null ? target.getLocation() : null; + } + + @Override + public String getName() { + return "AirSlam"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public Object createNewComboInstance(Player player) { + return new AirSlam(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Air.AirCombo.AirSlam.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Air.AirCombo.AirSlam.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirCombo.AirSlam.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public double getPower() { + return power; + } + + public void setPower(double power) { + this.power = power; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public LivingEntity getTarget() { + return target; + } + + public void setTarget(LivingEntity target) { + this.target = target; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.AirCombo.AirSlam.Enabled"); + } +} diff --git a/src/ability/airbending/combo/SwiftStream.java b/src/ability/airbending/combo/SwiftStream.java new file mode 100644 index 0000000..0b2929c --- /dev/null +++ b/src/ability/airbending/combo/SwiftStream.java @@ -0,0 +1,197 @@ +package com.jedk1.jedcore.ability.airbending.combo; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.FlightAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + +public class SwiftStream extends FlightAbility implements AddonAbility, ComboAbility { + + private final List affectedEntities = new ArrayList<>(); + + @Attribute(Attribute.COOLDOWN) + public long cooldown; + @Attribute("DragFactor") + public double dragFactor; + @Attribute(Attribute.DURATION) + public long duration; + + public SwiftStream(Player player) { + super(player); + + if (!bPlayer.canBendIgnoreBinds(this) || !bPlayer.canUseFlight()) { + return; + } + + setFields(); + start(); + + if (!isRemoved()) { + launch(); + bPlayer.addCooldown(this); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Air.AirCombo.SwiftStream.Cooldown"); + dragFactor = config.getDouble("Abilities.Air.AirCombo.SwiftStream.DragFactor"); + duration = config.getLong("Abilities.Air.AirCombo.SwiftStream.Duration"); + } + + public void launch() { + Vector v = player.getEyeLocation().getDirection().normalize(); + + v = v.multiply(5); + v.add(new Vector(0, 0.2, 0)); + + GeneralMethods.setVelocity(this, player, v); + } + + public void affectNearby() { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), 2.5)) { + if (e instanceof LivingEntity livingEntity && !affectedEntities.contains(e) && e.getEntityId() != player.getEntityId()) { + Vector v = player.getVelocity().clone(); + v = v.multiply(dragFactor); + v = v.setY(player.getVelocity().getY()); + v = v.add(new Vector(0, 0.15, 0)); + + GeneralMethods.setVelocity(this, e, v); + + affectedEntities.add(livingEntity); + + new HorizontalVelocityTracker(e, player, 200, this); + } + } + } + + @Override + public void progress() { + if (!player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + remove(); + return; + } + + if (System.currentTimeMillis() > getStartTime() + duration) { + remove(); + return; + } + + playAirbendingParticles(player.getLocation(), 4); + affectNearby(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return player.getLocation(); + } + + @Override + public String getName() { + return "SwiftStream"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public Object createNewComboInstance(Player player) { + return new SwiftStream(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Air.AirCombo.SwiftStream.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Air.AirCombo.SwiftStream.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirCombo.SwiftStream.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public double getDragFactor() { + return dragFactor; + } + + public void setDragFactor(double dragFactor) { + this.dragFactor = dragFactor; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public List getAffectedEntities() { + return affectedEntities; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.AirCombo.SwiftStream.Enabled"); + } +} diff --git a/src/ability/avatar/SpiritBeam.java b/src/ability/avatar/SpiritBeam.java new file mode 100644 index 0000000..689a3b5 --- /dev/null +++ b/src/ability/avatar/SpiritBeam.java @@ -0,0 +1,279 @@ +package com.jedk1.jedcore.ability.avatar; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class SpiritBeam extends AvatarAbility implements AddonAbility { + + private Location location; + private Vector direction; + private boolean damagesBlocks; + private long regen; + private boolean avatarOnly; + + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.RADIUS) + private double radius; + + public SpiritBeam(Player player) { + super(player); + + if (bPlayer.isOnCooldown(this)) return; + + setFields(); + + if (avatarOnly && !bPlayer.isAvatarState()) return; + + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + duration = config.getInt("Abilities.Avatar.SpiritBeam.Duration"); + cooldown = config.getInt("Abilities.Avatar.SpiritBeam.Cooldown"); + damage = config.getDouble("Abilities.Avatar.SpiritBeam.Damage"); + range = config.getInt("Abilities.Avatar.SpiritBeam.Range"); + avatarOnly = config.getBoolean("Abilities.Avatar.SpiritBeam.AvatarStateOnly"); + damagesBlocks = config.getBoolean("Abilities.Avatar.SpiritBeam.BlockDamage.Enabled"); + regen = config.getLong("Abilities.Avatar.SpiritBeam.BlockDamage.Regen"); + radius = config.getDouble("Abilities.Avatar.SpiritBeam.BlockDamage.Radius"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + bPlayer.addCooldown(this); + remove(); + return; + } + + if (System.currentTimeMillis() > getStartTime() + duration) { + bPlayer.addCooldown(this); + remove(); + return; + } + + if (!player.isSneaking()) { + bPlayer.addCooldown(this); + remove(); + return; + } + + if (avatarOnly && !bPlayer.isAvatarState()) { + bPlayer.addCooldown(this); + remove(); + return; + } + + createBeam(); + } + + private void createBeam() { + location = player.getLocation().add(0, 1.2, 0); + Vector beamDirection = location.getDirection().normalize().multiply(0.5); + + for (double i = 0; i < range; i += 0.5) { + location = location.add(beamDirection); + + if (isBeamObstructed(location)) { + return; + } + + displayBeamParticles(location, beamDirection); + JCMethods.emitLight(location); + damageNearbyEntities(location); + + if (handleBlockCollision(location)) { + return; + } + } + } + + private boolean isBeamObstructed(Location location) { + return RegionProtection.isRegionProtected(player, location, this); + } + + private void displayBeamParticles(Location location, Vector direction) { + String purple = "#A020F0"; + JCMethods.displayColoredParticles(purple, location, 1, 0f, 0f, 0f, 0f); + JCMethods.displayColoredParticles(purple, location, 1, (float) Math.random() / 3, (float) Math.random() / 3, (float) Math.random() / 3, 0f); + + float randomOffset = (float) Math.random() / 3; + ParticleEffect.BLOCK_CRACK.display(location, 1, randomOffset, randomOffset, randomOffset, 0.1F, Material.NETHER_PORTAL.createBlockData()); + ParticleEffect.BLOCK_CRACK.display(location, 1, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), 0.1F, Material.NETHER_PORTAL.createBlockData()); + } + + private void damageNearbyEntities(Location location) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { + if (entity instanceof LivingEntity livingEntity && livingEntity.getEntityId() != player.getEntityId()) { + livingEntity.setFireTicks(100); + DamageHandler.damageEntity(livingEntity, damage, this); + } + } + } + + private boolean handleBlockCollision(Location location) { + if (location.getBlock().getType().isSolid()) { + location.getWorld().createExplosion(location, 0F); + if (damagesBlocks) { + damageBlocksInRadius(location); + } + return true; + } + return false; + } + + private void damageBlocksInRadius(Location center) { + for (Location loc : GeneralMethods.getCircle(center, (int) radius, 0, false, true, 0)) { + if (!JCMethods.isUnbreakable(loc.getBlock())) { + new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); + } + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "SpiritBeam"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Avatar.SpiritBeam.Description"); + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public boolean isAvatarOnly() { + return avatarOnly; + } + + public void setAvatarOnly(boolean avatarOnly) { + this.avatarOnly = avatarOnly; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean damagesBlocks() { + return damagesBlocks; + } + + public void setDamagesBlocks(boolean blockdamage) { + this.damagesBlocks = blockdamage; + } + + public long getRegen() { + return regen; + } + + public void setRegen(long regen) { + this.regen = regen; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.SpiritBeam.Enabled"); + } +} diff --git a/src/ability/avatar/elementsphere/ESAir.java b/src/ability/avatar/elementsphere/ESAir.java new file mode 100644 index 0000000..a7e0820 --- /dev/null +++ b/src/ability/avatar/elementsphere/ESAir.java @@ -0,0 +1,223 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +public class ESAir extends AvatarAbility implements AddonAbility { + + private Location location; + private double travelled; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.KNOCKBACK) + private double knockback; + @Attribute(Attribute.SPEED) + private int speed; + + public ESAir(Player player) { + super(player); + + if (!hasAbility(player, ElementSphere.class)) { + return; + } + + ElementSphere currES = getAbility(player, ElementSphere.class); + if (currES.getAirUses() == 0) { + return; + } + + if (bPlayer.isOnCooldown("ESAir")) { + return; + } + + setFields(); + + if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), (int) range).getLocation())) { + return; + } + + location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); + + start(); + + if (!isRemoved()) { + bPlayer.addCooldown("ESAir", getCooldown()); + currES.setAirUses(currES.getAirUses() - 1); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Air.Cooldown"); + range = config.getDouble("Abilities.Avatar.ElementSphere.Air.Range"); + damage = config.getDouble("Abilities.Avatar.ElementSphere.Air.Damage"); + knockback = config.getDouble("Abilities.Avatar.ElementSphere.Air.Knockback"); + speed = config.getInt("Abilities.Avatar.ElementSphere.Air.Speed"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (travelled >= range) { + remove(); + return; + } + + advanceAttack(); + } + + private void advanceAttack() { + for (int i = 0; i < speed; i++) { + travelled++; + if (travelled >= range) return; + + location = location.add(location.getDirection().clone().multiply(1)); + + if (RegionProtection.isRegionProtected(this, location)) { + travelled = range; + return; + } + + if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { + travelled = range; + return; + } + + AirAbility.playAirbendingParticles(location, 5); + AirAbility.playAirbendingSound(location); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() + && !(entity instanceof ArmorStand) + && !RegionProtection.isRegionProtected(this, entity.getLocation()) + && !((entity instanceof Player targetPlayer) + && Commands.invincible.contains((targetPlayer).getName()))) { + DamageHandler.damageEntity(entity, damage, this); + GeneralMethods.setVelocity(this, entity, location.getDirection().multiply(knockback)); + travelled = range; + } + } + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "ElementSphereAir"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public double getDistanceTravelled() { + return travelled; + } + + public void setDistanceTravelled(double travelled) { + this.travelled = travelled; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getKnockback() { + return knockback; + } + + public void setKnockback(double knockback) { + this.knockback = knockback; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } +} diff --git a/src/ability/avatar/elementsphere/ESEarth.java b/src/ability/avatar/elementsphere/ESEarth.java new file mode 100644 index 0000000..c4517b8 --- /dev/null +++ b/src/ability/avatar/elementsphere/ESEarth.java @@ -0,0 +1,219 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import java.util.Arrays; +import java.util.concurrent.ThreadLocalRandom; + +public class ESEarth extends AvatarAbility implements AddonAbility { + + static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, Material.NETHER_PORTAL, Material.END_PORTAL, + Material.END_PORTAL_FRAME, Material.ENDER_CHEST, Material.CHEST, Material.TRAPPED_CHEST }; + + private TempFallingBlock tfb; + private long revertDelay; + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute("Size") + private int impactSize; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + public ESEarth(Player player) { + super(player); + if (!hasAbility(player, ElementSphere.class)) { + return; + } + ElementSphere currES = getAbility(player, ElementSphere.class); + if (currES.getEarthUses() == 0) { + return; + } + if (bPlayer.isOnCooldown("ESEarth")) { + return; + } + if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), 40).getLocation())) { + return; + } + setFields(); + start(); + if (!isRemoved()) { + bPlayer.addCooldown("ESEarth", getCooldown()); + currES.setEarthUses(currES.getEarthUses() - 1); + Location location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); + tfb = new TempFallingBlock(location, Material.DIRT.createBlockData(), location.getDirection().multiply(3), this); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + revertDelay = config.getLong("Abilities.Avatar.ElementSphere.Earth.ImpactRevert"); + damage = config.getDouble("Abilities.Avatar.ElementSphere.Earth.Damage"); + impactSize = config.getInt("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize"); + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Earth.Cooldown"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline()) { + tfb.remove(); + remove(); + return; + } + if (tfb.getFallingBlock().isDead()) { + remove(); + return; + } + if (RegionProtection.isRegionProtected(this, tfb.getLocation())){ + remove(); + return; + } + + EarthAbility.playEarthbendingSound(tfb.getLocation()); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), 2.5)) { + if (entity instanceof LivingEntity && !(entity instanceof ArmorStand) && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player targetPlayer) && Commands.invincible.contains(targetPlayer.getName()))) { + DamageHandler.damageEntity(entity, damage, this); + } + } + } + + // Unused + public static void explodeEarth(TempFallingBlock tempfallingblock) { + FallingBlock fb = tempfallingblock.getFallingBlock(); + ESEarth es = (ESEarth) tempfallingblock.getAbility(); + Player player = es.getPlayer(); + + ParticleEffect.SMOKE_LARGE.display(fb.getLocation(), 0, 0, 0, 0.3F, 25); + fb.getWorld().playSound(fb.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 2f, 0.5f); + + ThreadLocalRandom rand = ThreadLocalRandom.current(); + + for (Location l : GeneralMethods.getCircle(fb.getLocation(), es.impactSize, 1, false, true, 0)) { + if (isBreakable(l.getBlock()) && !RegionProtection.isRegionProtected(player, l, "ElementSphere") && EarthAbility.isEarthbendable(player, l.getBlock())) { + ParticleEffect.SMOKE_LARGE.display(l, 0, 0, 0, 0.1F, 2); + new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000), false); + } + + if (GeneralMethods.isSolid(l.getBlock().getRelative(BlockFace.DOWN)) && isBreakable(l.getBlock()) && ElementalAbility.isAir(l.getBlock().getType()) && rand.nextInt(20) == 0 && EarthAbility.isEarthbendable(player, l.getBlock().getRelative(BlockFace.DOWN))) { + Material type = l.getBlock().getRelative(BlockFace.DOWN).getType(); + new RegenTempBlock(l.getBlock(), type, type.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000)); + } + } + + tempfallingblock.remove(); + } + + public static boolean isBreakable(Block block) { + return !Arrays.asList(unbreakables).contains(block.getType()); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return tfb != null ? tfb.getLocation() : null; + } + + @Override + public String getName() { + return "ElementSphereEarth"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public long getRevertDelay() { + return revertDelay; + } + + public void setRevertDelay(long revertDelay) { + this.revertDelay = revertDelay; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getImpactSize() { + return impactSize; + } + + public void setImpactSize(int impactSize) { + this.impactSize = impactSize; + } + + public TempFallingBlock getTempFallingBlock() { + return tfb; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } +} diff --git a/src/ability/avatar/elementsphere/ESFire.java b/src/ability/avatar/elementsphere/ESFire.java new file mode 100644 index 0000000..32ec393 --- /dev/null +++ b/src/ability/avatar/elementsphere/ESFire.java @@ -0,0 +1,299 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.firebending.BlazeArc; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class ESFire extends AvatarAbility implements AddonAbility { + + private Location location; + private Vector direction; + private double travelled; + private boolean controllable; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.FIRE_TICK) + private long burnTime; + @Attribute(Attribute.SPEED) + private int speed; + + public ESFire(Player player) { + super(player); + + if (!hasAbility(player, ElementSphere.class)) { + return; + } + + ElementSphere currES = getAbility(player, ElementSphere.class); + if (currES.getFireUses() == 0) { + return; + } + + if (bPlayer.isOnCooldown("ESFire")) { + return; + } + + setFields(); + start(); + + if (!isRemoved()) { + bPlayer.addCooldown("ESFire", getCooldown()); + currES.setFireUses(currES.getFireUses() - 1); + location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); + direction = location.getDirection().clone(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Fire.Cooldown"); + range = config.getDouble("Abilities.Avatar.ElementSphere.Fire.Range"); + damage = config.getDouble("Abilities.Avatar.ElementSphere.Fire.Damage"); + burnTime = config.getLong("Abilities.Avatar.ElementSphere.Fire.BurnDuration"); + speed = config.getInt("Abilities.Avatar.ElementSphere.Fire.Speed"); + controllable = config.getBoolean("Abilities.Avatar.ElementSphere.Fire.Controllable"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + cooldown *= (long) BlueFireAbility.getCooldownFactor(); + range *= BlueFireAbility.getRangeFactor(); + damage *= BlueFireAbility.getDamageFactor(); + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (travelled >= range) { + remove(); + return; + } + + advanceAttack(); + } + + private void advanceAttack() { + for (int i = 0; i < speed; i++) { + if (!incrementTravelledAndCheckRange()) { + return; + } + + updateDirectionIfControllable(); + + location.add(direction.clone().multiply(1)); + + if (checkEnvironmentCollision()) { + return; + } + + displayAttackParticles(); + playAttackSoundsAndLight(); + placeFire(); + handleEntityCollisions(); + } + } + + private boolean incrementTravelledAndCheckRange() { + travelled++; + return travelled < range; + } + + private void updateDirectionIfControllable() { + if (!player.isDead() && controllable) { + direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); + } + } + + private boolean checkEnvironmentCollision() { + if (RegionProtection.isRegionProtected(this, location) || GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { + travelled = range; + return true; + } + return false; + } + + private void displayAttackParticles() { + ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; + flame.display(location, 5, Math.random(), Math.random(), Math.random(), 0.02); + ParticleEffect.SMOKE_LARGE.display(location, 2, Math.random(), Math.random(), Math.random(), 0.01); + } + + private void playAttackSoundsAndLight() { + FireAbility.playFirebendingSound(location); + JCMethods.emitLight(location); + } + + private void handleEntityCollisions() { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (isAttackableEntity(entity)) { + DamageHandler.damageEntity(entity, damage, this); + entity.setFireTicks(Math.round(burnTime / 50F)); + travelled = range; + return; + } + } + } + + private boolean isAttackableEntity(Entity entity) { + return entity instanceof LivingEntity && + entity.getEntityId() != player.getEntityId() && + !(entity instanceof ArmorStand) && + !RegionProtection.isRegionProtected(this, entity.getLocation()) && + !((entity instanceof Player targetPlayer) && Commands.invincible.contains((targetPlayer).getName())); + } + + private void placeFire() { + if (GeneralMethods.isSolid(location.getBlock().getRelative(BlockFace.DOWN))) { + location.getBlock().setType(Material.FIRE); + new BlazeArc(player, location, direction, 2); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "ElementSphereFire"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getDistanceTravelled() { + return travelled; + } + + public void setDistanceTravelled(double travelled) { + this.travelled = travelled; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public long getBurnTime() { + return burnTime; + } + + public void setBurnTime(long burnTime) { + this.burnTime = burnTime; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + public boolean isControllable() { + return controllable; + } + + public void setControllable(boolean controllable) { + this.controllable = controllable; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } +} diff --git a/src/ability/avatar/elementsphere/ESStream.java b/src/ability/avatar/elementsphere/ESStream.java new file mode 100644 index 0000000..efc8577 --- /dev/null +++ b/src/ability/avatar/elementsphere/ESStream.java @@ -0,0 +1,406 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.BlockState; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +/** + * @author jedk1 + * @author Finn_Bueno_ + */ +public class ESStream extends AvatarAbility implements AddonAbility { + + private boolean cancelAbility; + private int requiredUses; + private long regen; + private Location stream; + private Location origin; + private Vector dir; + private int angle; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.KNOCKBACK) + private double knockback; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.RADIUS) + private double radius; + + public ESStream(Player player) { + super(player); + + if (!hasAbility(player, ElementSphere.class)) { + return; + } + + ElementSphere currES = getAbility(player, ElementSphere.class); + + if (bPlayer.isOnCooldown("ESStream")) { + return; + } + + setFields(); + + if (currES.getAirUses() < requiredUses + || currES.getEarthUses() < requiredUses + || currES.getFireUses() < requiredUses + || currES.getWaterUses() < requiredUses) { + return; + } + + if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), (int) range).getLocation())) { + return; + } + + if (cancelAbility) { + currES.remove(); + } else { + currES.setAirUses(currES.getAirUses()-requiredUses); + currES.setEarthUses(currES.getEarthUses()-requiredUses); + currES.setFireUses(currES.getFireUses()-requiredUses); + currES.setWaterUses(currES.getWaterUses()-requiredUses); + } + + stream = player.getEyeLocation(); + origin = player.getEyeLocation(); + dir = player.getEyeLocation().getDirection(); + angle = 0; + + start(); + + if (!isRemoved()) { + bPlayer.addCooldown("ESStream", getCooldown()); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Stream.Cooldown"); + range = config.getDouble("Abilities.Avatar.ElementSphere.Stream.Range"); + damage = config.getDouble("Abilities.Avatar.ElementSphere.Stream.Damage"); + knockback = config.getDouble("Abilities.Avatar.ElementSphere.Stream.Knockback"); + requiredUses = config.getInt("Abilities.Avatar.ElementSphere.Stream.RequiredUses"); + cancelAbility = config.getBoolean("Abilities.Avatar.ElementSphere.Stream.EndAbility"); + radius = config.getInt("Abilities.Avatar.ElementSphere.Stream.ImpactCraterSize"); + regen = config.getLong("Abilities.Avatar.ElementSphere.Stream.ImpactRevert"); + } + + @Override + public void progress() { + if (!checkStreamValidity()) { + return; + } + + if (checkStreamRangeAndProtection()) { + return; + } + + handleNearbyEntities(); + + updateStreamDirection(); + + stream.add(dir); + + if (handleBlockCollision()) { + return; + } + + playStreamParticles(); + } + + private boolean checkStreamValidity() { + return player != null && player.isOnline(); + } + + private boolean checkStreamRangeAndProtection() { + if (origin.distance(stream) >= range || RegionProtection.isRegionProtected(player, stream, this)) { + remove(); + return true; + } + return false; + } + + private void handleNearbyEntities() { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(stream, 1.5)) { + if (e instanceof Player && e == player) { + continue; + } + applyStreamEffects(e); + } + } + + private void applyStreamEffects(Entity entity) { + GeneralMethods.setVelocity(this, entity, dir.normalize().multiply(knockback)); + if (entity instanceof LivingEntity) { + DamageHandler.damageEntity(entity, damage, this); + } + } + + private void updateStreamDirection() { + if (!player.isDead() && hasAbility(player, ElementSphere.class)) { + Location loc = stream.clone(); + dir = GeneralMethods.getDirection(loc, player.getTargetBlock(null, (int) range).getLocation()).normalize().multiply(1.2); + } + } + + private boolean handleBlockCollision() { + if (!isTransparent(stream.getBlock())) { + triggerCollisionEffects(); + remove(); + return true; + } + return false; + } + + private void triggerCollisionEffects() { + ThreadLocalRandom rand = ThreadLocalRandom.current(); + List blocks = getAffectedBlocks(); + damageNearbyEntitiesOnCollision(); + displayCollisionParticles(); + playCollisionSounds(rand); + spawnFallingBlocks(rand, blocks); + } + + private List getAffectedBlocks() { + List blocks = new ArrayList<>(); + for (Location loc : GeneralMethods.getCircle(stream, (int) radius, 0, false, true, 0)) { + if (JCMethods.isUnbreakable(loc.getBlock()) || RegionProtection.isRegionProtected(this, loc)) continue; + blocks.add(loc.getBlock().getState()); + new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), regen, false); + } + return blocks; + } + + private void damageNearbyEntitiesOnCollision() { + GeneralMethods.getEntitiesAroundPoint(stream, radius).stream().filter(e -> !(e instanceof Player) || e != player).filter(e -> !RegionProtection.isRegionProtected(this, e.getLocation()) && (!(e instanceof Player targetPlayer) || !Commands.invincible.contains((targetPlayer).getName()))).forEach(e -> { + GeneralMethods.setVelocity(this, e, dir.normalize().multiply(knockback)); + if (e instanceof LivingEntity) DamageHandler.damageEntity(e, damage, this); + }); + } + + private void displayCollisionParticles() { + ParticleEffect.FLAME.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.SMOKE_LARGE.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.FIREWORKS_SPARK.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.SMOKE_LARGE.display(stream, 20, 0.5F, 0.5F, 0.5F, 0.5F); + ParticleEffect.EXPLOSION_HUGE.display(stream, 5, 0.5F, 0.5F, 0.5F, 0.5F); + } + + private void playCollisionSounds(ThreadLocalRandom rand) { + stream.getWorld().playSound(stream, rand.nextBoolean() ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 1f, 1f); + stream.getWorld().playSound(stream, rand.nextBoolean() ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, 1f, 1f); + } + + private void spawnFallingBlocks(ThreadLocalRandom rand, List blocks) { + for (BlockState block : blocks) { + double x = (rand.nextBoolean() ? -1 : 1) * rand.nextDouble() / 3; + double z = (rand.nextBoolean() ? -1 : 1) * rand.nextDouble() / 3; + new TempFallingBlock(block.getLocation().add(0, 1, 0), block.getBlockData(), dir.clone().add(new Vector(x, 0, z)).normalize().multiply(-1), this); + } + } + + private void playStreamParticles() { + angle += 20; + if (angle > 360) { + angle = 0; + } + for (int i = 0; i < 4; i++) { + playIndividualStreamParticles(i); + } + } + + private void playIndividualStreamParticles(int particleIndex) { + for (double d = -4; d <= 0; d += 0.1) { + if (origin.distance(stream) < d) continue; + Location l = stream.clone().add(dir.clone().normalize().multiply(d)); + double r = Math.min(0.75, d * -1 / 5); + Vector ov = GeneralMethods.getOrthogonalVector(dir, angle + (90 * particleIndex) + d, r); + Location pl = l.clone().add(ov.clone()); + displayStreamParticle(pl, particleIndex); + } + } + + private void displayStreamParticle(Location location, int index) { + ThreadLocalRandom rand = ThreadLocalRandom.current(); + switch (index) { + case 0: + ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; + flame.display(location, 1, 0.05F, 0.05F, 0.05F, 0.005F); + break; + case 1: + String color = "#FFFFFF"; + float offset = 0.05F; + float speed = 0.005F; + int viewDistance = 50; + if (rand.nextInt(30) == 0) { + JCMethods.displayColoredParticles(color, location, 1, 0, 0, 0, speed); + } else { + JCMethods.displayColoredParticles(color, location, 1, offset, offset, offset, speed, viewDistance); + } + break; + case 2: + GeneralMethods.displayColoredParticle("06C1FF", location); + break; + case 3: + GeneralMethods.displayColoredParticle("754719", location); + break; + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return stream; + } + + @Override + public String getName() { + return "ElementSphereStream"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public double getKnockback() { + return knockback; + } + + public void setKnockback(double knockback) { + this.knockback = knockback; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean cancelsAbility() { + return cancelAbility; + } + + public void setCancelsAbility(boolean cancelAbility) { + this.cancelAbility = cancelAbility; + } + + public int getRequiredUses() { + return requiredUses; + } + + public void setRequiredUses(int requiredUses) { + this.requiredUses = requiredUses; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + public long getRegenTime() { + return regen; + } + + public void setRegenTime(long regen) { + this.regen = regen; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public Vector getDirection() { + return dir; + } + + public void setDirection(Vector dir) { + this.dir = dir; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } +} diff --git a/src/ability/avatar/elementsphere/ESWater.java b/src/ability/avatar/elementsphere/ESWater.java new file mode 100644 index 0000000..4d0fbb3 --- /dev/null +++ b/src/ability/avatar/elementsphere/ESWater.java @@ -0,0 +1,256 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class ESWater extends AvatarAbility implements AddonAbility { + + private Location location; + private Vector direction; + private double travelled; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.SPEED) + private int speed; + + public ESWater(Player player) { + super(player); + + if (!hasAbility(player, ElementSphere.class)) { + return; + } + + ElementSphere currES = getAbility(player, ElementSphere.class); + if (currES.getWaterUses() == 0) { + return; + } + + if (bPlayer.isOnCooldown("ESWater")) { + return; + } + + setFields(); + + location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); + + start(); + + if (!isRemoved()) { + bPlayer.addCooldown("ESWater", getCooldown()); + currES.setWaterUses(currES.getWaterUses() - 1); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Water.Cooldown"); + range = config.getDouble("Abilities.Avatar.ElementSphere.Water.Range"); + damage = config.getDouble("Abilities.Avatar.ElementSphere.Water.Damage"); + speed = config.getInt("Abilities.Avatar.ElementSphere.Water.Speed"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (travelled >= range) { + remove(); + return; + } + + advanceAttack(); + } + + private void advanceAttack() { + for (int i = 0; i < speed; i++) { + if (!incrementTravelledAndCheckRange()) { + return; + } + + updateDirection(); + + location.add(direction.clone().multiply(1)); + + if (checkCollision()) { + return; + } + + playAttackEffects(); + handleBlockTransformation(); + handleEntityCollisions(); + } + } + + private boolean incrementTravelledAndCheckRange() { + travelled++; + return travelled < range; + } + + private void updateDirection() { + if (!player.isDead()) { + direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); + } + } + + private boolean checkCollision() { + if (RegionProtection.isRegionProtected(this, location) || GeneralMethods.isSolid(location.getBlock()) || !isTransparent(location.getBlock())) { + travelled = range; + return true; + } + return false; + } + + private void playAttackEffects() { + WaterAbility.playWaterbendingSound(location); + if (isWater(location.getBlock())) { + ParticleEffect.WATER_BUBBLE.display(location, 3, 0.5, 0.5, 0.5); + } + } + + private void handleBlockTransformation() { + new RegenTempBlock(location.getBlock(), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 100L); + } + + private void handleEntityCollisions() { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (isAttackableEntity(entity)) { + DamageHandler.damageEntity(entity, damage, this); + travelled = range; + return; + } + } + } + + private boolean isAttackableEntity(Entity entity) { + return entity instanceof LivingEntity && + entity.getEntityId() != player.getEntityId() && + !(entity instanceof ArmorStand) && + !RegionProtection.isRegionProtected(this, entity.getLocation()) && + !((entity instanceof Player targetPlayer) && Commands.invincible.contains((targetPlayer).getName())); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "ElementSphereWater"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getDistanceTravelled() { + return travelled; + } + + public void setDistanceTravelled(double travelled) { + this.travelled = travelled; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } +} diff --git a/src/ability/avatar/elementsphere/ElementSphere.java b/src/ability/avatar/elementsphere/ElementSphere.java new file mode 100644 index 0000000..ee6b1ca --- /dev/null +++ b/src/ability/avatar/elementsphere/ElementSphere.java @@ -0,0 +1,523 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.ability.MultiAbility; +import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; +import com.projectkorra.projectkorra.ability.util.MultiAbilityManager.MultiAbilityInfoSub; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ThreadLocalRandom; + +public class ElementSphere extends AvatarAbility implements AddonAbility, MultiAbility { + + protected static final ConcurrentMap> abilities = new ConcurrentHashMap<>(); + private static final ArrayList multiAbilityInfo = new ArrayList<>(); + + static { + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AIR)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.EARTH)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.FIRE)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.WATER)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AVATAR)); + } + + private World world; + private int airUses; + private int fireUses; + private int waterUses; + private int earthUses; + private boolean setup; + private Location location; + private double yaw; + private int point; + private long endTime; + private long lastClickTime; + + @Attribute(Attribute.COOLDOWN) + public long cooldown; + @Attribute(Attribute.DURATION) + public long duration; + @Attribute(Attribute.HEIGHT) + private double height; + @Attribute(Attribute.SPEED) + private double speed; + + public ElementSphere(Player player) { + super(player); + + ElementSphere oldES = getAbility(player, ElementSphere.class); + + if (handleExistingSphere(player, oldES)) { + return; + } + + if (canStartNewSphere()) { + initializeNewSphere(player); + } + } + + private boolean handleExistingSphere(Player player, ElementSphere oldES) { + if (oldES != null) { + if (player.isSneaking()) { + oldES.prepareCancel(); + } else { + if (oldES.setup) { + handleElementSwitch(player); + } + } + return true; + } + return false; + } + + private void handleElementSwitch(Player player) { + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + return; + } + + switch (player.getInventory().getHeldItemSlot()) { + case 0: + if (checkPermission(player, "Air")) new ESAir(player); + break; + case 1: + if (checkPermission(player, "Earth")) new ESEarth(player); + break; + case 2: + if (checkPermission(player, "Fire")) new ESFire(player); + break; + case 3: + if (checkPermission(player, "Water")) new ESWater(player); + break; + case 4: + if (checkPermission(player, "Stream")) new ESStream(player); + break; + } + } + + private boolean checkPermission(Player player, String element) { + return player.hasPermission("bending.ability.ElementSphere." + element); + } + + private boolean canStartNewSphere() { + return bPlayer.canBend(this); + } + + private void initializeNewSphere(Player player) { + setFields(); + location = player.getLocation().clone().subtract(0, 1, 0); + world = player.getWorld(); + endTime = System.currentTimeMillis() + duration; + start(); + + if (!isRemoved()) { + bindAndCooldown(player); + enableFlight(player); + checkBoundAbilityName(); + } + } + + private void bindAndCooldown(Player player) { + MultiAbilityManager.bindMultiAbility(player, "ElementSphere"); + bPlayer.addCooldown(this); + } + + private void enableFlight(Player player) { + flightHandler.createInstance(player, this.getName()); + } + + private void checkBoundAbilityName() { + if (ChatColor.stripColor(bPlayer.getBoundAbilityName()) == null) { + remove(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + airUses = config.getInt("Abilities.Avatar.ElementSphere.Air.Uses"); + fireUses = config.getInt("Abilities.Avatar.ElementSphere.Fire.Uses"); + waterUses = config.getInt("Abilities.Avatar.ElementSphere.Water.Uses"); + earthUses = config.getInt("Abilities.Avatar.ElementSphere.Earth.Uses"); + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Cooldown"); + duration = config.getLong("Abilities.Avatar.ElementSphere.Duration"); + height = config.getDouble("Abilities.Avatar.ElementSphere.MaxControlledHeight"); + speed = config.getDouble("Abilities.Avatar.ElementSphere.FlySpeed"); + } + + @Override + public void progress() { + if (!checkPlayerValidity()) { + return; + } + + if (!checkAbilityPrerequisites()) { + return; + } + + if (isDurationOver()) { + remove(); + return; + } + + if (!hasUsableElements()) { + remove(); + return; + } + + handlePlayerMovement(); + handleFlight(); + handleEntityPush(); + updateLocationAndPlayParticles(); + + setup = true; + } + + private boolean checkPlayerValidity() { + return !player.isDead() && player.isOnline() && world == player.getWorld() && !player.getGameMode().equals(GameMode.SPECTATOR); + } + + private boolean checkAbilityPrerequisites() { + return bPlayer.isToggled() && MultiAbilityManager.hasMultiAbilityBound(player, "ElementSphere"); + } + + private boolean isDurationOver() { + return duration > 0 && System.currentTimeMillis() > endTime; + } + + private boolean hasUsableElements() { + return airUses > 0 || fireUses > 0 || waterUses > 0 || earthUses > 0; + } + + private void handlePlayerMovement() { + player.setFallDistance(0); + if (player.isSneaking()) { + player.setVelocity(player.getLocation().getDirection().multiply(speed)); + } + } + + private void handleFlight() { + Block block = getGround(); + if (block != null) { + double dy = player.getLocation().getY() - block.getY(); + if (dy > height) { + removeFlight(); + } else { + allowFlight(); + } + } + } + + private void handleEntityPush() { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (isPushableEntity(entity)) { + entity.setVelocity(entity.getLocation().toVector().subtract(player.getLocation().toVector()).multiply(1)); + } + } + } + + private boolean isPushableEntity(Entity entity) { + return entity instanceof LivingEntity && + entity.getEntityId() != player.getEntityId() && + !(entity instanceof ArmorStand) && + !RegionProtection.isRegionProtected(player, entity.getLocation(), this); + } + + private void updateLocationAndPlayParticles() { + location = player.getLocation().clone().subtract(0, 1, 0); + playParticles(); + } + + private void allowFlight() { + if (!player.getAllowFlight()) { + player.setAllowFlight(true); + } + if (!player.isFlying()) { + player.setFlying(true); + } + } + + private void removeFlight() { + if (player.getAllowFlight()) { + player.setAllowFlight(false); + } + if (player.isFlying()) { + player.setFlying(false); + } + } + + private Block getGround() { + Block standingblock = player.getLocation().getBlock(); + + for (int i = 0; i <= height + 5; i++) { + Block block = standingblock.getRelative(BlockFace.DOWN, i); + if (GeneralMethods.isSolid(block) || block.isLiquid()) { + return block; + } + } + + return null; + } + + private void playParticles() { + playAirParticles(); + playFireParticles(); + playWaterEarthParticles(); + updatePointCounter(); + } + + private void playAirParticles() { + if (airUses != 0) { + double currentYaw = yaw + 40; + yaw = currentYaw; + Location fakeLoc = createRotatedLocation(location.clone(), 0, currentYaw); + Vector direction = fakeLoc.getDirection(); + for (double j = -180; j <= 180; j += 45) { + Location tempLoc = calculateAirParticleLocation(fakeLoc, direction, j); + displayAirParticle(tempLoc); + } + } + } + + private Location createRotatedLocation(Location baseLoc, double pitchOffset, double yawOffset) { + Location newLoc = baseLoc.clone(); + newLoc.setPitch((float) pitchOffset); + newLoc.setYaw((float) yawOffset); + return newLoc; + } + + private Location calculateAirParticleLocation(Location center, Vector direction, double angleDegrees) { + Location tempLoc = center.clone(); + double angleRadians = Math.toRadians(angleDegrees); + Vector newDir = direction.clone().multiply(2 * Math.cos(angleRadians)); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + 2 + (2 * Math.sin(angleRadians))); + return tempLoc; + } + + private void displayAirParticle(Location loc) { + String color = "#FFFFFF"; + int count = 1; + float offsetX = 0; + float offsetY = 0; + float offsetZ = 0; + float particleSpeed = 0.003f; + int viewDistance = 50; + + if (ThreadLocalRandom.current().nextInt(30) == 0) { + JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed); + } else { + JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed, viewDistance); + } + } + + private void playFireParticles() { + if (fireUses != 0) { + ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; + for (int i = -180; i < 180; i += 40) { + Location particleLoc = calculateCircularLocation(location, 2, i, 2); + flame.display(particleLoc, 0, 0, 0, 0, 1); + JCMethods.emitLight(particleLoc); + } + } + } + + private Location calculateCircularLocation(Location center, double radius, double angleOffsetDegrees, double yOffset) { + double angleRadians = Math.toRadians(angleOffsetDegrees); + double x = radius * Math.cos(angleRadians + point); + double z = radius * Math.sin(angleRadians + point); + return center.clone().add(x, yOffset, z); + } + + private void playWaterEarthParticles() { + Location centerLoc = location.clone().add(0, 2, 0); + double xRotation = Math.PI * 2.1 / 3; + double yawRadians = -(centerLoc.getYaw() * Math.PI / 180 - 1.575); + + for (int i = -180; i < 180; i += 30) { + double angle = Math.toRadians(i); + Vector v = new Vector(Math.cos(angle + point), Math.sin(angle + point), 0.0D).multiply(2); + Vector v1 = v.clone(); + + rotateAroundAxisX(v, xRotation); + rotateAroundAxisY(v, yawRadians); + rotateAroundAxisX(v1, -xRotation); + rotateAroundAxisY(v1, yawRadians); + + if (waterUses != 0) { + GeneralMethods.displayColoredParticle("06C1FF", centerLoc.clone().add(v)); + } + if (earthUses != 0) { + GeneralMethods.displayColoredParticle("754719", centerLoc.clone().add(v1)); + } + } + } + + private void updatePointCounter() { + point = (point + 1) % 360; + } + + private void rotateAroundAxisX(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double y = v.getY() * cos - v.getZ() * sin; + double z = v.getY() * sin + v.getZ() * cos; + v.setY(y).setZ(z); + } + + private void rotateAroundAxisY(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double x = v.getX() * cos + v.getZ() * sin; + double z = v.getX() * -sin + v.getZ() * cos; + v.setX(x).setZ(z); + } + + @Override + public void remove() { + super.remove(); + MultiAbilityManager.unbindMultiAbility(player); + flightHandler.removeInstance(player, this.getName()); + } + + public void prepareCancel() { + if (System.currentTimeMillis() < lastClickTime + 500L) { + remove(); + } else { + lastClickTime = System.currentTimeMillis(); + } + } + + public int getAirUses() { + return airUses; + } + + public void setAirUses(int airuses) { + this.airUses = airuses; + } + + public int getEarthUses() { + return earthUses; + } + + public void setEarthUses(int earthuses) { + this.earthUses = earthuses; + } + + public int getFireUses() { + return fireUses; + } + + public void setFireUses(int fireuses) { + this.fireUses = fireuses; + } + + public int getWaterUses() { + return waterUses; + } + + public void setWaterUses(int wateruses) { + this.waterUses = wateruses; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public boolean requireAvatar() { + return false; + } + + @Override + public String getName() { + return "ElementSphere"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Avatar.ElementSphere.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } + + @Override + public ArrayList getMultiAbilities() { + FileConfiguration lang = getLanguageConfig(); + + String airName = lang.getString("Abilities.Avatar.ElementSphereAir.Name"); + String fireName = lang.getString("Abilities.Avatar.ElementSphereFire.Name"); + String waterName = lang.getString("Abilities.Avatar.ElementSphereWater.Name"); + String earthName = lang.getString("Abilities.Avatar.ElementSphereEarth.Name"); + String streamName = lang.getString("Abilities.Avatar.ElementSphereStream.Name"); + + multiAbilityInfo.get(0).setName(airName); + multiAbilityInfo.get(1).setName(earthName); + multiAbilityInfo.get(2).setName(fireName); + multiAbilityInfo.get(3).setName(waterName); + multiAbilityInfo.get(4).setName(streamName); + + return multiAbilityInfo; + } +} diff --git a/src/ability/chiblocking/Backstab.java b/src/ability/chiblocking/Backstab.java new file mode 100644 index 0000000..f6c87ec --- /dev/null +++ b/src/ability/chiblocking/Backstab.java @@ -0,0 +1,114 @@ +package com.jedk1.jedcore.ability.chiblocking; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.CoreAbility; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ChiAbility; +import com.projectkorra.projectkorra.chiblocking.passive.ChiPassive; +import org.bukkit.util.Vector; + +public class Backstab extends ChiAbility implements AddonAbility { + + public Backstab(Player player) { + super(player); + } + + @Override + public void progress() {} + + public static boolean punch(Player player, LivingEntity target) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + CoreAbility ability = CoreAbility.getAbility("Backstab"); + + if (bPlayer == null || !bPlayer.canBend(ability)) { + return false; + } + + ConfigurationSection config = JedCoreConfig.getConfig(player); + double activationAngle = Math.toRadians(config.getInt("Abilities.Chi.Backstab.MaxActivationAngle", 90)); + + Vector targetDirection = target.getLocation().getDirection().setY(0).normalize(); + Vector toTarget = target.getLocation().toVector().subtract(player.getLocation().toVector()).setY(0).normalize(); + + double angle = toTarget.angle(targetDirection); + + if (angle <= activationAngle && target.getLocation().distanceSquared(player.getLocation()) <= 5 * 5) { + bPlayer.addCooldown(ability); + + if (target instanceof Player) { + ChiPassive.blockChi((Player) target); + } + + return true; + } + + return false; + } + + public static double getDamage(World world) { + ConfigurationSection config = JedCoreConfig.getConfig(world); + return config.getDouble("Abilities.Chi.Backstab.Damage"); + } + + @Override + public long getCooldown() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getLong("Abilities.Chi.Backstab.Cooldown"); + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "Backstab"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Chi.Backstab.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Chi.Backstab.Enabled"); + } +} diff --git a/src/ability/chiblocking/DaggerThrow.java b/src/ability/chiblocking/DaggerThrow.java new file mode 100644 index 0000000..677e70a --- /dev/null +++ b/src/ability/chiblocking/DaggerThrow.java @@ -0,0 +1,348 @@ +package com.jedk1.jedcore.ability.chiblocking; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.AbilitySelector; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ChiAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class DaggerThrow extends ChiAbility implements AddonAbility { + private static final List INTERACTIONS = new ArrayList<>(); + private boolean particles; + + @Attribute(Attribute.DAMAGE) + private double damage; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private boolean limitEnabled; + @Attribute("MaxShots") + private int maxShots; + + private boolean requireArrows; + // require arrows (takes arrows from inv) + private boolean allowPickup; + // allow arrow pickup (disables pickup and removes the arrow entities) + + private long endTime; + private int shots = 1; + private int hits = 0; + private final List arrows = new ArrayList<>(); + + public DaggerThrow(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (bPlayer.isOnCooldown("DaggerThrowShot")) { + return; + } + + if (hasAbility(player, DaggerThrow.class)) { + DaggerThrow dt = getAbility(player, DaggerThrow.class); + dt.shootArrow(); + return; + } + + setFields(); + + start(); + if (!isRemoved()) { + shootArrow(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Chi.DaggerThrow.Cooldown"); + limitEnabled = config.getBoolean("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled"); + maxShots = config.getInt("Abilities.Chi.DaggerThrow.MaxDaggers.Amount"); + particles = config.getBoolean("Abilities.Chi.DaggerThrow.ParticleTrail"); + damage = config.getDouble("Abilities.Chi.DaggerThrow.Damage"); + requireArrows = config.getBoolean("Abilities.Chi.DaggerThrow.RequireArrows"); + allowPickup = config.getBoolean("Abilities.Chi.DaggerThrow.AllowPickup"); + + loadInteractions(); + } + + private void loadInteractions() { + INTERACTIONS.clear(); + + String path = "Abilities.Chi.DaggerThrow.Interactions"; + + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + ConfigurationSection section = config.getConfigurationSection(path); + for (String abilityName : section.getKeys(false)) { + INTERACTIONS.add(new AbilityInteraction(abilityName)); + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (System.currentTimeMillis() > endTime) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (shots > maxShots && limitEnabled) { + bPlayer.addCooldown(this); + remove(); + } + } + + private void shootArrow() { + shots++; + Location location = player.getEyeLocation(); + + Vector vector = location.toVector(). + add(location.getDirection().multiply(2.5)). + toLocation(location.getWorld()).toVector(). + subtract(player.getEyeLocation().toVector()); + + if (requireArrows) JCMethods.removeItemFromInventory(player, Material.ARROW, 1); + Arrow arrow = player.launchProjectile(Arrow.class); + arrow.setVelocity(vector); + arrow.getLocation().setDirection(vector); + arrow.setKnockbackStrength(0); + arrow.setBounce(false); + arrow.setMetadata("daggerthrow", new FixedMetadataValue(JedCore.plugin, "1")); + if (!allowPickup) arrow.setPickupStatus(Arrow.PickupStatus.DISALLOWED); + + if (particles) { + arrow.setCritical(true); + } + + arrows.add(arrow); + endTime = System.currentTimeMillis() + 500; + bPlayer.addCooldown("DaggerThrowShot", 100); + } + + public void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { + if (!(arrow.getShooter() instanceof Player shooter)) return; + + if (RegionProtection.isRegionProtected(shooter, arrow.getLocation(), "DaggerThrow")) return; + + arrow.setVelocity(new Vector(0, 0, 0)); + entity.setNoDamageTicks(0); + + double prevHealth = entity.getHealth(); + + DamageHandler.damageEntity(entity, damage, this); + + if (prevHealth > entity.getHealth()) { + arrow.remove(); + } + + if (!(entity instanceof Player target)) { + return; + } + + DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); + if (daggerThrow == null) { + return; + } + + daggerThrow.hits++; + BendingPlayer targetBPlayer = BendingPlayer.getBendingPlayer(target); + + for (AbilityInteraction interaction : INTERACTIONS) { + if (!interaction.enabled || daggerThrow.hits < interaction.hitRequirement) { + continue; + } + + CoreAbility abilityDefinition = AbilitySelector.getAbility(interaction.name); + if (abilityDefinition == null) { + continue; + } + + CoreAbility ability = CoreAbility.getAbility(target, abilityDefinition.getClass()); + if (ability == null) { + continue; + } + + ability.remove(); + targetBPlayer.addCooldown(ability, interaction.cooldown); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + return arrows.stream().map(Arrow::getLocation).collect(Collectors.toList()); + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Chi.DaggerThrow.AbilityCollisionRadius"); + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + Location location = collision.getLocationFirst(); + + Optional collidedObject = arrows.stream().filter(arrow -> arrow.getLocation().equals(location)).findAny(); + + if (collidedObject.isPresent()) { + arrows.remove(collidedObject.get()); + collidedObject.get().remove(); + } + } + } + + @Override + public String getName() { + return "DaggerThrow"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Chi.DaggerThrow.Description"); + } + + public boolean hasParticleTrail() { + return particles; + } + + public double getDamage() { + return damage; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public int getShots() { + return shots; + } + + public void setShots(int shots) { + this.shots = shots; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public boolean isLimitEnabled() { + return limitEnabled; + } + + public void setLimitEnabled(boolean limitEnabled) { + this.limitEnabled = limitEnabled; + } + + public int getMaxShots() { + return maxShots; + } + + public void setMaxShots(int maxShots) { + this.maxShots = maxShots; + } + + public int getHits() { + return hits; + } + + public void setHits(int hits) { + this.hits = hits; + } + + public List getArrows() { + return arrows; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Chi.DaggerThrow.Enabled"); + } + + private class AbilityInteraction { + public boolean enabled; + public long cooldown; + public int hitRequirement; + public String name; + + public AbilityInteraction(String abilityName) { + this.name = abilityName; + loadConfig(); + } + + public void loadConfig() { + ConfigurationSection config = JedCoreConfig.getConfig(player); + this.enabled = config.getBoolean("Abilities.Chi.DaggerThrow.Interactions." + name + ".Enabled", true); + this.cooldown = config.getLong("Abilities.Chi.DaggerThrow.Interactions." + name + ".Cooldown", 1000); + this.hitRequirement = config.getInt("Abilities.Chi.DaggerThrow.Interactions." + name + ".HitsRequired", 1); + } + } +} diff --git a/src/ability/earthbending/EarthKick.java b/src/ability/earthbending/EarthKick.java new file mode 100644 index 0000000..83a0c64 --- /dev/null +++ b/src/ability/earthbending/EarthKick.java @@ -0,0 +1,336 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.AABB; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.CollisionUtil; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.BlockUtil; +import com.jedk1.jedcore.util.TempFallingBlock; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.*; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.UUID; + +import static java.util.stream.Collectors.toList; + +public class EarthKick extends EarthAbility implements AddonAbility { + private final List temps = new ArrayList<>(); + + private BlockData materialData; + private Location location; + private final Random rand = new Random(); + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("MaxShots") + private int earthBlocks; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.DAMAGE) + private double metalDmg; + @Attribute("CollisionRadius") + private double entityCollisionRadius; + private Block block; + + private boolean multipleHits; + private int sourceRange; + private int spread; + private double velocity; + private boolean allowMetal; + + private Set hitEntities = new HashSet<>(); + + public EarthKick(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + location = player.getLocation(); + if ((player.getLocation().getPitch() > -5) && prepare()) { + if (RegionProtection.isRegionProtected(this, block.getLocation())) { + return; + } + launchBlocks(); + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.EarthKick.Cooldown"); + earthBlocks = config.getInt("Abilities.Earth.EarthKick.EarthBlocks"); + damage = config.getDouble("Abilities.Earth.EarthKick.Damage.Normal"); + metalDmg = config.getDouble("Abilities.Earth.EarthKick.Damage.Metal"); + entityCollisionRadius = config.getDouble("Abilities.Earth.EarthKick.EntityCollisionRadius"); + + multipleHits = config.getBoolean("Abilities.Earth.EarthKick.MultipleHits"); + sourceRange = config.getInt("Abilities.Earth.EarthKick.SourceRange"); + spread = config.getInt("Abilities.Earth.EarthKick.Spread"); + velocity = config.getDouble("Abilities.Earth.EarthKick.Velocity"); + allowMetal = config.getBoolean("Abilities.Earth.EarthKick.AllowMetal"); + + if (entityCollisionRadius < 1.0) { + entityCollisionRadius = 1.0; + } + } + + private boolean prepare() { + block = player.getTargetBlock(getTransparentMaterialSet(), sourceRange); + + if (!isEarthbendable(player, block)) { + return false; + } + + if (TempBlock.isTempBlock(block)) { + TempBlock.get(block).revertBlock(); + } + + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + if (block != null && (allowMetal || !isMetal(block))) { + materialData = block.getBlockData().clone(); + location.setX(block.getX() + 0.5); + location.setY(block.getY()); + location.setZ(block.getZ() + 0.5); + + return true; + } + + return false; + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + remove(); + return; + } + + bPlayer.addCooldown(this); + track(); + + if (temps.isEmpty()) { + remove(); + } + } + + private void launchBlocks() { + if (getMovedEarth().containsKey(block)) { + block.setType(Material.AIR); + } + if (block.getType() != Material.AIR) { + TempBlock air = new TempBlock(block, Material.AIR); + air.setRevertTime(5000L); + } + + location.setPitch(0); + location.add(location.getDirection()); + + if (!isAir(location.getBlock().getType())) { + location.setY(location.getY() + 1.0); + } + + ParticleEffect.CRIT.display(location, 10, Math.random(), Math.random(), Math.random(), 0.1); + + int yaw = Math.round(location.getYaw()); + + playEarthbendingSound(location); + + for (int i = 0; i < earthBlocks; i++) { + location.setYaw(yaw + rand.nextInt((spread * 2) + 1) - spread); + location.setPitch(rand.nextInt(25) - 45); + + Vector v = location.clone().add(0, 0.8, 0).getDirection().normalize(); + Location location1 = location.clone().add(new Vector(v.getX() * 2, v.getY(), v.getZ() * 2)); + Vector dir = location1.setDirection(location.getDirection()).getDirection().multiply(velocity); + + temps.add(new TempFallingBlock(location, materialData, dir, this)); + } + } + + public void track() { + List destroy = new ArrayList<>(); + + for (TempFallingBlock tfb : temps) { + FallingBlock fb = tfb.getFallingBlock(); + + if (fb == null || fb.isDead()) { + destroy.add(tfb); + continue; + } + + for (int i = 0; i < 2; i++) { + ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.1, materialData); + ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.2, materialData); + } + + AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); + + CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { + UUID uuid = entity.getUniqueId(); + if (this.multipleHits || hitEntities.add(uuid)) { + DamageHandler.damageEntity(entity, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : damage, this); + } + return false; + }); + } + + temps.removeAll(destroy); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public List getLocations() { + return temps.stream().map(TempFallingBlock::getLocation).collect(toList()); + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Earth.EarthKick.AbilityCollisionRadius"); + } + + @Override + public void handleCollision(Collision collision) { + CollisionUtil.handleFallingBlockCollisions(collision, temps); + } + + @Override + public String getName() { + return "EarthKick"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthKick.Description"); + } + + public List getTemps() { + return temps; + } + + public BlockData getMaterialData() { + return materialData; + } + + public void setMaterialData(BlockData materialData) { + this.materialData = materialData; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getEarthBlocksQuantity() { + return earthBlocks; + } + + public void setEarthBlocksQuantity(int earthBlocks) { + this.earthBlocks = earthBlocks; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getMetalDmg() { + return metalDmg; + } + + public void setMetalDmg(double metalDmg) { + this.metalDmg = metalDmg; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + public Block getBlock() { + return block; + } + + public void setBlock(Block block) { + this.block = block; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthKick.Enabled"); + } +} diff --git a/src/ability/earthbending/EarthLine.java b/src/ability/earthbending/EarthLine.java new file mode 100644 index 0000000..b0991dd --- /dev/null +++ b/src/ability/earthbending/EarthLine.java @@ -0,0 +1,492 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.util.RegenTempBlock; + +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.DamageHandler; + +import com.projectkorra.projectkorra.util.TempFallingBlock; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class EarthLine extends EarthAbility implements AddonAbility { + + private Location location; + private Location endLocation; + private Block sourceBlock; + private TempBlock sourceTempBlock; + private Material sourceType; + private boolean progressing; + private boolean hitted; + private int goOnAfterHit; + private long removalTime = -1; + + private long useCooldown; + private long prepareCooldown; + @Attribute(Attribute.DURATION) + private long maxDuration; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.SELECT_RANGE) + private double prepareRange; + private double sourceKeepRange; + @Attribute(Attribute.RADIUS) + private int affectingRadius; + @Attribute(Attribute.DAMAGE) + private double damage; + private boolean allowChangeDirection; + private CompositeRemovalPolicy removalPolicy; + + public EarthLine(Player player) { + super(player); + + if (!isEnabled()) return; + + if (!bPlayer.canBend(this)) { + return; + } + goOnAfterHit = 1; + + setFields(); + if (prepare()) { + start(); + if (!isRemoved() && prepareCooldown != 0) { + bPlayer.addCooldown(this, prepareCooldown); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new SwappedSlotsRemovalPolicy<>(bPlayer, EarthLine.class) + ); + + this.removalPolicy.load(config); + + useCooldown = config.getLong("Abilities.Earth.EarthLine.Cooldown"); + prepareCooldown = config.getLong("Abilities.Earth.EarthLine.PrepareCooldown"); + range = config.getInt("Abilities.Earth.EarthLine.Range"); + prepareRange = config.getDouble("Abilities.Earth.EarthLine.PrepareRange"); + sourceKeepRange = config.getDouble("Abilities.Earth.EarthLine.SourceKeepRange"); + affectingRadius = config.getInt("Abilities.Earth.EarthLine.AffectingRadius"); + damage = config.getDouble("Abilities.Earth.EarthLine.Damage"); + allowChangeDirection = config.getBoolean("Abilities.Earth.EarthLine.AllowChangeDirection"); + maxDuration = config.getLong("Abilities.Earth.EarthLine.MaxDuration"); + } + + public boolean prepare() { + final Block block = getEarthSourceBlock(this.range); + if (block == null || !this.isEarthbendable(block)) { + return false; + } else if (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block)) { + return false; + } + + boolean selectedABlockInUse = false; + for (final EarthLine el : getAbilities(this.player, EarthLine.class)) { + if (!el.progressing) { + el.remove(); + } else if (block.equals(el.sourceBlock)) { + selectedABlockInUse = true; + } + } + + if (selectedABlockInUse) { + return false; + } + + if (block.getLocation().distanceSquared(this.player.getLocation()) > this.prepareRange * this.prepareRange) { + return false; + } + + this.sourceBlock = block; + this.focusBlock(); + return true; + } + + private void focusBlock() { + if (DensityShift.isPassiveSand(this.sourceBlock)) { + DensityShift.revertSand(this.sourceBlock); + } + + if (this.sourceBlock.getType() == Material.SAND) { + this.sourceType = Material.SAND; + sourceTempBlock = new TempBlock(sourceBlock, Material.SANDSTONE.createBlockData()); + //this.sourceBlock.setType(Material.SANDSTONE); + } else if (this.sourceBlock.getType() == Material.RED_SAND) { + this.sourceType = Material.RED_SAND; + sourceTempBlock = new TempBlock(sourceBlock, Material.RED_SANDSTONE.createBlockData()); + //this.sourceBlock.setType(Material.RED_SANDSTONE); + } else if (this.sourceBlock.getType() == Material.STONE) { + //this.sourceBlock.setType(Material.COBBLESTONE); + this.sourceType = Material.STONE; + sourceTempBlock = new TempBlock(sourceBlock, Material.COBBLESTONE.createBlockData()); + } else { + this.sourceType = this.sourceBlock.getType(); + //this.sourceBlock.setType(Material.STONE); + sourceTempBlock = new TempBlock(sourceBlock, Material.STONE.createBlockData()); + } + + this.location = this.sourceBlock.getLocation(); + } + + private void unfocusBlock() { + //sourceBlock.setType(sourceType); + sourceTempBlock.revertBlock(); + } + + @Override + public void remove() { +// if (sourceBlock != null && sourceBlock.getType() != Material.AIR) { +// sourceBlock.setType(sourceType); // Ensure no duplication of the source block +// } + sourceTempBlock.revertBlock(); + super.remove(); + } + + private static Location getTargetLocation(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + double range = config.getInt("Abilities.Earth.EarthLine.Range"); + Entity target = GeneralMethods.getTargetedEntity(player, range, player.getNearbyEntities(range, range, range)); + Location location; + if (target == null) { + location = GeneralMethods.getTargetedLocation(player, range); + } else { + location = ((LivingEntity) target).getEyeLocation(); + } + return location; + } + + public void shootLine(Location endLocation) { + if (useCooldown != 0 && bPlayer.getCooldown(this.getName()) < useCooldown) bPlayer.addCooldown(this, useCooldown); + if (maxDuration > 0) removalTime = System.currentTimeMillis() + maxDuration; + this.endLocation = endLocation; + progressing = true; + sourceBlock.getWorld().playEffect(sourceBlock.getLocation(), Effect.GHAST_SHOOT, 0, 10); + } + + public static void shootLine(Player player) { + if (hasAbility(player, EarthLine.class)) { + EarthLine el = getAbility(player, EarthLine.class); + if (!el.progressing) { + el.shootLine(getTargetLocation(player)); + } + } + } + + private boolean sourceOutOfRange() { + return sourceBlock == null || sourceBlock.getLocation().add(0.5, 0.5, 0.5).distanceSquared(player.getLocation()) > sourceKeepRange * sourceKeepRange || sourceBlock.getWorld() != player.getWorld(); + } + + public void progress() { + if (!progressing) { + if (sourceOutOfRange()) { + unfocusBlock(); + remove(); + } + return; + } + + if (removalPolicy.shouldRemove()) { + remove(); + return; + } + + if (sourceBlock == null || RegionProtection.isRegionProtected(this, location)) { + remove(); + return; + } + + if (removalTime > -1 && System.currentTimeMillis() > removalTime) { + remove(); + return; + } + + if (sourceOutOfRange()) { + remove(); + return; + } + + if (RegionProtection.isRegionProtected(player, location, this)) { + remove(); + return; + } + + if (allowChangeDirection && player.isSneaking() && bPlayer.getBoundAbilityName().equalsIgnoreCase("EarthLine")) { + endLocation = getTargetLocation(player); + } + + double x1 = endLocation.getX(); + double z1 = endLocation.getZ(); + double x0 = sourceBlock.getX(); + double z0 = sourceBlock.getZ(); + Vector looking = new Vector(x1 - x0, 0.0D, z1 - z0); + Vector push = new Vector(x1 - x0, 0.34999999999999998D, z1 - z0); + if (location.distance(sourceBlock.getLocation()) < range) { + Material cloneType = location.getBlock().getType(); + Location locationYUP = location.getBlock().getLocation().clone().add(0.5, 0.1, 0.5); + + playEarthbendingSound(location); + + if (isEarthbendable(location.getBlock())) { + //new RegenTempBlock(location.getBlock(), Material.AIR, Material.AIR.createBlockData(), 700L); + new TempBlock(location.getBlock(), Material.AIR.createBlockData(), 700L); + new TempFallingBlock(locationYUP, cloneType.createBlockData(), new Vector(0.0, 0.35, 0.0), this); + } + + location.add(looking.normalize()); + + if (!climb()) { + remove(); + return; + } + + if (hitted) { + if (goOnAfterHit != 0) { + goOnAfterHit--; + } else { + remove(); + return; + } + } else { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, affectingRadius)) { + if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))){ + return; + } + if ((entity instanceof LivingEntity) && entity.getEntityId() != player.getEntityId()) { + GeneralMethods.setVelocity(this, entity, push.normalize().multiply(2)); + DamageHandler.damageEntity(entity, damage, this); + hitted = true; + } + } + } + } else { + remove(); + return; + } + + if (!isEarthbendable(player, location.getBlock()) && !isTransparent(location.getBlock())) { + remove(); + } + } + + private boolean climb() { + Block above = location.getBlock().getRelative(BlockFace.UP); + + if (!isTransparent(above)) { + // Attempt to climb since the current location has a block above it. + location.add(0, 1, 0); + above = location.getBlock().getRelative(BlockFace.UP); + + // The new location must be earthbendable and have something transparent above it. + return isEarthbendable(location.getBlock()) && isTransparent(above); + } else if (isTransparent(location.getBlock()) ) { + // Attempt to fall since the current location is transparent and the above block was transparent. + location.add(0, -1, 0); + + // The new location must be earthbendable and we already know the block above it is transparent. + return isEarthbendable(location.getBlock()); + } + + return true; + } + + @Override + public long getCooldown() { + return useCooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "EarthLine"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthLine.Description"); + } + + public Location getEndLocation() { + return endLocation; + } + + public void setEndLocation(Location endLocation) { + this.endLocation = endLocation; + } + + public Block getSourceBlock() { + return sourceBlock; + } + + public void setSourceBlock(Block sourceBlock) { + this.sourceBlock = sourceBlock; + } + + public Material getSourceType() { + return sourceType; + } + + public void setSourceType(Material sourceType) { + this.sourceType = sourceType; + } + + public boolean isProgressing() { + return progressing; + } + + public void setProgressing(boolean progressing) { + this.progressing = progressing; + } + + public int getGoOnAfterHit() { + return goOnAfterHit; + } + + public void setGoOnAfterHit(int goOnAfterHit) { + this.goOnAfterHit = goOnAfterHit; + } + + public long getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(long removalTime) { + this.removalTime = removalTime; + } + + public long getUseCooldown() { + return useCooldown; + } + + public void setUseCooldown(long useCooldown) { + this.useCooldown = useCooldown; + } + + public long getPrepareCooldown() { + return prepareCooldown; + } + + public void setPrepareCooldown(long prepareCooldown) { + this.prepareCooldown = prepareCooldown; + } + + public long getMaxDuration() { + return maxDuration; + } + + public void setMaxDuration(long maxDuration) { + this.maxDuration = maxDuration; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getPrepareRange() { + return prepareRange; + } + + public void setPrepareRange(double prepareRange) { + this.prepareRange = prepareRange; + } + + public double getSourceKeepRange() { + return sourceKeepRange; + } + + public void setSourceKeepRange(double sourceKeepRange) { + this.sourceKeepRange = sourceKeepRange; + } + + public int getAffectingRadius() { + return affectingRadius; + } + + public void setAffectingRadius(int affectingRadius) { + this.affectingRadius = affectingRadius; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean isAllowChangeDirection() { + return allowChangeDirection; + } + + public void setAllowChangeDirection(boolean allowChangeDirection) { + this.allowChangeDirection = allowChangeDirection; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthLine.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/earthbending/EarthPillar.java b/src/ability/earthbending/EarthPillar.java new file mode 100644 index 0000000..1935c15 --- /dev/null +++ b/src/ability/earthbending/EarthPillar.java @@ -0,0 +1,216 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.Collapse; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class EarthPillar extends EarthAbility implements AddonAbility { + + private static final ConcurrentHashMap AFFECTED_BLOCKS = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap> AFFECTED = new ConcurrentHashMap<>(); + + private Block block; + private BlockFace face; + @Attribute(Attribute.HEIGHT) + private int height; + @Attribute(Attribute.RANGE) + private int range; + private int step; + + private final List blocks = new ArrayList<>(); + + public EarthPillar(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + Block target = BlockSource.getEarthSourceBlock(player, range, ClickType.SHIFT_DOWN); + if (target != null && !AFFECTED_BLOCKS.containsKey(target)) { + List blocks = player.getLastTwoTargetBlocks(null, range); + if (blocks.size() > 1) { + this.player = player; + face = blocks.get(1).getFace(blocks.get(0)); + block = blocks.get(1); + height = getEarthbendableBlocksLength(block, getDirection(face).clone().multiply(-1), height); + start(); + } + } else if (target != null && AFFECTED_BLOCKS.containsKey(target)) { + List blocks = AFFECTED.get(AFFECTED_BLOCKS.get(target)); + if (blocks != null && !blocks.isEmpty()) { + for (Block b : blocks) { + Collapse.revertBlock(b); + } + playEarthbendingSound(target.getLocation()); + AFFECTED.remove(AFFECTED_BLOCKS.get(target)); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + height = config.getInt("Abilities.Earth.EarthPillar.Height"); + range = config.getInt("Abilities.Earth.EarthPillar.Range"); + } + + @Override + public void progress() { + if (step < height) { + step++; + movePillar(); + } else { + AFFECTED.put(this, blocks); + remove(); + } + } + + private void movePillar() { + moveEarth(block, getDirection(face), height); + block = block.getRelative(face); + AFFECTED_BLOCKS.put(block, this); + blocks.add(block); + } + + private Vector getDirection(BlockFace face) { + switch (face) { + case UP: + return new Vector(0, 1, 0); + case DOWN: + return new Vector(0, -1, 0); + case NORTH: + return new Vector(0, 0, -1); + case SOUTH: + return new Vector(0, 0, 1); + case EAST: + return new Vector(1, 0, 0); + case WEST: + return new Vector(-1, 0, 0); + default: + return null; + } + } + + public static void progressAll() { + for (Block block : AFFECTED_BLOCKS.keySet()) { + if (!EarthAbility.isEarthbendable(AFFECTED_BLOCKS.get(block).getPlayer(), block)) { + AFFECTED_BLOCKS.remove(block); + } + } + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return block != null ? block.getLocation() : null; + } + + @Override + public String getName() { + return "EarthPillar"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthPillar.Description"); + } + + public Block getBlock() { + return block; + } + + public void setBlock(Block block) { + this.block = block; + } + + public BlockFace getFace() { + return face; + } + + public void setFace(BlockFace face) { + this.face = face; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public List getBlocks() { + return blocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthPillar.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/earthbending/EarthShard.java b/src/ability/earthbending/EarthShard.java new file mode 100644 index 0000000..793da8e --- /dev/null +++ b/src/ability/earthbending/EarthShard.java @@ -0,0 +1,274 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.AABB; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.CollisionUtil; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.BlockUtil; +import com.jedk1.jedcore.util.ThreadUtil; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.jedk1.jedcore.util.TempFallingBlock; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.stream.Collectors; + +public class EarthShard extends EarthAbility implements AddonAbility { + + @Attribute(Attribute.RANGE) + public static int range; + + public static int abilityRange; + + @Attribute(Attribute.DAMAGE) + public static double normalDmg, metalDmg; + + @Attribute("MaxShots") + public static int maxShards; + + @Attribute(Attribute.COOLDOWN) + public static long cooldown; + + private boolean isThrown = false; + private final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + private Location origin; + private double abilityCollisionRadius, entityCollisionRadius; + private boolean allowKnockup; + private double knockupVelocity; + + private final List tblockTracker = new ArrayList<>(); + private final List readyBlocksTracker = new ArrayList<>(); + private final List fallingBlocks = new ArrayList<>(); + + public EarthShard(Player player) { + super(player); + if (!bPlayer.canBend(this)) return; + + if (hasAbility(player, EarthShard.class)) { + for (EarthShard es : getAbilities(player, EarthShard.class)) { + if (es.isThrown && System.currentTimeMillis() - es.getStartTime() >= 20000) { + es.remove(); + } else { + es.select(); + return; + } + } + } + + setFields(); + origin = player.getLocation().clone(); + raiseEarthBlock(getEarthSourceBlock(range)); + start(); + } + + private void setFields() { + ConfigurationSection c = JedCoreConfig.getConfig(player); + range = c.getInt("Abilities.Earth.EarthShard.PrepareRange"); + abilityRange = c.getInt("Abilities.Earth.EarthShard.AbilityRange"); + normalDmg = c.getDouble("Abilities.Earth.EarthShard.Damage.Normal"); + metalDmg = c.getDouble("Abilities.Earth.EarthShard.Damage.Metal"); + maxShards = c.getInt("Abilities.Earth.EarthShard.MaxShards"); + cooldown = c.getLong("Abilities.Earth.EarthShard.Cooldown"); + abilityCollisionRadius = c.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); + entityCollisionRadius = c.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); + allowKnockup = c.getBoolean("Abilities.Earth.EarthShard.KnockUp.Allow"); + knockupVelocity = c.getDouble("Abilities.Earth.EarthShard.KnockUp.Velocity"); + } + + public void select() { + raiseEarthBlock(getEarthSourceBlock(range)); + } + + public void raiseEarthBlock(Block block) { + if (block == null || tblockTracker.size() >= maxShards) return; + + Vector blockVec = block.getLocation().toVector(); blockVec.setY(0); + for (TempBlock tb : tblockTracker) { + Vector tempVec = tb.getLocation().toVector(); tempVec.setY(0); + if (tempVec.equals(blockVec)) return; + } + + for (int i = 1; i <= 3; i++) { + if (!isTransparent(block.getRelative(BlockFace.UP, i))) return; + } + + if (!isEarthbendable(block)) return; + + if (isMetal(block)) { + playMetalbendingSound(block.getLocation()); + } else { + ParticleEffect.BLOCK_CRACK.display(block.getLocation().add(0, 1, 0), 20, 0, 0, 0, 0, block.getBlockData()); + playEarthbendingSound(block.getLocation()); + } + + Material mat = getCorrectType(block); + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + Location loc = block.getLocation().add(0.5, 0, 0.5); + TempFallingBlock tfb = new TempFallingBlock(loc, mat.createBlockData(), new Vector(0, 0.8, 0), this); + fallingBlocks.add(tfb); + tblockTracker.add(new TempBlock(block, Material.AIR.createBlockData())); + + if (allowKnockup) { + for (Entity e : block.getWorld().getNearbyEntities(block.getLocation(), 1.5, 1.5, 1.5)) { + if (!(e instanceof FallingBlock) && e.getLocation().getY() >= block.getY()) { + ThreadUtil.ensureEntity(e, () -> e.setVelocity(e.getVelocity().add(new Vector(0, knockupVelocity, 0)))); + } + } + } + } + + private Material getCorrectType(Block b) { + switch (b.getType()) { + case SAND: return Material.SANDSTONE; + case RED_SAND: return Material.RED_SANDSTONE; + case GRAVEL: return Material.COBBLESTONE; + default: + if (b.getType().name().endsWith("CONCRETE_POWDER")) { + return Material.getMaterial(b.getType().name().replace("_POWDER", "")); + } + return b.getType(); + } + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + remove(); return; + } + + if (!isThrown) { + if (!bPlayer.canBendIgnoreCooldowns(this) || tblockTracker.isEmpty()) { + remove(); return; + } + + for (TempFallingBlock tfb : new ArrayList<>(TempFallingBlock.getFromAbility(this))) { + FallingBlock fb = tfb.getFallingBlock(); + if (fb == null || fb.isDead() || fb.getLocation().getBlockY() == origin.getBlockY() + 2) { + tfb.remove(); + readyBlocksTracker.add(new TempBlock(fb.getLocation().getBlock(), fb.getBlockData())); + } + } + } else { + for (TempFallingBlock tfb : new ArrayList<>(TempFallingBlock.getFromAbility(this))) { + FallingBlock fb = tfb.getFallingBlock(); + if (fb == null) continue; + AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); + CollisionDetector.checkEntityCollisions(player, collider, e -> { + DamageHandler.damageEntity(e, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : normalDmg, this); + if (e instanceof LivingEntity le) le.setNoDamageTicks(0); + ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 20, 0, 0, 0, 0, fb.getBlockData()); + tfb.remove(); + return false; + }); + } + + if (TempFallingBlock.getFromAbility(this).isEmpty()) { + remove(); + } + } + } + + public void throwShard() { + if (isThrown || readyBlocksTracker.isEmpty()) return; + + Location targetLoc = GeneralMethods.getTargetedLocation(player, abilityRange); + Entity ent = GeneralMethods.getTargetedEntity(player, abilityRange, new ArrayList<>()); + if (ent != null) targetLoc = ent.getLocation(); + + for (TempBlock tb : readyBlocksTracker) { + Vector vel = GeneralMethods.getDirection(tb.getLocation(), targetLoc) + .normalize().multiply(2).add(new Vector(0, 0.2, 0)); + TempFallingBlock tfb = new TempFallingBlock(tb.getLocation(), tb.getBlockData(), vel, this); + fallingBlocks.add(tfb); + } + + revertBlocks(); + isThrown = true; + BendingPlayer.getBendingPlayer(player).addCooldown(this); + } + + private void revertBlocks() { + tblockTracker.forEach(TempBlock::revertBlock); + readyBlocksTracker.forEach(TempBlock::revertBlock); + tblockTracker.clear(); + readyBlocksTracker.clear(); + } + + @Override + public void remove() { + TempFallingBlock.getFromAbility(this).forEach(TempFallingBlock::remove); + revertBlocks(); + super.remove(); + } + + @Override + public long getCooldown() { return cooldown; } + + @Override + public Location getLocation() { return null; } + + @Override + public List getLocations() { + return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); + } + + public void handleCollision(Collision collision) { + CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); + } + + @Override + public double getCollisionRadius() { return abilityCollisionRadius; } + + @Override + public String getName() { return "EarthShard"; } + + @Override + public boolean isHarmlessAbility() { return false; } + + @Override + public boolean isSneakAbility() { return true; } + + @Override + public String getAuthor() { return JedCore.dev; } + + @Override + public String getVersion() { return JedCore.version; } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthShard.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthShard.Enabled"); + } +} diff --git a/src/ability/earthbending/EarthSurf.java b/src/ability/earthbending/EarthSurf.java new file mode 100644 index 0000000..83df672 --- /dev/null +++ b/src/ability/earthbending/EarthSurf.java @@ -0,0 +1,503 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.MaterialUtil; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.TempBlock; + +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.*; + +public class EarthSurf extends EarthAbility implements AddonAbility { + private static final double TARGET_HEIGHT = 1.5; + + private Location location; + private double prevHealth; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private long minimumCooldown; + @Attribute(Attribute.DURATION) + private long duration; + private boolean cooldownEnabled; + private boolean durationEnabled; + private boolean removeOnAnyDamage; + @Attribute(Attribute.SPEED) + private double speed; + private double springStiffness; + private final Set ridingBlocks = new HashSet<>(); + private CollisionDetector collisionDetector = new DefaultCollisionDetector(); + private DoubleSmoother heightSmoother; + + public EarthSurf(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, EarthSurf.class)) { + getAbility(player, EarthSurf.class).remove(); + return; + } + + setFields(); + + location = player.getLocation(); + + if (canStart()) { + prevHealth = player.getHealth(); + + this.flightHandler.createInstance(player, this.getName()); + player.setAllowFlight(true); + player.setFlying(false); + start(); + } + } + + private boolean canStart() { + Block beneath = getBlockBeneath(player.getLocation().clone()); + double maxHeight = getMaxHeight(); + + return isEarthbendable(player, beneath) && !isMetal(beneath) && beneath.getLocation().distanceSquared(player.getLocation()) <= maxHeight * maxHeight; + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.Cooldown"); + minimumCooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown"); + duration = config.getLong("Abilities.Earth.EarthSurf.Duration.Duration"); + cooldownEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Enabled"); + durationEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Duration.Enabled"); + removeOnAnyDamage = config.getBoolean("Abilities.Earth.EarthSurf.RemoveOnAnyDamage"); + speed = config.getDouble("Abilities.Earth.EarthSurf.Speed"); + springStiffness = config.getDouble("Abilities.Earth.EarthSurf.SpringStiffness"); + + int smootherSize = config.getInt("Abilities.Earth.EarthSurf.HeightTolerance"); + this.heightSmoother = new DoubleSmoother(Math.max(smootherSize, 1)); + + if (config.getBoolean("Abilities.Earth.EarthSurf.RelaxedCollisions")) { + this.collisionDetector = new RelaxedCollisionDetector(); + } + + if (!config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Scaled")) { + minimumCooldown = cooldown; + } + } + + @Override + public void progress() { + if (shouldRemove()) { + remove(); + return; + } + + this.player.setFlying(false); + + if (!collisionDetector.isColliding(player) && player.getHealth() >= prevHealth) { + movePlayer(); + + if (removeOnAnyDamage) { + prevHealth = player.getHealth(); + } + } else { + remove(); + } + } + + private boolean shouldRemove() { + if (player == null || player.isDead() || !player.isOnline()) return true; + if (!bPlayer.canBendIgnoreCooldowns(this)) return true; + if (!isEarthbendable(player, getBlockBeneath(player.getLocation().clone()))) return true; + if (durationEnabled && System.currentTimeMillis() > getStartTime() + duration) return true; + + return player.isSneaking(); + } + + private void movePlayer() { + location = player.getEyeLocation().clone(); + location.setPitch(0); + Vector direction = location.getDirection().normalize(); + + // How far the player is above the ground. + double height = getPlayerDistance(); + double maxHeight = getMaxHeight(); + double smoothedHeight = heightSmoother.add(height); + + // Destroy ability if player gets too far from ground. + if (smoothedHeight > maxHeight) { + remove(); + return; + } + + // Calculate the spring force to push the player back to the target height. + double displacement = height - TARGET_HEIGHT; + double force = -springStiffness * displacement; + + double maxForce = 0.5; + if (Math.abs(force) > maxForce) { + // Cap the force to maxForce so the player isn't instantly pulled to the ground. + force = force / Math.abs(force) * maxForce; + } + + Vector velocity = direction.clone().multiply(speed).setY(force); + + rideWave(); + + player.setVelocity(velocity); + player.setFallDistance(0); + } + + private double getMaxHeight() { + return TARGET_HEIGHT + 2.0; + } + + private double getPlayerDistance() { + Location l = player.getLocation().clone(); + while (true) { + if (l.getBlockY() <= l.getWorld().getMinHeight()) break; + if (ElementalAbility.isAir(l.getBlock().getType()) && ridingBlocks.contains(l.getBlock())) break; + if (GeneralMethods.isSolid(l.getBlock())) break; + + l.add(0, -0.1, 0); + } + return player.getLocation().getY() - l.getY(); + } + + private Block getBlockBeneath(Location l) { + while (l.getBlockY() > l.getWorld().getMinHeight() && MaterialUtil.isTransparent(l.getBlock())) { + l.add(0, -0.5, 0); + } + return l.getBlock(); + } + + private void rideWave() { + for (int i = 0; i < 3; i++) { + Location loc = location.clone(); + if (i < 2) + loc.add(getSideDirection(i)); + + //Player Positioning + double distOffset = 2.5; + Location bL = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); + while (!ElementalAbility.isAir(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()).getBlock().getType())) { + loc.add(0, 0.1, 0); + } + + if (isEarthbendable(player, getBlockBeneath(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()))) && getBlockBeneath(bL) != null) { + Block block = loc.clone().add(0, -3.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset - 0.5)).toLocation(player.getWorld()).getBlock(); + Location temp = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); + + if (RegionProtection.isRegionProtected(this, block.getLocation())) { + continue; + } + // Don't render blocks above the player because it looks bad. + // TODO: Change this check to see if it's a reachable position instead. + if (block.getLocation().getY() > this.player.getLocation().getY()) { + continue; + } + + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + if (!GeneralMethods.isSolid(block.getLocation().add(0, 1, 0).getBlock()) && !ElementalAbility.isAir(block.getLocation().add(0, 1, 0).getBlock().getType())) { + if (DensityShift.isPassiveSand(block.getRelative(BlockFace.UP))) { + DensityShift.revertSand(block.getRelative(BlockFace.UP)); + } + + new TempBlock(block.getRelative(BlockFace.UP), Material.AIR.createBlockData()); + } + + if (GeneralMethods.isSolid(block)) { + ridingBlocks.add(block); + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L, true, ridingBlocks::remove); + } else { + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L); + } + + new TempFallingBlock(temp, getBlockBeneath(bL).getBlockData(), new Vector(0, 0.25, 0), this, true); + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()), 1.5D)) { + if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { + e.setVelocity(new Vector(0, 0.3, 0)); + } + } + } + } + } + + private Vector getSideDirection(int side) { + Vector direction = location.clone().getDirection().normalize(); + switch (side) { + case 0: // RIGHT + return new Vector(-direction.getZ(), 0.0, direction.getX()).normalize(); + case 1: // LEFT + return new Vector(direction.getZ(), 0.0, -direction.getX()).normalize(); + default: + break; + } + + return null; + } + + @Override + public void remove() { + this.flightHandler.removeInstance(player, this.getName()); + + if (cooldownEnabled && player.isOnline()) { + long scaledCooldown = cooldown; + + if (durationEnabled && duration > 0) { + double t = Math.min((System.currentTimeMillis() - this.getStartTime()) / (double) duration, 1.0); + scaledCooldown = Math.max((long) (cooldown * t), minimumCooldown); + } + + bPlayer.addCooldown(this, scaledCooldown); + } + + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "EarthSurf"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthSurf.Description"); + } + + public static double getTargetHeight() { + return TARGET_HEIGHT; + } + + public void setLocation(Location location) { + this.location = location; + } + + public double getPrevHealth() { + return prevHealth; + } + + public void setPrevHealth(double prevHealth) { + this.prevHealth = prevHealth; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getMinimumCooldown() { + return minimumCooldown; + } + + public void setMinimumCooldown(long minimumCooldown) { + this.minimumCooldown = minimumCooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public boolean isCooldownEnabled() { + return cooldownEnabled; + } + + public void setCooldownEnabled(boolean cooldownEnabled) { + this.cooldownEnabled = cooldownEnabled; + } + + public boolean isDurationEnabled() { + return durationEnabled; + } + + public void setDurationEnabled(boolean durationEnabled) { + this.durationEnabled = durationEnabled; + } + + public boolean isRemoveOnAnyDamage() { + return removeOnAnyDamage; + } + + public void setRemoveOnAnyDamage(boolean removeOnAnyDamage) { + this.removeOnAnyDamage = removeOnAnyDamage; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public double getSpringStiffness() { + return springStiffness; + } + + public void setSpringStiffness(double springStiffness) { + this.springStiffness = springStiffness; + } + + public Set getRidingBlocks() { + return ridingBlocks; + } + + public CollisionDetector getCollisionDetector() { + return collisionDetector; + } + + public void setCollisionDetector(CollisionDetector collisionDetector) { + this.collisionDetector = collisionDetector; + } + + public DoubleSmoother getHeightSmoother() { + return heightSmoother; + } + + public void setHeightSmoother(DoubleSmoother heightSmoother) { + this.heightSmoother = heightSmoother; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + return config.getBoolean("Abilities.Earth.EarthSurf.Enabled"); + } + + private interface CollisionDetector { + boolean isColliding(Player player); + } + + private abstract static class AbstractCollisionDetector implements CollisionDetector { + protected boolean isCollision(Location location) { + Block block = location.getBlock(); + return !MaterialUtil.isTransparent(block) || block.isLiquid() || block.getType().isSolid(); + } + } + + private class DefaultCollisionDetector extends AbstractCollisionDetector { + @Override + public boolean isColliding(Player player) { + // The location in front of the player, where the player will be in one second. + Location front = player.getEyeLocation().clone(); + front.setPitch(0); + + Vector direction = front.getDirection().clone().setY(0).normalize(); + double playerSpeed = player.getVelocity().clone().setY(0).length(); + + front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); + + for (int i = 0; i < 3; ++i) { + Location location = front.clone().add(0, -i, 0); + if (isCollision(location)) { + return true; + } + } + + return false; + } + } + + private class RelaxedCollisionDetector extends AbstractCollisionDetector { + @Override + public boolean isColliding(Player player) { + // The location in front of the player, where the player will be in one second. + Location front = player.getEyeLocation().clone().subtract(0.0, 0.5, 0.0); + front.setPitch(0); + + Vector direction = front.getDirection().clone().setY(0).normalize(); + double playerSpeed = player.getVelocity().clone().setY(0).length(); + + front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); + + return isCollision(front); + } + } + + private static class DoubleSmoother { + private final double[] values; + private final int size; + private int index; + + public DoubleSmoother(int size) { + this.size = size; + this.index = 0; + + values = new double[size]; + } + + public double add(double value) { + values[index] = value; + index = (index + 1) % size; + return get(); + } + + public double get() { + return Arrays.stream(this.values).sum() / this.size; + } + } +} diff --git a/src/ability/earthbending/Fissure.java b/src/ability/earthbending/Fissure.java new file mode 100644 index 0000000..7f947a5 --- /dev/null +++ b/src/ability/earthbending/Fissure.java @@ -0,0 +1,441 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.Information; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +public class Fissure extends LavaAbility implements AddonAbility { + + @Attribute(Attribute.RANGE) + private int slapRange; + @Attribute(Attribute.WIDTH) + private int maxWidth; + private long slapDelay; + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + private Location location; + private Vector direction; + private Vector blockDirection; + private long time; + private long step; + private int slap; + private int width; + private boolean progressed; + + static Random rand = new Random(); + + private final List centerSlap = new ArrayList<>(); + private final List blocks = new ArrayList<>(); + private final List tempblocks = new ArrayList<>(); + + public Fissure(Player player) { + super(player); + + if (!bPlayer.canBend(this) || hasAbility(player, Fissure.class) || !bPlayer.canLavabend()) { + return; + } + + setFields(); + time = System.currentTimeMillis(); + step = System.currentTimeMillis() + slapDelay; + location = player.getLocation().clone(); + location.setPitch(0); + direction = location.getDirection(); + blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); + blockDirection = blockDirection.setZ(Math.round(direction.getZ())); + if (prepareLine()) { + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + slapRange = config.getInt("Abilities.Earth.Fissure.SlapRange"); + maxWidth = config.getInt("Abilities.Earth.Fissure.MaxWidth"); + slapDelay = config.getInt("Abilities.Earth.Fissure.SlapDelay"); + duration = config.getInt("Abilities.Earth.Fissure.Duration"); + cooldown = config.getInt("Abilities.Earth.Fissure.Cooldown"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (System.currentTimeMillis() > step && slap <= centerSlap.size()) { + time = System.currentTimeMillis(); + step = System.currentTimeMillis() + slapDelay; + slapCenter(); + slap++; + } + if (System.currentTimeMillis() > time + duration) { + remove(); + } + } + + private boolean prepareLine() { + direction = player.getEyeLocation().getDirection().setY(0).normalize(); + blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); + blockDirection = blockDirection.setZ(Math.round(direction.getZ())); + Location origin = player.getLocation().add(0, -1, 0).add(blockDirection.multiply(2)); + if (isEarthbendable(player, origin.getBlock())) { + BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, slapRange); + + while (bi.hasNext()) { + Block b = bi.next(); + + if (b.getY() > 1 && b.getY() < 255 && !RegionProtection.isRegionProtected(this, b.getLocation())) { + if (EarthAbility.getMovedEarth().containsKey(b)){ + Information info = EarthAbility.getMovedEarth().get(b); + if(!info.getBlock().equals(b)) { + continue; + } + } + + while (!isEarthbendable(player, b)) { + b = b.getRelative(BlockFace.DOWN); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b)) { + break; + } + } + + while (!isTransparent(b.getRelative(BlockFace.UP))) { + b = b.getRelative(BlockFace.UP); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(player, b)) { + centerSlap.add(b.getLocation()); + } else { + break; + } + } + } + return true; + } + return false; + } + + private void slapCenter() { + for (Location location : centerSlap) { + if (centerSlap.indexOf(location) == slap) { + addTempBlock(location.getBlock(), Material.LAVA); + } + } + if (slap >= centerSlap.size()) { + progressed = true; + } + } + + public static void performAction(Player player) { + if (hasAbility(player, Fissure.class)) { + getAbility(player, Fissure.class).performAction(); + } + } + + private void performAction() { + if (width < maxWidth) { + expandFissure(); + } else if (blocks.contains(player.getTargetBlock(null, 10))) { + forceRevert(); + } + } + + private void expandFissure() { + if (progressed && width <= maxWidth) { + width++; + for (Location location : centerSlap) { + Block left = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)), width); + expand(left); + + Block right = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)).getOppositeFace(), width); + expand(right); + } + } + Collections.reverse(blocks); + } + + private void expand(Block block) { + if (block != null && block.getY() > 1 && block.getY() < 255 && !RegionProtection.isRegionProtected(this, block.getLocation())) { + if (EarthAbility.getMovedEarth().containsKey(block)){ + Information info = EarthAbility.getMovedEarth().get(block); + if(!info.getBlock().equals(block)) { + return; + } + } + + while (!isEarthbendable(player, block)) { + block = block.getRelative(BlockFace.DOWN); + if (block.getY() < 1 || block.getY() > 255) { + break; + } + if (isEarthbendable(player, block)) { + break; + } + } + + while (!isTransparent(player, block.getRelative(BlockFace.UP))) { + block = block.getRelative(BlockFace.UP); + if (block.getY() < 1 || block.getY() > 255) { + break; + } + if (isEarthbendable(player, block.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(player, block)) { + addTempBlock(block, Material.LAVA); + } + } + } + + private void addTempBlock(Block block, Material material) { + ParticleEffect.LAVA.display(block.getLocation(), 0, 0, 0, 0, 1); + playEarthbendingSound(block.getLocation()); + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + tempblocks.add(new TempBlock(block, material.createBlockData(), this)); + blocks.add(block); + } + + public BlockFace getLeftBlockFace(BlockFace forward) { + switch (forward) { + case NORTH: + return BlockFace.WEST; + case SOUTH: + return BlockFace.EAST; + case WEST: + return BlockFace.SOUTH; + case EAST: + return BlockFace.NORTH; + case NORTH_WEST: + return BlockFace.SOUTH_WEST; + case NORTH_EAST: + return BlockFace.NORTH_WEST; + case SOUTH_WEST: + return BlockFace.SOUTH_EAST; + case SOUTH_EAST: + return BlockFace.NORTH_EAST; + default: + return BlockFace.NORTH; + } + } + + private void forceRevert() { + coolLava(); + } + + private void coolLava() { + tempblocks.forEach(TempBlock::revertBlock); + for (Block block : blocks) { + new TempBlock(block, Material.STONE.createBlockData(), 500 + (long) rand.nextInt((int) 1000)); + } + blocks.clear(); + tempblocks.clear(); + } + + @Override + public void remove() { + coolLava(); + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "Fissure"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.Fissure.Description"); + } + + public int getSlapRange() { + return slapRange; + } + + public void setSlapRange(int slapRange) { + this.slapRange = slapRange; + } + + public int getMaxWidth() { + return maxWidth; + } + + public void setMaxWidth(int maxWidth) { + this.maxWidth = maxWidth; + } + + public long getSlapDelay() { + return slapDelay; + } + + public void setSlapDelay(long slapDelay) { + this.slapDelay = slapDelay; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public void setLocation(Location location) { + this.location = location; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public Vector getBlockDirection() { + return blockDirection; + } + + public void setBlockDirection(Vector blockDirection) { + this.blockDirection = blockDirection; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public long getStep() { + return step; + } + + public void setStep(long step) { + this.step = step; + } + + public int getSlap() { + return slap; + } + + public void setSlap(int slap) { + this.slap = slap; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public boolean isProgressed() { + return progressed; + } + + public void setProgressed(boolean progressed) { + this.progressed = progressed; + } + + public List getCenterSlap() { + return centerSlap; + } + + public List getBlocks() { + return blocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.Fissure.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/earthbending/LavaDisc.java b/src/ability/earthbending/LavaDisc.java new file mode 100644 index 0000000..65cdf08 --- /dev/null +++ b/src/ability/earthbending/LavaDisc.java @@ -0,0 +1,553 @@ +package com.jedk1.jedcore.ability.earthbending; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; + +public class LavaDisc extends LavaAbility implements AddonAbility { + + private Location location; + private int recallCount; + + private long time; + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + private int recallLimit; + private boolean trailFlow; + + private CompositeRemovalPolicy removalPolicy; + private DiscRenderer discRenderer; + private State state; + private final Set trailBlocks = new HashSet<>(); + + public LavaDisc(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { + return; + } + + // Allow new LavaDisc if all existing instances for that player are in CleanupState. + for (LavaDisc disc : CoreAbility.getAbilities(player, LavaDisc.class)) { + if (!(disc.state instanceof CleanupState)) { + return; + } + } + + state = new HoldState(); + time = System.currentTimeMillis(); + discRenderer = new DiscRenderer(this.player); + + setFields(); + + if (prepare()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + damage = config.getDouble("Abilities.Earth.LavaDisc.Damage"); + cooldown = config.getLong("Abilities.Earth.LavaDisc.Cooldown"); + duration = config.getLong("Abilities.Earth.LavaDisc.Duration"); + recallLimit = config.getInt("Abilities.Earth.LavaDisc.RecallLimit") - 1; + trailFlow = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.TrailFlow"); + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new SwappedSlotsRemovalPolicy<>(bPlayer, LavaDisc.class) + ); + + this.removalPolicy.load(config); + } + + private boolean prepare() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + long sourceRegen = config.getLong("Abilities.Earth.LavaDisc.Source.RegenTime"); + boolean lavaOnly = config.getBoolean("Abilities.Earth.LavaDisc.Source.LavaOnly"); + double sourceRange = config.getDouble("Abilities.Earth.LavaDisc.Source.Range"); + + if (getLavaSourceBlock(player, sourceRange) != null) { + Block block = getLavaSourceBlock(player, sourceRange); + new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); + return true; + } else if (getEarthSourceBlock(sourceRange) != null) { + if (lavaOnly) + return false; + Block block = getEarthSourceBlock(sourceRange); + new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); + return true; + } + + return false; + } + + @Override + public void progress() { + if (this.removalPolicy.shouldRemove()) { + if (!player.isOnline()) { + // Revert all of the lava blocks if the player goes offline. + for (Block block : trailBlocks) { + RegenTempBlock.revert(block); + } + bPlayer.addCooldown(this); + remove(); + return; + } else if (!(state instanceof CleanupState)) { + state = new CleanupState(); + } + } + + if (!hasAbility(player, LavaDisc.class)) { + return; + } + + state.update(); + } + + public static boolean canFlowFrom(Block from) { + Material type = from.getType(); + if (type != Material.LAVA && !ElementalAbility.isAir(type)) { + return true; + } + + for (LavaDisc disc : CoreAbility.getAbilities(LavaDisc.class)) { + if (disc.trailFlow) continue; + + if (disc.trailBlocks.contains(from)) { + return false; + } + } + + return true; + } + + private boolean isLocationSafe() { + if (!isLocationSafe(location)) { + return false; + } + + Block block = location.getBlock(); + + return isTransparent(block); + } + + private boolean isLocationSafe(Location location) { + if (location == null || location.getWorld() == null) { + return false; + } + + return location.getY() >= location.getWorld().getMinHeight() && location.getY() <= (location.getWorld().getMaxHeight() - 1); + } + + private void doDamage(Entity entity) { + DamageHandler.damageEntity(entity, damage, this); + entity.setFireTicks(20); + new FireDamageTimer(entity, player, this); + ParticleEffect.LAVA.display(entity.getLocation(), 15, Math.random(), Math.random(), Math.random(), 0.1); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "LavaDisc"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaDisc.Description"); + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getRecallCount() { + return recallCount; + } + + public void setRecallCount(int recallCount) { + this.recallCount = recallCount; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public int getRecallLimit() { + return recallLimit; + } + + public void setRecallLimit(int recallLimit) { + this.recallLimit = recallLimit; + } + + public boolean isTrailFlow() { + return trailFlow; + } + + public void setTrailFlow(boolean trailFlow) { + this.trailFlow = trailFlow; + } + + public DiscRenderer getDiscRenderer() { + return discRenderer; + } + + public void setDiscRenderer(DiscRenderer discRenderer) { + this.discRenderer = discRenderer; + } + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + public Set getTrailBlocks() { + return trailBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.LavaDisc.Enabled"); + } + + private interface State { + void update(); + } + + // Renders the particles showing that the player is holding lava. + // Transitions to ForwardTravelState when the player stops sneaking. + private class HoldState implements State { + @Override + public void update() { + location = player.getEyeLocation(); + Vector dV = location.getDirection().normalize(); + location.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); + + dV = dV.multiply(0.1); + + while (!isLocationSafe() && isLocationSafe(player.getLocation())) { + location.subtract(dV); + if (location.distanceSquared(player.getEyeLocation()) > (3 * 3)) { + break; + } + } + + discRenderer.render(location, false); + + location.setPitch(0); + + if (!player.isSneaking()) { + time = System.currentTimeMillis(); + state = new ForwardTravelState(location.getDirection().normalize()); + } + } + } + + private abstract class TravelState implements State { + private final boolean passHit; + + protected Vector direction; + protected boolean hasHit; + + public TravelState() { + this(player.getEyeLocation().getDirection()); + } + + public TravelState(Vector direction) { + this.direction = direction; + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + passHit = config.getBoolean("Abilities.Earth.LavaDisc.ContinueAfterEntityHit"); + } + + protected void move() { + for (int i = 0; i < 5; i++) { + location = location.add(direction.clone().multiply(0.15)); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.0D)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + doDamage(entity); + if (!passHit) { + hasHit = true; + return; + } + } + } + } + } + } + + // Moves the disc forward. Makes the disc destroy blocks if enabled. + // Transitions to ReverseTravelState if the player starts sneaking and can recall. + // Transitions to CleanupState if it times out or hits an entity. + private class ForwardTravelState extends TravelState { + public ForwardTravelState() { + this(player.getEyeLocation().getDirection()); + } + + public ForwardTravelState(Vector direction) { + super(direction); + } + + @Override + public void update() { + if (!isLocationSafe() || System.currentTimeMillis() > time + duration) { + state = new CleanupState(); + return; + } + + if (player.isSneaking() && recallCount <= recallLimit) { + state = new ReverseTravelState(); + return; + } + + alterPitch(); + move(); + discRenderer.render(location, true); + + if (hasHit) { + state = new CleanupState(); + } + } + + private void alterPitch() { + Location loc = player.getLocation().clone(); + + if (loc.getPitch() < -20) + loc.setPitch(-20); + if (loc.getPitch() > 20) + loc.setPitch(20); + + direction = loc.getDirection().normalize(); + } + } + + // Returns the disc to the player. + // Transitions to ForwardTravelState if the player stops sneaking. + // Transitions to HoldState if the disc gets close enough to the player. + private class ReverseTravelState extends TravelState { + @Override + public void update() { + if (!player.isSneaking()) { + state = new ForwardTravelState(); + return; + } + + Location loc = player.getEyeLocation(); + Vector dV = loc.getDirection().normalize(); + loc.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); + + Vector vector = loc.toVector().subtract(location.toVector()); + direction = loc.setDirection(vector).getDirection().normalize(); + + move(); + discRenderer.render(location, true); + + double distanceAway = location.distance(loc); + if (distanceAway < 0.5) { + recallCount++; + // Player is holding the disc when it gets close enough to them. + state = new HoldState(); + } + } + } + + // Waits for the RegenTempBlocks to revert. + // This exists so the instance stays alive and block flow events can stop the lava from flowing. + private class CleanupState implements State { + private final long startTime; + private final long regenTime; + + public CleanupState() { + this.startTime = System.currentTimeMillis(); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); + bPlayer.addCooldown(LavaDisc.this); + } + + @Override + public void update() { + if (System.currentTimeMillis() >= startTime + regenTime || trailBlocks.isEmpty()) { + remove(); + } + } + } + + private class DiscRenderer { + private final Player player; + private int angle; + + private final boolean damageBlocks; + private final List meltable; + private final long regenTime; + private final boolean lavaTrail; + + private final int particles; + + + public DiscRenderer(Player player) { + this.player = player; + this.angle = 0; + + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + damageBlocks = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.BlockDamage"); + meltable = config.getStringList("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks"); + regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); + lavaTrail = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.LavaTrail"); + particles = config.getInt("Abilities.Earth.LavaDisc.Particles"); + } + + void render(Location location, boolean largeLava) { + if (largeLava) + ParticleEffect.LAVA.display(location, particles * 2, Math.random(), Math.random(), Math.random(), 0.1); + else + ParticleEffect.LAVA.display(location, 1, Math.random(), Math.random(), Math.random(), 0.1); + + angle += 1; + if (angle > 360) + angle = 0; + + for (Location l : JCMethods.getCirclePoints(location, 20, 1, angle)) { + ParticleEffect.REDSTONE.display(l, 0, 196, 93, 0, 0.005F, new Particle.DustOptions(Color.fromRGB(196, 93, 0), 1)); + if (largeLava && damageBlocks) + damageBlocks(l); + } + + for (Location l : JCMethods.getCirclePoints(location, 10, 0.5, angle)) { + ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.01); + ParticleEffect.SMOKE_NORMAL.display(l, 1, 0, 0, 0, 0.05); + if (largeLava && damageBlocks) + damageBlocks(l); + } + } + + private void damageBlocks(Location l) { + if (!RegionProtection.isRegionProtected(player, l, LavaDisc.this)) { + if (!TempBlock.isTempBlock(l.getBlock()) && (isEarthbendable(player, l.getBlock()) || isMetal(l.getBlock()) || meltable.contains(l.getBlock().getType().name()))) { + if (DensityShift.isPassiveSand(l.getBlock())) { + DensityShift.revertSand(l.getBlock()); + } + + if (lavaTrail) { + new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled) bd).setLevel(4)), regenTime); + + trailBlocks.add(l.getBlock()); + } else { + new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), regenTime); + } + + ParticleEffect.LAVA.display(l, particles * 2, Math.random(), Math.random(), Math.random(), 0.2); + } + } + } + } +} diff --git a/src/ability/earthbending/LavaFlux.java b/src/ability/earthbending/LavaFlux.java new file mode 100644 index 0000000..6368fbf --- /dev/null +++ b/src/ability/earthbending/LavaFlux.java @@ -0,0 +1,451 @@ +package com.jedk1.jedcore.ability.earthbending; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.Information; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.Vector; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; + +public class LavaFlux extends LavaAbility implements AddonAbility { + + @Attribute(Attribute.SPEED) + private int speed; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + private long cleanup; + @Attribute(Attribute.DAMAGE) + private double damage; + private boolean wave; + + private Location location; + private int step; + private int counter; + private long time; + private boolean complete; + + private double knockUp; + private double knockBack; + + Random rand = new Random(); + + private static final BlockData LAVA = Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(1)); + + private final List flux = new ArrayList<>(); + + private Map blocks = new HashMap<>(); + private Map above = new HashMap<>(); + + public LavaFlux(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { + return; + } + + setFields(); + time = System.currentTimeMillis(); + if (prepareLine()) { + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + speed = config.getInt("Abilities.Earth.LavaFlux.Speed"); + if (speed < 1) speed = 1; + range = config.getInt("Abilities.Earth.LavaFlux.Range"); + cooldown = config.getLong("Abilities.Earth.LavaFlux.Cooldown"); + duration = config.getLong("Abilities.Earth.LavaFlux.Duration"); + cleanup = config.getLong("Abilities.Earth.LavaFlux.Cleanup"); + damage = config.getDouble("Abilities.Earth.LavaFlux.Damage"); + wave = config.getBoolean("Abilities.Earth.LavaFlux.Wave"); + knockUp = config.getDouble("Abilities.Earth.LavaFlux.KnockUp"); + knockBack = config.getDouble("Abilities.Earth.LavaFlux.KnockBack"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + counter++; + if (!complete) { + if (speed <= 1 || counter % speed == 0) { + for (int i = 0; i <= 2; i++) { + step++; + progressFlux(); + } + } + } else if (duration > cleanup) { + if (System.currentTimeMillis() > time + duration) { + for (TempBlock tb : blocks.values()) { + if (!tb.isReverted()) tb.setType(Material.STONE); + } + remove(); + } + } + } + + private boolean prepareLine() { + Vector direction = player.getEyeLocation().getDirection().setY(0).normalize(); + Vector blockdirection = direction.clone().setX(Math.round(direction.getX())); + blockdirection = blockdirection.setZ(Math.round(direction.getZ())); + Location origin = player.getLocation().add(0, -1, 0).add(blockdirection.multiply(2)); + if (isEarthbendable(player, origin.getBlock())) { + BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, range); + + while (bi.hasNext()) { + Block b = bi.next(); + + if (b.getY() > b.getWorld().getMinHeight() && b.getY() < b.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, b.getLocation()) && !EarthAbility.getMovedEarth().containsKey(b)) { + if (isWater(b)) break; + while (!isEarthbendable(player, b)) { + b = b.getRelative(BlockFace.DOWN); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b)) { + break; + } + } + + while (!isTransparent(b.getRelative(BlockFace.UP))) { + b = b.getRelative(BlockFace.UP); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(player, b)) { + flux.add(b.getLocation()); + Block left = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)), 1); + expand(left); + Block right = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)).getOppositeFace(), 1); + expand(right); + } else { + break; + } + } + } + return true; + } + return false; + } + + private void progressFlux() { + for (Location location : flux) { + if (flux.indexOf(location) <= step) { + if (!blocks.containsKey(location.getBlock())) { //Make a new temp block if we haven't made one there before + blocks.put(location.getBlock(), new TempBlock(location.getBlock(), LAVA, duration + cleanup, this)); + } + + //new RegenTempBlock(location.getBlock(), Material.LAVA, LAVA, duration + cleanup); + this.location = location; + if (flux.indexOf(location) == step) { + Block above = location.getBlock().getRelative(BlockFace.UP); + ParticleEffect.LAVA.display(above.getLocation(), 2, Math.random(), Math.random(), Math.random(), 0); + applyDamageFromWave(above.getLocation()); + + if (isPlant(above) || isSnow(above)) { + final Block above2 = above.getRelative(BlockFace.UP); + if (isPlant(above) || isSnow(above)) { + TempBlock tb = new TempBlock(above, Material.AIR.createBlockData(), duration + cleanup, this); + this.above.put(above, tb); + if (isPlant(above2) && above2.getBlockData() instanceof Bisected) { + TempBlock tb2 = new TempBlock(above2, Material.AIR.createBlockData(), duration + cleanup + 30_000, this); + tb.addAttachedBlock(tb2); + } + } + } else if (wave && isTransparent(above)) { + new TempBlock(location.getBlock().getRelative(BlockFace.UP), LAVA, speed * 150L, this); + } + } + } + } + if (step >= flux.size()) { + wave = false; + complete = true; + time = System.currentTimeMillis(); + + for (TempBlock tb : blocks.values()) { //Make sure they all revert at the same time because it looks nice + long time = duration + cleanup + rand.nextInt(1000); + tb.setRevertTime(time); + + if (this.above.containsKey(tb.getBlock().getRelative(BlockFace.UP))) { + this.above.get(tb.getBlock().getRelative(BlockFace.UP)).setRevertTime(time); + } + } + } + } + + private void applyDamageFromWave(Location location) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 1.5)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + LivingEntity livingEntity = (LivingEntity) entity; + + DamageHandler.damageEntity(entity, damage, this); + new FireDamageTimer(entity, player, this); + + Vector direction = livingEntity.getLocation().toVector().subtract(player.getLocation().toVector()).normalize(); + Vector knockbackVelocity = direction.multiply(knockBack).setY(knockUp); + + livingEntity.setVelocity(knockbackVelocity); + } + } + } + + private void expand(Block block) { + if (block != null && block.getY() > block.getWorld().getMinHeight() && block.getY() < block.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, block.getLocation())) { + if (EarthAbility.getMovedEarth().containsKey(block)){ + Information info = EarthAbility.getMovedEarth().get(block); + if(!info.getBlock().equals(block)) { + return; + } + } + + if (isWater(block)) return; + while (!isEarthbendable(block)) { + block = block.getRelative(BlockFace.DOWN); + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(block)) { + break; + } + } + + while (!isTransparent(block.getRelative(BlockFace.UP))) { + block = block.getRelative(BlockFace.UP); + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(block.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(block)) { + flux.add(block.getLocation()); + } + } + } + + public BlockFace getLeftBlockFace(BlockFace forward) { + switch (forward) { + case NORTH: + return BlockFace.WEST; + case SOUTH: + return BlockFace.EAST; + case WEST: + return BlockFace.SOUTH; + case NORTH_WEST: + return BlockFace.SOUTH_WEST; + case NORTH_EAST: + return BlockFace.NORTH_WEST; + case SOUTH_WEST: + return BlockFace.SOUTH_EAST; + case SOUTH_EAST: + return BlockFace.NORTH_EAST; + default: + return BlockFace.NORTH; + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "LavaFlux"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaFlux.Description"); + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public long getCleanup() { + return cleanup; + } + + public void setCleanup(long cleanup) { + this.cleanup = cleanup; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean isWave() { + return wave; + } + + public void setWave(boolean wave) { + this.wave = wave; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public int getCounter() { + return counter; + } + + public void setCounter(int counter) { + this.counter = counter; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public boolean isComplete() { + return complete; + } + + public void setComplete(boolean complete) { + this.complete = complete; + } + + public List getFlux() { + return flux; + } + + @Override + public void load() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + if (config.get("Abilities.Earth.LavaFlux.Speed") instanceof String) { + config.set("Abilities.Earth.LavaFlux.Speed", 1); + JedCore.plugin.saveConfig(); + JedCore.plugin.reloadConfig(); + } + } + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.LavaFlux.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/earthbending/LavaThrow.java b/src/ability/earthbending/LavaThrow.java new file mode 100644 index 0000000..07bd010 --- /dev/null +++ b/src/ability/earthbending/LavaThrow.java @@ -0,0 +1,344 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; + +import org.bukkit.FluidCollisionMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.RayTraceResult; +import org.bukkit.util.Vector; + +import java.util.concurrent.ConcurrentHashMap; + +public class LavaThrow extends LavaAbility implements AddonAbility { + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.SELECT_RANGE) + private int sourceRange; + private long sourceRegen; + @Attribute("MaxShots") + private int shotMax; + @Attribute(Attribute.FIRE_TICK) + private int fireTicks; + @Attribute("CurveFactor") + private double curveFactor; + + private Location location; + private int shots; + private Block selectedSource; + private boolean isInitialState = true; + + private final ConcurrentHashMap blasts = new ConcurrentHashMap<>(); + + public LavaThrow(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { + return; + } + + setFields(); + + location = player.getLocation(); + location.setPitch(0); + + if (prepare()) { + player.getWorld().playSound(selectedSource.getLocation(), Sound.ITEM_BUCKET_FILL_LAVA, 1.0f, 1.0f); + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.LavaThrow.Cooldown"); + range = config.getInt("Abilities.Earth.LavaThrow.Range"); + damage = config.getDouble("Abilities.Earth.LavaThrow.Damage"); + sourceRange = config.getInt("Abilities.Earth.LavaThrow.SourceGrabRange"); + sourceRegen = config.getLong("Abilities.Earth.LavaThrow.SourceRegenDelay"); + shotMax = config.getInt("Abilities.Earth.LavaThrow.MaxShots"); + fireTicks = config.getInt("Abilities.Earth.LavaThrow.FireTicks"); + curveFactor = config.getDouble("Abilities.Earth.LavaThrow.CurveFactor"); + } + + @Override + public void progress() { + if (player == null || player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.getBoundAbilityName().equalsIgnoreCase("LAVATHROW")) { + remove(); + if (shots > 0) bPlayer.addCooldown(this); + return; + } + + if (player.getLocation().distance(selectedSource.getLocation()) >= sourceRange) { + remove(); + if (shots > 0) bPlayer.addCooldown(this); + return; + } + + if (blasts.isEmpty() && shots >= shotMax && !isInitialState) { + remove(); + bPlayer.addCooldown(this); + return; + } + + selectedSource.getWorld().spawnParticle(Particle.FLAME, selectedSource.getLocation(), 2, 0.3, 1.0, 0.3, 0.05); + selectedSource.getWorld().spawnParticle(Particle.LAVA, selectedSource.getLocation(), 2, 0.2, 0.2, 0.2, 0); + + handleBlasts(); + } + + private boolean prepare() { + Block targetBlock = getTargetLavaBlock(sourceRange); + + if (targetBlock != null) { + selectedSource = targetBlock; + } + + return selectedSource != null; + } + + public Block getTargetLavaBlock(int maxDistance) { + Location eyeLocation = player.getEyeLocation(); + Vector direction = eyeLocation.getDirection(); + World world = player.getWorld(); + + RayTraceResult result = world.rayTraceBlocks( + eyeLocation, direction, maxDistance, + FluidCollisionMode.ALWAYS, true + ); + + if (result != null) { + Block hitBlock = result.getHitBlock(); + if (LavaAbility.isLava(hitBlock)) { + return hitBlock; + } + } + return null; + } + + public void createBlast() { + if (selectedSource != null && shots < shotMax) { + isInitialState = false; + shots++; + + if (shots >= shotMax) { + bPlayer.addCooldown(this); + } + + Location origin = selectedSource.getLocation().clone().add(0, 2, 0); + player.getWorld().playSound(origin, Sound.ITEM_BUCKET_EMPTY_LAVA, 1.0f, 1.0f); + double viewRange = range + origin.distance(player.getEyeLocation()); + Location viewTarget = GeneralMethods.getTargetedLocation(player, viewRange, Material.WATER, Material.LAVA); + Vector direction = viewTarget.clone().subtract(origin).toVector().normalize(); + Location head = origin.clone(); + + head.setDirection(direction); + blasts.put(head, origin); + + new RegenTempBlock(selectedSource.getRelative(BlockFace.UP), Material.LAVA, + Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); + new RegenTempBlock(selectedSource, Material.AIR, Material.AIR.createBlockData(), sourceRegen, false); + } + } + + public void handleBlasts() { + for (Location l : blasts.keySet()) { + Location head = l.clone(); + Location origin = blasts.get(l); + + if (l.distance(origin) > range) { + blasts.remove(l); + continue; + } + + if (GeneralMethods.isSolid(l.getBlock())) { + blasts.remove(l); + continue; + } + + Vector currentDirection = head.getDirection(); + Vector playerLookDirection = player.getEyeLocation().getDirection(); + + Vector curveVector = playerLookDirection.clone() + .subtract(currentDirection) + .multiply(curveFactor); + + Vector newDirection = currentDirection.clone() + .add(curveVector) + .normalize(); + + head.setDirection(newDirection); + head = head.add(newDirection.multiply(1)); + + new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); + ParticleEffect.LAVA.display(head, 1, Math.random(), Math.random(), Math.random(), 0); + + boolean hit = false; + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 2.0D)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { + DamageHandler.damageEntity(entity, damage, this); + blasts.remove(l); + + hit = true; + entity.setFireTicks(this.fireTicks); + } + } + + if (!hit) { + blasts.remove(l); + blasts.put(head, origin); + } + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "LavaThrow"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaThrow.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getSourceRange() { + return sourceRange; + } + + public void setSourceRange(int sourceRange) { + this.sourceRange = sourceRange; + } + + public long getSourceRegen() { + return sourceRegen; + } + + public void setSourceRegen(long sourceRegen) { + this.sourceRegen = sourceRegen; + } + + public int getShotMax() { + return shotMax; + } + + public void setShotMax(int shotMax) { + this.shotMax = shotMax; + } + + public int getFireTicks() { + return fireTicks; + } + + public void setFireTicks(int fireTicks) { + this.fireTicks = fireTicks; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getShots() { + return shots; + } + + public void setShots(int shots) { + this.shots = shots; + } + + public ConcurrentHashMap getBlasts() { + return blasts; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.LavaThrow.Enabled"); + } +} diff --git a/src/ability/earthbending/MagnetShield.java b/src/ability/earthbending/MagnetShield.java new file mode 100644 index 0000000..4373c5c --- /dev/null +++ b/src/ability/earthbending/MagnetShield.java @@ -0,0 +1,281 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; + +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + + +public class MagnetShield extends MetalAbility implements AddonAbility { + + private static List METAL_LIST; + + private boolean isClickState = false; + private long startTime; + + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.RANGE) + private double range; + + private double velocity; + private boolean repelArrows; + private boolean repelLivingEntities; + private long shiftCooldown; + private long clickCooldown; + + public MagnetShield(Player player) { + super(player); + + if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { + return; + } + + if (!bPlayer.canBend(this)) { + return; + } + + player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); + + setFields(); + loadMaterialsFromConfig(); + start(); + } + + public MagnetShield(Player player, boolean isClickState) { + super(player); + + if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { + return; + } + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, MagnetShield.class)) { + getAbility(player, MagnetShield.class).remove(); + return; + } + + setFields(); + + if (isClickState) { + this.isClickState = true; + startTime = System.currentTimeMillis(); + bPlayer.addCooldown(this, duration + 1); + } + + player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); + + loadMaterialsFromConfig(); + start(); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + remove(); + return; + } + + if (isClickState) { + if (System.currentTimeMillis() - startTime >= duration) { + bPlayer.addCooldown(this, clickCooldown); + remove(); + return; + } + } else { + if (!player.isSneaking()) { + bPlayer.addCooldown(this, shiftCooldown); + remove(); + return; + } + } + + renderMagneticFieldLines(); + repelMetal(); + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return player.getLocation(); + } + + @Override + public String getName() { + return "MagnetShield"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MagnetShield.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MagnetShield.Enabled"); + } + + private void renderMagneticFieldLines() { + Location playerLocation = player.getLocation(); + int numLoops = 5; + int pointsPerLoop = 30; + double verticalSpacing = 0.06; + + for (int loop = 0; loop < numLoops; loop++) { + double currentRadius = range * (1 - (double) loop / numLoops); + double currentHeight = ((loop - numLoops / 2.0) * verticalSpacing) + 0.3; + + for (int i = 0; i < pointsPerLoop; i++) { + double angle = 2 * Math.PI * i / pointsPerLoop; + double x = currentRadius * Math.cos(angle); + double z = currentRadius * Math.sin(angle); + Location particleLocation = playerLocation.clone().add(x, currentHeight, z); + JedCore.plugin.getParticleAdapter().displayMagneticParticles(particleLocation); + } + } + } + + private void loadMaterialsFromConfig() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + List materialNames = config.getStringList("Abilities.Earth.MagnetShield.Materials"); + METAL_LIST = new ArrayList<>(); + + for (String materialName : materialNames) { + Material material = Material.getMaterial(materialName.toUpperCase()); + if (material != null) { + METAL_LIST.add(material); + } else { + System.out.println("Invalid material in config: " + materialName); + } + } + } + + private void repelMetal() { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), range)) { + if (e instanceof Item) { + Item i = (Item) e; + if (isMetalMaterial(i.getItemStack().getType())) { + Vector direction = GeneralMethods.getDirection(player.getLocation(), i.getLocation()).multiply(velocity); + i.setVelocity(direction); + } + } else if (e instanceof FallingBlock) { + FallingBlock fb = (FallingBlock) e; + + if (isMetalMaterial(fb.getBlockData().getMaterial())) { + Vector direction = GeneralMethods.getDirection(player.getLocation(), fb.getLocation()).multiply(velocity); + fb.setVelocity(direction); + fb.setDropItem(false); + } + } else if (e instanceof Arrow && repelArrows) { + Arrow arrow = (Arrow) e; + Vector currentVelocity = arrow.getVelocity(); + Vector reversedVelocity = currentVelocity.multiply(-1); + arrow.setVelocity(reversedVelocity); + } else if (e instanceof LivingEntity && repelLivingEntities) { + LivingEntity livingEntity = (LivingEntity) e; + + if (livingEntity.getUniqueId().equals(player.getUniqueId())) continue; + + EntityEquipment equipment = livingEntity.getEquipment(); + if (equipment == null) continue; + + ItemStack mainHand = equipment.getItemInMainHand(); + ItemStack offHand = equipment.getItemInOffHand(); + ItemStack helmet = equipment.getHelmet(); + ItemStack chestplate = equipment.getChestplate(); + ItemStack leggings = equipment.getLeggings(); + ItemStack boots = equipment.getBoots(); + + boolean isMetal = isMetalItem(mainHand) || isMetalItem(offHand) || + isMetalItem(helmet) || isMetalItem(chestplate) || + isMetalItem(leggings) || isMetalItem(boots); + + if (isMetal) { + Vector direction = GeneralMethods.getDirection(player.getLocation(), e.getLocation()).multiply(velocity); + livingEntity.setVelocity(direction); + } + } + } + } + + private boolean isMetalItem(ItemStack itemStack) { + return itemStack != null && METAL_LIST.contains(itemStack.getType()); + } + + private boolean isMetalMaterial(Material material) { + return METAL_LIST.contains(material); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + duration = config.getLong("Abilities.Earth.MagnetShield.Duration"); + shiftCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Shift"); + clickCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Click"); + range = config.getDouble("Abilities.Earth.MagnetShield.Range"); + repelArrows = config.getBoolean("Abilities.Earth.MagnetShield.RepelArrows"); + repelLivingEntities = config.getBoolean("Abilities.Earth.MagnetShield.RepelLivingEntities"); + velocity = config.getDouble("Abilities.Earth.MagnetShield.Velocity"); + } +} \ No newline at end of file diff --git a/src/ability/earthbending/MetalArmor.java b/src/ability/earthbending/MetalArmor.java new file mode 100644 index 0000000..ca1861e --- /dev/null +++ b/src/ability/earthbending/MetalArmor.java @@ -0,0 +1,212 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.earthbending.EarthArmor; +import com.projectkorra.projectkorra.util.TempArmor; +import com.projectkorra.projectkorra.util.TempPotionEffect; + +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.potion.PotionEffect; + +import java.util.Arrays; +import java.util.List; + +public class MetalArmor extends EarthAbility implements AddonAbility { + + private static final int GOLD_BLOCK_COLOR = 0xF2F204; + private static final List METAL_COLORS = Arrays.asList( + 0xa39d91, 0xf4f4f4, 0xa2a38f, 0xF2F204, 0xb75656, 0xfff4f4 + ); + + private boolean useIronArmor; + private int resistStrength; + private int resistDuration; + + public MetalArmor(Player player) { + super(player); + + if (bPlayer == null || !bPlayer.canBendIgnoreCooldowns(CoreAbility.getAbility(EarthArmor.class)) || !bPlayer.canMetalbend()) { + return; + } + + if (!CoreAbility.hasAbility(player, EarthArmor.class)) { + return; + } + + setFields(); + start(); + } + + private void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + useIronArmor = config.getBoolean("Abilities.Earth.EarthArmor.UseIronArmor"); + resistStrength = config.getInt("Abilities.Earth.EarthArmor.Resistance.Strength"); + resistDuration = config.getInt("Abilities.Earth.EarthArmor.Resistance.Duration"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (!CoreAbility.hasAbility(player, EarthArmor.class)) { + remove(); + return; + } + + EarthArmor ea = CoreAbility.getAbility(player, EarthArmor.class); + if (!bPlayer.isToggled()) { + remove(); + ea.remove(); + return; + } + + if (ea.isFormed()) { + if (isMetalHelmet()) { + ItemStack[] armors = { new ItemStack(Material.CHAINMAIL_BOOTS, 1), + new ItemStack(Material.CHAINMAIL_LEGGINGS, 1), + new ItemStack(Material.CHAINMAIL_CHESTPLATE, 1), + new ItemStack(Material.CHAINMAIL_HELMET, 1) }; + + if(useIronArmor){ + armors = new ItemStack[]{ new ItemStack(Material.IRON_BOOTS, 1), + new ItemStack(Material.IRON_LEGGINGS, 1), + new ItemStack(Material.IRON_CHESTPLATE, 1), + new ItemStack(Material.IRON_HELMET, 1) }; + } + + if(useIronArmor && getHelmetColor().equals(Color.fromRGB(GOLD_BLOCK_COLOR))) { + armors = new ItemStack[]{ new ItemStack(Material.GOLDEN_BOOTS, 1), + new ItemStack(Material.GOLDEN_LEGGINGS, 1), + new ItemStack(Material.GOLDEN_CHESTPLATE, 1), + new ItemStack(Material.GOLDEN_HELMET, 1) }; + } + + player.getInventory().setArmorContents(armors); + + PotionEffect resistance = JedCore.plugin.getPotionEffectAdapter().getResistanceEffect(resistDuration, resistStrength); + new TempPotionEffect(player, resistance); + } + + remove(); + } + } + + private boolean isMetalHelmet() { + Color color = getHelmetColor(); + + return METAL_COLORS.contains(color.asRGB()); + } + + private Color getHelmetColor() { + if (!TempArmor.hasTempArmor(player)) { + return Color.BLACK; + } + + ItemStack helm = player.getInventory().getHelmet(); + if (helm.getType() != Material.LEATHER_HELMET) { + return Color.BLACK; + } + + LeatherArmorMeta meta = (LeatherArmorMeta)helm.getItemMeta(); + if (meta == null) { + return Color.BLACK; + } + + return meta.getColor(); + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalArmor"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public boolean isUseIronArmor() { + return useIronArmor; + } + + public void setUseIronArmor(boolean useIronArmor) { + this.useIronArmor = useIronArmor; + } + + public int getResistStrength() { + return resistStrength; + } + + public void setResistStrength(int resistStrength) { + this.resistStrength = resistStrength; + } + + public int getResistDuration() { + return resistDuration; + } + + public void setResistDuration(int resistDuration) { + this.resistDuration = resistDuration; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthArmor.Enabled"); + } +} diff --git a/src/ability/earthbending/MetalFragments.java b/src/ability/earthbending/MetalFragments.java new file mode 100644 index 0000000..9a95cdd --- /dev/null +++ b/src/ability/earthbending/MetalFragments.java @@ -0,0 +1,430 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.*; + +public class MetalFragments extends MetalAbility implements AddonAbility { + + @Attribute("MaxSources") + private int maxSources; + @Attribute(Attribute.SELECT_RANGE) + private int selectRange; + @Attribute("MaxShots") + private int maxFragments; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private double velocity; + + public List sources = new ArrayList<>(); + private final List thrownFragments = new ArrayList<>(); + private final List tblockTracker = new ArrayList<>(); + //private List fblockTracker = new ArrayList<>(); + private final HashMap counters = new HashMap<>(); + + public MetalFragments(Player player) { + super(player); + + if (hasAbility(player, MetalFragments.class)) { + MetalFragments.selectAnotherSource(player); + return; + } + + if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { + return; + } + + setFields(); + + if (tblockTracker.size() >= maxSources) { + return; + } + + if (prepare()) { + Block b = selectSource(); + if (RegionProtection.isRegionProtected(player, b.getLocation(), this)) { + return; + } + + start(); + if (!isRemoved()) { + translateUpward(b); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + maxSources = config.getInt("Abilities.Earth.MetalFragments.MaxSources"); + selectRange = config.getInt("Abilities.Earth.MetalFragments.SourceRange"); + maxFragments = config.getInt("Abilities.Earth.MetalFragments.MaxFragments"); + damage = config.getDouble("Abilities.Earth.MetalFragments.Damage"); + cooldown = config.getInt("Abilities.Earth.MetalFragments.Cooldown"); + velocity = config.getDouble("Abilities.Earth.MetalFragments.Velocity"); + } + + public static void shootFragment(Player player) { + if (hasAbility(player, MetalFragments.class)) { + getAbility(player, MetalFragments.class).shootFragment(); + } + } + + private void shootFragment() { + if (sources.size() <= 0) + return; + + Random randy = new Random(); + int i = randy.nextInt(sources.size()); + Block source = sources.get(i); + ItemStack is; + + switch (source.getType()) { + case GOLD_BLOCK: + case GOLD_ORE: + is = new ItemStack(Material.GOLD_INGOT, 1); + break; + case COAL_BLOCK: + is = new ItemStack(Material.COAL, 1); + break; + case COAL_ORE: + is = new ItemStack(Material.COAL_ORE, 1); + break; + default: + is = new ItemStack(Material.IRON_INGOT, 1); + break; + } + + Vector direction; + if (GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()) != null) { + direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()).getLocation()); + } else { + direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedLocation(player, 30)); + } + + Item ii = player.getWorld().dropItemNaturally(source.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(direction)).getLocation(), is); + ii.setPickupDelay(Integer.MAX_VALUE); + ii.setVelocity(direction.normalize().multiply(velocity)); + playMetalbendingSound(ii.getLocation()); + thrownFragments.add(ii); + + if (counters.containsKey(source)) { + int count = counters.get(source); + count++; + + if (count >= maxFragments) { + counters.remove(source); + source.getWorld().spawnFallingBlock(source.getLocation().add(0.5, 0, 0.5), source.getBlockData()); + TempBlock tempBlock = TempBlock.get(source); + if (tempBlock != null) { + tempBlock.revertBlock(); + } + sources.remove(source); + source.getWorld().playSound(source.getLocation(), Sound.ENTITY_ITEM_BREAK, 10, 5); + } else { + counters.put(source, count); + } + + if (sources.size() == 0) { + remove(); + } + } + } + + public static void selectAnotherSource(Player player) { + if (hasAbility(player, MetalFragments.class)) { + getAbility(player, MetalFragments.class).selectAnotherSource(); + } + } + + private void selectAnotherSource() { + if (tblockTracker.size() >= maxSources) + return; + + if (prepare()) { + Block b = selectSource(); + translateUpward(b); + } + } + + public boolean prepare() { + Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); + + if (block == null) + return false; + + return isMetal(block); + } + + public Block selectSource() { + Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); + if (isMetal(block)) + return block; + return null; + } + + public void translateUpward(Block block) { + if (block == null) + return; + + if (sources.contains(block)) + return; + + if (block.getRelative(BlockFace.UP).getType().isSolid()) + return; + + if (isEarthbendable(player, block)) { + new TempFallingBlock(block.getLocation().add(0.5, 0, 0.5), block.getBlockData(), new Vector(0, 0.8, 0), this); + block.setType(Material.AIR); + + playMetalbendingSound(block.getLocation()); + } + } + + public void progress() { + if (player == null || player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!hasAbility(player, MetalFragments.class)) { + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + + Iterator itr = tblockTracker.iterator(); + while (itr.hasNext()) { + TempBlock tb = itr.next(); + if (player.getLocation().distance(tb.getLocation()) >= 10) { + player.getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlockData()); + sources.remove(tb.getBlock()); + tb.revertBlock(); + itr.remove(); + } + } + + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fb = tfb.getFallingBlock(); + if (fb.getLocation().getY() >= player.getEyeLocation().getY() + 1) { + Block block = fb.getLocation().getBlock(); + TempBlock tb = new TempBlock(block, fb.getBlockData()); + + tblockTracker.add(tb); + sources.add(tb.getBlock()); + counters.put(tb.getBlock(), 0); + tfb.remove(); + } + + if (fb.isOnGround()) { + fb.getLocation().getBlock().setBlockData(fb.getBlockData()); + } + } + for (ListIterator iterator = thrownFragments.listIterator(); iterator.hasNext();) { + Item f = iterator.next(); + + boolean touchedLiving = false; + for (Entity e : GeneralMethods.getEntitiesAroundPoint(f.getLocation(), 1)) { + if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { + touchedLiving = true; + DamageHandler.damageEntity(e, damage, this); + } + } + if (touchedLiving || f.isOnGround() || f.isDead()) { + ParticleEffect.ITEM_CRACK.display(f.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, f.getItemStack()); + f.remove(); + iterator.remove(); + } + } + + //removeDeadFBlocks(); + } + + /* + public void removeDeadFBlocks() { + for (int i = 0; i < fblockTracker.size(); i++) + if (fblockTracker.get(i).isDead()) + fblockTracker.remove(i); + } + */ + + public void removeDeadItems() { + thrownFragments.removeIf(Item::isDead); + } + + + public void dropSources() { + for (TempBlock tb : tblockTracker) { + tb.getBlock().getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlock().getBlockData()); + tb.revertBlock(); + } + + tblockTracker.clear(); + } + + public void removeFragments() { + for (Item i : thrownFragments) { + ParticleEffect.ITEM_CRACK.display(i.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, i.getItemStack()); + i.remove(); + } + thrownFragments.clear(); + } + + public static void remove(Player player, Block block) { + if (hasAbility(player, MetalFragments.class)) { + MetalFragments mf = getAbility(player, MetalFragments.class); + if (mf.sources.contains(block)) { + mf.remove(); + } + } + } + + @Override + public void remove() { + dropSources(); + removeFragments(); + removeDeadItems(); + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalFragments"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalFragments.Description"); + } + + public int getMaxSources() { + return maxSources; + } + + public void setMaxSources(int maxSources) { + this.maxSources = maxSources; + } + + public int getSelectRange() { + return selectRange; + } + + public void setSelectRange(int selectRange) { + this.selectRange = selectRange; + } + + public int getMaxFragments() { + return maxFragments; + } + + public void setMaxFragments(int maxFragments) { + this.maxFragments = maxFragments; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public List getSources() { + return sources; + } + + public void setSources(List sources) { + this.sources = sources; + } + + public List getThrownFragments() { + return thrownFragments; + } + + public List getTblockTracker() { + return tblockTracker; + } + + public HashMap getCounters() { + return counters; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MetalFragments.Enabled"); + } +} diff --git a/src/ability/earthbending/MetalHook.java b/src/ability/earthbending/MetalHook.java new file mode 100644 index 0000000..3cbf551 --- /dev/null +++ b/src/ability/earthbending/MetalHook.java @@ -0,0 +1,396 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; + +import com.projectkorra.projectkorra.attribute.Attribute; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class MetalHook extends MetalAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private int range; + @Attribute("MaxHooks") + private int maxHooks; + private int totalHooks; + private int hooksUsed; + private boolean noSource; + private boolean barrierHooking; + + private boolean hasHook; + private boolean wasSprinting; + private long time; + + private Location destination; + + private final ConcurrentHashMap hooks = new ConcurrentHashMap<>(); + private final List hookIds = new ArrayList<>(); + + public MetalHook(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { + return; + } + + if (hasAbility(player, MetalHook.class)) { + MetalHook mh = getAbility(player, MetalHook.class); + mh.launchHook(); + return; + } + + setFields(); + + if (!hasRequiredInv()) { + return; + } + + wasSprinting = player.isSprinting(); + flightHandler.createInstance(player, this.getName()); + player.setAllowFlight(true); + + start(); + launchHook(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.MetalHook.Cooldown"); + range = config.getInt("Abilities.Earth.MetalHook.Range"); + maxHooks = config.getInt("Abilities.Earth.MetalHook.MaxHooks"); + totalHooks = config.getInt("Abilities.Earth.MetalHook.TotalHooks"); + noSource = config.getBoolean("Abilities.Earth.MetalHook.RequireItem"); + barrierHooking = config.getBoolean("Abilities.Earth.MetalHook.BarrierHooking"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + removeAllArrows(); + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this) || hooks.isEmpty()) { + removeAllArrows(); + remove(); + return; + } + + if (!wasSprinting && player.isSprinting()) { + removeAllArrows(); + remove(); + return; + } + + wasSprinting = player.isSprinting(); + + if (player.isSneaking()) { + player.setVelocity(new Vector()); + + if (System.currentTimeMillis() > (time + 1000)) { + removeAllArrows(); + remove(); + return; + } + } else { + time = System.currentTimeMillis(); + } + + Vector target = new Vector(); + + for (Arrow a : hooks.keySet()) { + if (a != null) { + if (!isActiveArrow(a)) { + hooks.remove(a); + hookIds.remove(a.getUniqueId()); + a.remove(); + continue; + } + + if (a.getAttachedBlock() == null) { + hooks.replace(a, hooks.get(a), false); + } else { + hooks.replace(a, hooks.get(a), true); + hasHook = true; + } + + //Draws the particle lines. + for (Location location : JCMethods.getLinePoints(player.getLocation().add(0, 1, 0), a.getLocation(), ((int) player.getLocation().add(0,1,0).distance(a.getLocation()) * 2))) { + GeneralMethods.displayColoredParticle("#CCCCCC", location); + } + + if (hooks.get(a)) { + target.add(GeneralMethods.getDirection(player.getEyeLocation(), a.getLocation())); + } + } + } + + if (hasHook) { + destination = player.getLocation().clone().add(target); + + if (player.getLocation().distance(destination) > 2) { + player.setFlying(false); + double velocity = 0.8; + + GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); + } else if (player.getLocation().distance(destination) < 2 && player.getLocation().distance(destination) >= 1) { + player.setFlying(false); + double velocity = 0.35; + + GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); + } else { + GeneralMethods.setVelocity(this, player, new Vector(0, 0, 0)); + + if (player.getAllowFlight()) { + player.setFlying(true); + } + } + } + } + + private boolean isActiveArrow(Arrow arrow) { + if (arrow.isDead()) return false; + if (player.getWorld() != arrow.getWorld()) return false; + + Block attached = arrow.getAttachedBlock(); + + if (!barrierHooking && attached != null && attached.getType() == Material.BARRIER) return false; + + return player.getEyeLocation().distanceSquared(arrow.getLocation()) < range * range; + } + + @Override + public void remove() { + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + + flightHandler.removeInstance(player, this.getName()); + + super.remove(); + } + + public void launchHook() { + if (!hasRequiredInv()) return; + + Vector dir = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, range)); + + if (!hookIds.isEmpty() && hookIds.size() > (maxHooks - 1)) { + for (Arrow a : hooks.keySet()) { + if (a.getUniqueId().equals(hookIds.get(0))) { + hooks.remove(a); + hookIds.remove(0); + a.remove(); + break; + } + } + } + + if (totalHooks > 0 && hooksUsed++ > totalHooks) { + remove(); + return; + } + + Arrow a = player.getWorld().spawnArrow(player.getEyeLocation().add(player.getLocation().getDirection().multiply(2)), dir, 3, 0f); + a.setMetadata("metalhook", new FixedMetadataValue(JedCore.plugin, "1")); + + hooks.put(a, false); + hookIds.add(a.getUniqueId()); + } + + public void removeAllArrows() { + for (Arrow a : hooks.keySet()) { + a.remove(); + } + } + + public boolean hasRequiredInv() { + if (noSource) return true; + + if (player.getInventory().getChestplate() != null) { + Material[] chestplates = {Material.IRON_CHESTPLATE, Material.CHAINMAIL_CHESTPLATE}; + Material playerChest = player.getInventory().getChestplate().getType(); + + if (Arrays.asList(chestplates).contains(playerChest)) { + return true; + } + } + + Material[] metals = {Material.IRON_INGOT, Material.IRON_BLOCK}; + + for (ItemStack items : player.getInventory()) { + if (items != null && Arrays.asList(metals).contains(items.getType())) { + return true; + } + } + + return false; + } + + public int getMaxHooks() { + return this.maxHooks; + } + + public void setMaxHooks(int maxhooks) { + this.maxHooks = maxhooks; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalHook"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalHook.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public int getTotalHooks() { + return totalHooks; + } + + public void setTotalHooks(int totalHooks) { + this.totalHooks = totalHooks; + } + + public int getHooksUsed() { + return hooksUsed; + } + + public void setHooksUsed(int hooksUsed) { + this.hooksUsed = hooksUsed; + } + + public boolean isNoSource() { + return noSource; + } + + public void setNoSource(boolean noSource) { + this.noSource = noSource; + } + + public boolean isBarrierHooking() { + return barrierHooking; + } + + public void setBarrierHooking(boolean barrierHooking) { + this.barrierHooking = barrierHooking; + } + + public boolean isHasHook() { + return hasHook; + } + + public void setHasHook(boolean hasHook) { + this.hasHook = hasHook; + } + + public boolean isWasSprinting() { + return wasSprinting; + } + + public void setWasSprinting(boolean wasSprinting) { + this.wasSprinting = wasSprinting; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public Location getDestination() { + return destination; + } + + public void setDestination(Location destination) { + this.destination = destination; + } + + public ConcurrentHashMap getHooks() { + return hooks; + } + + public List getHookIds() { + return hookIds; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MetalHook.Enabled"); + } +} diff --git a/src/ability/earthbending/MetalShred.java b/src/ability/earthbending/MetalShred.java new file mode 100644 index 0000000..ef79f8c --- /dev/null +++ b/src/ability/earthbending/MetalShred.java @@ -0,0 +1,483 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + +public class MetalShred extends MetalAbility implements AddonAbility { + + @Attribute(Attribute.SELECT_RANGE) + private int selectRange; + private int extendTick; + @Attribute(Attribute.DAMAGE) + private double damage; + + private boolean horizontal = false; + private boolean started = false; + private boolean stop = false; + private boolean stopCoil = false; + private boolean extending = false; + private int length = 0; + private int fullLength = 0; + private long lastExtendTime; + private Block source; + private Block lastBlock; + private final List tblocks = new ArrayList<>(); + + public MetalShred(Player player) { + super(player); + + if (hasAbility(player, MetalShred.class)) { + getAbility(player, MetalShred.class).remove(); + } + + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + if (selectSource()) { + if (horizontal) { + raiseBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); + } else { + shiftBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); + } + + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + selectRange = config.getInt("Abilities.Earth.MetalShred.SourceRange"); + extendTick = config.getInt("Abilities.Earth.MetalShred.ExtendTick"); + damage = config.getDouble("Abilities.Earth.MetalShred.Damage"); + } + + public boolean selectSource() { + Block b = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); + + if (!isMetal(b)) + return false; + + source = b; + + if (ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType()) && !isMetal(source.getRelative(BlockFace.DOWN))) { + horizontal = true; + } + + return true; + } + + public void raiseBlock(Block b, Vector d) { + Block up = b.getRelative(BlockFace.UP); + Block away = b.getRelative(GeneralMethods.getCardinalDirection(d)); + Block awayup = away.getRelative(BlockFace.UP); + Block deeperb = b.getRelative(BlockFace.DOWN); + Block deepera = away.getRelative(BlockFace.DOWN); + + for (TempBlock tb : tblocks) { + if (!ElementalAbility.isAir(tb.getBlock().getType())) + tb.setType(Material.AIR); + } + + if (!up.getType().isSolid()) { + TempBlock tbu = new TempBlock(up, b.getBlockData()); + tblocks.add(tbu); + } + + if (!awayup.getType().isSolid()) { + TempBlock tbau = new TempBlock(awayup, away.getBlockData()); + tblocks.add(tbau); + } + + if (isMetal(b)) { + TempBlock tbd = new TempBlock(b, Material.AIR.createBlockData()); + tblocks.add(tbd); + } + + if (isMetal(away)) { + TempBlock tba = new TempBlock(away, Material.AIR.createBlockData()); + tblocks.add(tba); + } + + if (isMetal(deeperb)) { + TempBlock tbdb = new TempBlock(deeperb, Material.AIR.createBlockData()); + tblocks.add(tbdb); + } + + if (isMetal(deepera)) { + TempBlock tbda = new TempBlock(deepera, Material.AIR.createBlockData()); + tblocks.add(tbda); + } + + playMetalbendingSound(b.getLocation()); + } + + public void shiftBlock(Block b, Vector d) { + Block under = b.getRelative(BlockFace.DOWN); + Block side = b.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); + Block underside = under.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); + + for (TempBlock tb : tblocks) { + if (!ElementalAbility.isAir(tb.getBlock().getType())) + tb.setType(Material.AIR); + } + + if (!side.getType().isSolid()) { + TempBlock tbs = new TempBlock(side, b.getBlockData()); + tblocks.add(tbs); + } + + if (!underside.getType().isSolid()) { + TempBlock tbus = new TempBlock(underside, under.getBlockData()); + tblocks.add(tbus); + } + + if (isMetal(b)) { + TempBlock tb1 = new TempBlock(b, Material.AIR.createBlockData()); + tblocks.add(tb1); + } + + if (isMetal(under)) { + TempBlock tb2 = new TempBlock(under, Material.AIR.createBlockData()); + tblocks.add(tb2); + } + + playMetalbendingSound(b.getLocation()); + } + + private void peelCoil(Block b) { + Block under = b.getRelative(BlockFace.DOWN); + + if (length <= 0) + return; + + if (!b.getType().isSolid()) { + TempBlock tbb = new TempBlock(b, Material.IRON_BLOCK.createBlockData()); + tblocks.add(tbb); + } + + else + stopCoil = true; + + if (!under.getType().isSolid()) { + TempBlock tbu = new TempBlock(under, Material.IRON_BLOCK.createBlockData()); + tblocks.add(tbu); + } + + else + stopCoil = true; + + playMetalbendingSound(b.getLocation()); + + length--; + } + + public static void startShred(Player player) { + if (hasAbility(player, MetalShred.class)) { + getAbility(player, MetalShred.class).startShred(); + } + } + + private void startShred() { + started = true; + } + + public static void extend(Player player) { + if (hasAbility(player, MetalShred.class)) { + getAbility(player, MetalShred.class).extend(); + } + } + + private void extend() { + if (extending) { + extending = false; + return; + } + + if (!stop) + return; + + lastExtendTime = System.currentTimeMillis(); + fullLength = length; + if (lastBlock != null) + lastBlock = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(player.getLocation(), lastBlock.getLocation())).getOppositeFace()); + else { + return; + } + extending = true; + } + + @Override + public void progress() { + if (!player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + + if (!player.isSprinting()) { + if (started) + stop = true; + } + + if (!horizontal && stop && !stopCoil && extending && System.currentTimeMillis() > lastExtendTime + extendTick) { + lastExtendTime = System.currentTimeMillis(); + if (length > 0) { + + Block b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(lastBlock.getLocation(), GeneralMethods.getTargetedLocation(player, fullLength)))); + + peelCoil(b); + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(b.getLocation(), 2)) { + if (!(e instanceof LivingEntity) || e.getEntityId() == player.getEntityId()) { + continue; + } + if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))) { + continue; + } + DamageHandler.damageEntity(e, damage, this); + GeneralMethods.setVelocity(this, e, e.getVelocity().add(player.getLocation().getDirection().add(new Vector(0, 0.1, 0)))); + } + + lastBlock = b; + } + + return; + } + + if (stop || !started) + return; + + Block b; + + if (lastBlock != null) { + b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); + } + + else { + b = source.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); + } + + if (!isMetal(b)) { + if (!ElementalAbility.isAir(b.getType())) { + remove(); + } + return; + } + + if (b.getLocation().getX() == player.getLocation().getBlockX() || b.getLocation().getZ() == player.getLocation().getBlockZ()) { + if (horizontal) + raiseBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); + else + shiftBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); + + length++; + lastBlock = b; + } + } + + private void revertAll() { + for (TempBlock tb : tblocks) { + tb.revertBlock(); + } + } + + @Override + public void remove() { + revertAll(); + super.remove(); + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalShred"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalShred.Description"); + } + + public int getSelectRange() { + return selectRange; + } + + public void setSelectRange(int selectRange) { + this.selectRange = selectRange; + } + + public int getExtendTick() { + return extendTick; + } + + public void setExtendTick(int extendTick) { + this.extendTick = extendTick; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean isHorizontal() { + return horizontal; + } + + public void setHorizontal(boolean horizontal) { + this.horizontal = horizontal; + } + + @Override + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + + public boolean isStop() { + return stop; + } + + public void setStop(boolean stop) { + this.stop = stop; + } + + public boolean isStopCoil() { + return stopCoil; + } + + public void setStopCoil(boolean stopCoil) { + this.stopCoil = stopCoil; + } + + public boolean isExtending() { + return extending; + } + + public void setExtending(boolean extending) { + this.extending = extending; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public int getFullLength() { + return fullLength; + } + + public void setFullLength(int fullLength) { + this.fullLength = fullLength; + } + + public long getLastExtendTime() { + return lastExtendTime; + } + + public void setLastExtendTime(long lastExtendTime) { + this.lastExtendTime = lastExtendTime; + } + + public Block getSource() { + return source; + } + + public void setSource(Block source) { + this.source = source; + } + + public Block getLastBlock() { + return lastBlock; + } + + public void setLastBlock(Block lastBlock) { + this.lastBlock = lastBlock; + } + + public List getTblocks() { + return tblocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MetalShred.Enabled"); + } +} diff --git a/src/ability/earthbending/MudSurge.java b/src/ability/earthbending/MudSurge.java new file mode 100644 index 0000000..c9b02e5 --- /dev/null +++ b/src/ability/earthbending/MudSurge.java @@ -0,0 +1,654 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionUtil; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; + +import com.jedk1.jedcore.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.stream.Collectors; + +public class MudSurge extends EarthAbility implements AddonAbility { + private int prepareRange; + private int blindChance; + private int blindTicks; + private boolean multipleHits; + @Attribute(Attribute.DAMAGE) + private double damage; + private int waves; + private int waterSearchRadius; + private boolean wetSource; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("CollisionRadius") + private double collisionRadius; + + public static int surgeInterval = 300; + public static int mudPoolRadius = 2; + public static Set mudTypes = new HashSet<>(); + + static { + mudTypes.addAll(Arrays.asList(Material.SAND, Material.RED_SAND, Material.CLAY, Material.TERRACOTTA, Material.BLACK_TERRACOTTA, Material.BLUE_TERRACOTTA, + Material.BROWN_TERRACOTTA, Material.CYAN_TERRACOTTA, Material.GRAY_TERRACOTTA, Material.GREEN_TERRACOTTA, + Material.LIGHT_BLUE_TERRACOTTA, Material.LIGHT_GRAY_TERRACOTTA, Material.LIME_TERRACOTTA, + Material.MAGENTA_TERRACOTTA, Material.ORANGE_TERRACOTTA, Material.PINK_TERRACOTTA, + Material.PURPLE_TERRACOTTA, Material.RED_TERRACOTTA, Material.WHITE_TERRACOTTA, Material.YELLOW_TERRACOTTA, + Material.GRASS_BLOCK, Material.DIRT, Material.MYCELIUM, Material.COARSE_DIRT, + Material.SOUL_SAND, Material.SOUL_SOIL, Material.RED_SANDSTONE, Material.SANDSTONE, Material.CHISELED_SANDSTONE, + Material.CHISELED_RED_SANDSTONE, Material.SMOOTH_SANDSTONE, Material.SMOOTH_RED_SANDSTONE, Material.CUT_SANDSTONE, + Material.CUT_RED_SANDSTONE)); + if (GeneralMethods.getMCVersion() >= 1170) { + mudTypes.add(Material.getMaterial("ROOTED_DIRT")); + } + if (GeneralMethods.getMCVersion() >= 1190) { + mudTypes.add(Material.getMaterial("MUD")); + mudTypes.add(Material.getMaterial("MUDDY_MANGROVE_ROOTS")); + mudTypes.add(Material.getMaterial("PACKED_MUD")); + } + } + + private CompositeRemovalPolicy removalPolicy; + + private Block source; + + private int wavesOnTheRun = 0; + private boolean mudFormed = false; + private boolean doNotSurge = false; + public boolean started = false; + + private final List mudArea = new ArrayList<>(); + private ListIterator mudAreaItr; + private final List mudBlocks = new ArrayList<>(); + private final List blind = new ArrayList<>(); + private final List affectedEntities = new ArrayList<>(); + + private final List fallingBlocks = new ArrayList<>(); + + private final Random rand = new Random(); + + public MudSurge(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, MudSurge.class)) { + MudSurge ms = getAbility(player, MudSurge.class); + if (!ms.hasStarted()) { + ms.remove(); + } else { + return; + } + } + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new OutOfRangeRemovalPolicy(this.player, 25.0, () -> this.source.getLocation()), + new SwappedSlotsRemovalPolicy<>(bPlayer, MudSurge.class) + ); + + setFields(); + + if (getSource()) { + start(); + if (!isRemoved()) { + loadMudPool(); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + this.removalPolicy.load(config); + + prepareRange = config.getInt("Abilities.Earth.MudSurge.SourceRange"); + blindChance = config.getInt("Abilities.Earth.MudSurge.BlindChance"); + damage = config.getDouble("Abilities.Earth.MudSurge.Damage"); + waves = config.getInt("Abilities.Earth.MudSurge.Waves"); + waterSearchRadius = config.getInt("Abilities.Earth.MudSurge.WaterSearchRadius"); + wetSource = config.getBoolean("Abilities.Earth.MudSurge.WetSourceOnly"); + cooldown = config.getLong("Abilities.Earth.MudSurge.Cooldown"); + blindTicks = config.getInt("Abilities.Earth.MudSurge.BlindTicks"); + multipleHits = config.getBoolean("Abilities.Earth.MudSurge.MultipleHits"); + collisionRadius = config.getDouble("Abilities.Earth.MudSurge.CollisionRadius"); + } + + @Override + public void progress() { + if (removalPolicy.shouldRemove()) { + remove(); + return; + } + + long lastSurgeTime = 0; + if (mudFormed && started && System.currentTimeMillis() > lastSurgeTime + surgeInterval) { + surge(); + affect(); + if (TempFallingBlock.getFromAbility(this).isEmpty()) { + remove(); + return; + } + return; + } + + if (!mudFormed) { + createMudPool(); + } + } + + private boolean getSource() { + Block block = getMudSourceBlock(prepareRange); + + if (block != null) { + if (isMudBlock(block)) { + boolean water = true; + + if (wetSource) { + water = false; + List nearby = GeneralMethods.getBlocksAroundPoint(block.getLocation(), waterSearchRadius); + + for (Block b : nearby) { + if (b.getType() == Material.WATER) { + water = true; + break; + } + } + } + + if (water) { + this.source = block; + return true; + } + } + } + + return false; + } + + private void startSurge() { + started = true; + this.bPlayer.addCooldown(this); + + // Clear out the policies that only apply while sourcing. + this.removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); + this.removalPolicy.removePolicyType(OutOfRangeRemovalPolicy.class); + this.removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); + } + + private boolean hasStarted() { + return this.started; + } + + public static boolean isSurgeBlock(Block block) { + if (block.getType() != Material.BROWN_TERRACOTTA) { + return false; + } + + for (MudSurge surge : CoreAbility.getAbilities(MudSurge.class)) { + if (surge.mudArea.contains(block)) { + return true; + } + } + + return false; + } + + // Returns true if the event should be cancelled. + public static boolean onFallDamage(Player player) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null || !bPlayer.hasElement(Element.EARTH)) { + return false; + } + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + boolean fallDamage = config.getBoolean("Abilities.Earth.MudSurge.AllowFallDamage"); + if (fallDamage) { + return false; + } + + Block block = player.getLocation().clone().subtract(0, 0.1, 0).getBlock(); + return isSurgeBlock(block); + } + + public static void mudSurge(Player player) { + if (!hasAbility(player, MudSurge.class)) + return; + + getAbility(player, MudSurge.class).startSurge(); + } + + private Block getMudSourceBlock(int range) { + Block testBlock = GeneralMethods.getTargetedLocation(player, range, ElementalAbility.getTransparentMaterials()).getBlock(); + if (isMudBlock(testBlock)) + return testBlock; + + Location loc = player.getEyeLocation(); + Vector dir = player.getEyeLocation().getDirection().clone().normalize(); + + for (int i = 0; i <= range; i++) { + Block block = loc.clone().add(dir.clone().multiply(i == 0 ? 1 : i)).getBlock(); + if (RegionProtection.isRegionProtected(player, block.getLocation(), this)) + continue; + + if (isMudBlock(block)) + return block; + } + + return null; + } + + private boolean isMudBlock(Block block) { + for (Material mat : mudTypes) { + if (mat.name().equalsIgnoreCase(block.getType().name())) + return true; + } + + return false; + } + + private void createMud(Block block) { + mudBlocks.add(new TempBlock(block, Material.BROWN_TERRACOTTA.createBlockData())); + } + + private void loadMudPool() { + List area = GeneralMethods.getCircle(source.getLocation(), mudPoolRadius, 3, false, true, 0); + + for (Location l : area) { + Block b = l.getBlock(); + + if (isMudBlock(b)) { + if (isTransparent(b.getRelative(BlockFace.UP))) { + boolean water = true; + + if (wetSource) { + water = false; + List nearby = GeneralMethods.getBlocksAroundPoint(l, waterSearchRadius); + + for (Block block : nearby) { + if (block.getType() == Material.WATER) { + water = true; + break; + } + } + } + + if (water) { + mudArea.add(b); + playEarthbendingSound(b.getLocation()); + } + } + } + } + + Collections.shuffle(mudArea); + mudAreaItr = mudArea.listIterator(); + } + + private void createMudPool() { + if (!mudAreaItr.hasNext()) { + mudFormed = true; + return; + } + + Block b = mudAreaItr.next(); + + if (b != null) + createMud(b); + } + + private void revertMudPool() { + for (TempBlock tb : mudBlocks) + tb.revertBlock(); + + mudBlocks.clear(); + } + + private void surge() { + if (wavesOnTheRun >= waves) { + doNotSurge = true; + return; + } + + if (doNotSurge) + return; + + for (TempBlock tb : mudBlocks) { + Vector direction = GeneralMethods.getDirection(tb.getLocation().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, 30)).multiply(0.07); + + double x = rand.nextDouble() / 5; + double z = rand.nextDouble() / 5; + + x = (rand.nextBoolean()) ? -x : x; + z = (rand.nextBoolean()) ? -z : z; + + fallingBlocks.add(new TempFallingBlock(tb.getLocation().add(0.5, 1, 0.5), Material.BROWN_TERRACOTTA.createBlockData(), direction.clone().add(new Vector(x, 0.2, z)), this)); + + playEarthbendingSound(tb.getLocation()); + } + + wavesOnTheRun++; + } + + private void affect() { + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fb = tfb.getFallingBlock(); + if (fb.isDead()) { + tfb.remove(); + continue; + } + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(fb.getLocation(), 1.5)) { + if (fb.isDead()) { + tfb.remove(); + continue; + } + if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))){ + continue; + } + + if (e instanceof LivingEntity) { + if (this.multipleHits || !this.affectedEntities.contains(e)) { + DamageHandler.damageEntity(e, damage, this); + if (!this.multipleHits) { + this.affectedEntities.add(e); + } + } + + if (e instanceof Player) { + if (e.getEntityId() == player.getEntityId()) + continue; + + if (rand.nextInt(100) < blindChance && !blind.contains(e)) { + ((Player) e).addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, this.blindTicks, 2)); + } + + blind.add((Player) e); + } + + e.setVelocity(fb.getVelocity().multiply(0.8)); + tfb.remove(); + } + } + } + } + + @Override + public void remove() { + revertMudPool(); + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); + } + + @Override + public void handleCollision(Collision collision) { + CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); + } + + @Override + public double getCollisionRadius() { + return collisionRadius; + } + + @Override + public String getName() { + return "MudSurge"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MudSurge.Description"); + } + + public int getPrepareRange() { + return prepareRange; + } + + public void setPrepareRange(int prepareRange) { + this.prepareRange = prepareRange; + } + + public int getBlindChance() { + return blindChance; + } + + public void setBlindChance(int blindChance) { + this.blindChance = blindChance; + } + + public int getBlindTicks() { + return blindTicks; + } + + public void setBlindTicks(int blindTicks) { + this.blindTicks = blindTicks; + } + + public boolean isMultipleHits() { + return multipleHits; + } + + public void setMultipleHits(boolean multipleHits) { + this.multipleHits = multipleHits; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getWaves() { + return waves; + } + + public void setWaves(int waves) { + this.waves = waves; + } + + public int getWaterSearchRadius() { + return waterSearchRadius; + } + + public void setWaterSearchRadius(int waterSearchRadius) { + this.waterSearchRadius = waterSearchRadius; + } + + public boolean isWetSource() { + return wetSource; + } + + public void setWetSource(boolean wetSource) { + this.wetSource = wetSource; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public void setCollisionRadius(double collisionRadius) { + this.collisionRadius = collisionRadius; + } + + public static int getSurgeInterval() { + return surgeInterval; + } + + public static void setSurgeInterval(int surgeInterval) { + MudSurge.surgeInterval = surgeInterval; + } + + public static int getMudPoolRadius() { + return mudPoolRadius; + } + + public static void setMudPoolRadius(int mudPoolRadius) { + MudSurge.mudPoolRadius = mudPoolRadius; + } + + public static Material[] getMudTypes() { + return mudTypes.toArray(new Material[0]); + } + + public static Set getMudTypesSet() { + return mudTypes; + } + + public static void setMudTypes(Material[] mudTypes) { + MudSurge.mudTypes.clear(); + MudSurge.mudTypes.addAll(Arrays.asList(mudTypes)); + } + + public CompositeRemovalPolicy getRemovalPolicy() { + return removalPolicy; + } + + public void setRemovalPolicy(CompositeRemovalPolicy removalPolicy) { + this.removalPolicy = removalPolicy; + } + + public void setSource(Block source) { + this.source = source; + } + + public int getWavesOnTheRun() { + return wavesOnTheRun; + } + + public void setWavesOnTheRun(int wavesOnTheRun) { + this.wavesOnTheRun = wavesOnTheRun; + } + + public boolean isMudFormed() { + return mudFormed; + } + + public void setMudFormed(boolean mudFormed) { + this.mudFormed = mudFormed; + } + + public boolean isDoNotSurge() { + return doNotSurge; + } + + public void setDoNotSurge(boolean doNotSurge) { + this.doNotSurge = doNotSurge; + } + + @Override + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + + public List getMudArea() { + return mudArea; + } + + public ListIterator getMudAreaItr() { + return mudAreaItr; + } + + public void setMudAreaItr(ListIterator mudAreaItr) { + this.mudAreaItr = mudAreaItr; + } + + public List getMudBlocks() { + return mudBlocks; + } + + public List getBlind() { + return blind; + } + + public List getAffectedEntities() { + return affectedEntities; + } + + public List getFallingBlocks() { + return fallingBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MudSurge.Enabled"); + } +} diff --git a/src/ability/earthbending/SandBlast.java b/src/ability/earthbending/SandBlast.java new file mode 100644 index 0000000..75de3b1 --- /dev/null +++ b/src/ability/earthbending/SandBlast.java @@ -0,0 +1,377 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.SandAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; + +import com.jedk1.jedcore.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Random; +import java.util.stream.Collectors; + +public class SandBlast extends SandAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.SELECT_RANGE) + private double sourceRange; + @Attribute(Attribute.RANGE) + private int range; + @Attribute("MaxShots") + private int maxBlasts; + @Attribute(Attribute.DAMAGE) + private static double damage; + + private Block source; + private BlockData sourceData; + private int blasts; + private boolean blasting; + private Vector direction; + private TempBlock tempBlock; + private final List affectedEntities = new ArrayList<>(); + private final List fallingBlocks = new ArrayList<>(); + + Random rand = new Random(); + + public SandBlast(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, SandBlast.class)) { + SandBlast sb = getAbility(player, SandBlast.class); + sb.remove(); + } + + setFields(); + if (prepare()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.SandBlast.Cooldown"); + sourceRange = config.getDouble("Abilities.Earth.SandBlast.SourceRange"); + range = config.getInt("Abilities.Earth.SandBlast.Range"); + maxBlasts = config.getInt("Abilities.Earth.SandBlast.MaxSandBlocks"); + damage = config.getDouble("Abilities.Earth.SandBlast.Damage"); + } + + private boolean prepare() { + source = getEarthSourceBlock(sourceRange); + + if (source != null) { + if (isSand(source) && ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType())) { + this.sourceData = source.getBlockData().clone(); + if (DensityShift.isPassiveSand(source)) { + DensityShift.revertSand(source); + } + tempBlock = new TempBlock(source, Material.SANDSTONE.createBlockData()); + return true; + } + } + return false; + } + + @Override + public void progress() { + if (!hasAbility(player, SandBlast.class)) { + return; + } + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (player.getWorld() != source.getWorld()) { + remove(); + return; + } + if (blasting) { + if (blasts <= maxBlasts) { + blastSand(); + blasts++; + } else { + if (TempFallingBlock.getFromAbility(this).isEmpty()) { + remove(); + return; + } + } + affect(); + } + } + + @Override + public void remove() { + if (this.tempBlock != null) { + this.tempBlock.revertBlock(); + } + super.remove(); + } + + public static void blastSand(Player player) { + if (hasAbility(player, SandBlast.class)) { + SandBlast sb = getAbility(player, SandBlast.class); + if (sb.blasting) { + return; + } + sb.blastSand(); + } + } + + private void blastSand() { + if (!blasting) { + blasting = true; + direction = GeneralMethods.getDirection(source.getLocation().clone().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, range)).multiply(0.07); + this.bPlayer.addCooldown(this); + } + tempBlock.revertBlock(); + + //FallingBlock fblock = source.getWorld().spawnFallingBlock(source.getLocation().clone().add(0, 1, 0), source.getType(), source.getData()); + + if (rand.nextInt(2) == 0) { + DensityShift.playSandbendingSound(source.getLocation().add(0, 1, 0)); + } + + double x = rand.nextDouble() / 10; + double z = rand.nextDouble() / 10; + + x = (rand.nextBoolean()) ? -x : x; + z = (rand.nextBoolean()) ? -z : z; + + //fblock.setVelocity(direction.clone().add(new Vector(x, 0.2, z))); + //fblock.setDropItem(false); + //fblocks.put(fblock, player); + + fallingBlocks.add(new TempFallingBlock(source.getLocation().add(0, 1, 0), sourceData, direction.clone().add(new Vector(x, 0.2, z)), this)); + + } + + public void affect() { + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fblock = tfb.getFallingBlock(); + if (fblock.isDead()) { + tfb.remove(); + continue; + } + + if (RegionProtection.isRegionProtected(player, fblock.getLocation(), this)) { + tfb.remove(); + continue; + } + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(fblock.getLocation(), 1.5)) { + if (entity instanceof LivingEntity && !(entity instanceof ArmorStand)) { + if (entity == this.player) continue; + if (affectedEntities.contains(entity)) continue; + + if (!entity.isDead()) { + DamageHandler.damageEntity(entity, damage, this); + + affectedEntities.add(entity); + + LivingEntity le = (LivingEntity) entity; + if (le.hasPotionEffect(PotionEffectType.BLINDNESS)) { + le.removePotionEffect(PotionEffectType.BLINDNESS); + } + + le.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 60, 1)); + } + } + } + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + Location location = collision.getLocationFirst(); + + Optional collidedObject = fallingBlocks.stream().filter(temp -> temp.getLocation().equals(location)).findAny(); + + if (collidedObject.isPresent()) { + fallingBlocks.remove(collidedObject.get()); + collidedObject.get().remove(); + } + } + } + + @Override + public String getName() { + return "SandBlast"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.SandBlast.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public double getSourceRange() { + return sourceRange; + } + + public void setSourceRange(double sourceRange) { + this.sourceRange = sourceRange; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public int getMaxBlasts() { + return maxBlasts; + } + + public void setMaxBlasts(int maxBlasts) { + this.maxBlasts = maxBlasts; + } + + public static double getDamage() { + return damage; + } + + public static void setDamage(double damage) { + SandBlast.damage = damage; + } + + public Block getSource() { + return source; + } + + public void setSource(Block source) { + this.source = source; + } + + public BlockData getSourceData() { + return sourceData; + } + + public void setSourceData(BlockData sourceData) { + this.sourceData = sourceData; + } + + public int getBlasts() { + return blasts; + } + + public void setBlasts(int blasts) { + this.blasts = blasts; + } + + public boolean isBlasting() { + return blasting; + } + + public void setBlasting(boolean blasting) { + this.blasting = blasting; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public TempBlock getTempBlock() { + return tempBlock; + } + + public void setTempBlock(TempBlock tempBlock) { + this.tempBlock = tempBlock; + } + + public List getAffectedEntities() { + return affectedEntities; + } + + public List getFallingBlocks() { + return fallingBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.SandBlast.Enabled"); + } +} diff --git a/src/ability/earthbending/combo/Crevice.java b/src/ability/earthbending/combo/Crevice.java new file mode 100644 index 0000000..f4e22c4 --- /dev/null +++ b/src/ability/earthbending/combo/Crevice.java @@ -0,0 +1,370 @@ +package com.jedk1.jedcore.ability.earthbending.combo; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.ClickType; + +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Random; + +public class Crevice extends EarthAbility implements AddonAbility, ComboAbility { + + @Attribute(Attribute.RANGE) + private double range; + private long regenDelay; + @Attribute("Depth") + private int randomDepth; + private int avatarDepth; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + private Location origin; + private Location location; + private Vector direction; + private double travelled; + private boolean skip; + + private final List> columns = new ArrayList<>(); + + private final Random rand = new Random(); + + public Crevice(Player player) { + super(player); + if (!bPlayer.canBendIgnoreBinds(this)) { + return; + } + + setFields(); + createInstance(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + range = config.getDouble("Abilities.Earth.EarthCombo.Crevice.Range"); + regenDelay = config.getLong("Abilities.Earth.EarthCombo.Crevice.RevertDelay"); + randomDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.Depth"); + avatarDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth"); + cooldown = config.getLong("Abilities.Earth.EarthCombo.Crevice.Cooldown"); + } + + private void createInstance() { + origin = player.getTargetBlock(null, 6).getLocation(); + if (isEarthbendable(origin.getBlock())) { + Location tempLoc = player.getLocation().clone(); + tempLoc.setPitch(0); + direction = tempLoc.getDirection().clone(); + origin.setDirection(tempLoc.getDirection()); + location = origin.clone(); + if (bPlayer.isAvatarState()) { + randomDepth = avatarDepth; + } + + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + prepareRevert(); + remove(); + return; + } + if (travelled >= range || skip) { + if (System.currentTimeMillis() > getStartTime() + regenDelay) { + prepareRevert(); + remove(); + return; + } + return; + } + advanceCrevice(); + } + + @Override + public void remove() { + prepareRevert(); + super.remove(); + } + + public static void closeCrevice(Player player) { + Block target = player.getTargetBlock(null, 10); + for (Block near : GeneralMethods.getBlocksAroundPoint(target.getLocation(), 2)) { + for (Crevice c : getAbilities(Crevice.class)) { + for (List tbs : c.columns) { + for (TempBlock tb : tbs) { + if (near.getLocation().equals(tb.getLocation())) { + c.prepareRevert(); + c.remove(); + return; + } + } + } + } + } + } + + private void advanceCrevice() { + switch (rand.nextInt(2)) { + case 0: + if (location.getYaw() <= origin.getYaw()) { + location.setYaw(location.getYaw() + 40); + direction = location.getDirection().clone(); + } + break; + case 1: + if (location.getYaw() >= origin.getYaw()) { + location.setYaw(location.getYaw() - 40); + direction = location.getDirection().clone(); + } + break; + default: + direction = location.getDirection().clone(); + break; + } + + Location tempLoc = location.clone(); + location = location.add(direction.multiply(1)); + playEarthbendingSound(tempLoc); + location.getWorld().playSound(location, Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, (float) 0.5, (float) 0.5); + if (skip) { + return; + } + + travelled++; + if (travelled >= range) + return; + + if (RegionProtection.isRegionProtected(player, location, "RaiseEarth")) { + return; + } + + if (!isTransparent(location.getBlock().getRelative(BlockFace.UP))) { + location.add(0, 1, 0); + if (!isTransparent(location.getBlock().getRelative(BlockFace.UP)) || !isEarthbendable(location.getBlock())) { + skip = true; + return; + } + } else if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { + location.subtract(0, 1, 0); + if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { + skip = true; + return; + } + } + + removePillar(tempLoc, randInt(randomDepth + 1 - 2, randomDepth + 1 + 2)); + removePillar(GeneralMethods.getRightSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); + removePillar(GeneralMethods.getLeftSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); + } + + private int randInt(int min, int max) { + return rand.nextInt(max - min) + min; + } + + private void removePillar(Location location, int depth) { + List blocks = new ArrayList<>(); + Location tempLoc = location.clone().getBlock().getLocation(); + tempLoc.add(0, 1, 0); + for (int i = 0; i < depth + 1; i++) { + if (tempLoc.getY() < Objects.requireNonNull(tempLoc.getWorld()).getMinHeight() || tempLoc.getY() > tempLoc.getWorld().getMaxHeight()) { + break; + } + if (RegionProtection.isRegionProtected(player, tempLoc, this)) { + continue; + } + if (i == 0 && !isTransparent(tempLoc.getBlock())) { + continue; + } + if (i > 0 && !isEarthbendable(tempLoc.getBlock())) { + continue; + } + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tempLoc, 1)) { + entity.setVelocity(new Vector(0, -0.75, 0)); + } + + + blocks.add(new TempBlock(tempLoc.getBlock(), Material.AIR.createBlockData())); + tempLoc.subtract(0, 1, 0); + } + + Collections.reverse(blocks); + + columns.add(blocks); + } + + private void prepareRevert() { + for (int i = 0; i < columns.size(); ++i) { + List tbs = columns.get(i); + for (TempBlock tb : tbs) { + tb.revertBlock(); + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 1)) { + entity.setVelocity(new Vector(0, 0.7, 0)); + } + new RegenTempBlock(tb.getBlock(), Material.AIR, Material.AIR.createBlockData(), i * 50L); + } + } + columns.clear(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "Crevice"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public Object createNewComboInstance(Player player) { + return new Crevice(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.Crevice.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.Crevice.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.Crevice.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public long getRegenDelay() { + return regenDelay; + } + + public void setRegenDelay(long regenDelay) { + this.regenDelay = regenDelay; + } + + public int getDepth() { + return randomDepth; + } + + public void setDepth(int depth) { + this.randomDepth = depth; + } + + public int getAvatarDepth() { + return avatarDepth; + } + + public void setAvatarDepth(int avatarDepth) { + this.avatarDepth = avatarDepth; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getDistanceTravelled() { + return travelled; + } + + public void setDistanceTravelled(double travelled) { + this.travelled = travelled; + } + + public List> getColumns() { + return columns; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthCombo.Crevice.Enabled"); + } +} diff --git a/src/ability/earthbending/combo/MagmaBlast.java b/src/ability/earthbending/combo/MagmaBlast.java new file mode 100644 index 0000000..9b1f9d7 --- /dev/null +++ b/src/ability/earthbending/combo/MagmaBlast.java @@ -0,0 +1,615 @@ +package com.jedk1.jedcore.ability.earthbending.combo; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.MaterialUtil; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; + +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.stream.Collectors; + +public class MagmaBlast extends LavaAbility implements AddonAbility, ComboAbility { + private static final int PARTICLE_COUNT = 20; + private static final int RAISE_HEIGHT = 3; + private static final Random rand = new Random(); + + private final Set sources = new HashSet<>(); + private final List blocks = new ArrayList<>(); + private final List firedBlocks = new ArrayList<>(); + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long maxDuration; + private long shotCooldown; + @Attribute("MaxSources") + private int maxSources; + @Attribute(Attribute.SELECT_RANGE) + private int sourceRange; + @Attribute(Attribute.SELECT_RANGE) + private double selectRange; + @Attribute(Attribute.DAMAGE) + private double damage; + private double fireSpeed; + // How far away the player is allowed to be from the sources before the ability is destroyed. + private double maxDistanceFromSources; + private float explosionRadius = 2.0f; + // This will destroy the instance if LavaFlow is on cooldown. + private boolean requireLavaFlow; + private boolean playerCollisions; + private boolean entitySelection; + + private Location origin; + private int counter; + private long canLavaFlowTime; + private long lastShot; + private boolean stopFiring; + + public MagmaBlast(Player player) { + super(player); + setFields(); + + if (!bPlayer.canBendIgnoreBinds(this)) { + return; + } + + origin = player.getLocation().clone(); + + if (raiseSources()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + maxSources = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots"); + sourceRange = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange"); + damage = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage"); + cooldown = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown"); + requireLavaFlow = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow"); + playerCollisions = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions"); + entitySelection = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection"); + selectRange = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange"); + explosionRadius = (float) config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius"); + fireSpeed = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed"); + maxDuration = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration"); + maxDistanceFromSources = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources"); + shotCooldown = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown"); + } + + // Select random nearby earth blocks as sources and raise them in the air. + private boolean raiseSources() { + List potentialBlocks = GeneralMethods.getBlocksAroundPoint(origin, sourceRange).stream().filter(ElementalAbility::isEarth).collect(Collectors.toList()); + + Collections.shuffle(potentialBlocks); + + for (Block newSource : potentialBlocks) { + if (!isValidSource(newSource)) continue; + + newSource.getWorld().playSound(newSource.getLocation(), Sound.ENTITY_GHAST_SHOOT, 0.8f, 0.3f); + sources.add(new TempFallingBlock(newSource.getLocation().add(0, 1, 0), Material.MAGMA_BLOCK.createBlockData(), new Vector(0, 0.9, 0), this)); + + if (sources.size() >= maxSources) { + break; + } + } + + return !sources.isEmpty(); + } + + // Checks to make sure the source block has room to fly upwards. + private boolean isValidSource(Block block) { + for (int i = 0; i <= RAISE_HEIGHT; ++i) { + if (!MaterialUtil.isTransparent(block.getRelative(BlockFace.UP, i + 1)) || block.isLiquid()) { + return false; + } + } + + return true; + } + + public boolean shouldBlockLavaFlow() { + long time = System.currentTimeMillis(); + return time < canLavaFlowTime; + } + + @Override + public void progress() { + stopFiring = false; + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (System.currentTimeMillis() > this.getStartTime() + maxDuration) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBinds(this) || !(bPlayer.getBoundAbility() instanceof LavaFlow)) { + remove(); + return; + } + + if (requireLavaFlow && !bPlayer.canBend(getAbility("LavaFlow"))) { + remove(); + return; + } + + displayAnimation(); + handleSources(); + + if (playerCollisions) { + doPlayerCollisions(); + } + + if (sources.isEmpty() && firedBlocks.isEmpty() && blocks.isEmpty()) { + remove(); + return; + } + + if (hasBlocks() && this.player.getLocation().distanceSquared(origin) > maxDistanceFromSources * maxDistanceFromSources) { + remove(); + } + } + + @Override + public void remove() { + bPlayer.addCooldown(this); + super.remove(); + + for (TempFallingBlock ftb : sources) { + ftb.remove(); + } + + for (TempBlock tb : blocks) { + tb.revertBlock(); + } + + for (TempFallingBlock tfb : firedBlocks) { + tfb.remove(); + } + } + + private void handleSources() { + if (sources.isEmpty()) return; + + for (Iterator iter = sources.iterator(); iter.hasNext();) { + TempFallingBlock tfb = iter.next(); + + if (tfb.getLocation().getBlockY() >= (origin.getBlockY() + RAISE_HEIGHT)) { + blocks.add(new TempBlock(tfb.getLocation().getBlock(), Material.MAGMA_BLOCK.createBlockData())); + iter.remove(); + tfb.remove(); + } + } + } + + private void displayAnimation() { + if (++counter == 3) { + counter = 0; + } else { + return; + } + + for (Iterator iterator = firedBlocks.iterator(); iterator.hasNext();) { + TempFallingBlock tfb = iterator.next(); + + if (!tfb.getFallingBlock().isDead()) { + playParticles(tfb.getLocation()); + } else { + tfb.remove(); + iterator.remove(); + } + } + + for (TempBlock tb : blocks) { + playParticles(tb.getLocation()); + } + } + + private void doPlayerCollisions() { + List blocksCopy = new ArrayList<>(firedBlocks); + + for (TempFallingBlock tfb : blocksCopy) { + if (!firedBlocks.contains(tfb)) continue; + + boolean didExplode = false; + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), this.explosionRadius)) { + if (!(e instanceof LivingEntity)) continue; + if (e == this.player) continue; + + if (blast(tfb, true)) { + didExplode = true; + } + } + + if (didExplode) { + firedBlocks.remove(tfb); + } + } + } + + private void playParticles(Location location) { + location.add(.5,.5,.5); + ParticleEffect.LAVA.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); + ParticleEffect.SMOKE_NORMAL.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); + for (int i = 0; i < 10; i++) { + GeneralMethods.displayColoredParticle("FFA400", getOffsetLocation(location, 2)); + GeneralMethods.displayColoredParticle("FF8C00", getOffsetLocation(location, 2)); + } + } + + // Returns true if any source blocks still exist. Returns false is all of the source blocks have been fired. + public boolean hasBlocks() { + return !sources.isEmpty() || !blocks.isEmpty(); + } + + private Location getOffsetLocation(Location loc, double offset) { + return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); + } + + public static void performAction(Player player) { + MagmaBlast mb = getAbility(player, MagmaBlast.class); + + if (mb != null) { + mb.performAction(); + } + } + + private void performAction() { + long time = System.currentTimeMillis(); + + if (blocks.isEmpty() || stopFiring || time < lastShot + shotCooldown) return; + + Location target = null; + + if (entitySelection) { + Entity targetEntity = GeneralMethods.getTargetedEntity(player, selectRange); + + if (targetEntity instanceof LivingEntity) { + target = ((LivingEntity) targetEntity).getEyeLocation(); + } + } + + if (target == null) { + target = GeneralMethods.getTargetedLocation(player, selectRange, Material.MAGMA_BLOCK); + } + + TempBlock tb = getClosestSource(target); + + if (tb == null) return; + + stopFiring = true; + canLavaFlowTime = time + 1000; + blocks.remove(tb); + + Vector direction = GeneralMethods.getDirection(tb.getLocation().clone().add(0.5f, 0.5f, 0.5f), target).normalize(); + + tb.revertBlock(); + + FallingBlock fallingBlock = tb.getLocation().getWorld().spawnFallingBlock( + tb.getLocation().clone().add(0.5, 0.5, 0.5), + Material.MAGMA_BLOCK.createBlockData() + ); + + fallingBlock.setTicksLived(Integer.MAX_VALUE); + fallingBlock.setMetadata("magmablast", new FixedMetadataValue(JedCore.plugin, "1")); + fallingBlock.setDropItem(false); + fallingBlock.setCancelDrop(true); + + TempFallingBlock tfb = new TempFallingBlock(tb.getLocation(), Material.MAGMA_BLOCK.createBlockData(), direction.multiply(fireSpeed), this, true); + firedBlocks.add(tfb); + + lastShot = time; + } + + // Get the closest fireable source block to the target location. + private TempBlock getClosestSource(Location target) { + double distanceSq = Double.MAX_VALUE; + TempBlock closest = null; + + for (TempBlock tempBlock : blocks) { + double currentDistSq = tempBlock.getLocation().distanceSquared(target); + + if (currentDistSq < distanceSq) { + distanceSq = currentDistSq; + closest = tempBlock; + } + } + + return closest; + } + + public static void blast(TempFallingBlock tfb) { + blast(tfb, false); + } + + public static boolean blast(TempFallingBlock tfb, boolean entityCollision) { + MagmaBlast mb = (MagmaBlast) tfb.getAbility(); + Location location = tfb.getLocation().clone().add(0.5, 0.5, 0.5); + + Block hitBlock = location.getBlock(); + if (hitBlock.getType().isSolid()) { + blastEffects(location, mb); + tfb.remove(); + mb.firedBlocks.remove(tfb); + return true; + } + + float radius = mb.explosionRadius; + boolean didHit = false; + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, radius)) { + if (!(entity instanceof LivingEntity)) continue; + if (entity == mb.player) continue; + + DamageHandler.damageEntity(entity, mb.getDamage(), mb); + ((LivingEntity) entity).setNoDamageTicks(0); + didHit = true; + } + + if (didHit || entityCollision) { + blastEffects(location, mb); + tfb.remove(); + mb.firedBlocks.remove(tfb); + return true; + } + + return false; + } + + private static void blastEffects(Location location, MagmaBlast mb) { + float radius = mb.explosionRadius; + float speed = 0.1f; + + ParticleEffect.FLAME.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); + ParticleEffect.SMOKE_LARGE.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); + ParticleEffect.FIREWORKS_SPARK.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); + + location.getWorld().playSound(location, + (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, + 1f, 1f); + location.getWorld().playSound(location, + (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, + 1f, 1f); + } + + // Generates a random number between -max and max. + private static float randomBinomial(float max) { + return (rand.nextFloat() * max) - (rand.nextFloat() * max); + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MagmaBlast"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public Object createNewComboInstance(Player player) { + return new MagmaBlast(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.MagmaBlast.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.MagmaBlast.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.MagmaBlast.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public Set getSources() { + return sources; + } + + public List getBlocks() { + return blocks; + } + + public List getFiredBlocks() { + return firedBlocks; + } + + public long getMaxDuration() { + return maxDuration; + } + + public void setMaxDuration(long maxDuration) { + this.maxDuration = maxDuration; + } + + public long getShotCooldown() { + return shotCooldown; + } + + public void setShotCooldown(long shotCooldown) { + this.shotCooldown = shotCooldown; + } + + public int getMaxSources() { + return maxSources; + } + + public void setMaxSources(int maxSources) { + this.maxSources = maxSources; + } + + public int getSourceRange() { + return sourceRange; + } + + public void setSourceRange(int sourceRange) { + this.sourceRange = sourceRange; + } + + public double getSelectRange() { + return selectRange; + } + + public void setSelectRange(double selectRange) { + this.selectRange = selectRange; + } + + public double getFireSpeed() { + return fireSpeed; + } + + public void setFireSpeed(double fireSpeed) { + this.fireSpeed = fireSpeed; + } + + public double getMaxDistanceFromSources() { + return maxDistanceFromSources; + } + + public void setMaxDistanceFromSources(double maxDistanceFromSources) { + this.maxDistanceFromSources = maxDistanceFromSources; + } + + public float getExplosionRadius() { + return explosionRadius; + } + + public void setExplosionRadius(float explosionRadius) { + this.explosionRadius = explosionRadius; + } + + public boolean isRequireLavaFlow() { + return requireLavaFlow; + } + + public void setRequireLavaFlow(boolean requireLavaFlow) { + this.requireLavaFlow = requireLavaFlow; + } + + public boolean isPlayerCollisions() { + return playerCollisions; + } + + public void setPlayerCollisions(boolean playerCollisions) { + this.playerCollisions = playerCollisions; + } + + public boolean isEntitySelection() { + return entitySelection; + } + + public void setEntitySelection(boolean entitySelection) { + this.entitySelection = entitySelection; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public long getCanLavaFlowTime() { + return canLavaFlowTime; + } + + public void setCanLavaFlowTime(long canLavaFlowTime) { + this.canLavaFlowTime = canLavaFlowTime; + } + + public long getLastShotTime() { + return lastShot; + } + + public void setLastShotTime(long lastShot) { + this.lastShot = lastShot; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/firebending/Combustion.java b/src/ability/firebending/Combustion.java new file mode 100644 index 0000000..1e4edff --- /dev/null +++ b/src/ability/firebending/Combustion.java @@ -0,0 +1,629 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.util.FireTick; + +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.Tag; +import com.jedk1.jedcore.util.MaterialUtil; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.CombustionAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +public class Combustion extends CombustionAbility implements AddonAbility { + + private State state; + private Location location; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private CompositeRemovalPolicy removalPolicy; + + private ArrayList skipMaterials; // use a configured list of blocks to skip through + + public Combustion(Player player) { + super(player); + + if (!isEnabled()) return; + + if (this.player == null || !bPlayer.canBend(this) || !bPlayer.canCombustionbend()) { + return; + } + + if (hasAbility(player, Combustion.class)) { + Combustion c = getAbility(player, Combustion.class); + if (c.state instanceof ChargeState) + return; + } + + setFields(); + + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.Combustion.Cooldown"); + + this.location = null; + this.state = new ChargeState(); + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new SwappedSlotsRemovalPolicy<>(bPlayer, Combustion.class) + ); + + this.removalPolicy.load(config, "Abilities.Fire.Combustion"); + + this.skipMaterials = loadSkipMaterials(); + } + + @Override + public void progress() { + if (this.removalPolicy.shouldRemove()) { + remove(); + return; + } + + state.update(); + } + + public static void combust(Player player) { + if(hasAbility(player, Combustion.class)) { + Combustion c = getAbility(player, Combustion.class); + + c.selfCombust(); + } + } + + public void selfCombust() { + if (this.state instanceof TravelState) { + this.state = new CombustState(location); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + // Only enable the collision while traveling. + if (state instanceof TravelState) { + return location; + } + + return null; + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Fire.Combustion.AbilityCollisionRadius"); + } + + @Override + public String getName() { + return "Combustion"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.Combustion.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.Combustion.Enabled"); + } + + private ArrayList loadSkipMaterials() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + ArrayList skipList = new ArrayList<>(); + + if (config.contains("Abilities.Fire.Combustion.SkipMaterials")) { + List configuredSkipList = config.getStringList("Abilities.Fire.Combustion.SkipMaterials"); + + for (String entry : configuredSkipList) { + if (entry.startsWith("#")) { + String tagName = entry.substring(1).toLowerCase(); + + NamespacedKey tagKey = NamespacedKey.minecraft(tagName); + Tag materialTag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, tagKey, Material.class); + + if (materialTag != null) { + skipList.addAll(materialTag.getValues().stream() + .map(material -> material.name().toLowerCase()) + .collect(Collectors.toList())); + } + } else { + skipList.add(entry.toLowerCase()); + } + } + } + + return skipList; + } + + private interface State { + void update(); + } + + // This is the initial state of Combustion. + // It's used to render the particle ring that happens during charging. + // This state transitions to TravelState if the player stops sneaking after charging is done. + // This state transitions to CombustState if the player takes damage while charging. + private class ChargeState implements State { + private final long startTime; + private int currPoint = (int) player.getLocation().getYaw() + 90; + private final long warmup; + private final double playerStartHealth; + private final boolean instantExplodeIfHit; + + public ChargeState() { + this.startTime = System.currentTimeMillis(); + this.playerStartHealth = player.getHealth(); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + this.instantExplodeIfHit = config.getBoolean("Abilities.Fire.Combustion.InstantExplodeIfHit"); + this.warmup = config.getLong("Abilities.Fire.Combustion.Warmup"); + } + + @Override + public void update() { + long time = System.currentTimeMillis(); + + boolean charged = time >= this.startTime + warmup; + + if (player.isSneaking()) { + if (!bPlayer.canBendIgnoreBinds(Combustion.this)) { + remove(); + return; + } + + playParticleRing(60, 1.75F, 2); + + if (instantExplodeIfHit && player.getHealth() < playerStartHealth) { + // Remove and combust at player's location + state = new CombustState(player.getLocation(), true); + bPlayer.addCooldown(Combustion.this); + return; + } + + if (charged) { + ParticleEffect.SMOKE_LARGE.display(player.getLocation(), 1, Math.random(), Math.random(), Math.random(), 0.1); + } + } else { + if (charged) { + state = new TravelState(); + bPlayer.addCooldown(Combustion.this); + } else { + remove(); + } + } + } + + private void playParticleRing(int points, float size, int speed) { + for (int i = 0; i < speed; ++i) { + currPoint += 360 / points; + + if (currPoint > 360) { + currPoint = 0; + } + + double angle = currPoint * 3.141592653589793D / 180.0D; + double x = size * Math.cos(angle); + double z = size * Math.sin(angle); + + Location loc = player.getLocation().add(x, 1.0D, z); + playFirebendingParticles(loc, 3, 0.0, 0.0, 0.0); + ParticleEffect.SMOKE_NORMAL.display(loc, 4, 0.0, 0.0, 0.0, 0.01); + JCMethods.emitLight(loc); + } + } + } + + // This state is used after the player releases a charged Combustion. + // It's used for moving and rendering the projectile. + // This state transitions to CombustState when it collides with terrain or an entity. + private class TravelState implements State { + private Vector direction; + private final int range; + private final double speed; + private final boolean explodeOnDeath; + private final double entityCollisionRadius; + private double distanceTraveled; + + public TravelState() { + removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); + + Location origin = player.getEyeLocation().clone(); + origin.setY(origin.getY() - 0.8D); + location = origin.clone(); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + range = config.getInt("Abilities.Fire.Combustion.Range"); + speed = config.getDouble("Abilities.Fire.Combustion.Speed"); + explodeOnDeath = config.getBoolean("Abilities.Fire.Combustion.ExplodeOnDeath"); + entityCollisionRadius = config.getDouble("Abilities.Fire.Combustion.EntityCollisionRadius"); + + if (explodeOnDeath) { + removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); + removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); + } + + direction = player.getEyeLocation().getDirection().normalize(); + distanceTraveled = 0; + } + + @Override + public void update() { + if (explodeOnDeath && player.isDead()) { + state = new CombustState(location); + return; + } + + // Manually handle the region protection check because the CannotBendRemovalPolicy no longer checks it + // when explodeOnDeath is true. This stops players from firing Combustion and then walking into a + // protected area. + if (explodeOnDeath) { + if (RegionProtection.isRegionProtected(Combustion.this, player.getLocation())) { + remove(); + return; + } + } + + if (distanceTraveled >= range) { + remove(); + return; + } + + travel(); + } + + private void travel() { + double stepDistance = speed; + + for (int i = 0; i < (int) (speed * 5); ++i) { + render(); + + Sphere collider = new Sphere(location.toVector(), entityCollisionRadius); + + boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { + location = entity.getLocation(); + state = new CombustState(location); + return true; + }); + + if (hit) { + return; + } + + if (!MaterialUtil.isTransparent(location.getBlock()) || isWater(location.getBlock())) { + Material blockMaterial = location.getBlock().getType(); + String blockMaterialName = blockMaterial.name().toLowerCase(); + + boolean shouldSkip = skipMaterials.contains(blockMaterialName); + + if (!shouldSkip) { + state = new CombustState(location); + return; + } + } + + direction = player.getEyeLocation().getDirection().normalize(); + location = location.add(direction.clone().multiply(stepDistance)); + + distanceTraveled += stepDistance; + + if (distanceTraveled >= range) { + remove(); + return; + } + } + } + + private void render() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + ParticleEffect.SOUL_FIRE_FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); + } else { + ParticleEffect.FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); + } + ParticleEffect.SMOKE_LARGE.display(location, 1, 0.0, 0.0, 0.0F, 0.06); + ParticleEffect.FIREWORKS_SPARK.display(location, 1, 0.0, 0.0, 0.0F, 0.06); + + location.getWorld().playSound(location, Sound.ENTITY_FIREWORK_ROCKET_BLAST, 1.0F, 0.01F); + + JCMethods.emitLight(location); + } + } + + @Override + public void handleCollision(final Collision collision) { + super.handleCollision(collision); + + if (collision.isRemovingFirst()) { + state = new CombustState(collision.getLocationFirst()); + } + } + + // This state is used for doing the explosion. + // ChargeState can transition to this state if the player takes damage while charging. + // TravelState can transition to this state if the projectile collides with terrain, entity, or collidable ability. + private class CombustState implements State { + private final long startTime; + private final long regenTime; + private boolean waitForRegen; + + public CombustState(Location location) { + this(location, false); + } + + public CombustState(Location location, boolean misfire) { + removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); + // This stops players from moving into a protected area to bypass the regen wait time. + removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + this.startTime = System.currentTimeMillis(); + this.regenTime = config.getLong("Abilities.Fire.Combustion.RegenTime"); + this.waitForRegen = config.getBoolean("Abilities.Fire.Combustion.WaitForRegen"); + + double damage = config.getDouble("Abilities.Fire.Combustion.Damage"); + int fireTick = config.getInt("Abilities.Fire.Combustion.FireTick"); + int power = config.getInt("Abilities.Fire.Combustion.Power"); + boolean damageBlocks = config.getBoolean("Abilities.Fire.Combustion.DamageBlocks"); + boolean regenBlocks = config.getBoolean("Abilities.Fire.Combustion.RegenBlocks"); + + ExplosionMethod explosionMethod; + if (regenBlocks) { + explosionMethod = new RegenExplosionMethod(damageBlocks, regenTime); + } else { + explosionMethod = new PermanentExplosionMethod(damageBlocks); + } + + // Don't wait for regen if the blocks aren't even being destroyed. + if (!damageBlocks) { + waitForRegen = false; + } + + double modifier = 0; + if (misfire) { + modifier = config.getInt("Abilities.Fire.Combustion.MisfireModifier"); + } + + int destroyedCount = explosionMethod.explode(location, power + modifier, damage + modifier, fireTick); + + // Don't wait for regen if nothing was actually destroyed. + if (destroyedCount <= 0) { + waitForRegen = false; + } + + AirAbility.removeAirSpouts(location, power, player); + WaterAbility.removeWaterSpouts(location, power, player); + } + + @Override + public void update() { + if (!waitForRegen || System.currentTimeMillis() >= (this.startTime + this.regenTime)) { + remove(); + } + } + } + + private interface ExplosionMethod { + // Returns how many blocks were destroyed. + int explode(Location location, double size, double damage, int fireTick); + } + + private abstract class AbstractExplosionMethod implements ExplosionMethod { + protected List blocks = Arrays.asList( + Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.BEDROCK, Material.CHEST, Material.TRAPPED_CHEST, Material.OBSIDIAN, + Material.NETHER_PORTAL, Material.END_PORTAL, Material.END_PORTAL_FRAME, Material.FIRE, + Material.WATER, Material.LAVA, Material.DROPPER, Material.FURNACE, + Material.DISPENSER, Material.HOPPER, Material.BEACON, Material.BARRIER, Material.SPAWNER + ); + + private final boolean destroy; + private final Random rand = new Random(); + + public AbstractExplosionMethod(boolean destroy) { + this.destroy = destroy; + } + + public int explode(Location location, double size, double damage, int fireTick) { + render(location); + + if (!destroy) { + return 0; + } + + location.getWorld().createExplosion(location, 0.0F); + int destroyCount = destroyBlocks(location, (int)size); + damageEntities(location, size, damage, fireTick); + + return destroyCount; + } + + private void render(Location location) { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + ParticleEffect.SOUL_FIRE_FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + } else { + ParticleEffect.FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + } + ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + ParticleEffect.FIREWORKS_SPARK.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random()); + ParticleEffect.EXPLOSION_HUGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + + location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 1f, 1f); + } + + private int destroyBlocks(Location location, int size) { + int count = 0; + + for (Location l : GeneralMethods.getCircle(location, size, size, false, true, 0)) { + if (!RegionProtection.isRegionProtected(Combustion.this, l)) { + if (destroyBlock(l)) { + ++count; + } + } + } + + return count; + } + + private void damageEntities(Location location, double size, double damage, int fireTick) { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, size)) { + if (e instanceof LivingEntity) { + if (!RegionProtection.isRegionProtected(Combustion.this, e.getLocation())) { + DamageHandler.damageEntity(e, damage, Combustion.this); + FireTick.set(e, fireTick); + } + } + } + } + + protected void placeRandomFire(Location location) { + int chance = rand.nextInt(3); + + if ((!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) || (chance != 0)) + return; + + location.getBlock().setType(Material.FIRE); + } + + protected void placeRandomBlock(Location location) { + int chance = rand.nextInt(3); + + if (!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) + return; + + Material block = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType(); + + if (chance == 0) + location.getBlock().setType(block); + } + + // Returns how many blocks were destroyed. + public abstract boolean destroyBlock(Location location); + } + + private class RegenExplosionMethod extends AbstractExplosionMethod { + private final long regenTime; + + public RegenExplosionMethod(boolean destroy, long regenTime) { + super(destroy); + this.regenTime = regenTime; + } + + @Override + public boolean destroyBlock(Location l) { + Block block = l.getBlock(); + + if (TempBlock.isTempBlock(block)) + TempBlock.revertBlock(block, Material.AIR); + if (TempBlock.isTempBlock(block)) + TempBlock.removeBlock(block); + + if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), regenTime, false); + placeRandomBlock(l); + placeRandomFire(l); + + return true; + } + + return false; + } + } + + private class PermanentExplosionMethod extends AbstractExplosionMethod { + public PermanentExplosionMethod(boolean destroy) { + super(destroy); + } + + @Override + public boolean destroyBlock(Location l) { + Block block = l.getBlock(); + + if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { + Block newBlock = l.getWorld().getBlockAt(l); + newBlock.setType(Material.AIR); + placeRandomBlock(l); + placeRandomFire(l); + + return true; + } + + return false; + } + } +} diff --git a/src/ability/firebending/Discharge.java b/src/ability/firebending/Discharge.java new file mode 100644 index 0000000..49e62dc --- /dev/null +++ b/src/ability/firebending/Discharge.java @@ -0,0 +1,347 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.LightningAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; + +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Random; + +public class Discharge extends LightningAbility implements AddonAbility { + private final HashMap branches = new HashMap<>(); + + private Location location; + private Vector direction; + private boolean hit; + private int spaces; + private double branchSpace; + private final Random rand = new Random(); + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.COOLDOWN) + private long cooldown, avatarCooldown; + @Attribute(Attribute.DURATION) + private long duration; + private boolean slotSwapping; + @Attribute("CollisionRadius") + private double entityCollisionRadius; + + private float soundVolume; + private int soundInterval; + + public Discharge(Player player) { + super(player); + + if (!bPlayer.canBend(this) || hasAbility(player, Discharge.class) || !bPlayer.canLightningbend()) { + return; + } + + setFields(); + + direction = player.getEyeLocation().getDirection().normalize(); + + if (bPlayer.isAvatarState() || JCMethods.isSozinsComet(player.getWorld())) { + this.cooldown = avatarCooldown; + } + + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + damage = config.getDouble("Abilities.Fire.Discharge.Damage"); + cooldown = config.getLong("Abilities.Fire.Discharge.Cooldown"); + avatarCooldown = config.getLong("Abilities.Fire.Discharge.AvatarCooldown"); + duration = config.getLong("Abilities.Fire.Discharge.Duration"); + slotSwapping = config.getBoolean("Abilities.Fire.Discharge.SlotSwapping"); + entityCollisionRadius = config.getDouble("Abilities.Fire.Discharge.EntityCollisionRadius"); + + soundVolume = (float) config.getDouble("Abilities.Fire.Discharge.Sound.Volume"); + soundInterval = config.getInt("Abilities.Fire.Discharge.Sound.Interval"); + + branchSpace = 0.2; + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!canBend()) { + remove(); + return; + } + + if (System.currentTimeMillis() < (getStartTime() + duration) && !hit) { + advanceLocation(); + } else { + remove(); + } + } + + private boolean canBend() { + if (!slotSwapping) { + return bPlayer.canBendIgnoreCooldowns(this); + } else { + return bPlayer.canBendIgnoreBindsCooldowns(this); + } + } + + private void advanceLocation() { + if (location == null) { + Location origin = player.getEyeLocation().clone(); + location = origin.clone(); + branches.put(branches.size() + 1, location); + } + + spaces++; + if (spaces % 3 == 0) { + Location prevBranch = branches.get(1); + branches.put(branches.size() + 1, prevBranch); + } + + List cleanup = new ArrayList<>(); + + for (int i : branches.keySet()) { + Location origin = branches.get(i); + + if (origin != null) { + Location l = origin.clone(); + + if (!isTransparent(l.getBlock())) { + cleanup.add(i); + continue; + } + + l.add(createBranch(), createBranch(), createBranch()); + branchSpace += 0.001; + + for (int j = 0; j < 5; j++) { + playLightningbendingParticle(l.clone(), 0f, 0f, 0f); + JCMethods.emitLight(l.clone()); + + if (rand.nextInt(soundInterval) == 0) { + player.getWorld().playSound(l, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); + } + + Vector vec = l.toVector(); + + hit = CollisionDetector.checkEntityCollisions(player, new Sphere(l.toVector(), entityCollisionRadius), (entity) -> { + if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))) { + return true; + } + Vector knockbackVector = entity.getLocation().toVector().subtract(vec).normalize().multiply(0.8); + GeneralMethods.setVelocity(this, entity, knockbackVector); + + DamageHandler.damageEntity(entity, damage, this); + + for (int k = 0; k < 5; k++) { + playLightningbendingParticle(entity.getLocation(), (float) Math.random(), (float) Math.random(), (float) Math.random()); + JCMethods.emitLight(entity.getLocation()); + } + + entity.getWorld().playSound(entity.getLocation(), Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); + player.getWorld().playSound(player.getLocation(), Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); + + return true; + }); + + l = l.add(direction.clone().multiply(0.2)); + } + + branches.put(i, l); + } + } + + for (int i : cleanup) { + branches.remove(i); + } + + cleanup.clear(); + } + + private double createBranch() { + int i = rand.nextInt(3); + + switch (i) { + case 0: + return branchSpace; + case 2: + return -branchSpace; + default: + return 0.0; + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public List getLocations() { + return new ArrayList<>(branches.values()); + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Fire.Discharge.AbilityCollisionRadius"); + } + + @Override + public String getName() { + return "Discharge"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.Discharge.Description"); + } + + public HashMap getBranches() { + return branches; + } + + public void setLocation(Location location) { + this.location = location; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public boolean isHit() { + return hit; + } + + public void setHit(boolean hit) { + this.hit = hit; + } + + public int getSpaces() { + return spaces; + } + + public void setSpaces(int spaces) { + this.spaces = spaces; + } + + public double getBranchSpace() { + return branchSpace; + } + + public void setBranchSpace(double branchSpace) { + this.branchSpace = branchSpace; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getAvatarCooldown() { + return avatarCooldown; + } + + public void setAvatarCooldown(long avatarCooldown) { + this.avatarCooldown = avatarCooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public boolean isSlotSwapping() { + return slotSwapping; + } + + public void setSlotSwapping(boolean slotSwapping) { + this.slotSwapping = slotSwapping; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.Discharge.Enabled"); + } +} diff --git a/src/ability/firebending/FireBall.java b/src/ability/firebending/FireBall.java new file mode 100644 index 0000000..7d739f0 --- /dev/null +++ b/src/ability/firebending/FireBall.java @@ -0,0 +1,308 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.AirShieldReflector; +import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.airbending.AirShield; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.firebending.BlazeArc; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; + +public class FireBall extends FireAbility implements AddonAbility { + + private Location location; + private Vector direction; + private double distanceTravelled; + + @Attribute(Attribute.RANGE) + private long range; + @Attribute(Attribute.FIRE_TICK) + private long fireTicks; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DAMAGE) + private double damage; + private boolean controllable; + private boolean fireTrail; + @Attribute("CollisionRadius") + private double collisionRadius; + + public FireBall(Player player) { + super(player); + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + location = player.getEyeLocation(); + direction = player.getEyeLocation().getDirection().normalize(); + + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + range = config.getLong("Abilities.Fire.FireBall.Range"); + fireTicks = config.getLong("Abilities.Fire.FireBall.FireDuration"); + cooldown = config.getLong("Abilities.Fire.FireBall.Cooldown"); + damage = config.getDouble("Abilities.Fire.FireBall.Damage"); + controllable = config.getBoolean("Abilities.Fire.FireBall.Controllable"); + fireTrail = config.getBoolean("Abilities.Fire.FireBall.FireTrail"); + collisionRadius = config.getDouble("Abilities.Fire.FireBall.CollisionRadius"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + range *= BlueFireAbility.getRangeFactor(); + cooldown *= BlueFireAbility.getCooldownFactor(); + damage *= BlueFireAbility.getDamageFactor(); + } + + if (isDay(player.getWorld())) { + range = (long) getDayFactor(range); + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + damage = getDayFactor(damage); + } + } + + @Override + public void progress(){ + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (distanceTravelled >= range) { + remove(); + return; + } + + if (RegionProtection.isRegionProtected(player, location, this)) { + remove(); + return; + } + + progressFireball(); + } + + private void progressFireball() { + for (int i = 0; i < 2; i++) { + distanceTravelled ++; + if (distanceTravelled >= range) { + return; + } + + if (controllable) { + direction = player.getLocation().getDirection(); + } + + location = location.add(direction); + if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())) { + distanceTravelled = range; + return; + } + + ParticleEffect.SMOKE_LARGE.display(location, 1, 0, 0, 0, 0); + ParticleEffect.SMOKE_LARGE.display(location, 1, 0, 0, 0, 0); + for (int j = 0; j < 5; j++) { + playFirebendingParticles(location, 1, 0, 0, 0); + } + + JCMethods.emitLight(location); + + boolean hitTarget = CollisionDetector.checkEntityCollisions(player, new Sphere(location.toVector(), collisionRadius), this::doDamage); + + if (!hitTarget) { + if (this.distanceTravelled > 2 && this.fireTrail) { + new BlazeArc(player, location.clone().subtract(direction).subtract(direction), direction, 2); + } + } else { + remove(); + return; + } + } + } + + private boolean doDamage(Entity entity) { + if (!(entity instanceof LivingEntity)) return false; + + distanceTravelled = range; + DamageHandler.damageEntity(entity, damage, this); + + FireTick.set(entity, Math.round(fireTicks / 50F)); + new FireDamageTimer(entity, player, this); + return false; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + remove(); + } else { + CoreAbility second = collision.getAbilitySecond(); + if (second instanceof AirShield) { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + boolean reflect = config.getBoolean("Abilities.Fire.FireBall.Collisions.AirShield.Reflect", true); + + if (reflect) { + AirShield shield = (AirShield) second; + AirShieldReflector.reflect(shield, this.location, this.direction); + } + } + } + } + + @Override + public String getName() { + return "FireBall"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireBall.Description"); + } + + public void setLocation(Location location) { + this.location = location; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getDistanceTravelled() { + return distanceTravelled; + } + + public void setDistanceTravelled(double distanceTravelled) { + this.distanceTravelled = distanceTravelled; + } + + public long getRange() { + return range; + } + + public void setRange(long range) { + this.range = range; + } + + public long getFireTicks() { + return fireTicks; + } + + public void setFireTicks(long fireTicks) { + this.fireTicks = fireTicks; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean isControllable() { + return controllable; + } + + public void setControllable(boolean controllable) { + this.controllable = controllable; + } + + public boolean isFireTrail() { + return fireTrail; + } + + public void setFireTrail(boolean fireTrail) { + this.fireTrail = fireTrail; + } + + @Override + public double getCollisionRadius() { + return collisionRadius; + } + + public void setCollisionRadius(double collisionRadius) { + this.collisionRadius = collisionRadius; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FireBall.Enabled"); + } +} diff --git a/src/ability/firebending/FireBreath.java b/src/ability/firebending/FireBreath.java new file mode 100644 index 0000000..6a063c8 --- /dev/null +++ b/src/ability/firebending/FireBreath.java @@ -0,0 +1,427 @@ +package com.jedk1.jedcore.ability.firebending; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.UUID; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.listener.CommandListener; +import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.ChatUtil; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.firebending.BlazeArc; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; + +public class FireBreath extends FireAbility implements AddonAbility { + + public static List rainbowPlayer = new ArrayList<>(); + + private int ticks; + Random rand = new Random(); + private final List locations = new ArrayList<>(); + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + private int particles; + @Attribute(Attribute.DAMAGE) + private double playerDamage; + @Attribute(Attribute.DAMAGE) + private double mobDamage; + @Attribute(Attribute.DURATION) + private int fireDuration; + @Attribute(Attribute.RANGE) + private int range; + private boolean spawnFire; + private boolean meltEnabled; + private int meltChance; + + + public FireBreath(Player player) { + super(player); + if (!bPlayer.canBend(this) || hasAbility(player, FireBreath.class)) { + return; + } + + setFields(); + + if (bPlayer.isAvatarState()) { + range = range * 2; + playerDamage = playerDamage * 1.5; + mobDamage = mobDamage * 2; + duration = duration * 3; + } else if (JCMethods.isSozinsComet(player.getWorld())) { + range = range * 2; + playerDamage = playerDamage * 1.5; + mobDamage = mobDamage * 2; + } + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.FireBreath.Cooldown"); + duration = config.getLong("Abilities.Fire.FireBreath.Duration"); + particles = config.getInt("Abilities.Fire.FireBreath.Particles"); + playerDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Player"); + mobDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Mob"); + fireDuration = config.getInt("Abilities.Fire.FireBreath.FireDuration"); + range = config.getInt("Abilities.Fire.FireBreath.Range"); + spawnFire = config.getBoolean("Abilities.Fire.FireBreath.Avatar.FireEnabled"); + meltEnabled = config.getBoolean("Abilities.Fire.FireBreath.Melt.Enabled"); + meltChance = config.getInt("Abilities.Fire.FireBreath.Melt.Chance"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + cooldown *= BlueFireAbility.getCooldownFactor(); + range *= BlueFireAbility.getRangeFactor(); + playerDamage *= BlueFireAbility.getDamageFactor(); + mobDamage *= BlueFireAbility.getDamageFactor(); + } + + if (isDay(player.getWorld())) { + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + range = (int) getDayFactor(range); + playerDamage = getDayFactor(playerDamage); + mobDamage = getDayFactor(mobDamage); + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (!player.isSneaking()) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (System.currentTimeMillis() < getStartTime() + duration) { + createBeam(); + } else { + bPlayer.addCooldown(this); + remove(); + } + } + + private boolean isLocationSafe(Location loc) { + Block block = loc.getBlock(); + if (RegionProtection.isRegionProtected(player, loc, this)) { + return false; + } + if (!isTransparent(block)) { + return false; + } + return !isWater(block); + } + + private void createBeam() { + Location loc = player.getEyeLocation(); + Vector dir = player.getLocation().getDirection(); + double step = 1; + double size = 0; + double offset = 0; + double damageRegion = 1.5; + + locations.clear(); + + for (double k = 0; k < range; k += step) { + loc = loc.add(dir.clone().multiply(step)); + size += 0.005; + offset += 0.3; + damageRegion += 0.01; + if (meltEnabled) { + for (Block b : GeneralMethods.getBlocksAroundPoint(loc, damageRegion)) { + if (isIce(b) && rand.nextInt(meltChance) == 0) { + if (TempBlock.isTempBlock(b)) { + TempBlock temp = TempBlock.get(b); + if (PhaseChange.getFrozenBlocksMap().containsKey(temp)) { + temp.revertBlock(); + PhaseChange.getFrozenBlocksMap().remove(temp); + } + } + } + } + } + if (!isLocationSafe(loc)) + return; + + locations.add(loc); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + if (entity instanceof Player) { + FireTick.set(entity, fireDuration / 50); + DamageHandler.damageEntity(entity, playerDamage, this); + } else { + FireTick.set(entity, fireDuration / 50); + DamageHandler.damageEntity(entity, mobDamage, this); + } + } + } + + playFirebendingSound(loc); + if (bPlayer.isAvatarState() && spawnFire) { + new BlazeArc(player, loc, dir, 2); + } + + if (rainbowPlayer.contains(player.getUniqueId())) { + ticks++; + if (ticks >= 301) + ticks = 0; + if (isInRange(ticks, 0, 50)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 140, 32, 32); + } else if (isInRange(ticks, 51, 100)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 196, 93, 0); + } else if (isInRange(ticks, 101, 150)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 186, 166, 37); + } else if (isInRange(ticks, 151, 200)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 36, 171, 47); + } else if (isInRange(ticks, 201, 250)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 36, 142, 171); + } else if (isInRange(ticks, 251, 300)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 128, 36, 171); + } + } else { + playFirebendingParticles(loc, particles, Math.random(), Math.random(), Math.random()); + ParticleEffect.SMOKE_NORMAL.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + JCMethods.emitLight(loc); + } + } + } + + private void displayParticle(Location location, int amount, int r, int g, int b) { + ParticleEffect.REDSTONE.display(location, amount, 0, 0, 0, 0.005, new Particle.DustOptions(Color.fromRGB(r, g, b), 1)); + JCMethods.emitLight(location); + } + + private boolean isInRange(int x, int min, int max) { + return min <= x && x <= max; + } + + /** + * Generates an offset location around a given location with variable offset + * amount. + */ + private Location getOffsetLocation(Location loc, double offset) { + return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); + } + + public static void toggleRainbowBreath(Player player, boolean activate) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + + boolean easterEgg = config.getBoolean("Abilities.Fire.FireBreath.RainbowBreath.Enabled"); + String bindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "")); + String unbindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "")); + String deniedMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "")); + + if (easterEgg && (player.hasPermission("bending.ability.FireBreath.RainbowBreath") + || Arrays.asList(CommandListener.DEVELOPERS).contains(player.getUniqueId().toString()))) { + if (activate) { + if (!rainbowPlayer.contains(player.getUniqueId())) { + rainbowPlayer.add(player.getUniqueId()); + if (!bindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + bindMsg); + } + } else { + if (rainbowPlayer.contains(player.getUniqueId())) { + rainbowPlayer.remove(player.getUniqueId()); + if (!unbindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + unbindMsg); + } + } + } else if (!deniedMsg.equals("")) { + player.sendMessage(Element.FIRE.getColor() + deniedMsg); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return player.getLocation(); + } + + @Override + public List getLocations() { + return locations; + } + + @Override + public String getName() { + return "FireBreath"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireBreath.Description"); + } + + public static List getRainbowPlayer() { + return rainbowPlayer; + } + + public static void setRainbowPlayer(List rainbowPlayer) { + FireBreath.rainbowPlayer = rainbowPlayer; + } + + public int getTicks() { + return ticks; + } + + public void setTicks(int ticks) { + this.ticks = ticks; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public int getParticles() { + return particles; + } + + public void setParticles(int particles) { + this.particles = particles; + } + + public double getPlayerDamage() { + return playerDamage; + } + + public void setPlayerDamage(double playerDamage) { + this.playerDamage = playerDamage; + } + + public double getMobDamage() { + return mobDamage; + } + + public void setMobDamage(double mobDamage) { + this.mobDamage = mobDamage; + } + + public int getFireDuration() { + return fireDuration; + } + + public void setFireDuration(int fireDuration) { + this.fireDuration = fireDuration; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public boolean isSpawnFire() { + return spawnFire; + } + + public void setSpawnFire(boolean spawnFire) { + this.spawnFire = spawnFire; + } + + public boolean isMeltEnabled() { + return meltEnabled; + } + + public void setMeltEnabled(boolean meltEnabled) { + this.meltEnabled = meltEnabled; + } + + public int getMeltChance() { + return meltChance; + } + + public void setMeltChance(int meltChance) { + this.meltChance = meltChance; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FireBreath.Enabled"); + } +} diff --git a/src/ability/firebending/FireComet.java b/src/ability/firebending/FireComet.java new file mode 100644 index 0000000..d49f2d4 --- /dev/null +++ b/src/ability/firebending/FireComet.java @@ -0,0 +1,465 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; + +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.BlockState; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Random; + +public class FireComet extends FireAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.CHARGE_DURATION) + private long charge; + private long regen; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.RADIUS) + private double blastRadius; + private boolean cometOnly; + private boolean avatarBypass; + private Location location; + private Location launchLoc; + private Vector vector; + + //Charging Animation + private int angle; + + private boolean fire; + private long time; + private boolean charged; + + private int point; + + private final Random rand = new Random(); + + public FireComet(Player player) { + super(player); + + if (!bPlayer.canBend(this) || hasAbility(player, FireComet.class)) { + return; + } + + setFields(); + + if (!JCMethods.isSozinsComet(player.getWorld())) { + if (GeneralMethods.hasRPG() && getSozinsCometOnly()) { + if (!(bPlayer.isAvatarState() && getAvatarBypassComet())) { + return; + } + } + } + + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + if (JCMethods.isSozinsComet(player.getWorld()) || bPlayer.isAvatarState()) { + cooldown = config.getLong("Abilities.Fire.FireComet.SozinsComet.Cooldown"); + charge = config.getLong("Abilities.Fire.FireComet.SozinsComet.ChargeUp"); + damage = config.getDouble("Abilities.Fire.FireComet.SozinsComet.Damage"); + blastRadius = config.getDouble("Abilities.Fire.FireComet.SozinsComet.BlastRadius"); + } else { + cooldown = config.getLong("Abilities.Fire.FireComet.Cooldown"); + charge = config.getLong("Abilities.Fire.FireComet.ChargeUp"); + damage = config.getDouble("Abilities.Fire.FireComet.Damage"); + blastRadius = config.getDouble("Abilities.Fire.FireComet.BlastRadius"); + } + + regen = config.getLong("Abilities.Fire.FireComet.RegenDelay"); + range = config.getInt("Abilities.Fire.FireComet.Range"); + cometOnly = config.getBoolean("Abilities.Fire.FireComet.SozinsCometOnly"); + avatarBypass = config.getBoolean("Abilities.Fire.FireComet.AvatarStateBypassComet"); + time = System.currentTimeMillis(); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + cooldown *= BlueFireAbility.getCooldownFactor(); + damage *= BlueFireAbility.getDamageFactor(); + range *= BlueFireAbility.getRangeFactor(); + } + + if (isDay(player.getWorld())) { + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + damage = getDayFactor(damage); + range = (int) getDayFactor(range); + } + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (System.currentTimeMillis() > getTime() + getCharge()) { + if (RegionProtection.isRegionProtected(this, player.getLocation())) { + remove(); + return; + } + + if (!charged) { + charged = true; + Objects.requireNonNull(location.getWorld()).playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 2F, 0.8F); + } + + if (!isFired()) { + if (!player.isSneaking()) { + vector = player.getLocation().getDirection(); + + if (location == null) { + location = GeneralMethods.getTargetedLocation(player, 6); + } + + launchLoc = location.clone(); + setFired(true); + } else { + location = GeneralMethods.getTargetedLocation(player, 6); + } + } else { + if (!advance()) { + blast(); + remove(); + return; + } + } + + displayComet(); + } else { + if (!player.isSneaking()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + remove(); + return; + } + + location = GeneralMethods.getTargetedLocation(player, 6); + displayChargingAnim(); + } + } + + public boolean advance() { + location = location.add(vector.multiply(1)); + + playFirebendingSound(location); + + if (location.distance(launchLoc) > range || !isTransparent(location.getBlock())) { + return false; + } + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, 3.0)) { + if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { + return false; + } + } + + return true; + } + + public void blast() { + List blocks = new ArrayList<>(); + + for (Location loc : GeneralMethods.getCircle(location, (int) blastRadius, 0, false, true, 0)) { + if (JCMethods.isUnbreakable(loc.getBlock())) continue; + if (RegionProtection.isRegionProtected(this, loc)) continue; + + blocks.add(loc.getBlock().getState()); + new RegenTempBlock(loc.getBlock(), Material.AIR, Material.AIR.createBlockData(), getRegenDelay(), false); + } + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, blastRadius)) { + if (e instanceof Player && e == player) { + continue; + } + + if (RegionProtection.isRegionProtected(this, e.getLocation())) { + continue; + } + + if (e instanceof LivingEntity) { + DamageHandler.damageEntity(e, getDamage(), this); + } + } + + playFirebendingParticles(location, 20, Math.random(), Math.random(), Math.random()); + ParticleEffect.FIREWORKS_SPARK.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + + JCMethods.emitLight(location); + + location.getWorld().playSound(location, (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, 5F, 1F); + location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 5F, 0.8F); + + int i = 0; + for (BlockState block : blocks) { + double x = rand.nextDouble() / 3; + double z = rand.nextDouble() / 3; + + x = (rand.nextBoolean()) ? -x : x; + z = (rand.nextBoolean()) ? -z : z; + + i++; + + if (i % 2 == 0) { + new TempFallingBlock(block.getLocation(), block.getBlockData(), vector.clone().add(new Vector(x, 0, z)).normalize().multiply(-1), this); + } + } + } + + public void displayChargingAnim() { + this.angle += 10; + + Location location = this.location.clone(); + double angle = (this.angle * Math.PI / 180); + double xRotation = 3.141592653589793D / 3 * 2.1; + Vector v = new Vector(Math.cos(angle + point), Math.sin(angle), 0.0D).multiply(2.2); + Vector v1 = v.clone(); + + rotateAroundAxisX(v, xRotation); + rotateAroundAxisY(v, -((location.getYaw() * Math.PI / 180) - 1.575)); + rotateAroundAxisX(v1, -xRotation); + rotateAroundAxisY(v1, -((location.getYaw() * Math.PI / 180) - 1.575)); + +// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { +// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); +// } else { +// ParticleEffect.FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); +// } + playFirebendingParticles(location.clone().add(v), 1, 0, 0, 0); + playFirebendingParticles(location.clone().add(v1), 1, 0, 0, 0); + ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); + ParticleEffect.SMOKE_LARGE.display(location.clone().add(v1), 1, 0, 0, 0, 0.02); + + JCMethods.emitLight(location.clone().add(v)); + JCMethods.emitLight(location.clone().add(v1)); + + if (this.angle == 360) { + this.angle = 0; + } + + long init = getTime() + getCharge(); + int percentage = (int) (((init - System.currentTimeMillis()) * 100) / getCharge()); + double size = (1 - (percentage / 100.0F)) * 1.5; + + for (int i = 0; i < 360; i += 45) { + for (Location l : JCMethods.getVerticalCirclePoints(location.clone().subtract(0, size, 0), 45, size, i)) { +// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { +// ParticleEffect.SOUL_FIRE_FLAME.display(l, 1, 0, 0, 0, 0.02); +// } else { +// ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.02); +// } + playFirebendingParticles(l, 1, 0, 0, 0); + JCMethods.emitLight(l); + } + } + + if (size == 1.5) { + ParticleEffect.EXPLOSION_LARGE.display(this.location, 3, Math.random(), Math.random(), Math.random(), 0.03); + } + } + + public void displayComet() { + for (int angle = 0; angle < 360; angle += 45) { + for (Location l : JCMethods.getVerticalCirclePoints(location.clone().subtract(0, 1.5, 0), 45, 1.5, angle)) { +// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { +// ParticleEffect.SOUL_FIRE_FLAME.display(l, 1, 0, 0, 0, 0.05); +// } else { +// ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.05); +// } + playFirebendingParticles(l, 1, 0, 0, 0); + JCMethods.emitLight(l); + } + } + + point++; + + Location location = this.location.clone(); + for (int i = -180; i < 180; i += 45) { + double angle = (i * Math.PI / 180); + double xRotation = 3.141592653589793D / 3 * 2.1; + Vector v = new Vector(Math.cos(angle + point), Math.sin(angle + point), 0.0D).multiply(2.2); + Vector v1 = v.clone(); + + rotateAroundAxisX(v, xRotation); + rotateAroundAxisY(v, -((location.getYaw() * Math.PI / 180) - 1.575)); + rotateAroundAxisX(v1, -xRotation); + rotateAroundAxisY(v1, -((location.getYaw() * Math.PI / 180) - 1.575)); + +// if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { +// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.SOUL_FIRE_FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); +// } else { +// ParticleEffect.FLAME.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); +// ParticleEffect.FLAME.display(location.clone().add(v1), 1, 0, 0, 0, 0.01); +// } + playFirebendingParticles(location.clone().add(v), 1, 0, 0, 0); + playFirebendingParticles(location.clone().add(v1), 1, 0, 0, 0); + ParticleEffect.SMOKE_LARGE.display(location.clone().add(v), 1, 0, 0, 0, 0.02); + ParticleEffect.SMOKE_LARGE.display(location.clone().add(v1), 1, 0, 0, 0, 0.02); + + JCMethods.emitLight(location.clone().add(v)); + JCMethods.emitLight(location.clone().add(v1)); + } + + if (point == 360) { + point = 0; + } + } + + private void rotateAroundAxisX(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double y = v.getY() * cos - v.getZ() * sin; + double z = v.getY() * sin + v.getZ() * cos; + + v.setY(y).setZ(z); + } + + private void rotateAroundAxisY(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double x = v.getX() * cos + v.getZ() * sin; + double z = v.getX() * -sin + v.getZ() * cos; + + v.setX(x).setZ(z); + } + + @Override + public void remove() { + if (player != null && player.isOnline() && isFired()) { + bPlayer.addCooldown(this); + } + + super.remove(); + } + + public double getDamage() { + return damage; + } + + public int getRange() { + return range; + } + + public void setFired(boolean fire) { + this.fire = fire; + } + + public boolean isFired() { + return fire; + } + + public long getCharge() { + return charge; + } + + public long getTime() { + return time; + } + + public boolean getSozinsCometOnly() { + return cometOnly; + } + + public boolean getAvatarBypassComet() { + return avatarBypass; + } + + public long getRegenDelay() { + return regen; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "FireComet"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireComet.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FireComet.Enabled"); + } +} diff --git a/src/ability/firebending/FirePunch.java b/src/ability/firebending/FirePunch.java new file mode 100644 index 0000000..8dfc35c --- /dev/null +++ b/src/ability/firebending/FirePunch.java @@ -0,0 +1,180 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.inventory.MainHand; + +public class FirePunch extends FireAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.FIRE_TICK) + private int fireTicks; + + private Boolean flameInMainHand = null; + + private Location location; + + public FirePunch(Player player) { + super(player); + + if (!bPlayer.canBend(this) || hasAbility(player, this.getClass())) + return; + + setFields(); + + start(); + } + + private void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(player); + + cooldown = config.getLong("Abilities.Fire.FirePunch.Cooldown"); + damage = config.getDouble("Abilities.Fire.FirePunch.Damage"); + fireTicks = config.getInt("Abilities.Fire.FirePunch.FireTicks"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(Element.BLUE_FIRE)) { + cooldown *= BlueFireAbility.getCooldownFactor(); + damage *= BlueFireAbility.getDamageFactor(); + } + + if (isDay(player.getWorld())) { + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + damage = getDayFactor(damage); + } + } + + @Override + public void progress() { + if (!player.isOnline() || player.isDead() || !bPlayer.canBend(this)) { + remove(); + return; + } + + Location hand = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); + + playFirebendingParticles(hand, 3, 0, 0, 0); + ParticleEffect.SMOKE_NORMAL.display(hand, 1); + JCMethods.emitLight(hand); + } + + public static void swapHands(Player player) { + FirePunch fp = getAbility(player, FirePunch.class); + if (fp == null) + return; + if (fp.flameInMainHand == null) + fp.flameInMainHand = true; + else fp.flameInMainHand = !fp.flameInMainHand; + } + + public Location getRightHandPos() { + return (player.getMainHand() == MainHand.RIGHT == ((flameInMainHand == null) || flameInMainHand) ? + GeneralMethods.getRightSide(player.getLocation(), .55) : + GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); + } + + public void punch(LivingEntity target) { + remove(); + DamageHandler.damageEntity(target, damage, this); + FireTick.set(target, fireTicks / 50); + if (cooldown > fireTicks) { + new FireDamageTimer(target, player, this); + } + bPlayer.addCooldown(this); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "FirePunch"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FirePunch.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getFireTicks() { + return fireTicks; + } + + public void setFireTicks(int fireTicks) { + this.fireTicks = fireTicks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FirePunch.Enabled"); + } +} diff --git a/src/ability/firebending/FireShots.java b/src/ability/firebending/FireShots.java new file mode 100644 index 0000000..a03efeb --- /dev/null +++ b/src/ability/firebending/FireShots.java @@ -0,0 +1,416 @@ +package com.jedk1.jedcore.ability.firebending; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.AirShieldReflector; +import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.airbending.AirShield; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.Ability; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.inventory.MainHand; +import org.bukkit.util.Vector; + +public class FireShots extends FireAbility implements AddonAbility { + + private final List shots = new ArrayList<>(); + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("MaxShots") + private int startAmount; + @Attribute(Attribute.FIRE_TICK) + private int fireticks; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute("CollisionRadius") + private double collisionRadius; + private Boolean flameInMainHand = null; + + public int amount; + + public FireShots(Player player){ + super(player); + + if (!bPlayer.canBend(this) || hasAbility(player, FireShots.class)) { + return; + } + + if (!player.hasGravity()) + player.setGravity(true); + + setFields(); + + amount = startAmount; + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.FireShots.Cooldown"); + startAmount = config.getInt("Abilities.Fire.FireShots.FireBalls"); + fireticks = config.getInt("Abilities.Fire.FireShots.FireDuration"); + range = config.getInt("Abilities.Fire.FireShots.Range"); + damage = config.getDouble("Abilities.Fire.FireShots.Damage"); + collisionRadius = config.getDouble("Abilities.Fire.FireShots.CollisionRadius"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + cooldown *= BlueFireAbility.getCooldownFactor(); + range *= BlueFireAbility.getRangeFactor(); + damage *= BlueFireAbility.getDamageFactor(); + } + + if (isDay(player.getWorld())) { + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + range = (int) getDayFactor(range); + damage = getDayFactor(damage); + } + } + + public class FireShot { + + private final Ability ability; + private final Player player; + private Location location; + private final int range; + private final int fireTicks; + private double distanceTravelled; + private final double damage; + private Vector direction = null; + + public FireShot(Ability ability, Player player, Location location, int range, int fireTicks, double damage) { + this.ability = ability; + this.player = player; + this.location = location; + this.range = range; + this.fireTicks = fireTicks; + this.damage = damage; + } + + public boolean progress() { + if (player.isDead() || !player.isOnline()) { + return false; + } + if (distanceTravelled >= range) { + return false; + } + for (int i = 0; i < 2; i++) { + distanceTravelled ++; + if (distanceTravelled >= range) + return false; + + Vector dir = direction; + if (dir == null) { + dir = this.player.getLocation().getDirection().clone(); + } + + location = location.add(dir); + + if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())){ + return false; + } + + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + ParticleEffect.SOUL_FIRE_FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); + } else { + ParticleEffect.FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); + } + ParticleEffect.SMOKE_NORMAL.display(location, 2, 0.0, 0.0, 0.0, 0.01); + + JCMethods.emitLight(location); + + Sphere collider = new Sphere(location.toVector(), collisionRadius); + + boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { + DamageHandler.damageEntity(entity, damage, ability); + FireTick.set(entity, Math.round(fireTicks / 50F)); + new FireDamageTimer(entity, player, FireShots.this); + return true; + }); + + if (hit) { + return false; + } + } + return true; + } + + public Ability getAbility() { + return ability; + } + + public Player getPlayer() { + return player; + } + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getRange() { + return range; + } + + public int getFireTicks() { + return fireTicks; + } + + public double getDistanceTravelled() { + return distanceTravelled; + } + + public void setDistanceTravelled(double distanceTravelled) { + this.distanceTravelled = distanceTravelled; + } + + public double getDamage() { + return damage; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreCooldowns(this)) { + amount = 0; + if (!bPlayer.isOnCooldown(this)) { + bPlayer.addCooldown(this); + } + } + + shots.removeIf(shot -> !shot.progress()); + + if (amount <= 0 && shots.isEmpty()) { + remove(); + return; + } + + if (amount > 0) { + displayFireBalls(); + } + } + + public static void fireShot(Player player) { + FireShots fs = getAbility(player, FireShots.class); + if (fs != null) { + fs.fireShot(); + } + } + + public static void swapHands(Player player) { + FireShots fs = getAbility(player, FireShots.class); + if (fs == null) + return; + if (fs.flameInMainHand == null) + fs.flameInMainHand = true; + else fs.flameInMainHand = !fs.flameInMainHand; + } + + public void fireShot() { + if (amount >= 1) { + if (--amount <= 0) { + bPlayer.addCooldown(this); + } + shots.add(new FireShot(this, player, getRightHandPos(), range, fireticks, damage)); + } + } + + public Location getRightHandPos() { + return (player.getMainHand()==MainHand.RIGHT == ((flameInMainHand == null) || flameInMainHand) ? + GeneralMethods.getRightSide(player.getLocation(), .55) : + GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); + } + + private void displayFireBalls() { + playFirebendingParticles(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0); + ParticleEffect.SMOKE_NORMAL.display(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0, 0.01); + JCMethods.emitLight(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld())); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + List list = shots.stream().map(shot -> shot.location).collect(Collectors.toList()); + list.add(getRightHandPos()); + return list; + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); + + collidedShot.ifPresent(shots::remove); + } else { + CoreAbility second = collision.getAbilitySecond(); + if (second instanceof AirShield) { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + boolean reflect = config.getBoolean("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); + + if (reflect) { + Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); + + if (collidedShot.isPresent()) { + FireShot fireShot = collidedShot.get(); + AirShield shield = (AirShield) second; + + fireShot.direction = player.getLocation().getDirection().clone(); + AirShieldReflector.reflect(shield, fireShot.location, fireShot.direction); + } + } + } + } + } + + @Override + public String getName() { + return "FireShots"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireShots.Description"); + } + + public List getShots() { + return shots; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public int getStartAmount() { + return startAmount; + } + + public void setStartAmount(int startAmount) { + this.startAmount = startAmount; + } + + public int getFireticks() { + return fireticks; + } + + public void setFireticks(int fireticks) { + this.fireticks = fireticks; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + @Override + public double getCollisionRadius() { + return collisionRadius; + } + + public void setCollisionRadius(double collisionRadius) { + this.collisionRadius = collisionRadius; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FireShots.Enabled"); + } +} diff --git a/src/ability/firebending/FireSki.java b/src/ability/firebending/FireSki.java new file mode 100644 index 0000000..0b5648d --- /dev/null +++ b/src/ability/firebending/FireSki.java @@ -0,0 +1,333 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.ParticleEffect; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class FireSki extends FireAbility implements AddonAbility { + + private Location location; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.SPEED) + private double speed; + private boolean ignite; + @Attribute(Attribute.FIRE_TICK) + private int fireTicks; + private double requiredHeight; + + public FireSki(Player player) { + super(player); + if (!isEnabled()) { + return; + } + + if (hasAbility(player, FireSki.class)) { + FireSki fs = getAbility(player, FireSki.class); + fs.remove(); + return; + } + + if (!bPlayer.canBend(getAbility("FireJet"))) { + return; + } + + setFields(); + + if (CollisionDetector.isOnGround(player) || CollisionDetector.distanceAboveGround(player) < requiredHeight) { + return; + } + + this.flightHandler.createInstance(player, this.getName()); + + location = player.getLocation(); + player.setAllowFlight(true); + player.setFlying(true); + + bPlayer.addCooldown(getAbility("FireJet"), getCooldown()); + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.FireSki.Cooldown"); + duration = config.getLong("Abilities.Fire.FireSki.Duration"); + speed = config.getDouble("Abilities.Fire.FireSki.Speed"); + ignite = config.getBoolean("Abilities.Fire.FireSki.IgniteEntities"); + fireTicks = config.getInt("Abilities.Fire.FireSki.FireTicks"); + requiredHeight = config.getDouble("Abilities.Fire.FireSki.RequiredHeight"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + cooldown *= BlueFireAbility.getCooldownFactor(); + } + + if (isDay(player.getWorld())) { + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + } + } + + private void allowFlight() { + player.setAllowFlight(true); + player.setFlying(true); + } + + private void removeFlight() { + player.setAllowFlight(false); + player.setFlying(false); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(getAbility("FireJet"))) { + remove(); + return; + } + if (!collision()) { + movePlayer(); + if (System.currentTimeMillis() > getStartTime() + duration || isWater(player.getLocation().getBlock())) { + remove(); + } + } else { + remove(); + } + } + + private void movePlayer() { + location = player.getEyeLocation(); + location.setPitch(0); + Vector dV = location.getDirection().normalize(); + Vector travel; + + if (getPlayerDistance() > 1.8) { + removeFlight(); + travel = new Vector(dV.getX() * speed, -0.09, dV.getZ() * speed); + } else if (getPlayerDistance() < 1.7) { + allowFlight(); + travel = new Vector(dV.getX() * speed, 0.2, dV.getZ() * speed); + } else { + travel = new Vector(dV.getX() * speed, 0, dV.getZ() * speed); + } + + playFirebendingSound(player.getLocation()); + createBeam(); + + if (ignite) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(player.getLocation().clone().add(0, -1, 0), 2.0)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + FireTick.set(entity, this.fireTicks); + } + } + } + + GeneralMethods.setVelocity(this, player, travel); + player.setFallDistance(0); + } + + private double getPlayerDistance() { + Location l = player.getLocation().clone(); + while (l.getBlockY() > l.getWorld().getMinHeight() && !GeneralMethods.isSolid(l.getBlock())) { + l.add(0, -0.1, 0); + } + return player.getLocation().getY() - l.getY(); + } + + private void createBeam() { + Location right = player.getEyeLocation().add(getRightHeadDirection(player).multiply(1.75)); + right.setPitch(-15); + Location right1 = right.subtract(right.getDirection().multiply(4)).add(0, -1.5, 0); + + Location left = player.getEyeLocation().add(getLeftHeadDirection(player).multiply(1.75)); + left.setPitch(-15); + Location left1 = left.subtract(left.getDirection().multiply(4)).add(0, -1.5, 0); + + double size = 0; + + for (Location l : JCMethods.getLinePoints(player.getEyeLocation().add(0, -0.5, 0).add(getRightHeadDirection(player).multiply(0.2)), right1, 6)) { + size += 0.05; + playFirebendingParticles(l, 4, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01)); + ParticleEffect.SMOKE_NORMAL.display(l, 1, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01), 0.08); + JCMethods.emitLight(l); + } + + size = 0; + for (Location l : JCMethods.getLinePoints(player.getEyeLocation().add(0, -0.5, 0).add(getLeftHeadDirection(player).multiply(0.2)), left1, 6)) { + size += 0.05; + playFirebendingParticles(l, 4, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01)); + ParticleEffect.SMOKE_NORMAL.display(l, 1, (Math.random() * size + 0.01), (Math.random() * size + 0.01), (Math.random() * size + 0.01), 0.08); + JCMethods.emitLight(l); + } + } + + public Vector getRightHeadDirection(Player player) { + Vector direction = player.getLocation().getDirection().normalize(); + return new Vector(-direction.getZ(), 0.0, direction.getX()).normalize(); + } + + public Vector getLeftHeadDirection(Player player) { + Vector direction = player.getLocation().getDirection().normalize(); + return new Vector(direction.getZ(), 0.0, -direction.getX()).normalize(); + } + + private boolean collision() { + Location l = player.getEyeLocation(); + l.setPitch(0); + Vector dV = l.getDirection().normalize(); + l.add(new Vector(dV.getX() * 0.8, 0, dV.getZ() * 0.8)); + + if (l.getBlock().getType().isSolid()) { + return true; + } + if (l.clone().add(0, -1, 0).getBlock().getType().isSolid()) { + return true; + } + return l.clone().add(0, -2, 0).getBlock().getType().isSolid(); + } + + @Override + public void remove() { + removeFlight(); + + this.flightHandler.removeInstance(player, this.getName()); + + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "FireSki"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public void setLocation(Location location) { + this.location = location; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public boolean isIgnite() { + return ignite; + } + + public void setIgnite(boolean ignite) { + this.ignite = ignite; + } + + public int getFireTicks() { + return fireTicks; + } + + public void setFireTicks(int fireTicks) { + this.fireTicks = fireTicks; + } + + public double getRequiredHeight() { + return requiredHeight; + } + + public void setRequiredHeight(double requiredHeight) { + this.requiredHeight = requiredHeight; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FireSki.Enabled"); + } + + public static boolean isPunchActivated(World world) { + ConfigurationSection config = JedCoreConfig.getConfig(world); + return config.getBoolean("Abilities.Fire.FireSki.PunchActivated"); + } +} diff --git a/src/ability/firebending/LightningBurst.java b/src/ability/firebending/LightningBurst.java new file mode 100644 index 0000000..2227761 --- /dev/null +++ b/src/ability/firebending/LightningBurst.java @@ -0,0 +1,370 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.LightningAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; + +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; + +public class LightningBurst extends LightningAbility implements AddonAbility { + + private static final ConcurrentHashMap BOLTS = new ConcurrentHashMap<>(); + + Random rand = new Random(); + @Attribute(Attribute.COOLDOWN) + private long cooldown, avatarCooldown; + @Attribute(Attribute.CHARGE_DURATION) + private long chargeUp, avatarChargeup; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.RADIUS) + private double radius; + + private boolean charged; + private static int ID = Integer.MIN_VALUE; + + private float soundVolume; + private int soundInterval; + + public LightningBurst(Player player) { + super(player); + if (!bPlayer.canBend(this) || hasAbility(player, LightningBurst.class)) { + return; + } + + setFields(); + if (bPlayer.isAvatarState() || JCMethods.isSozinsComet(player.getWorld())) { + chargeUp = avatarChargeup; + cooldown = avatarCooldown; + } + + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.LightningBurst.Cooldown"); + chargeUp = config.getLong("Abilities.Fire.LightningBurst.ChargeUp"); + avatarCooldown = config.getLong("Abilities.Fire.LightningBurst.AvatarCooldown"); + avatarChargeup = config.getLong("Abilities.Fire.LightningBurst.AvatarChargeUp"); + damage = config.getDouble("Abilities.Fire.LightningBurst.Damage"); + radius = config.getDouble("Abilities.Fire.LightningBurst.Radius"); + + soundVolume = (float) config.getDouble("Abilities.Fire.LightningBurst.Sound.Volume"); + soundInterval = config.getInt("Abilities.Fire.LightningBurst.Sound.Interval"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + if (RegionProtection.isRegionProtected(player, player.getLocation(), this)) { + remove(); + return; + } + if (!player.isSneaking()) { + if (!isCharging()) { + Location fake = player.getLocation().add(0, -2, 0); + fake.setPitch(0); + for (int i = -180; i < 180; i += 55) { + fake.setYaw(i); + for (double j = -180; j <= 180; j += 55) { + Location temp = fake.clone(); + Vector dir = fake.getDirection().clone().multiply(2 * Math.cos(Math.toRadians(j))); + temp.add(dir); + temp.setY(temp.getY() + 2 + (2 * Math.sin(Math.toRadians(j)))); + dir = GeneralMethods.getDirection(player.getLocation().add(0, 0, 0), temp); + spawnBolt(player.getLocation().clone().add(0, 1, 0).setDirection(dir), radius, 1, 20, true); + } + } + bPlayer.addCooldown(this); + } + remove(); + } else if (System.currentTimeMillis() > getStartTime() + chargeUp){ + setCharging(false); + displayCharging(); + } + } + + private void spawnBolt(Location location, double max, double gap, int arc, boolean doDamage) { + int id = ID; + BOLTS.put(id, new Bolt(this, location, id, max, gap, arc, doDamage)); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + } + + private void displayCharging() { + Location fake = player.getLocation().add(0, 0, 0); + fake.setPitch(0); + for (int i = -180; i < 180; i += 55) { + fake.setYaw(i); + for (double j = -180; j <= 180; j += 55) { + if (rand.nextInt(100) == 0) { + Location temp = fake.clone(); + Vector dir = fake.getDirection().clone().multiply(1.2 * Math.cos(Math.toRadians(j))); + temp.add(dir); + temp.setY(temp.getY() + 1.2 + (1.2 * Math.sin(Math.toRadians(j)))); + dir = GeneralMethods.getDirection(temp, player.getLocation().add(0, 1, 0)); + spawnBolt(temp.setDirection(dir), 1, 0.2, 20, false); + } + } + } + } + + public static void progressAll() { + BOLTS.values().forEach(Bolt::progress); + } + + public boolean isCharging() { + return !charged; + } + + public void setCharging(boolean charging) { + this.charged = !charging; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "LightningBurst"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.LightningBurst.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getAvatarCooldown() { + return avatarCooldown; + } + + public void setAvatarCooldown(long avatarCooldown) { + this.avatarCooldown = avatarCooldown; + } + + public long getChargeUp() { + return chargeUp; + } + + public void setChargeUp(long chargeUp) { + this.chargeUp = chargeUp; + } + + public long getAvatarChargeup() { + return avatarChargeup; + } + + public void setAvatarChargeup(long avatarChargeup) { + this.avatarChargeup = avatarChargeup; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + public boolean isCharged() { + return charged; + } + + public void setCharged(boolean charged) { + this.charged = charged; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.LightningBurst.Enabled"); + } + + public class Bolt { + + private final LightningBurst ability; + private Location location; + private final float initYaw; + private final float initPitch; + private double step; + private final double max; + private final double gap; + private final int id; + private final int arc; + private final boolean doDamage; + + public Bolt(LightningBurst ability, Location location, int id, double max, double gap, int arc, boolean doDamage) { + this.ability = ability; + this.location = location; + this.id = id; + this.max = max; + this.arc = arc; + this.gap = gap; + this.doDamage = doDamage; + initYaw = location.getYaw(); + initPitch = location.getPitch(); + } + + private void progress() { + if (this.step >= max) { + BOLTS.remove(id); + return; + } + if (RegionProtection.isRegionProtected(player, location, LightningBurst.this) || !isTransparent(location.getBlock())) { + BOLTS.remove(id); + return; + } + double step = 0.2; + for (double i = 0; i < gap; i+= step) { + this.step += step; + location = location.add(location.getDirection().clone().multiply(step)); + + playLightningbendingParticle(location, 0f, 0f, 0f); + JCMethods.emitLight(location); + } + switch (rand.nextInt(3)) { + case 0: + location.setYaw(initYaw - arc); + break; + case 1: + location.setYaw(initYaw + arc); + break; + default: + location.setYaw(initYaw); + break; + } + switch (rand.nextInt(3)) { + case 0: + location.setPitch(initPitch - arc); + break; + case 1: + location.setPitch(initPitch + arc); + break; + default: + location.setPitch(initPitch); + break; + } + + if (rand.nextInt(soundInterval) == 0) { + location.getWorld().playSound(location, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); + } + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && doDamage) { + DamageHandler.damageEntity(entity, damage, ability); + } + } + } + + public LightningBurst getAbility() { + return ability; + } + + public Location getLocation() { + return location; + } + + public float getInitYaw() { + return initYaw; + } + + public float getInitPitch() { + return initPitch; + } + + public double getStep() { + return step; + } + + public double getMax() { + return max; + } + + public double getGap() { + return gap; + } + + public int getId() { + return id; + } + + public int getArc() { + return arc; + } + + public boolean isDoDamage() { + return doDamage; + } + } +} \ No newline at end of file diff --git a/src/ability/passive/WallRun.java b/src/ability/passive/WallRun.java new file mode 100644 index 0000000..a60418f --- /dev/null +++ b/src/ability/passive/WallRun.java @@ -0,0 +1,265 @@ +package com.jedk1.jedcore.ability.passive; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.ChiAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.ParticleEffect; + +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.List; + +public class WallRun extends ChiAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + + private boolean enabled; + + private boolean particles; + private boolean air; + private boolean earth; + private boolean water; + private boolean fire; + private boolean chi; + + private List invalid; + + public WallRun(Player player) { + super(player); + + setFields(); + if (!enabled) return; + + if (bPlayer.isOnCooldown("WallRun")) return; + + if (hasAbility(player, WallRun.class)) { + getAbility(player, WallRun.class).remove(); + return; + } + + if (player.getGameMode().equals(GameMode.SPECTATOR)) { + return; + } + + if (isEligible() && !JCMethods.isDisabledWorld(player.getWorld())) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + enabled = config.getBoolean("Abilities.Passives.WallRun.Enabled"); + cooldown = config.getLong("Abilities.Passives.WallRun.Cooldown"); + duration = config.getLong("Abilities.Passives.WallRun.Duration"); + particles = config.getBoolean("Abilities.Passives.WallRun.Particles"); + air = config.getBoolean("Abilities.Passives.WallRun.Air"); + earth = config.getBoolean("Abilities.Passives.WallRun.Earth"); + water = config.getBoolean("Abilities.Passives.WallRun.Water"); + fire = config.getBoolean("Abilities.Passives.WallRun.Fire"); + chi = config.getBoolean("Abilities.Passives.WallRun.Chi"); + invalid = config.getStringList("Abilities.Passives.WallRun.InvalidBlocks"); + } + + private boolean isEligible() { + if (!player.isSprinting()) + return false; + + if (!bPlayer.isToggled()) { + return false; + } + + if (bPlayer.getElements().contains(Element.AIR) && air) { + return true; + } else if (bPlayer.getElements().contains(Element.EARTH) && earth) { + return true; + } else if (bPlayer.getElements().contains(Element.WATER) && water) { + return true; + } else if (bPlayer.getElements().contains(Element.FIRE) && fire) { + return true; + } else return bPlayer.getElements().contains(Element.CHI) && chi; + } + + private boolean isAgainstWall() { + Location location = player.getLocation(); + if (location.getBlock().getRelative(BlockFace.NORTH).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.NORTH).getType().name())) { + return true; + } else if (location.getBlock().getRelative(BlockFace.SOUTH).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.SOUTH).getType().name())) { + return true; + } else if (location.getBlock().getRelative(BlockFace.WEST).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.WEST).getType().name())) { + return true; + } else return location.getBlock().getRelative(BlockFace.EAST).getType().isSolid() && !invalid.contains(location.getBlock().getRelative(BlockFace.EAST).getType().name()); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline() || player.isOnGround()) { + remove(); + return; + } + if (!isAgainstWall()) { + remove(); + return; + } + if (System.currentTimeMillis() > getStartTime() + duration) { + remove(); + return; + } + + if (System.currentTimeMillis() - getStartTime() > 50L) { + bPlayer.addCooldown("WallRun", getCooldown()); + } + + if (particles) { + ParticleEffect.CRIT.display(player.getLocation(), 4, Math.random(), Math.random(), Math.random(), 0); + ParticleEffect.BLOCK_CRACK.display(player.getLocation(), 3, Math.random(), Math.random(), Math.random(), 0.1, Material.STONE.createBlockData()); + AirAbility.playAirbendingParticles(player.getLocation(), 5); + } + + Vector dir = player.getLocation().getDirection(); + dir.multiply(1.15); + GeneralMethods.setVelocity(this, player, dir); + } + + public long getCooldown() { + return cooldown; + } + + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "WallRun"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return "To use WallRun, sprint towards a wall, jump, then rapidly click to activate. You don't have to bind this ability to use it. It is a passive."; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean hasParticles() { + return particles; + } + + public void setHasParticles(boolean particles) { + this.particles = particles; + } + + public boolean allowsAir() { + return air; + } + + public void setAllowsAir(boolean air) { + this.air = air; + } + + public boolean allowsEarth() { + return earth; + } + + public void setAllowsEarth(boolean earth) { + this.earth = earth; + } + + public boolean allowsWater() { + return water; + } + + public void setAllowsWater(boolean water) { + this.water = water; + } + + public boolean allowsFire() { + return fire; + } + + public void setAllowsFire(boolean fire) { + this.fire = fire; + } + + public boolean allowsChi() { + return chi; + } + + public void setAllowsChi(boolean chi) { + this.chi = chi; + } + + public List getInvalid() { + return invalid; + } + + public void setInvalid(List invalid) { + this.invalid = invalid; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Passives.WallRun.Enabled"); + } +} diff --git a/src/ability/waterbending/BloodPuppet.java b/src/ability/waterbending/BloodPuppet.java new file mode 100644 index 0000000..6e3bf14 --- /dev/null +++ b/src/ability/waterbending/BloodPuppet.java @@ -0,0 +1,511 @@ +package com.jedk1.jedcore.ability.waterbending; + +import java.util.*; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.util.Vector; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.BloodAbility; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.util.DamageHandler; + +public class BloodPuppet extends BloodAbility implements AddonAbility { + + private boolean nightOnly; + private boolean fullMoonOnly; + private boolean undeadMobs; + private boolean bloodPuppetThroughBlocks; + private boolean requireBound; + private int distance; + @Attribute(Attribute.DURATION) + private long holdTime; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + private long endTime; + + public LivingEntity puppet; + private long lastDamageTime = 0; + + Random rand = new Random(); + + public BloodPuppet(Player player) { + super(player); + if (!isEligible(player, true)) { + return; + } + + setFields(); + endTime = System.currentTimeMillis() + holdTime; + + if (grab()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + nightOnly = config.getBoolean("Abilities.Water.BloodPuppet.NightOnly"); + fullMoonOnly = config.getBoolean("Abilities.Water.BloodPuppet.FullMoonOnly"); + undeadMobs = config.getBoolean("Abilities.Water.BloodPuppet.UndeadMobs"); + bloodPuppetThroughBlocks = config.getBoolean("Abilities.Water.BloodPuppet.IgnoreWalls"); + requireBound = config.getBoolean("Abilities.Water.BloodPuppet.RequireBound"); + distance = config.getInt("Abilities.Water.BloodPuppet.Distance"); + holdTime = config.getLong("Abilities.Water.BloodPuppet.HoldTime"); + cooldown = config.getLong("Abilities.Water.BloodPuppet.Cooldown"); + } + + public boolean isEligible(Player player, boolean hasAbility) { + if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, BloodPuppet.class))) { + return false; + } + if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { + return false; + } + return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); + } + + private boolean canAttack() { + switch (puppet.getType()) { + case SKELETON: + case SPIDER: + case GIANT: + case ZOMBIE: + case SLIME: + case GHAST: + case PIGLIN: + case ZOMBIFIED_PIGLIN: + case ENDERMAN: + case CAVE_SPIDER: + case SILVERFISH: + case BLAZE: + case MAGMA_CUBE: + case WITCH: + case ENDERMITE: + case DROWNED: + case PLAYER: + return true; + default: + return false; + } + } + + private boolean grab() { + List entities = new ArrayList<>(); + for (int i = 1; i < distance; i++) { + Location location; + if (bloodPuppetThroughBlocks) { + location = player.getTargetBlock(null, i).getLocation(); + } else { + location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); + } + entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); + entities.remove(player); + if (!entities.isEmpty() && !entities.contains(player)) { + break; + } + } + if (entities.isEmpty()) { + return false; + } + Entity e = entities.get(0); + + if (e == null) + return false; + + if (!(e instanceof LivingEntity)) + return false; + + if (!undeadMobs && GeneralMethods.isUndead(e)) + return false; + + if ((e instanceof Player) && !canBeBloodbent((Player) e)) { + return false; + } + if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { + return false; + } + + for (BloodPuppet bb : getAbilities(BloodPuppet.class)) { + if (bb.puppet.getEntityId() == e.getEntityId()) { + return false; + } + } + + puppet = (LivingEntity) e; + DamageHandler.damageEntity(puppet, 0, this); + if (puppet instanceof Creature) + ((Creature) puppet).setTarget(null); + + if (e instanceof Player && BendingPlayer.getBendingPlayer((Player) e) != null) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer((Player) e); + bPlayer.blockChi(); + } + + return true; + } + + private boolean canBeBloodbent(Player player) { + if (Commands.invincible.contains(player.getName())) { + return false; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (requireBound) { + if (bPlayer.getAbilities().containsValue("Bloodbending")) { + return false; + } + return !bPlayer.getAbilities().containsValue("BloodPuppet"); + } else { + if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { + return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); + } + } + return true; + } + + public static void attack(Player player) { + if (hasAbility(player, BloodPuppet.class)) { + getAbility(player, BloodPuppet.class).attack(); + } + } + + private void attack() { + if (!canAttack()) + return; + + long damageCd = 0; + if (System.currentTimeMillis() > lastDamageTime + damageCd) { + lastDamageTime = System.currentTimeMillis(); + + if (puppet instanceof Skeleton) { + Skeleton skelly = (Skeleton) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(skelly.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); + Arrow a = puppet.getWorld().spawnArrow(loc, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()), 0.6f, 12); + a.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else if (puppet instanceof Creeper) { + Creeper creep = (Creeper) puppet; + creep.setPowered(true); + } + + else if (puppet instanceof Ghast) { + Ghast gaga = (Ghast) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(gaga.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); + Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); + fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.25)); + fb.setIsIncendiary(true); + fb.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else if (puppet instanceof Blaze) { + Blaze balawalaze = (Blaze) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(balawalaze.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); + Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); + fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.5)); + fb.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else if (puppet instanceof Witch) { + Witch missmagus = (Witch) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(missmagus.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + ThrownPotion tp = missmagus.launchProjectile(ThrownPotion.class, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation())); + ItemStack potionItem = new ItemStack(Material.SPLASH_POTION, 1); + PotionMeta potion = (PotionMeta) potionItem.getItemMeta(); + potion.setBasePotionType(JedCore.plugin.getPotionEffectAdapter().getHarmingPotionType()); + potionItem.setItemMeta(potion); + tp.setItem(potionItem); + tp.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.125)); + tp.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(puppet.getLocation(), 2)) { + if (e.getEntityId() == puppet.getEntityId()) + continue; + + if (e instanceof LivingEntity) { + int damage = 2; + if (puppet instanceof Player) { + Player p = (Player) puppet; + + switch (p.getInventory().getItemInMainHand().getType()) { + case WOODEN_SWORD: + case GOLDEN_SWORD: + damage = 5; + break; + case STONE_SWORD: + damage = 6; + break; + case IRON_SWORD: + damage = 7; + break; + case DIAMOND_SWORD: + damage = 8; + break; + default: + break; + } + } + ((LivingEntity) e).damage(damage, puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + } + } + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + if (!isEligible(player, false)) { + remove(); + return; + } + + if (!player.isSneaking()) { + remove(); + return; + } + + if (System.currentTimeMillis() > endTime) { + remove(); + return; + } + + if ((puppet instanceof Player && !((Player) puppet).isOnline()) || puppet.isDead()) { + remove(); + return; + } + + Location newLocation = puppet.getLocation(); + + Location location = GeneralMethods.getTargetedLocation(player, distance + 1); + double distance = location.distance(newLocation); + double dx, dy, dz; + dx = location.getX() - newLocation.getX(); + dy = location.getY() - newLocation.getY(); + dz = location.getZ() - newLocation.getZ(); + Vector vector = new Vector(dx, dy, dz); + if (distance > .5) { + puppet.setVelocity(vector.normalize().multiply(.5)); + } else { + puppet.setVelocity(new Vector(0, 0, 0)); + } + puppet.setFallDistance(0); + if (puppet instanceof Creature) { + ((Creature) puppet).setTarget(null); + } + AirAbility.breakBreathbendingHold(puppet); + } + + @Override + public void remove() { + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + if (puppet instanceof Player && ((Player) puppet).isOnline()) { + BendingPlayer.getBendingPlayer((Player) puppet).unblockChi(); + } + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "BloodPuppet"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.BloodPuppet.Description"); + } + + public boolean isNightOnly() { + return nightOnly; + } + + public void setNightOnly(boolean nightOnly) { + this.nightOnly = nightOnly; + } + + public boolean isFullMoonOnly() { + return fullMoonOnly; + } + + public void setFullMoonOnly(boolean fullMoonOnly) { + this.fullMoonOnly = fullMoonOnly; + } + + public boolean isUndeadMobs() { + return undeadMobs; + } + + public void setUndeadMobs(boolean undeadMobs) { + this.undeadMobs = undeadMobs; + } + + public boolean canBloodPuppetThroughBlocks() { + return bloodPuppetThroughBlocks; + } + + public void setCanBloodPuppetThroughBlocks(boolean bloodPuppetThroughBlocks) { + this.bloodPuppetThroughBlocks = bloodPuppetThroughBlocks; + } + + public boolean requiresBound() { + return requireBound; + } + + public void setRequireBound(boolean requireBound) { + this.requireBound = requireBound; + } + + public int getDistance() { + return distance; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public long getHoldTime() { + return holdTime; + } + + public void setHoldTime(long holdTime) { + this.holdTime = holdTime; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public LivingEntity getPuppet() { + return puppet; + } + + public void setPuppet(LivingEntity puppet) { + this.puppet = puppet; + } + + public long getLastDamageTime() { + return lastDamageTime; + } + + public void setLastDamageTime(long lastDamageTime) { + this.lastDamageTime = lastDamageTime; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.BloodPuppet.Enabled"); + } +} diff --git a/src/ability/waterbending/BloodShot.java b/src/ability/waterbending/BloodShot.java new file mode 100644 index 0000000..ea1ef6a --- /dev/null +++ b/src/ability/waterbending/BloodShot.java @@ -0,0 +1,131 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BloodAbility; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.*; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; +import org.bukkit.Particle.DustTransition; + +import java.util.List; + +import static java.lang.Thread.sleep; + +public class BloodShot extends BloodAbility implements AddonAbility { + + private static final String path = "ExtraAbilities.Hihelloy.BloodShot."; + + private long cooldown; + private double damage; + private int range; + private double hitRadius; + private double selfDamage; + private double speed; + + private Location origin; + private Vector direction; + + public BloodShot(Player player) { + super(player); + + if (!bPlayer.canBend(this) || bPlayer.isOnCooldown(this)) return; + + setFieldsFromConfig(); + DamageHandler.damageEntity(player, selfDamage, this); + this.origin = player.getEyeLocation().clone(); + this.direction = origin.getDirection().normalize(); + + bPlayer.addCooldown(this); + start(); + + launchWave(); + } + + private void setFieldsFromConfig() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + cooldown = config.getLong(path + "Cooldown"); + damage = config.getDouble(path + "Damage"); + range = config.getInt(path + "Range"); + hitRadius = config.getDouble(path + "Hitradius"); + selfDamage = config.getDouble(path + "SelfDamage"); + speed = config.getDouble(path + "Speed"); + } + + public void launchWave() { + // Schedule task using Folia-safe method + Bukkit.getGlobalRegionScheduler().run(JedCore.plugin, scheduledTask -> { + Location current = origin.clone(); + DustTransition dust = new DustTransition(Color.RED, Color.RED, 1.2F); + + for (int i = 0; i < range; i++) { + current.add(direction.clone().multiply(speed)); + + // Check if ability is still active + if (!this.bPlayer.canBend(this) || !player.isOnline() || player.isDead()) { + remove(); + return; + } + + Location particleLoc = current.clone(); + + // Execute particle and hit detection on main thread + Bukkit.getScheduler().runTask(JedCore.plugin, () -> { + World world = particleLoc.getWorld(); + if (world == null) return; + + world.spawnParticle(Particle.DUST_COLOR_TRANSITION, particleLoc, 10, 0.2, 0.2, 0.2, 0, dust); + world.playSound(particleLoc, Sound.ENTITY_PLAYER_ATTACK_STRONG, 1.0f, 2f); + + List entities = GeneralMethods.getEntitiesAroundPoint(particleLoc, hitRadius); + for (Entity entity : entities) { + if (entity instanceof LivingEntity && !entity.equals(player)) { + DamageHandler.damageEntity(entity, damage, this); + entity.setFireTicks(0); + remove(); + } + } + }); + + // Delay between iterations (speed can be adjusted here) + try { + sleep(10); // ~1 tick + } catch (InterruptedException ignored) {} + } + + // Clean up after loop ends + Bukkit.getScheduler().runTask(JedCore.plugin, this::remove); + }); + } + + // Required AddonAbility metadata + @Override public String getName() { return "BloodShot"; } + @Override public String getInstructions() { return "Left-click to fire a blood energy wave."; } + @Override public String getDescription() { + return "An ability that fires a wave of blood energy to damage opponents, but hurts you as well."; + } + @Override public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean(path + "Enabled"); + } + @Override public long getCooldown() { return cooldown; } + @Override public boolean isSneakAbility() { return false; } + @Override public boolean isHarmlessAbility() { return false; } + @Override public void progress() {} // Not used in instant abilities + @Override public void load() {} + @Override public void stop() {} + @Override public String getAuthor() { return "Hihelloy"; } + @Override public String getVersion() { return "1.0"; } + @Override public Location getLocation() { return origin; } + + @Override + public void remove() { + super.remove(); + } +} diff --git a/src/ability/waterbending/Bloodbending.java b/src/ability/waterbending/Bloodbending.java new file mode 100644 index 0000000..5c2e122 --- /dev/null +++ b/src/ability/waterbending/Bloodbending.java @@ -0,0 +1,377 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.ThrownEntityTracker; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.BloodAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; + +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Bloodbending extends BloodAbility implements AddonAbility { + + private boolean nightOnly; + private boolean fullMoonOnly; + private boolean undeadMobs; + private boolean bloodbendingThroughBlocks; + private boolean requireBound; + private int distance; + @Attribute(Attribute.DURATION) + private long holdTime; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + private long time; + public LivingEntity victim; + private BendingPlayer victimBPlayer; + private boolean grabbed; + + public Bloodbending(Player player) { + super(player); + if (this.player == null || !isEligible(player, true)) { + return; + } + setFields(); + time = System.currentTimeMillis() + holdTime; + if (grab()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + nightOnly = config.getBoolean("Abilities.Water.Bloodbending.NightOnly"); + fullMoonOnly = config.getBoolean("Abilities.Water.Bloodbending.FullMoonOnly"); + undeadMobs = config.getBoolean("Abilities.Water.Bloodbending.UndeadMobs"); + bloodbendingThroughBlocks = config.getBoolean("Abilities.Water.Bloodbending.IgnoreWalls"); + requireBound = config.getBoolean("Abilities.Water.Bloodbending.RequireBound"); + distance = config.getInt("Abilities.Water.Bloodbending.Distance"); + holdTime = config.getLong("Abilities.Water.Bloodbending.HoldTime"); + cooldown = config.getLong("Abilities.Water.Bloodbending.Cooldown"); + } + + public boolean isEligible(Player player, boolean hasAbility) { + if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, Bloodbending.class))) { + return false; + } + if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { + return false; + } + return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); + } + + public static void launch(Player player) { + if (hasAbility(player, Bloodbending.class)) { + getAbility(player, Bloodbending.class).launch(); + } + } + + private void launch() { + if (Arrays.asList(ElementalAbility.getTransparentMaterials()).contains(player.getEyeLocation().getBlock().getType())) { + Vector direction = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, 20, ElementalAbility.getTransparentMaterials())).normalize().multiply(3); + if (!victim.isDead()) { + victim.setVelocity(direction); + + new HorizontalVelocityTracker(victim, player, 200L, this); + new ThrownEntityTracker(this, victim, player, 200L); + } + remove(); + } + } + + private boolean grab() { + List entities = new ArrayList<>(); + for (int i = 1; i < distance; i++) { + Location location; + if (bloodbendingThroughBlocks) { + location = player.getTargetBlock(null, i).getLocation(); + } else { + location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); + } + entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); + entities.remove(player); + + if (!entities.isEmpty() && !entities.contains(player)) { + break; + } + } + if (entities.isEmpty()) { + return false; + } + Entity e = entities.get(0); + if (e == null) { + return false; + } + if (!(e instanceof LivingEntity)) { + return false; + } + if (e instanceof ArmorStand) { + return false; + } + if (!undeadMobs && GeneralMethods.isUndead(e)) { + return false; + } + if ((e instanceof Player) && !canBeBloodbent((Player) e)) { + return false; + } + if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { + return false; + } + for (Bloodbending bb : getAbilities(Bloodbending.class)) { + if (bb.victim.getEntityId() == e.getEntityId()) { + return false; + } + } + + victim = (LivingEntity) e; + DamageHandler.damageEntity(victim, 0, this); + HorizontalVelocityTracker.remove(victim); + if (victim instanceof Creature) { + ((Creature) victim).setTarget(null); + } + if ((e instanceof Player) && BendingPlayer.getBendingPlayer((Player) e) != null) { + victimBPlayer = BendingPlayer.getBendingPlayer((Player) e); + } + return true; + } + + private boolean canBeBloodbent(Player player) { + if (Commands.invincible.contains(player.getName())) { + return false; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (requireBound) { + if (bPlayer.getAbilities().containsValue("Bloodbending")) { + return false; + } + return !bPlayer.getAbilities().containsValue("BloodPuppet"); + } else { + if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { + return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); + } + } + return true; + } + + @Override + public void progress() { + if (!isEligible(player, false)) { + remove(); + return; + } + if (!grabbed) { + if (victim instanceof Player && victimBPlayer != null) { + victimBPlayer.blockChi(); + grabbed = true; + } + } + + if (!player.isSneaking()) { + remove(); + return; + } + if (!player.isOnline() || player.isDead()) { + remove(); + return; + } + if (System.currentTimeMillis() > time) { + remove(); + return; + } + if (victim.isDead()) { + remove(); + return; + } + if ((victim instanceof Player) && !((Player) victim).isOnline()) { + remove(); + return; + } + Location oldLocation = victim.getLocation(); + Location loc = GeneralMethods.getTargetedLocation(player, (int) player.getLocation().distance(oldLocation)); + double distance = loc.distance(oldLocation); + Vector v = GeneralMethods.getDirection(oldLocation, GeneralMethods.getTargetedLocation(player, 10)); + if (distance > 1.2D) { + victim.setVelocity(v.normalize().multiply(0.8D)); + } else { + victim.setVelocity(new Vector(0, 0, 0)); + } + victim.setFallDistance(0.0F); + if (victim instanceof Creature) { + ((Creature) victim).setTarget(null); + } + AirAbility.breakBreathbendingHold(victim); + } + + @Override + public void remove() { + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + if (victim instanceof Player && victimBPlayer != null) { + victimBPlayer.unblockChi(); + } + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "Bloodbending"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.Bloodbending.Description"); + } + + public boolean isNightOnly() { + return nightOnly; + } + + public void setNightOnly(boolean nightOnly) { + this.nightOnly = nightOnly; + } + + public boolean isFullMoonOnly() { + return fullMoonOnly; + } + + public void setFullMoonOnly(boolean fullMoonOnly) { + this.fullMoonOnly = fullMoonOnly; + } + + public boolean isUndeadMobs() { + return undeadMobs; + } + + public void setUndeadMobs(boolean undeadMobs) { + this.undeadMobs = undeadMobs; + } + + public boolean isBloodbendingThroughBlocks() { + return bloodbendingThroughBlocks; + } + + public void setBloodbendingThroughBlocks(boolean bloodbendingThroughBlocks) { + this.bloodbendingThroughBlocks = bloodbendingThroughBlocks; + } + + public boolean isRequireBound() { + return requireBound; + } + + public void setRequireBound(boolean requireBound) { + this.requireBound = requireBound; + } + + public int getDistance() { + return distance; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public long getHoldTime() { + return holdTime; + } + + public void setHoldTime(long holdTime) { + this.holdTime = holdTime; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public LivingEntity getVictim() { + return victim; + } + + public void setVictim(LivingEntity victim) { + this.victim = victim; + } + + public BendingPlayer getVictimBPlayer() { + return victimBPlayer; + } + + public void setVictimBPlayer(BendingPlayer victimBPlayer) { + this.victimBPlayer = victimBPlayer; + } + + public boolean isGrabbed() { + return grabbed; + } + + public void setGrabbed(boolean grabbed) { + this.grabbed = grabbed; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.Bloodbending.Enabled"); + } +} diff --git a/src/ability/waterbending/Drain.java b/src/ability/waterbending/Drain.java new file mode 100644 index 0000000..ea33485 --- /dev/null +++ b/src/ability/waterbending/Drain.java @@ -0,0 +1,605 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.util.WaterReturn; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.block.data.Waterlogged; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; + +public class Drain extends WaterAbility implements AddonAbility { + + private final List locations = new ArrayList<>(); + static final Set WATER_TEMPS = new HashSet<>(); + + //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. + private static float MAX_TEMP = 1.0F; + private static float MIN_HUMIDITY = 0.01F; + + private long regenDelay; + @Attribute(Attribute.DURATION) + private long duration; // 2000 + @Attribute(Attribute.COOLDOWN) + private long cooldown; // 2000 + private double absorbSpeed; // 0.1 + @Attribute(Attribute.RADIUS) + private int radius; // 6 + @Attribute("Chance") + private int chance; // 20 + private int absorbRate; // 6 + private int holdRange; // 2 + private boolean blastsEnabled; // true + private int maxBlasts; + private boolean keepSrc; // false + private boolean useRain; + private boolean usePlants; + + private double blastRange; // 20 + private double blastDamage; // 1.5 + private double blastSpeed; // 2 + + private boolean drainTemps; + + private long endTime; + private int absorbed = 0; + private int charge = 7; + private boolean noFill; + private int blasts; + private boolean hasCharge; + private final Material[] fillables = { Material.GLASS_BOTTLE, Material.BUCKET }; + + Random rand = new Random(); + + public Drain(Player player) { + super(player); + if (!bPlayer.canBend(this) || hasAbility(player, Drain.class)) { + return; + } + setFields(); + this.usePlants = bPlayer.canPlantbend(); + endTime = System.currentTimeMillis() + duration; + if (!canFill()) { + if (!blastsEnabled) + return; + noFill = true; + } + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + regenDelay = config.getLong("Abilities.Water.Drain.RegenDelay"); + duration = config.getLong("Abilities.Water.Drain.Duration"); + cooldown = config.getLong("Abilities.Water.Drain.Cooldown"); + absorbSpeed = config.getDouble("Abilities.Water.Drain.AbsorbSpeed"); + radius = config.getInt("Abilities.Water.Drain.Radius"); + chance = config.getInt("Abilities.Water.Drain.AbsorbChance"); + absorbRate = config.getInt("Abilities.Water.Drain.AbsorbRate"); + holdRange = config.getInt("Abilities.Water.Drain.HoldRange"); + blastsEnabled = config.getBoolean("Abilities.Water.Drain.BlastsEnabled"); + maxBlasts = config.getInt("Abilities.Water.Drain.MaxBlasts"); + keepSrc = config.getBoolean("Abilities.Water.Drain.KeepSource"); + blastRange = config.getDouble("Abilities.Water.Drain.BlastRange"); + blastDamage = config.getDouble("Abilities.Water.Drain.BlastDamage"); + blastSpeed = config.getDouble("Abilities.Water.Drain.BlastSpeed"); + useRain = config.getBoolean("Abilities.Water.Drain.AllowRainSource"); + drainTemps = config.getBoolean("Abilities.Water.Drain.DrainTempBlocks"); + + applyModifiers(); + } + + private void applyModifiers() { + if (isNight(player.getWorld())) { + cooldown -= ((long) getNightFactor(cooldown) - cooldown); + blastRange = getNightFactor(blastRange); + blastDamage = getNightFactor(blastDamage); + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (!noFill) { + if (!player.isSneaking()) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (!canFill()) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (System.currentTimeMillis() > endTime) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (absorbed >= absorbRate) { + fill(); + absorbed = 0; + } + checkForValidSource(); + } else { + if (blasts >= maxBlasts) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (player.isSneaking()) { + if (charge >= 2) { + checkForValidSource(); + } + if (absorbed >= absorbRate) { + hasCharge = true; + absorbed = 0; + if (charge >= 3) { + charge -= 2; + } + } + } else if (!hasCharge || !keepSrc) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (hasCharge) { + displayWaterSource(); + } + } + dragWater(); + } + + public static void fireBlast(Player player) { + if (hasAbility(player, Drain.class)) { + getAbility(player, Drain.class).fireBlast(); + } + } + + private void fireBlast() { + if (charge <= 1) { + hasCharge = false; + charge = 7; + blasts++; + new DrainBlast(player, blastRange, blastDamage, blastSpeed, holdRange); + } + } + + private void displayWaterSource() { + Location location = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)); + Block block = location.getBlock(); + if (!GeneralMethods.isSolid(block) || isTransparent(block)) { + TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(charge)), 100L); + WATER_TEMPS.add(tb); + tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); + } + } + + private boolean canFill() { + for (ItemStack items : player.getInventory()) { + if (items != null && Arrays.asList(fillables).contains(items.getType())) { + return true; + } + } + return false; + } + + private void fill() { + for (int x = 0; x < absorbed; x++) { + for (Material fillable : fillables) { + int slot = player.getInventory().first(fillable); + if (slot == -1){ + continue; + } + if (player.getInventory().getItem(slot).getAmount() > 1) { + player.getInventory().getItem(slot).setAmount(player.getInventory().getItem(slot).getAmount() - 1); + + ItemStack filled = getFilled(fillable); + HashMap cantfit = player.getInventory().addItem(filled); + for (int id : cantfit.keySet()) { + player.getWorld().dropItem(player.getEyeLocation(), cantfit.get(id)); + } + } else { + player.getInventory().setItem(slot, getFilled(fillable)); + } + break; + } + } + } + + private ItemStack getFilled(Material type) { + ItemStack filled = null; + if (type == Material.GLASS_BOTTLE) { + filled = WaterReturn.waterBottleItem(); + } else if (type == Material.BUCKET) { + filled = new ItemStack(Material.WATER_BUCKET, 1); + } + + return filled; + } + + private void checkForValidSource() { + List locs = GeneralMethods.getCircle(player.getLocation(), radius, radius, false, true, 0); + for (int i = 0; i < locs.size(); i++) { + Block block = locs.get(rand.nextInt(locs.size()-1)).getBlock(); + if (rand.nextInt(chance) == 0) { + Location pLoc = player.getLocation(); + World world = pLoc.getWorld(); + double temp = world.getTemperature(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); + double humidity = world.getHumidity(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); + if (block.getY() > world.getMinHeight() && block.getY() < world.getMaxHeight()) { + Location bLoc = block.getLocation(); + if (useRain && world.hasStorm() && !(temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { + if (pLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { + if (bLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { + locations.add(bLoc.clone().add(.5, .5, .5)); + return; + } + } + } + if (usePlants && JCMethods.isSmallPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { + drainPlant(block); + } else if (usePlants && ElementalAbility.isPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { + locations.add(bLoc.clone().add(.5, .5, .5)); + new TempBlock(block, Material.AIR.createBlockData(), regenDelay); + } else if (isWater(block)) { + TempBlock tb = TempBlock.get(block); + if ((tb == null || (drainTemps && !WATER_TEMPS.contains(tb)))) { + drainWater(block); + } + } + } + } + } + } + + private boolean isObstructed(Location location1, Location location2) { + Vector loc1 = location1.toVector(); + Vector loc2 = location2.toVector(); + + Vector direction = loc2.subtract(loc1); + direction.normalize(); + + Location loc; + + double max = location1.distance(location2); + + for (double i = 1; i <= max; i++) { + loc = location1.clone().add(direction.clone().multiply(i)); + if (!isTransparent(loc.getBlock())) + return true; + } + + return false; + } + + private void drainPlant(Block block) { + if (JCMethods.isSmallPlant(block)) { + if (JCMethods.isSmallPlant(block.getRelative(BlockFace.DOWN))) { + if (JCMethods.isDoublePlant(block.getType())) { + block = block.getRelative(BlockFace.DOWN); + locations.add(block.getLocation().clone().add(.5, .5, .5)); + new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); + return; + } + block = block.getRelative(BlockFace.DOWN); + } + locations.add(block.getLocation().clone().add(.5, .5, .5)); + new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); + } + } + + private void drainWater(Block block) { + if (isTransparent(block.getRelative(BlockFace.UP)) && !isWater(block.getRelative(BlockFace.UP))) { + locations.add(block.getLocation().clone().add(.5, .5, .5)); + if (block.getBlockData() instanceof Waterlogged) { + new TempBlock(block, block.getType().createBlockData(bd -> ((Waterlogged) bd).setWaterlogged(false)), regenDelay); + } else { + TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(1)), regenDelay); + WATER_TEMPS.add(tb); + tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); + } + } + } + + private void dragWater() { + List toRemove = new ArrayList<>(); + if (!locations.isEmpty()) { + for (Location l : locations) { + Location playerLoc = player.getLocation().add(0, 1, 0); + if (noFill) + playerLoc = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)).subtract(0, .8, 0); + Vector dir = GeneralMethods.getDirection(l, playerLoc); + l = l.add(dir.multiply(absorbSpeed)); + ParticleEffect.WATER_SPLASH.display(l, 1, 0, 0, 0, 0); + GeneralMethods.displayColoredParticle("0099FF", l); + if (l.distance(playerLoc) < 1) { + toRemove.add(locations.indexOf(l)); + absorbed++; + } + } + } + if (!toRemove.isEmpty()) { + for (int i : toRemove) { + if (i < locations.size()) + locations.remove(i); + } + toRemove.clear(); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "Drain"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.Drain.Description"); + } + + @Override + public List getLocations() { + return locations; + } + + public long getRegenDelay() { + return regenDelay; + } + + public void setRegenDelay(long regenDelay) { + this.regenDelay = regenDelay; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public double getAbsorbSpeed() { + return absorbSpeed; + } + + public void setAbsorbSpeed(double absorbSpeed) { + this.absorbSpeed = absorbSpeed; + } + + public int getRadius() { + return radius; + } + + public void setRadius(int radius) { + this.radius = radius; + } + + public int getChance() { + return chance; + } + + public void setChance(int chance) { + this.chance = chance; + } + + public int getAbsorbRate() { + return absorbRate; + } + + public void setAbsorbRate(int absorbRate) { + this.absorbRate = absorbRate; + } + + public int getHoldRange() { + return holdRange; + } + + public void setHoldRange(int holdRange) { + this.holdRange = holdRange; + } + + public boolean isBlastsEnabled() { + return blastsEnabled; + } + + public void setBlastsEnabled(boolean blastsEnabled) { + this.blastsEnabled = blastsEnabled; + } + + public int getMaxBlasts() { + return maxBlasts; + } + + public void setMaxBlasts(int maxBlasts) { + this.maxBlasts = maxBlasts; + } + + public boolean isKeepSrc() { + return keepSrc; + } + + public void setKeepSrc(boolean keepSrc) { + this.keepSrc = keepSrc; + } + + public boolean isUseRain() { + return useRain; + } + + public void setUseRain(boolean useRain) { + this.useRain = useRain; + } + + public boolean isUsePlants() { + return usePlants; + } + + public void setUsePlants(boolean usePlants) { + this.usePlants = usePlants; + } + + public double getBlastRange() { + return blastRange; + } + + public void setBlastRange(double blastRange) { + this.blastRange = blastRange; + } + + public double getBlastDamage() { + return blastDamage; + } + + public void setBlastDamage(double blastDamage) { + this.blastDamage = blastDamage; + } + + public double getBlastSpeed() { + return blastSpeed; + } + + public void setBlastSpeed(double blastSpeed) { + this.blastSpeed = blastSpeed; + } + + public boolean isDrainTemps() { + return drainTemps; + } + + public void setDrainTemps(boolean drainTemps) { + this.drainTemps = drainTemps; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public int getAbsorbed() { + return absorbed; + } + + public void setAbsorbed(int absorbed) { + this.absorbed = absorbed; + } + + public int getCharge() { + return charge; + } + + public void setCharge(int charge) { + this.charge = charge; + } + + public boolean isNoFill() { + return noFill; + } + + public void setNoFill(boolean noFill) { + this.noFill = noFill; + } + + public int getBlasts() { + return blasts; + } + + public void setBlasts(int blasts) { + this.blasts = blasts; + } + + public boolean isHasCharge() { + return hasCharge; + } + + public void setHasCharge(boolean hasCharge) { + this.hasCharge = hasCharge; + } + + public Material[] getFillables() { + return fillables; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.Drain.Enabled"); + } +} diff --git a/src/ability/waterbending/DrainBlast.java b/src/ability/waterbending/DrainBlast.java new file mode 100644 index 0000000..7656c6f --- /dev/null +++ b/src/ability/waterbending/DrainBlast.java @@ -0,0 +1,169 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class DrainBlast extends WaterAbility implements AddonAbility { + + private Location location; + private Vector direction; + private double travelled; + + @Attribute(Attribute.RANGE) + private final double blastRange; // 20 + @Attribute(Attribute.DAMAGE) + private final double blastDamage; // 1.5 + @Attribute(Attribute.SPEED) + private final double blastSpeed; // 2 + + public DrainBlast(Player player, double range, double damage, double speed, int holdrange) { + super(player); + this.blastRange = range; + this.blastDamage = damage; + this.blastSpeed = speed; + location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(holdrange)); + start(); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (travelled >= blastRange) { + remove(); + return; + } + advanceAttack(); + } + + private void advanceAttack() { + for (int i = 0; i < blastSpeed; i++) { + travelled++; + if (travelled >= blastRange) + return; + + if (!player.isDead()) + direction = GeneralMethods.getDirection(player.getLocation(), GeneralMethods.getTargetedLocation(player, blastRange, Material.WATER)).normalize(); + location = location.add(direction.clone().multiply(1)); + if (GeneralMethods.isSolid(location.getBlock()) || !isTransparent(location.getBlock())) { + travelled = blastRange; + return; + } + + playWaterbendingSound(location); + TempBlock tb = new TempBlock(location.getBlock(), Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 100L); + Drain.WATER_TEMPS.add(tb); + tb.setRevertTask(() -> Drain.WATER_TEMPS.remove(tb)); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { + DamageHandler.damageEntity(entity, blastDamage, this); + travelled = blastRange; + } + } + } + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "Drain"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.Drain.Description"); + } + + public void setLocation(Location location) { + this.location = location; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getDistanceTravelled() { + return travelled; + } + + public void setDistanceTravelled(double travelled) { + this.travelled = travelled; + } + + public double getBlastRange() { + return blastRange; + } + + public double getBlastDamage() { + return blastDamage; + } + + public double getBlastSpeed() { + return blastSpeed; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.Drain.Enabled"); + } +} diff --git a/src/ability/waterbending/FrostBreath.java b/src/ability/waterbending/FrostBreath.java new file mode 100644 index 0000000..9a2ab0f --- /dev/null +++ b/src/ability/waterbending/FrostBreath.java @@ -0,0 +1,440 @@ +package com.jedk1.jedcore.ability.waterbending; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.IceAbility; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; + +public class FrostBreath extends IceAbility implements AddonAbility { + + private static final List INVALID_MATERIALS = new ArrayList(){{ + addAll(Arrays.asList( + Material.ICE, + Material.LAVA, + Material.AIR, + Material.VOID_AIR, + Material.CAVE_AIR)); + if (GeneralMethods.getMCVersion() >= 1170) { + add(Material.getMaterial("LIGHT")); + } + }}; + + //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. + private static float MAX_TEMP = 1.0F; + private static float MIN_HUMIDITY = 0.01F; + + public Config config; + + private State state; + private final List frozenBlocks = new ArrayList<>(); + + public FrostBreath(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { + return; + } + + this.config = new Config(player); + this.state = new BeamState(); + + double temp = player.getLocation().getWorld().getTemperature(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); + double humidity = player.getLocation().getWorld().getHumidity(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); + + if (config.restrictBiomes && (temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { + return; + } + + start(); + } + + @Override + public void progress() { + if (!state.update()) { + remove(); + } + + long time = System.currentTimeMillis(); + + frozenBlocks.removeIf(frozen -> { + if (time >= frozen.endTime) { + removeFrozenBlock(frozen.tempBlock); + frozen.tempBlock.revertBlock(); + return true; + } + + return false; + }); + } + + @Override + public void remove() { + super.remove(); + + frozenBlocks.forEach(fb -> { + removeFrozenBlock(fb.tempBlock); + fb.tempBlock.revertBlock(); + }); + frozenBlocks.clear(); + } + + @Override + public long getCooldown() { + return config.cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "FrostBreath"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.FrostBreath.Description"); + } + + public static List getInvalidMaterials() { + return INVALID_MATERIALS; + } + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + public List getFrozenBlocks() { + return frozenBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.FrostBreath.Enabled"); + } + + private void addFrozenBlock(TempBlock tempBlock) { + PhaseChange.getFrozenBlocksMap().put(tempBlock, player); + } + + private void removeFrozenBlock(TempBlock tempBlock) { + PhaseChange.getFrozenBlocksMap().remove(tempBlock); + } + + private interface State { + boolean update(); + } + + private class BeamState implements State { + @Override + public boolean update() { + if (player == null || !player.isOnline()) { + return transition(); + } + + if (!bPlayer.canBendIgnoreCooldowns(FrostBreath.this)) { + return transition(); + } + + if (!player.isSneaking() || player.isDead()) { + return transition(); + } + + if (System.currentTimeMillis() >= getStartTime() + config.duration) { + return transition(); + } + + createBeam(); + + return true; + } + + private boolean transition() { + state = new SnowMeltingState(); + + return true; + } + + private boolean isLocationSafe(Location loc) { + Block block = loc.getBlock(); + + if (RegionProtection.isRegionProtected(player, loc, FrostBreath.this)) { + return false; + } + + return isTransparent(block); + } + + private boolean isFreezable(Location location, Entity entity) { + if (RegionProtection.isRegionProtected(FrostBreath.this, location)) { + return false; + } + + if (entity instanceof Player && Commands.invincible.contains(entity.getName())) { + return false; + } + + return !location.getBlock().getType().isSolid(); + } + + private void createBeam() { + Location loc = player.getEyeLocation(); + Vector dir = player.getLocation().getDirection(); + double step = 1; + double size = 0; + double offset = 0; + double damageRegion = 1.5; + + for (double i = 0; i < config.range; i += step) { + loc = loc.add(dir.clone().multiply(step)); + size += 0.005; + offset += 0.3; + damageRegion += 0.01; + + if (!isLocationSafe(loc)) + return; + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + for (Location cageLocation : createCage(entity.getLocation())) { + if (isFreezable(cageLocation, entity)) { + Block block = cageLocation.getBlock(); + + updateFrozenBlock(block, Material.ICE, config.freezeDuration); + } + } + + if (config.slowEnabled) { + ((LivingEntity) entity).addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect((int) config.slowDuration, 5)); + } + + if (config.damageEnabled) { + if (entity instanceof Player) { + DamageHandler.damageEntity(entity, config.playerDamage, FrostBreath.this); + } else { + DamageHandler.damageEntity(entity, config.mobDamage, FrostBreath.this); + } + } + } + } + + if (config.snowEnabled) { + freezeGround(loc); + } + + ParticleEffect.SNOW_SHOVEL.display(loc, config.particles, Math.random(), Math.random(), Math.random(), size); + + JCMethods.displayColoredParticles("#DCDCDC", loc, 1, Math.random(), Math.random(), Math.random(), 0.003f); + JCMethods.displayColoredParticles("#9696FF", loc, 1, Math.random(), Math.random(), Math.random(), 0.0035f); + } + } + + private Location getOffsetLocation(Location loc, double offset) { + return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); + } + + private void freezeGround(Location loc) { + for (Location l : GeneralMethods.getCircle(loc, 2, 2, false, true, 0)) { + if (!RegionProtection.isRegionProtected(player, l, FrostBreath.this)) { + Block block = l.getBlock(); + + if (isWater(l.getBlock())) { + updateFrozenBlock(block, Material.ICE, config.frozenWaterDuration); + } else if (isTransparent(l.getBlock()) && l.clone().add(0, -1, 0).getBlock().getType().isSolid() && !INVALID_MATERIALS.contains(l.clone().add(0, -1, 0).getBlock().getType())) { + if (config.bendSnow) { + updateFrozenBlock(block, Material.SNOW, config.snowDuration); + } else { + TempBlock current = TempBlock.get(block); + + // Refresh any existing TempBlock so the timer resets. + if (current != null) { + current.revertBlock(); + } + + TempBlock tempBlock = new TempBlock(block, Material.SNOW.createBlockData()); + tempBlock.setRevertTime(config.snowDuration); + } + } + } + } + } + + private void updateFrozenBlock(Block block, Material type, long duration) { + // Store the TempBlock as a FrozenBlock block so it can be reverted later. + for (FrozenBlock fb : frozenBlocks) { + if (fb.tempBlock.getBlock().equals(block)) { + if (fb.tempBlock.getBlockData().getMaterial() != type) { + // Completely overwrite this FrozenBlock if the new type doesn't match the old one. + removeFrozenBlock(fb.tempBlock); + fb.tempBlock.revertBlock(); + frozenBlocks.remove(fb); + break; + } + + fb.endTime = System.currentTimeMillis() + duration; + return; + } + } + + TempBlock tempBlock = new TempBlock(block, type.createBlockData()); + + frozenBlocks.add(new FrozenBlock(tempBlock, System.currentTimeMillis() + duration)); + + // Add the TempBlock to a ProjectKorra block list so it can be used as a water source. + // I don't believe there exists a way to make a TempBlock water bendable right now, so this + // is a hack to make it work. + addFrozenBlock(tempBlock); + } + + private List createCage(Location centerBlock) { + List selectedBlocks = new ArrayList<>(); + + int bX = centerBlock.getBlockX(); + int bY = centerBlock.getBlockY(); + int bZ = centerBlock.getBlockZ(); + + for (int x = bX - 1; x <= bX + 1; x++) { + for (int y = bY - 1; y <= bY + 1; y++) { + Location l = new Location(centerBlock.getWorld(), x, y, bZ); + selectedBlocks.add(l); + } + } + + for (int y = bY - 1; y <= bY + 2; y++) { + Location l = new Location(centerBlock.getWorld(), bX, y, bZ); + selectedBlocks.add(l); + } + + for (int z = bZ - 1; z <= bZ + 1; z++) { + for (int y = bY - 1; y <= bY + 1; y++) { + Location l = new Location(centerBlock.getWorld(), bX, y, z); + selectedBlocks.add(l); + } + } + + for (int x = bX - 1; x <= bX + 1; x++) { + for (int z = bZ - 1; z <= bZ + 1; z++) { + Location l = new Location(centerBlock.getWorld(), x, bY, z); + selectedBlocks.add(l); + } + } + + return selectedBlocks; + } + } + + // Wait for the frozen blocks to melt and remove it from bendable water list. + private class SnowMeltingState implements State { + SnowMeltingState() { + bPlayer.addCooldown(FrostBreath.this); + } + + @Override + public boolean update() { + return !frozenBlocks.isEmpty(); + } + } + + private static class FrozenBlock { + TempBlock tempBlock; + long endTime; + + FrozenBlock(TempBlock tempBlock, long endTime) { + this.tempBlock = tempBlock; + this.endTime = endTime; + } + } + + public static class Config { + long cooldown; + long duration; + int particles; + int freezeDuration; + int snowDuration; + int frozenWaterDuration; + int range; + boolean snowEnabled; + boolean bendSnow; + boolean damageEnabled; + double playerDamage; + double mobDamage; + boolean slowEnabled; + long slowDuration; + boolean restrictBiomes; + + Config(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + + cooldown = config.getLong("Abilities.Water.FrostBreath.Cooldown"); + duration = config.getLong("Abilities.Water.FrostBreath.Duration"); + particles = config.getInt("Abilities.Water.FrostBreath.Particles"); + freezeDuration = config.getInt("Abilities.Water.FrostBreath.FrostDuration"); + snowDuration = config.getInt("Abilities.Water.FrostBreath.SnowDuration"); + frozenWaterDuration = config.getInt("Abilities.Water.FrostBreath.FrozenWaterDuration"); + range = config.getInt("Abilities.Water.FrostBreath.Range"); + snowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Snow"); + bendSnow = config.getBoolean("Abilities.Water.FrostBreath.BendableSnow"); + damageEnabled = config.getBoolean("Abilities.Water.FrostBreath.Damage.Enabled"); + playerDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Player"); + mobDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Mob"); + slowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Slow.Enabled"); + slowDuration = config.getLong("Abilities.Water.FrostBreath.Slow.Duration"); + restrictBiomes = config.getBoolean("Abilities.Water.FrostBreath.RestrictBiomes"); + } + } +} diff --git a/src/ability/waterbending/HealingWaters.java b/src/ability/waterbending/HealingWaters.java new file mode 100644 index 0000000..c5aa09f --- /dev/null +++ b/src/ability/waterbending/HealingWaters.java @@ -0,0 +1,267 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.LightManager; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.HealingAbility; +import com.projectkorra.projectkorra.chiblocking.Smokescreen; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; + +import com.projectkorra.projectkorra.waterbending.util.WaterReturn; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Random; + +public class HealingWaters extends HealingAbility implements AddonAbility { + + private static long time = 0; + private static boolean enabled = true; + + public HealingWaters(Player player) { + super(player); + } + + public static void heal(Server server) { + if (enabled) { + if (System.currentTimeMillis() - time >= 1000) { + time = System.currentTimeMillis(); + for (Player player : server.getOnlinePlayers()) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer != null && bPlayer.canBend(getAbility("HealingWaters"))) { + heal(player); + } + } + } + } + } + + @SuppressWarnings("deprecation") + private static void heal(Player player) { + if (inWater(player)) { + if (player.isSneaking()) { + Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); + if (entity instanceof LivingEntity && inWater(entity)) { + Location playerLoc = entity.getLocation(); + playerLoc.add(0, 1, 0); + JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHPToEntity((LivingEntity) entity); + emitLight(playerLoc); + emitLight(entity.getLocation()); + } + } else { + Location playerLoc = player.getLocation(); + playerLoc.add(0, 1, 0); + JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHP(player); + emitLight(playerLoc); + } + + } else if(hasWaterSupply(player) && player.isSneaking()) { + Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); + if (entity != null) { + if (entity instanceof LivingEntity) { + Damageable dLe = (Damageable) entity; + if (dLe.getHealth() < dLe.getMaxHealth()) { + Location playerLoc = entity.getLocation(); + playerLoc.add(0, 1, 0); + JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHPToEntity((LivingEntity) entity); + entity.setFireTicks(0); + Random rand = new Random(); + if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); + emitLight(playerLoc); + emitLight(entity.getLocation()); + } + } + } else { + Location playerLoc = player.getLocation(); + playerLoc.add(0, 1, 0); + + JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f); + + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHP(player); + player.setFireTicks(0); + Random rand = new Random(); + if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); + emitLight(playerLoc); + } + } + } + + @SuppressWarnings("deprecation") + private static void giveHPToEntity(LivingEntity le) { + if (!le.isDead() && le.getHealth() < le.getMaxHealth()) { + applyHealingToEntity(le); + } + for (PotionEffect effect : le.getActivePotionEffects()) { + if (isNegativeEffect(effect.getType())) { + le.removePotionEffect(effect.getType()); + } + } + } + + private static void giveHP(Player player){ + if (!player.isDead() && player.getHealth() < 20) { + applyHealing(player); + } + for(PotionEffect effect : player.getActivePotionEffects()) { + if(isNegativeEffect(effect.getType())) { + if((effect.getType() == PotionEffectType.BLINDNESS) && Smokescreen.getBlindedTimes().containsKey(player.getName())) { + return; + } + player.removePotionEffect(effect.getType()); + } + } + } + + + + private static boolean inWater(Entity entity) { + Block block = entity.getLocation().getBlock(); + return isWater(block) && !TempBlock.isTempBlock(block); + } + + private static boolean hasWaterSupply(Player player){ + ItemStack heldItem = player.getInventory().getItemInMainHand(); + return (heldItem.isSimilar(WaterReturn.waterBottleItem()) || heldItem.getType() == Material.WATER_BUCKET); + + } + + private static void drainWaterSupply(Player player){ + ItemStack heldItem = player.getInventory().getItemInMainHand(); + ItemStack emptyBottle = new ItemStack(Material.GLASS_BOTTLE, 1); + if (heldItem.isSimilar(WaterReturn.waterBottleItem())) { + if (heldItem.getAmount() > 1) { + heldItem.setAmount(heldItem.getAmount() - 1); + HashMap cantFit = player.getInventory().addItem(emptyBottle); + for (int id : cantFit.keySet()) { + player.getWorld().dropItem(player.getEyeLocation(), cantFit.get(id)); + } + } else { + player.getInventory().setItemInMainHand(emptyBottle); + } + } + } + + @SuppressWarnings("deprecation") + private static void applyHealing(Player player) { + if (!RegionProtection.isRegionProtected(player, player.getLocation(), "HealingWaters")) + if(player.getHealth() < player.getMaxHealth()) { + player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, getPower(player))); + AirAbility.breakBreathbendingHold(player); + } + } + + @SuppressWarnings("deprecation") + private static void applyHealingToEntity(LivingEntity le) { + if (le.getHealth() < le.getMaxHealth()) { + le.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, 1)); + AirAbility.breakBreathbendingHold(le); + } + } + + public static int getPower(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + return config.getInt("Abilities.Water.HealingWaters.Power"); + } + + public static double getRange(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + return config.getDouble("Abilities.Water.HealingWaters.Range"); + } + + public static int getDrainChance(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + return config.getInt("Abilities.Water.HealingWaters.DrainChance"); + } + + public static void emitLight(Location loc) { + ConfigurationSection config = JedCoreConfig.getConfig((Player)null); + if (config.getBoolean("Abilities.Water.HealingWaters.DynamicLight.Enabled")) { + int brightness = config.getInt("Abilities.Water.HealingWaters.DynamicLight.Brightness"); + long keepAlive = config.getLong("Abilities.Water.HealingWaters.DynamicLight.KeepAlive"); + + LightManager.createLight(loc).brightness(brightness).timeUntilFadeout(keepAlive).emit(); + } + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "HealingWaters"; + } + + @Override + public boolean isHarmlessAbility() { + return true; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.HealingWaters.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + enabled = config.getBoolean("Abilities.Water.HealingWaters.Enabled"); + return enabled; + } + + @Override + public void progress() {} +} \ No newline at end of file diff --git a/src/ability/waterbending/IceClaws.java b/src/ability/waterbending/IceClaws.java new file mode 100644 index 0000000..e211317 --- /dev/null +++ b/src/ability/waterbending/IceClaws.java @@ -0,0 +1,299 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.ability.firebending.FirePunch; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.IceAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; + +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.MainHand; +import org.bukkit.potion.PotionEffectType; + +public class IceClaws extends IceAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.CHARGE_DURATION) + private long chargeUp; + private int slowDur; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.RANGE) + private double range; + private boolean throwable; + + private Location head; + private Location origin; + private boolean launched; + + private Boolean iceInMainHand = null; + + public IceClaws(Player player) { + super(player); + if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { + return; + } + + if (hasAbility(player, IceClaws.class)) { + IceClaws ic = getAbility(player, IceClaws.class); + if (!ic.throwable) { + ic.remove(); + } + return; + } + + setFields(); + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Water.IceClaws.Cooldown"); + chargeUp = config.getLong("Abilities.Water.IceClaws.ChargeTime"); + slowDur = config.getInt("Abilities.Water.IceClaws.SlowDuration")/50; + damage = config.getDouble("Abilities.Water.IceClaws.Damage"); + range = config.getDouble("Abilities.Water.IceClaws.Range"); + throwable = config.getBoolean("Abilities.Water.IceClaws.Throwable"); + + applyModifiers(); + } + + private void applyModifiers() { + cooldown -= ((long) getNightFactor(cooldown) - cooldown); + damage = getNightFactor(damage); + range = getNightFactor(range); + } + + @Override + public void progress() { + if (player == null || player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + if (System.currentTimeMillis() > getStartTime() + chargeUp) { + if (!launched && throwable) { + displayClaws(); + } else { + if (!shoot()) { + remove(); + } + } + } else if (player.isSneaking()) { + displayChargeUp(); + } else { + remove(); + } + } + + + public static void swapHands(Player player) { + IceClaws ic = getAbility(player, IceClaws.class); + if (ic == null) + return; + if (ic.iceInMainHand == null) + ic.iceInMainHand = true; + else ic.iceInMainHand = !ic.iceInMainHand; + } + + public Location getRightHandPos() { + return (player.getMainHand() == MainHand.RIGHT == ((iceInMainHand == null) || iceInMainHand) ? + GeneralMethods.getRightSide(player.getLocation(), .55) : + GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); + } + + public boolean shoot() { + for (double i = 0; i < 1; i+=.5) { + head.add(origin.clone().getDirection().multiply(.5)); + if (origin.distance(head) >= range) return false; + if (!isTransparent(head.getBlock())) return false; + GeneralMethods.displayColoredParticle("66FFFF", head); + GeneralMethods.displayColoredParticle("CCFFFF", head); + ParticleEffect.SNOW_SHOVEL.display(head, 1, 0, 0, 0, 0); + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(head, 1.5)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { + freezeEntity((LivingEntity) entity); + return false; + } + } + } + return true; + + } + + public static void throwClaws(Player player) { + if (hasAbility(player, IceClaws.class)) { + IceClaws ic = getAbility(player, IceClaws.class); + if (!ic.launched && player.isSneaking()) { + ic.launched = true; + ic.origin = ic.player.getEyeLocation(); + ic.head = ic.origin.clone(); + } + } + } + + private void displayClaws() { + Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); + GeneralMethods.displayColoredParticle("66FFFF", location); + GeneralMethods.displayColoredParticle("CCFFFF", location); + } + + private void displayChargeUp() { + Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); + ParticleEffect.WATER_SPLASH.display(location, 1, Math.random()/3, Math.random()/3, Math.random()/3, 0.0); + } + + public static boolean freezeEntity(Player player, LivingEntity entity) { + if (hasAbility(player, IceClaws.class)) { + getAbility(player, IceClaws.class).freezeEntity(entity); + return true; + } + return false; + } + + private void freezeEntity(LivingEntity entity) { + if (entity.hasPotionEffect(PotionEffectType.SPEED)) { + entity.removePotionEffect(PotionEffectType.SPEED); + } + // todo: doesnt seem to be affecting mobs? frostbreath does. + entity.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect(slowDur, 3)); + bPlayer.addCooldown(this); + remove(); + DamageHandler.damageEntity(entity, damage, this); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return head; + } + + @Override + public String getName() { + return "IceClaws"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.IceClaws.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getChargeUp() { + return chargeUp; + } + + public void setChargeUp(long chargeUp) { + this.chargeUp = chargeUp; + } + + public int getSlowDuration() { + return slowDur; + } + + public void setSlowDuration(int slowDuration) { + this.slowDur = slowDuration; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public boolean isThrowable() { + return throwable; + } + + public void setThrowable(boolean throwable) { + this.throwable = throwable; + } + + public Location getHead() { + return head; + } + + public void setHead(Location head) { + this.head = head; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public boolean isLaunched() { + return launched; + } + + public void setLaunched(boolean launched) { + this.launched = launched; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.IceClaws.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/waterbending/IcePassive.java b/src/ability/waterbending/IcePassive.java new file mode 100644 index 0000000..37478f0 --- /dev/null +++ b/src/ability/waterbending/IcePassive.java @@ -0,0 +1,71 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.ability.IceAbility; +import com.projectkorra.projectkorra.util.ParticleEffect; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.permissions.Permission; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.HashMap; +import java.util.Map; + +public class IcePassive { + + public static void handleSkating() { + Map> resultCache = new HashMap<>(); + + for (Player player: Bukkit.getServer().getOnlinePlayers()) { + Pair result = resultCache.get(player.getWorld()); + if (result == null) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + + boolean enabled = config.getBoolean("Abilities.Water.Ice.Passive.Skate.Enabled"); + int speedFactor = config.getInt("Abilities.Water.Ice.Passive.Skate.SpeedFactor"); + + result = new Pair<>(enabled, speedFactor); + resultCache.put(player.getWorld(), result); + } + + boolean enabled = result.first; + int speedFactor = result.second; + + if (!enabled) continue; + if (JCMethods.isDisabledWorld(player.getWorld())) continue; + if (!player.isOnGround()) continue; + if (!player.isSprinting()) continue; + if (!IceAbility.isIce(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) continue; + + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + + if (bPlayer == null) continue; + if (!bPlayer.canIcebend()) continue; + if (!bPlayer.isPassiveToggled(Element.WATER)) continue; + + if (!player.hasPermission("bending.ability.IceSkate")) continue; + + ParticleEffect.SNOW_SHOVEL.display(player.getLocation().clone().add(0, 0.2, 0), 15, Math.random()/2, Math.random()/2, Math.random()/2, 0); + player.removePotionEffect(PotionEffectType.SPEED); + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 60, speedFactor)); + } + } + + private static class Pair { + T first; + U second; + + Pair(T first, U second) { + this.first = first; + this.second = second; + } + } +} diff --git a/src/ability/waterbending/combo/Maelstrom.java b/src/ability/waterbending/combo/Maelstrom.java new file mode 100644 index 0000000..ec02664 --- /dev/null +++ b/src/ability/waterbending/combo/Maelstrom.java @@ -0,0 +1,331 @@ +package com.jedk1.jedcore.ability.waterbending.combo; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.waterbending.Torrent; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + +public class Maelstrom extends WaterAbility implements AddonAbility, ComboAbility { + + private int depth; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + + private final List pool = new ArrayList<>(); + private final List wave = new ArrayList<>(); + private Location origin; + private int step; + private int levelStep; + private int angle; + private boolean canRemove; + + public Maelstrom(Player player) { + super(player); + if (!bPlayer.canBendIgnoreBinds(this) || hasAbility(player, Maelstrom.class)) { + return; + } + setFields(); + if (setOrigin()) { + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + Torrent t = getAbility(player, Torrent.class); + if (t != null) { + t.remove(); + } + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Water.WaterCombo.Maelstrom.Cooldown"); + duration = config.getLong("Abilities.Water.WaterCombo.Maelstrom.Duration"); + depth = config.getInt("Abilities.Water.WaterCombo.Maelstrom.MaxDepth"); + range = config.getInt("Abilities.Water.WaterCombo.Maelstrom.Range"); + canRemove = true; + + applyModifiers(); + } + + private void applyModifiers() { + if (isNight(player.getWorld())) { + cooldown -= ((long) getNightFactor(cooldown) - cooldown); + range = (int) getNightFactor(range); + } + } + + public boolean setOrigin() { + Block block = BlockSource.getWaterSourceBlock(player, range, ClickType.LEFT_CLICK, true, false, false); + if (block != null) { + if (!isTransparent(block.getRelative(BlockFace.UP))) { + return false; + } + for (int i = 0; i < depth; i++) { + if (!isWater(block.getRelative(BlockFace.DOWN, i))) { + setDepth(i - 1); + break; + } + } + if (getDepth() < 3) { + return false; + } + origin = block.getLocation().clone(); + for (Location l : GeneralMethods.getCircle(origin, getDepth(), 1, false, false, 0)) { + if (!isWater(l.getBlock())) { + return false; + } + } + return true; + } + return false; + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.getWorld() != origin.getWorld()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + remove(); + return; + } + if (System.currentTimeMillis() > getStartTime() + duration) { + remove(); + return; + } + removeWater(false); + playAnimation(); + dragEntities(); + if (canRemove && (step == 0 || step % 20 == 0)) { + if (levelStep < getDepth()) { + levelStep++; + removeWater(true); + } + if (step == 20) { + step = 0; + } + } + step++; + } + + public void removeWater(boolean increase) { + if (increase) { + pool.clear(); + for (int i = 0; i < levelStep; i++) { + for (Location l : GeneralMethods.getCircle(origin.clone().subtract(0, i, 0), levelStep - i, 1, false, false, 0)) { + if (!isWater(l.getBlock()) && !isTransparent(l.getBlock())) { + canRemove = false; + break; + } + if (!pool.contains(l.getBlock())) { + pool.add(l.getBlock()); + } + } + } + } + for (Block b : pool) { + if (wave.contains(b)) continue; + new RegenTempBlock(b, Material.AIR, Material.AIR.createBlockData(), 100); + } + } + + public void dragEntities(){ + for(Block b : pool){ + if (pool.indexOf(b) % 3 == 0) { + Location l = b.getLocation(); + for(Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 1.5D)){ + Vector direction = GeneralMethods.getDirection(entity.getLocation(), origin.clone().subtract(-0.5, (levelStep - 1), -0.5)); + entity.setVelocity(direction.multiply(0.2)); + } + } + } + } + + public void playAnimation() { + wave.clear(); + int waves = 5; + int newAngle = this.angle; + for (int i = 0; i < levelStep; i++) { + for (int degree = 0; degree < waves; degree++) { + double size = (levelStep - i) - 1; + double angle = ((newAngle + (degree * (360F / waves))) * Math.PI / 180); + double x = size * Math.cos(angle); + double z = size * Math.sin(angle); + Location loc = origin.clone(); + loc.add(x + 0.5, -(i - 0.5), z + 0.5); + Block b = loc.getBlock(); + for (int j = 0; j < 2; j++) { + wave.add(b.getRelative(BlockFace.DOWN, j)); + new RegenTempBlock(b.getRelative(BlockFace.DOWN, j), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(1)), 0); + ParticleEffect.WATER_SPLASH.display(loc, 3, Math.random(), Math.random(), Math.random(), 0); + } + } + newAngle += 15; + } + this.angle+=(levelStep * 2); + + } + + public void setDepth(int depth) { + this.depth = depth; + } + + public int getDepth() { + return depth; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return origin; + } + + @Override + public String getName() { + return "Maelstrom"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public Object createNewComboInstance(Player player) { + return new Maelstrom(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.Maelstrom.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Water.WaterCombo.Maelstrom.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.WaterCombo.Maelstrom.Description"); + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public List getPool() { + return pool; + } + + public List getWave() { + return wave; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public int getAngle() { + return angle; + } + + public void setAngle(int angle) { + this.angle = angle; + } + + public boolean canRemove() { + return canRemove; + } + + public void setCanRemove(boolean canRemove) { + this.canRemove = canRemove; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.WaterCombo.Maelstrom.Enabled"); + } +} diff --git a/src/ability/waterbending/combo/WaterFlow.java b/src/ability/waterbending/combo/WaterFlow.java new file mode 100644 index 0000000..ee9c1f8 --- /dev/null +++ b/src/ability/waterbending/combo/WaterFlow.java @@ -0,0 +1,728 @@ +package com.jedk1.jedcore.ability.waterbending.combo; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.MaterialUtil; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.airbending.AirSpout; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.earthbending.Catapult; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.WaterManipulation; +import com.projectkorra.projectkorra.waterbending.WaterSpout; + +import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; +import com.projectkorra.projectkorra.waterbending.util.WaterReturn; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; + +public class WaterFlow extends WaterAbility implements AddonAbility, ComboAbility { + + @Attribute(Attribute.SELECT_RANGE) + private int sourceRange; //10 + @Attribute(Attribute.RANGE) + private int maxRange; //40 + private int minRange; //8 + @Attribute(Attribute.DURATION) + private long duration; //10000 + @Attribute(Attribute.COOLDOWN) + private long cooldown; //15000 + private long meltDelay; //5000 + @Attribute("Length") + private long trail; //80 + private boolean avatar; //true + private boolean stayAtSource; //true + private int stayRange; //100 + private boolean fullMoonEnabled; + private int fullMoonCooldown; + private int fullMoonDuration; + private boolean playerRideOwnFlow; + private int size; //1; + private int avatarSize; //3; + private int fullMoonSizeSmall; //2; + private int fullMoonSizeLarge; //3; + private long avatarDuration; //60000; + private boolean canUseBottle; + private boolean canUsePlants; + private boolean removeOnAnyDamage; + + private long time; + private Location origin; + private Location head; + private int range; + private Block sourceBlock; + private boolean frozen; + private double prevHealth; + private int headSize; + private boolean usingBottle; + private final ConcurrentHashMap directions = new ConcurrentHashMap<>(); + private final List blocks = new ArrayList<>(); + + Random rand = new Random(); + + public WaterFlow(Player player) { + super(player); + if (!bPlayer.canBendIgnoreBinds(this)) { + return; + } + if (JCMethods.isLunarEclipse(player.getWorld())) { + return; + } + if (hasAbility(player, WaterFlow.class)) { + getAbility(player, WaterFlow.class).remove(); + return; + } + setFields(); + + usingBottle = false; + + if (prepare()) { + headSize = size; + trail = trail * size; + range = maxRange; + prevHealth = player.getHealth(); + time = System.currentTimeMillis(); + + int augment = (int) Math.round(getNightFactor(player.getWorld())); + if (isFullMoon(player.getWorld()) && fullMoonEnabled && sourceBlock != null) { + List sources = getNearbySources(sourceBlock, 3); + if (sources.size() > 9) { + headSize = fullMoonSizeSmall; + } + if (sources.size() > 36) { + headSize = fullMoonSizeLarge; + } + trail = trail * augment; + range = range - (range / 3); + maxRange = range; + duration = duration * fullMoonDuration; + cooldown = cooldown * fullMoonCooldown; + } + if (bPlayer.isAvatarState()) { + headSize = avatarSize; + if (avatar) { + duration = 0; + } else { + duration = avatarDuration; + } + } + start(); + if (hasAbility(player, WaterManipulation.class)) { + WaterManipulation manip = getAbility(player, WaterManipulation.class); + manip.remove(); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + sourceRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.SourceRange"); + maxRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MaxRange"); + minRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MinRange"); + duration = config.getLong("Abilities.Water.WaterCombo.WaterFlow.Duration"); + cooldown = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Cooldown"); + meltDelay = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MeltDelay"); + trail = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Trail"); + avatar = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.IsAvatarStateToggle"); + avatarDuration = config.getLong("Abilities.Water.WaterCombo.WaterFlow.AvatarStateDuration"); + stayAtSource = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.PlayerStayNearSource"); + stayRange = config.getInt("Abilities.Water.WaterCombo.WaterFlow.MaxDistanceFromSource"); + canUseBottle = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.BottleSource"); + canUsePlants = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.PlantSource"); + removeOnAnyDamage = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.RemoveOnAnyDamage"); + fullMoonCooldown = config.getInt("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Cooldown"); + fullMoonDuration = config.getInt("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Duration"); + fullMoonEnabled = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Enabled"); + playerRideOwnFlow = config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.PlayerRideOwnFlow"); + size = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.Normal"); + avatarSize = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.AvatarState"); + fullMoonSizeSmall = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonSmall"); + fullMoonSizeLarge = config.getInt("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonLarge"); + + applyModifiers(); + } + + private void applyModifiers() { + if (isNight(player.getWorld())) { + maxRange = (int) getNightFactor(maxRange); + cooldown -= ((long) getNightFactor(cooldown) - cooldown); + } + } + + public static List getNearbySources(Block block, int searchRange) { + List sources = new ArrayList<>(); + for (Location l : GeneralMethods.getCircle(block.getLocation(), searchRange, 2, false, false, -1)) { + Block blockI = l.getBlock(); + if (isWater(block)) { + if (blockI.getType() == Material.WATER && JCMethods.isLiquidSource(blockI) && WaterManipulation.canPhysicsChange(blockI)) { + sources.add(blockI); + } + } + if (isLava(block)) { + if (blockI.getType() == Material.LAVA && JCMethods.isLiquidSource(blockI) && WaterManipulation.canPhysicsChange(blockI)) { + sources.add(blockI); + } + } + } + return sources; + } + + private boolean prepare() { + sourceBlock = BlockSource.getWaterSourceBlock(player, sourceRange, ClickType.SHIFT_DOWN, true, bPlayer.canIcebend(), canUsePlants); + if (sourceBlock != null) { + boolean isGoodSource = GeneralMethods.isAdjacentToThreeOrMoreSources(sourceBlock, false) || (TempBlock.isTempBlock(sourceBlock) && WaterAbility.isBendableWaterTempBlock(sourceBlock)); + + // canUsePlants needs to be checked here due to a bug with PK dynamic source caching. + // getWaterSourceBlock can return a plant even if canUsePlants is passed as false. + if (isGoodSource || (canUsePlants && isPlant(sourceBlock))) { + head = sourceBlock.getLocation().clone(); + origin = sourceBlock.getLocation().clone(); + if (isPlant(sourceBlock)) { + new PlantRegrowth(player, sourceBlock); + } + return true; + } + } + + if (canUseBottle && WaterReturn.hasWaterBottle(player)){ + Location eye = player.getEyeLocation(); + Location forward = eye.clone().add(eye.getDirection()); + + if (isTransparent(eye.getBlock()) && isTransparent(forward.getBlock())) { + head = forward.clone(); + origin = forward.clone(); + usingBottle = true; + WaterReturn.emptyWaterBottle(player); + return true; + } + } + return false; + } + + @SuppressWarnings("deprecation") + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreBinds(this) || !bPlayer.canBendIgnoreCooldowns(getAbility("WaterManipulation"))) { + remove(); + return; + } + if (duration > 0 && System.currentTimeMillis() > time + duration) { + remove(); + return; + } + if ((stayAtSource && player.getLocation().distance(origin) >= stayRange) || head.getY() > head.getWorld().getMaxHeight() || head.getY() < head.getWorld().getMinHeight()) { + remove(); + return; + } + if (RegionProtection.isRegionProtected(player, head, this)) { + remove(); + return; + } + if (AirAbility.isWithinAirShield(head)) { + remove(); + return; + } + if (prevHealth > player.getHealth()) { + remove(); + return; + } + + if (removeOnAnyDamage) { + // Only update the previous health if any damage should remove it. + prevHealth = player.getHealth(); + } + + if (!frozen) { + if (player.isSneaking()) { + if (range >= minRange) { + range -= 2; + } + //BlockSource.update(player, sourceRange, ClickType.RIGHT_CLICK); + } else { + if (range < maxRange) { + range += 2; + } + } + moveWater(); + //updateBlocks(); + manageLength(); + } + } + + private void manageLength() { + int pos = 0; + int ids = 0; + List tempList = new ArrayList<>(blocks); + for (Block block : tempList) { + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(block.getLocation(), 2.8)) { + if (entity.getEntityId() == player.getEntityId() && !playerRideOwnFlow) { + continue; + } + boolean isPlayer = entity instanceof Player; + if (isPlayer) { + if (getPlayers(AirSpout.class).contains(entity)) { + continue; + } else if (getPlayers(WaterSpout.class).contains(entity)) { + continue; + } else if (getPlayers(Catapult.class).contains(entity)) { + continue; + } + } + if (RegionProtection.isRegionProtected(this, entity.getLocation()) || (isPlayer && Commands.invincible.contains(entity.getName()))) { + continue; + } + Location temp = directions.get(block); + Vector dir = GeneralMethods.getDirection(entity.getLocation(), directions.get(block).add(temp.getDirection().multiply(1.5))); + GeneralMethods.setVelocity(this, entity, dir.clone().normalize().multiply(1)); + entity.setFallDistance(0f); + } + + if (!MaterialUtil.isTransparent(block) || RegionProtection.isRegionProtected(player, block.getLocation(), "Torrent")) { + blocks.remove(block); + directions.remove(block); + if (TempBlock.isTempBlock(block)) { + TempBlock.revertBlock(block, Material.AIR); + } + } else { + if (!isWater(block)) { + new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0))); + } + } + pos++; + if (pos > trail) { + ids++; + } + } + for (int i = 0; i < ids; i++) { + if (i >= blocks.size()) { + break; + } + Block block = blocks.get(i); + blocks.remove(block); + directions.remove(block); + if (TempBlock.isTempBlock(block)) { + TempBlock.revertBlock(block, Material.AIR); + } + } + tempList.clear(); + } + + private void moveWater() { + if (!MaterialUtil.isTransparent(head.getBlock()) || RegionProtection.isRegionProtected(player, head, "Torrent")) { + range -= 2; + } + Vector direction = GeneralMethods.getDirection(head, GeneralMethods.getTargetedLocation(player, range, Material.WATER)).normalize(); + head = head.add(direction.clone().multiply(1)); + head.setDirection(direction); + playWaterbendingSound(head); + for (Block block : GeneralMethods.getBlocksAroundPoint(head, headSize)) { + if (directions.containsKey(block)) { + directions.replace(block, head.clone()); + } else { + directions.put(block, head.clone()); + blocks.add(block); + } + } + } + + private void removeBlocks() { + for (Block block : directions.keySet()) { + if (TempBlock.isTempBlock(block)) { + TempBlock.revertBlock(block, Material.AIR); + } + } + } + + public static void freeze(Player player) { + if (hasAbility(player, WaterFlow.class)) { + WaterFlow wf = getAbility(player, WaterFlow.class); + if (!wf.bPlayer.canIcebend()) return; + if (!wf.frozen) { + wf.bPlayer.addCooldown(wf); + wf.freeze(); + } + } + } + + private void freeze() { + frozen = true; + for (Block block : directions.keySet()) { + if (TempBlock.isTempBlock(block)) { + if (rand.nextInt(5) == 0) { + playIcebendingSound(block.getLocation()); + } + new RegenTempBlock(block, Material.ICE, Material.ICE.createBlockData(), randInt((int) meltDelay - 250, (int) meltDelay + 250)); + } + } + } + + public int randInt(int min, int max) { + return rand.nextInt(max - min) + min; + } + + @Override + public void remove() { + if (player.isOnline() && cooldown > 0) { + bPlayer.addCooldown(this); + } + if (!frozen) { + removeBlocks(); + } + + if (usingBottle) { + new WaterReturn(player, head.getBlock()); + } + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return head; + } + + @Override + public String getName() { + return "WaterFlow"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public Object createNewComboInstance(Player player) { + return new WaterFlow(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.WaterFlow.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Water.WaterCombo.WaterFlow.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.WaterCombo.WaterFlow.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public int getSourceRange() { + return sourceRange; + } + + public void setSourceRange(int sourceRange) { + this.sourceRange = sourceRange; + } + + public int getMaxRange() { + return maxRange; + } + + public void setMaxRange(int maxRange) { + this.maxRange = maxRange; + } + + public int getMinRange() { + return minRange; + } + + public void setMinRange(int minRange) { + this.minRange = minRange; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getMeltDelay() { + return meltDelay; + } + + public void setMeltDelay(long meltDelay) { + this.meltDelay = meltDelay; + } + + public long getTrail() { + return trail; + } + + public void setTrail(long trail) { + this.trail = trail; + } + + public boolean isAvatar() { + return avatar; + } + + public void setAvatar(boolean avatar) { + this.avatar = avatar; + } + + public boolean isStayAtSource() { + return stayAtSource; + } + + public void setStayAtSource(boolean stayAtSource) { + this.stayAtSource = stayAtSource; + } + + public int getStayRange() { + return stayRange; + } + + public void setStayRange(int stayRange) { + this.stayRange = stayRange; + } + + public boolean isFullMoonEnabled() { + return fullMoonEnabled; + } + + public void setFullMoonEnabled(boolean fullMoonEnabled) { + this.fullMoonEnabled = fullMoonEnabled; + } + + public int getFullMoonCooldown() { + return fullMoonCooldown; + } + + public void setFullMoonCooldown(int fullMoonCooldown) { + this.fullMoonCooldown = fullMoonCooldown; + } + + public int getFullMoonDuration() { + return fullMoonDuration; + } + + public void setFullMoonDuration(int fullMoonDuration) { + this.fullMoonDuration = fullMoonDuration; + } + + public boolean isPlayerRideOwnFlow() { + return playerRideOwnFlow; + } + + public void setPlayerRideOwnFlow(boolean playerRideOwnFlow) { + this.playerRideOwnFlow = playerRideOwnFlow; + } + + public int getSize() { + return size; + } + + public void setSize(int size) { + this.size = size; + } + + public int getAvatarSize() { + return avatarSize; + } + + public void setAvatarSize(int avatarSize) { + this.avatarSize = avatarSize; + } + + public int getFullMoonSizeSmall() { + return fullMoonSizeSmall; + } + + public void setFullMoonSizeSmall(int fullMoonSizeSmall) { + this.fullMoonSizeSmall = fullMoonSizeSmall; + } + + public int getFullMoonSizeLarge() { + return fullMoonSizeLarge; + } + + public void setFullMoonSizeLarge(int fullMoonSizeLarge) { + this.fullMoonSizeLarge = fullMoonSizeLarge; + } + + public long getAvatarDuration() { + return avatarDuration; + } + + public void setAvatarDuration(long avatarDuration) { + this.avatarDuration = avatarDuration; + } + + public boolean isCanUseBottle() { + return canUseBottle; + } + + public void setCanUseBottle(boolean canUseBottle) { + this.canUseBottle = canUseBottle; + } + + public boolean isCanUsePlants() { + return canUsePlants; + } + + public void setCanUsePlants(boolean canUsePlants) { + this.canUsePlants = canUsePlants; + } + + public boolean isRemoveOnAnyDamage() { + return removeOnAnyDamage; + } + + public void setRemoveOnAnyDamage(boolean removeOnAnyDamage) { + this.removeOnAnyDamage = removeOnAnyDamage; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public Location getHead() { + return head; + } + + public void setHead(Location head) { + this.head = head; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public Block getSourceBlock() { + return sourceBlock; + } + + public void setSourceBlock(Block sourceBlock) { + this.sourceBlock = sourceBlock; + } + + public boolean isFrozen() { + return frozen; + } + + public void setFrozen(boolean frozen) { + this.frozen = frozen; + } + + public double getPrevHealth() { + return prevHealth; + } + + public void setPrevHealth(double prevHealth) { + this.prevHealth = prevHealth; + } + + public int getHeadSize() { + return headSize; + } + + public void setHeadSize(int headSize) { + this.headSize = headSize; + } + + public boolean isUsingBottle() { + return usingBottle; + } + + public void setUsingBottle(boolean usingBottle) { + this.usingBottle = usingBottle; + } + + public ConcurrentHashMap getDirections() { + return directions; + } + + public List getBlocks() { + return blocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.WaterCombo.WaterFlow.Enabled"); + } +} diff --git a/src/ability/waterbending/combo/WaterGimbal.java b/src/ability/waterbending/combo/WaterGimbal.java new file mode 100644 index 0000000..6fe64ca --- /dev/null +++ b/src/ability/waterbending/combo/WaterGimbal.java @@ -0,0 +1,649 @@ +package com.jedk1.jedcore.ability.waterbending.combo; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.ability.waterbending.WaterBlast; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.CollisionInitializer; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.WaterManipulation; +import com.projectkorra.projectkorra.waterbending.Torrent; + +import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; +import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; +import com.projectkorra.projectkorra.waterbending.util.WaterReturn; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +public class WaterGimbal extends WaterAbility implements AddonAbility, ComboAbility { + + @Attribute(Attribute.SELECT_RANGE) + private int sourceRange; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("Width") + private double ringSize; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.SPEED) + private double speed; + private int animSpeed; + private boolean plantSourcing; + private boolean snowSourcing; + private boolean requireAdjacentPlants; + private boolean canUseBottle; + private double abilityCollisionRadius; + private double entityCollisionRadius; + + private int step; + private boolean initializing; + private boolean leftVisible = true; + private boolean rightVisible = true; + private boolean rightConsumed = false; + private boolean leftConsumed = false; + private Block sourceBlock; + private TempBlock source; + private Location sourceLoc; + private Location origin1; + private Location origin2; + private boolean usingBottle; + + private final Random rand = new Random(); + + static { + CollisionInitializer.abilityMap.put("WaterGimbal", ""); + } + + public WaterGimbal(Player player) { + super(player); + if (!bPlayer.canBendIgnoreBinds(this)) { + return; + } + if (JCMethods.isLunarEclipse(player.getWorld())) { + return; + } + if (hasAbility(player, WaterGimbal.class)) { + return; + } + setFields(); + usingBottle = false; + if (grabSource()) { + start(); + initializing = true; + if (hasAbility(player, Torrent.class)) { + getAbility(player, Torrent.class).remove(); + } + if (hasAbility(player, WaterManipulation.class)) { + getAbility(player, WaterManipulation.class).remove(); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + sourceRange = config.getInt("Abilities.Water.WaterCombo.WaterGimbal.SourceRange"); + cooldown = config.getLong("Abilities.Water.WaterCombo.WaterGimbal.Cooldown"); + ringSize = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.RingSize"); + range = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.Range"); + damage = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.Damage"); + speed = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.Speed"); + animSpeed = config.getInt("Abilities.Water.WaterCombo.WaterGimbal.AnimationSpeed"); + plantSourcing = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.PlantSource"); + snowSourcing = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.SnowSource"); + requireAdjacentPlants = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.RequireAdjacentPlants"); + canUseBottle = config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.BottleSource"); + abilityCollisionRadius = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.AbilityCollisionRadius"); + entityCollisionRadius = config.getDouble("Abilities.Water.WaterCombo.WaterGimbal.EntityCollisionRadius"); + + applyModifiers(); + } + + private void applyModifiers() { + cooldown -= ((long) getNightFactor(cooldown) - cooldown); + range = getNightFactor(range); + damage = getNightFactor(damage); + } + + @Override + public void progress() { + if (player == null || player.isDead() || !player.isOnline() || !player.isSneaking()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreBinds(this) || !bPlayer.canBendIgnoreCooldowns(getAbility("WaterManipulation"))) { + remove(); + return; + } + if (hasAbility(player, WaterManipulation.class)) { + getAbility(player, WaterManipulation.class).remove(); + } + if (leftConsumed && rightConsumed) { + remove(); + return; + } + if (!initializing) { + getGimbalBlocks(player.getLocation()); + if (!leftVisible && !leftConsumed && origin1 != null) { + if (origin1.getBlockY() <= player.getEyeLocation().getBlockY()) { + new WaterBlast(player, origin1, range, damage, speed, entityCollisionRadius, abilityCollisionRadius, this); + leftConsumed = true; + } + } + + if (!rightVisible && !rightConsumed && origin2 != null) { + if (origin2.getBlockY() <= player.getEyeLocation().getBlockY()) { + new WaterBlast(player, origin2, range, damage, speed, entityCollisionRadius, abilityCollisionRadius, this); + rightConsumed = true; + } + } + } else { + Vector direction = GeneralMethods.getDirection(sourceLoc, player.getEyeLocation()); + sourceLoc = sourceLoc.add(direction.multiply(1).normalize()); + + if (source == null || !sourceLoc.getBlock().getLocation().equals(source.getLocation())) { + if (source != null) { + source.revertBlock(); + } + if (isTransparent(sourceLoc.getBlock())) { + source = new TempBlock(sourceLoc.getBlock(), Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0))); + } + } + + if (source != null && source.getLocation().distance(player.getLocation()) < 2.5) { + source.revertBlock(); + initializing = false; + } + } + } + + private boolean grabSource() { + sourceBlock = BlockSource.getWaterSourceBlock(player, sourceRange, ClickType.SHIFT_DOWN, true, true, plantSourcing, snowSourcing, false); + if (sourceBlock != null) { + // All of these extra checks need to be done because PK sourcing system is buggy. + boolean usingSnow = snowSourcing && (sourceBlock.getType() == Material.SNOW_BLOCK || sourceBlock.getType() == Material.SNOW); + + if (isPlant(sourceBlock) || usingSnow) { + if (usingSnow || !requireAdjacentPlants || JCMethods.isAdjacentToThreeOrMoreSources(sourceBlock, sourceBlock.getType())) { + playFocusWaterEffect(sourceBlock); + sourceLoc = sourceBlock.getLocation(); + + new PlantRegrowth(this.player, sourceBlock); + sourceBlock.setType(Material.AIR); + + return true; + } + } else if (!ElementalAbility.isSnow(sourceBlock)) { + boolean isTempBlock = TempBlock.isTempBlock(sourceBlock); + + if (GeneralMethods.isAdjacentToThreeOrMoreSources(sourceBlock, false) || (isTempBlock && WaterAbility.isBendableWaterTempBlock(sourceBlock))) { + playFocusWaterEffect(sourceBlock); + sourceLoc = sourceBlock.getLocation(); + + if (isTempBlock) { + PhaseChange.thaw(sourceBlock); + } + + return true; + } + } + } + + // Try to use bottles if no source blocks nearby. + // todo: works the first time, requires actual sources and still consumes water bottle afterwards + if (canUseBottle && hasWaterBottle(player)){ + Location eye = player.getEyeLocation(); + Location forward = eye.clone().add(eye.getDirection()); + + if (isTransparent(eye.getBlock()) && isTransparent(forward.getBlock())) { + sourceLoc = forward; + sourceBlock = sourceLoc.getBlock(); + usingBottle = true; + WaterReturn.emptyWaterBottle(player); + return true; + } + } + return false; + } + + // Custom function to see if player has bottle. + // This is to get around the WaterReturn limitation since OctopusForm will currently be using the bottle. + private boolean hasWaterBottle(Player player) { + PlayerInventory inventory = player.getInventory(); + return JedCore.plugin.getPotionEffectAdapter().hasWaterPotion(inventory); + } + + public static void prepareBlast(Player player) { + if (hasAbility(player, WaterGimbal.class)) { + getAbility(player, WaterGimbal.class).prepareBlast(); + if (hasAbility(player, WaterManipulation.class)) { + getAbility(player, WaterManipulation.class).remove(); + } + } + } + + public void prepareBlast() { + if (leftVisible) { + leftVisible = false; + return; + } + if (rightVisible) { + rightVisible = false; + } + } + + private void getGimbalBlocks(Location location) { + List ring1 = new ArrayList<>(); + List ring2 = new ArrayList<>(); + Location l = location.clone().add(0, 1, 0); + int count = 0; + + while (count < animSpeed) { + boolean completed = false; + double velocity = 0.15; + double angle = 3.0 + this.step * velocity; + double xRotation = Math.PI / 2.82 * 2.1; + Vector v1 = new Vector(Math.cos(angle), Math.sin(angle), 0.0D).multiply(ringSize); + Vector v2 = new Vector(Math.cos(angle), Math.sin(angle), 0.0D).multiply(ringSize); + rotateAroundAxisX(v1, xRotation); + rotateAroundAxisX(v2, -xRotation); + rotateAroundAxisY(v1, -((location.getYaw() * Math.PI / 180) - 1.575)); + rotateAroundAxisY(v2, -((location.getYaw() * Math.PI / 180) - 1.575)); + + if (!ring1.contains(l.clone().add(v1).getBlock()) && !leftConsumed) { + completed = true; + Block block = l.clone().add(v1).getBlock(); + if (isTransparent(block)) { + ring1.add(block); + } else { + for (int i = 0; i < 4; i++) { + if (isTransparent(block.getRelative(BlockFace.UP, i))) { + ring1.add(block.getRelative(BlockFace.UP, i)); + break; + } + } + } + } + + if (!ring2.contains(l.clone().add(v2).getBlock()) && !rightConsumed) { + completed = true; + Block block = l.clone().add(v2).getBlock(); + if (isTransparent(block)) { + ring2.add(block); + } else { + for (int i = 0; i < 4; i++) { + if (isTransparent(block.getRelative(BlockFace.UP, i))) { + ring2.add(block.getRelative(BlockFace.UP, i)); + break; + } + } + } + } + + if (completed) { + count++; + } + + if (leftConsumed && rightConsumed) { + break; + } + + this.step++; + } + + if (!leftConsumed) { + if (!ring1.isEmpty()) { + Collections.reverse(ring1); + origin1 = ring1.get(0).getLocation(); + } + for (Block block : ring1) { + new RegenTempBlock(block, Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 150L); + if (rand.nextInt(10) == 0) { + playWaterbendingSound(block.getLocation()); + } + } + } + + if (!rightConsumed) { + if (!ring2.isEmpty()) { + Collections.reverse(ring2); + origin2 = ring2.get(0).getLocation(); + } + for (Block block : ring2) { + new RegenTempBlock(block, Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(0)), 150L); + if (rand.nextInt(10) == 0) { + playWaterbendingSound(block.getLocation()); + } + } + } + } + + private void rotateAroundAxisX(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double y = v.getY() * cos - v.getZ() * sin; + double z = v.getY() * sin + v.getZ() * cos; + v.setY(y).setZ(z); + } + + private void rotateAroundAxisY(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double x = v.getX() * cos + v.getZ() * sin; + double z = v.getX() * -sin + v.getZ() * cos; + v.setX(x).setZ(z); + } + + @Override + public void remove() { + if (source != null) { + source.revertBlock(); + } + if (player.isOnline() && !initializing) { + bPlayer.addCooldown(this); + } + + if (usingBottle) { + new WaterReturn(player, sourceBlock); + } + super.remove(); + } + + public Player getPlayer() { + return player; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "WaterGimbal"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public Object createNewComboInstance(Player player) { + return new WaterGimbal(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.WaterGimbal.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Water.WaterCombo.WaterGimbal.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.WaterCombo.WaterGimbal.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public int getSourceRange() { + return sourceRange; + } + + public void setSourceRange(int sourceRange) { + this.sourceRange = sourceRange; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public double getRingSize() { + return ringSize; + } + + public void setRingSize(double ringSize) { + this.ringSize = ringSize; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public int getAnimSpeed() { + return animSpeed; + } + + public void setAnimSpeed(int animSpeed) { + this.animSpeed = animSpeed; + } + + public boolean isPlantSourcing() { + return plantSourcing; + } + + public void setPlantSourcing(boolean plantSourcing) { + this.plantSourcing = plantSourcing; + } + + public boolean isSnowSourcing() { + return snowSourcing; + } + + public void setSnowSourcing(boolean snowSourcing) { + this.snowSourcing = snowSourcing; + } + + public boolean isRequireAdjacentPlants() { + return requireAdjacentPlants; + } + + public void setRequireAdjacentPlants(boolean requireAdjacentPlants) { + this.requireAdjacentPlants = requireAdjacentPlants; + } + + public boolean isCanUseBottle() { + return canUseBottle; + } + + public void setCanUseBottle(boolean canUseBottle) { + this.canUseBottle = canUseBottle; + } + + public double getAbilityCollisionRadius() { + return abilityCollisionRadius; + } + + public void setAbilityCollisionRadius(double abilityCollisionRadius) { + this.abilityCollisionRadius = abilityCollisionRadius; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public boolean isInitializing() { + return initializing; + } + + public void setInitializing(boolean initializing) { + this.initializing = initializing; + } + + public boolean isLeftVisible() { + return leftVisible; + } + + public void setLeftVisible(boolean leftVisible) { + this.leftVisible = leftVisible; + } + + public boolean isRightVisible() { + return rightVisible; + } + + public void setRightVisible(boolean rightVisible) { + this.rightVisible = rightVisible; + } + + public boolean isRightConsumed() { + return rightConsumed; + } + + public void setRightConsumed(boolean rightConsumed) { + this.rightConsumed = rightConsumed; + } + + public boolean isLeftConsumed() { + return leftConsumed; + } + + public void setLeftConsumed(boolean leftConsumed) { + this.leftConsumed = leftConsumed; + } + + public Block getSourceBlock() { + return sourceBlock; + } + + public void setSourceBlock(Block sourceBlock) { + this.sourceBlock = sourceBlock; + } + + public TempBlock getSource() { + return source; + } + + public void setSource(TempBlock source) { + this.source = source; + } + + public Location getSourceLoc() { + return sourceLoc; + } + + public void setSourceLoc(Location sourceLoc) { + this.sourceLoc = sourceLoc; + } + + public Location getOrigin1() { + return origin1; + } + + public void setOrigin1(Location origin1) { + this.origin1 = origin1; + } + + public Location getOrigin2() { + return origin2; + } + + public void setOrigin2(Location origin2) { + this.origin2 = origin2; + } + + public boolean isUsingBottle() { + return usingBottle; + } + + public void setUsingBottle(boolean usingBottle) { + this.usingBottle = usingBottle; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.WaterCombo.WaterGimbal.Enabled"); + } +} diff --git a/src/command/Commands.java b/src/command/Commands.java new file mode 100644 index 0000000..1c23a38 --- /dev/null +++ b/src/command/Commands.java @@ -0,0 +1,9 @@ +package com.jedk1.jedcore.command; + + +public class Commands { + + public Commands() { + new JedCoreCommand(); + } +} diff --git a/src/command/JedCoreCommand.java b/src/command/JedCoreCommand.java new file mode 100644 index 0000000..b4b750a --- /dev/null +++ b/src/command/JedCoreCommand.java @@ -0,0 +1,65 @@ +package com.jedk1.jedcore.command; + +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.command.PKCommand; + +public class JedCoreCommand extends PKCommand { + + private static final String DOWNLOAD_URL = "https://github.com/Hihelloy-main/JedCore"; + + private static final Set DEVELOPERS = Set.of( + UUID.fromString("4eb6315e-9dd1-49f7-b582-c1170e497ab0"), // jedk1 + UUID.fromString("d57565a5-e6b0-44e3-a026-979d5de10c4d"), // s3xi + UUID.fromString("e98a2f7d-d571-4900-a625-483cbe6774fe"), // Aztl + UUID.fromString("b1318b21-5956-445c-a328-bad3175c1c7a") // Hihelloy + ); + + public JedCoreCommand() { + super("jedcore", "/bending jedcore", "This command shows the JedCore version and debug info.", new String[] { "jedcore", "jc" }); + } + + @Override + public void execute(CommandSender sender, List args) { + if (!correctLength(sender, args.size(), 0, 1) || (!hasPermission(sender) && !isSenderJedCoreDev(sender))) { + return; + } + + if (args.isEmpty()) { + sendBuildInfo(sender); + return; + } + + if (args.size() == 1 && (hasPermission(sender, "debug") || isSenderJedCoreDev(sender))) { + if (args.get(0).equalsIgnoreCase("refresh")) { + sender.sendMessage(ChatColor.AQUA + "JedCore refreshed."); + return; + } + } + + help(sender, false); + } + + public static void sendBuildInfo(CommandSender sender) { + sender.sendMessage(ChatColor.GRAY + "Running JedCore Build: " + ChatColor.RED + JedCore.plugin.getDescription().getVersion()); + sender.sendMessage(ChatColor.GRAY + "Developed by: " + ChatColor.RED + String.join(", ", JedCore.plugin.getDescription().getAuthors())); + sender.sendMessage(ChatColor.GRAY + "Modified by: " + ChatColor.RED + "plushmonkey"); + sender.sendMessage(ChatColor.GRAY + "Maintained by: " + ChatColor.RED + "Cozmyc"); + sender.sendMessage(ChatColor.GRAY + "Updated by: " + ChatColor.RED + "Hihelloy"); + sender.sendMessage(ChatColor.GRAY + "URL: " + ChatColor.RED + ChatColor.ITALIC + DOWNLOAD_URL); + } + + private boolean isSenderJedCoreDev(CommandSender sender) { + if (sender instanceof Player player) { + return DEVELOPERS.contains(player.getUniqueId()); + } + return false; + } +} diff --git a/src/configuration/Config.java b/src/configuration/Config.java new file mode 100644 index 0000000..d4c427b --- /dev/null +++ b/src/configuration/Config.java @@ -0,0 +1,67 @@ +package com.jedk1.jedcore.configuration; + +import com.jedk1.jedcore.JedCore; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; + +public class Config { + + JedCore plugin; + + private File file; + public FileConfiguration config; + + public Config(File file) { + this.plugin = JedCore.plugin; + this.file = new File(plugin.getDataFolder() + File.separator + file); + this.config = YamlConfiguration.loadConfiguration(this.file); + reloadConfig(); + } + + public void createConfig() { + if (!file.getParentFile().exists()) { + try { + file.getParentFile().mkdir(); + plugin.getLogger().info("Generating new directory for " + file.getName() + "!"); + } catch (Exception e) { + plugin.getLogger().info("Failed to generate directory!"); + e.printStackTrace(); + } + } + + if (!file.exists()) { + try { + file.createNewFile(); + plugin.getLogger().info("Generating new " + file.getName() + "!"); + } catch (Exception e) { + plugin.getLogger().info("Failed to generate " + file.getName() + "!"); + e.printStackTrace(); + } + } + } + + public FileConfiguration getConfig() { + return config; + } + + public void reloadConfig() { + createConfig(); + try { + config.load(file); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void saveConfig() { + try { + config.options().copyDefaults(true); + config.save(file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/configuration/JedCoreConfig.java b/src/configuration/JedCoreConfig.java new file mode 100644 index 0000000..1983fd8 --- /dev/null +++ b/src/configuration/JedCoreConfig.java @@ -0,0 +1,1069 @@ +package com.jedk1.jedcore.configuration; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.configuration.ConfigManager; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; + +public class JedCoreConfig { + + static JedCore plugin; + public static Config board; + private static final String path = "ExtraAbilities.Hihelloy.BloodShot."; + + public JedCoreConfig(JedCore plugin) { + JedCoreConfig.plugin = plugin; + board = new Config(new File("board.yml")); + loadConfigBoard(); + loadConfigCore(); + addDeathMessages(); + setupElementSphereNames(); + } + + private void loadConfigBoard() { + FileConfiguration config; + config = board.getConfig(); + config.addDefault("Settings.Enabled", false); + config.options().copyDefaults(true); + board.saveConfig(); + } + + private void loadConfigCore() { + FileConfiguration config; + config = JedCore.plugin.getConfig(); + + config.addDefault("Settings.Updater.Check", true); + config.addDefault("Settings.Updater.Notify", true); + config.addDefault("Properties.MobCollisions.Enabled", true); + config.addDefault("Properties.AbilityCollisions.Enabled", true); + config.addDefault("Properties.PerWorldConfig", true); + config.addDefault("Properties.FireTickMethod", "larger"); + config.addDefault("Properties.LogDebug", false); + + config.addDefault("Properties.ChiRestrictor.Enabled", false); + config.addDefault("Properties.ChiRestrictor.ResetCooldown", true); + config.addDefault("Properties.ChiRestrictor.MeleeDistance", 7); + config.addDefault("Properties.ChiRestrictor.Whitelist", new ArrayList()); + + config.addDefault("Properties.Fire.DynamicLight.Enabled", true); + config.addDefault("Properties.Fire.DynamicLight.Brightness", 13); + config.addDefault("Properties.Fire.DynamicLight.KeepAlive", 600); + + config.addDefault("Abilities.Avatar.ElementSphere.Enabled", true); + config.addDefault("Abilities.Avatar.ElementSphere.Description", "ElementSphere is a very all round ability, being " + + "able to shoot attacks of each element, each with a " + + "different effect. To use, simply Left-Click. Once active, " + + "Sneak (Default: Shift) to fly around. Sneak and double " + + "Left-Click to disable the ability! " + + "To use each element, simply select hotbar slots 1-4 and Left-Click. " + + "Each element has limited uses! Once an element is used up, " + + "the element's ring will disappear!"); + config.addDefault("Abilities.Avatar.ElementSphere.Cooldown", 180000); + config.addDefault("Abilities.Avatar.ElementSphere.Duration", 60000); + config.addDefault("Abilities.Avatar.ElementSphere.MaxControlledHeight", 40); + config.addDefault("Abilities.Avatar.ElementSphere.FlySpeed", 1.5); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Knockback", 2); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Speed", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactRevert", 15000); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.BurnDuration", 3000); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Speed", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Controllable", false); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Speed", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Knockback", 2.0); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Damage", 12.0); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.RequiredUses", 10); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.EndAbility", true); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactCraterSize", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactRevert", 30000); + + config.addDefault("Abilities.Avatar.SpiritBeam.Enabled", true); + config.addDefault("Abilities.Avatar.SpiritBeam.Description", "An energybending ability usable by the Avatar. " + + "To use, one must enter the AvatarState and hold down Sneak (Default: Shift). " + + "This ability lasts only for a few seconds before requiring " + + "another activation."); + config.addDefault("Abilities.Avatar.SpiritBeam.Cooldown", 15000); + config.addDefault("Abilities.Avatar.SpiritBeam.Duration", 1000); + config.addDefault("Abilities.Avatar.SpiritBeam.Range", 40); + config.addDefault("Abilities.Avatar.SpiritBeam.Damage", 10.0); + config.addDefault("Abilities.Avatar.SpiritBeam.AvatarStateOnly", true); + config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Enabled", true); + config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Radius", 3); + config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Regen", 20000); + + config.addDefault("Abilities.Air.AirBlade.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.Description", "With this ability bound, Left-Click to shoot " + + "a strong blade of air at your targets to deal some damage!"); + config.addDefault("Abilities.Air.AirBlade.Cooldown", 3000); + config.addDefault("Abilities.Air.AirBlade.Range", 30.0); + config.addDefault("Abilities.Air.AirBlade.Damage", 4.0); + config.addDefault("Abilities.Air.AirBlade.EntityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirBlade.AbilityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.Enabled",true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveFirst",true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveSecond",true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.Enabled",true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveFirst",true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveSecond",false); + + config.addDefault("Abilities.Air.AirBreath.Enabled", true); + config.addDefault("Abilities.Air.AirBreath.Description", "To use, hold Sneak (Default: Shift) to release " + + "a strong breath of wind, knocking your opponents " + + "back. This ability also has a longer range and " + + "stronger knockback while in AvatarState!"); + config.addDefault("Abilities.Air.AirBreath.Cooldown", 3000); + config.addDefault("Abilities.Air.AirBreath.Duration", 3000); + config.addDefault("Abilities.Air.AirBreath.Particles", 3); + config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Lava", true); + config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Fire", true); + config.addDefault("Abilities.Air.AirBreath.ExtinguishEntities", true); + config.addDefault("Abilities.Air.AirBreath.Damage.Enabled", false); + config.addDefault("Abilities.Air.AirBreath.Damage.Player", 1.0); + config.addDefault("Abilities.Air.AirBreath.Damage.Mob", 2.0); + config.addDefault("Abilities.Air.AirBreath.Knockback", 0.8); + config.addDefault("Abilities.Air.AirBreath.Range", 10); + config.addDefault("Abilities.Air.AirBreath.LaunchPower", 1.0); + config.addDefault("Abilities.Air.AirBreath.RegenTargetOxygen", true); + config.addDefault("Abilities.Air.AirBreath.Avatar.Enabled", true); + config.addDefault("Abilities.Air.AirBreath.Avatar.Range", 20); + config.addDefault("Abilities.Air.AirBreath.Avatar.Knockback", 3.5); + + config.addDefault("Abilities.Air.AirGlide.Enabled", true); + config.addDefault("Abilities.Air.AirGlide.Description", "While falling, tap Sneak for a " + + "slow and steady descent. Tap Sneak again to stop gliding."); + config.addDefault("Abilities.Air.AirGlide.Speed", 0.5); + config.addDefault("Abilities.Air.AirGlide.FallSpeed", 0.1); + config.addDefault("Abilities.Air.AirGlide.Particles", 4); + config.addDefault("Abilities.Air.AirGlide.AllowAirSpout", false); + config.addDefault("Abilities.Air.AirGlide.Cooldown", 0); + config.addDefault("Abilities.Air.AirGlide.Duration", 0); + config.addDefault("Abilities.Air.AirGlide.RequireGround", false); + + config.addDefault("Abilities.Air.AirPunch.Enabled", true); + config.addDefault("Abilities.Air.AirPunch.Description", "Left-Click in rapid succession to punch high desnity packets of air " + + "at enemies to do slight damage. A few punches can be thrown before the ability goes on cooldown."); + config.addDefault("Abilities.Air.AirPunch.Cooldown", 5000); + config.addDefault("Abilities.Air.AirPunch.Threshold", 500); + config.addDefault("Abilities.Air.AirPunch.Shots", 4); + config.addDefault("Abilities.Air.AirPunch.Range", 30); + config.addDefault("Abilities.Air.AirPunch.Damage", 1.0); + config.addDefault("Abilities.Air.AirPunch.EntityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirPunch.AbilityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.Enabled", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveFirst", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveSecond", false); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.Enabled",true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveFirst",true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveSecond",false); + config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.Enabled", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveFirst", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveSecond", false); + + config.addDefault("Abilities.Air.Meditate.Enabled", true); + config.addDefault("Abilities.Air.Meditate.Description", "Hold Sneak (Default: Shift) to start meditating. " + + "After you have focused your energy, you will obtain several buffs."); + config.addDefault("Abilities.Air.Meditate.UnfocusMessage", "You have become unfocused due to taking damage!"); + config.addDefault("Abilities.Air.Meditate.LossFocusMessage", true); + config.addDefault("Abilities.Air.Meditate.ChargeTime", 5000); + config.addDefault("Abilities.Air.Meditate.Cooldown", 60000); + config.addDefault("Abilities.Air.Meditate.BoostDuration", 20000); + config.addDefault("Abilities.Air.Meditate.ParticleDensity", 5); + config.addDefault("Abilities.Air.Meditate.AbsorptionBoost", 2); + config.addDefault("Abilities.Air.Meditate.SpeedBoost", 3); + config.addDefault("Abilities.Air.Meditate.JumpBoost", 3); + + config.addDefault("Abilities.Air.SonicBlast.Enabled", true); + config.addDefault("Abilities.Air.SonicBlast.Description", "SonicBlast is a soundbending ability, known by very few airbenders. " + + "It allows the airbender to stun and deafen an opponent by creating a sonic blast. " + + "This is achieved by creating two regions of high and low pressure and bringing them together. " + + "To use, hold Sneak (Default: Shift) in the direction of the target. Once particles appear " + + "around you, let go of Sneak to shoot a SonicBlast at your target! The technique is very powerful, " + + "even if it doesn't seem it, and comes with a short cooldown."); + config.addDefault("Abilities.Air.SonicBlast.ChargeTime", 2000); + config.addDefault("Abilities.Air.SonicBlast.Damage", 4.0); + config.addDefault("Abilities.Air.SonicBlast.Effects.BlindnessDuration", 5000); + config.addDefault("Abilities.Air.SonicBlast.Effects.NauseaDuration", 5000); + config.addDefault("Abilities.Air.SonicBlast.Cooldown", 6000); + config.addDefault("Abilities.Air.SonicBlast.EntityCollisionRadius", 1.3); + config.addDefault("Abilities.Air.SonicBlast.AbilityCollisionRadius", 1.3); + config.addDefault("Abilities.Air.SonicBlast.Range", 20); + config.addDefault("Abilities.Air.SonicBlast.ChargeSwapping", true); + + config.addDefault("Abilities.Air.AirCombo.AirSlam.Enabled", true); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Description", "Kick your enemy up into the air then blast them away!"); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Cooldown", 8000); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Power", 5.0); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Range", 8); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Combination", Arrays.asList("AirSwipe:SHIFT_DOWN", "AirBlast:SHIFT_UP", "AirBlast:SHIFT_DOWN")); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Instructions", "AirSwipe (Hold sneak) > AirBlast (Release sneak) > AirBlast (Hold sneak)"); + + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Enabled", true); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Description", "Create a stream of air as you fly which causes nearby " + + "entities to be thrown in your direction."); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.DragFactor", 1.5); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Duration", 2000); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Cooldown", 6000); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Combination", Arrays.asList("Flight:SHIFT_DOWN", "Flight:SHIFT_UP", "Flight:SHIFT_DOWN", "Flight:SHIFT_UP")); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Instructions", "Flight (Double tap sneak)"); + + config.addDefault("Abilities.Earth.EarthArmor.Enabled", true); + config.addDefault("Abilities.Earth.EarthArmor.Description", "If the block is metal, then you will get metal armor!"); + config.addDefault("Abilities.Earth.EarthArmor.Resistance.Strength", 2); + config.addDefault("Abilities.Earth.EarthArmor.Resistance.Duration", 4000); + config.addDefault("Abilities.Earth.EarthArmor.UseIronArmor", false); + + config.addDefault("Abilities.Earth.EarthKick.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Description", "This move enables an earthbender to create a " + + "large earthen cover, ideal for defense. " + + "To use, Sneak (Default: Shift) at an earth " + + "source and it will raise and launch towards " + + "your foe!"); + config.addDefault("Abilities.Earth.EarthKick.Cooldown", 2000); + config.addDefault("Abilities.Earth.EarthKick.EarthBlocks", 10); + + double oldDamage = 0.0; + if (config.contains("Abilities.Earth.EarthKick.Damage")) { + oldDamage = config.getDouble("Abilities.Earth.EarthKick.Damage"); + config.set("Abilities.Earth.EarthKick.Damage", null); + } + + config.addDefault("Abilities.Earth.EarthKick.Damage.Normal", oldDamage > 0.0 ? oldDamage : 2.0); + config.addDefault("Abilities.Earth.EarthKick.Damage.Metal", 3.0); + config.addDefault("Abilities.Earth.EarthKick.EntityCollisionRadius", 1.5); + config.addDefault("Abilities.Earth.EarthKick.AbilityCollisionRadius", 1.5); + config.addDefault("Abilities.Earth.EarthKick.MultipleHits", true); + config.addDefault("Abilities.Earth.EarthKick.SourceRange", 2.0); + config.addDefault("Abilities.Earth.EarthKick.Spread", 20); + config.addDefault("Abilities.Earth.EarthKick.Velocity", 0.7); + config.addDefault("Abilities.Earth.EarthKick.AllowMetal", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveSecond", true); + + + config.addDefault("Abilities.Earth.EarthLine.Enabled", true); + config.addDefault("Abilities.Earth.EarthLine.Description", "To use, place your cursor over an earth-bendable block on the ground, " + + "then Sneak (Default: Shift) to select the block. After selecting the block you may release Sneak. " + + "If you then Left-Click at an object or player, a small piece of earth will come up " + + "from the ground and move towards your target to deal damage and knock them back. " + + "Additionally, hold Sneak to control the flow of the line!"); + config.addDefault("Abilities.Earth.EarthLine.Cooldown", 0); + config.addDefault("Abilities.Earth.EarthLine.PrepareCooldown", 3000); + config.addDefault("Abilities.Earth.EarthLine.Range", 30); + config.addDefault("Abilities.Earth.EarthLine.PrepareRange", 3); + config.addDefault("Abilities.Earth.EarthLine.SourceKeepRange", 7); + config.addDefault("Abilities.Earth.EarthLine.AffectingRadius", 2); + config.addDefault("Abilities.Earth.EarthLine.AllowChangeDirection", true); + config.addDefault("Abilities.Earth.EarthLine.MaxDuration", 2500); + config.addDefault("Abilities.Earth.EarthLine.Damage", 3.0); + config.addDefault("Abilities.Earth.EarthLine.RemovalPolicy.SwappedSlots.Enabled", false); + + config.addDefault("Abilities.Earth.EarthPillar.Enabled", true); + config.addDefault("Abilities.Earth.EarthPillar.Description", "With this ability bound, tap Sneak (Default: Shift) on any Earthbendable " + + "surface to create pillar of earth in the direction of the block face!"); + config.addDefault("Abilities.Earth.EarthPillar.Height", 6); + config.addDefault("Abilities.Earth.EarthPillar.Range", 10); + + config.addDefault("Abilities.Earth.EarthShard.Enabled", true); + config.addDefault("Abilities.Earth.EarthShard.Description", "EarthShard is a variation of EarthBlast " + + "which the earthbender may use to hit a target. This " + + "ability deals a fair amount of damage and is easy to " + + "rapid-fire. To use, simply shift at an earthbendable block, " + + "and it will ascend to your eye height. Then, click towards your " + + "target and the block will launch itself towards it."); + config.addDefault("Abilities.Earth.EarthShard.Cooldown", 1000); + config.addDefault("Abilities.Earth.EarthShard.Damage.Normal", 1.0); + config.addDefault("Abilities.Earth.EarthShard.Damage.Metal", 1.5); + config.addDefault("Abilities.Earth.EarthShard.PrepareRange", 5); + config.addDefault("Abilities.Earth.EarthShard.AbilityRange", 30); + config.addDefault("Abilities.Earth.EarthShard.MaxShards", 3); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Allow", true); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Velocity", 1.0); + config.addDefault("Abilities.Earth.EarthShard.AbilityCollisionRadius", 2.0); + config.addDefault("Abilities.Earth.EarthShard.EntityCollisionRadius", 1.4); + + config.addDefault("Abilities.Earth.EarthSurf.Enabled", true); + config.addDefault("Abilities.Earth.EarthSurf.Description", "This ability allows an earth bender to " + + "ride up on a wave of earth, allowing them to travel a little faster than " + + "normal. To use, simply be in the air just above " + + "the ground, and Left Click! Additionally, if an entity just so happens to get caught in " + + "the wave, they will be moved with the wave."); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Cooldown", 3000); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown", 2000); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Scaled", true); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Enabled", false); + config.addDefault("Abilities.Earth.EarthSurf.Duration.Duration", 7000); + config.addDefault("Abilities.Earth.EarthSurf.Duration.Enabled", false); + config.addDefault("Abilities.Earth.EarthSurf.RelaxedCollisions", true); + config.addDefault("Abilities.Earth.EarthSurf.RemoveOnAnyDamage", false); + config.addDefault("Abilities.Earth.EarthSurf.Speed", 0.55); + config.addDefault("Abilities.Earth.EarthSurf.HeightTolerance", 3); + config.addDefault("Abilities.Earth.EarthSurf.SpringStiffness", 0.35); + + config.addDefault("Abilities.Earth.Fissure.Enabled", true); + config.addDefault("Abilities.Earth.Fissure.Description", "Fissure is an advanced Lavabending " + + "ability enabling a lavabender to tear up the ground, " + + "swallowing up any enemies. To use, simply swing at an enemy " + + "and a line of lava will crack open. " + + "Then, tap Sneak (Default: Shift) to expand the crevice. " + + "The crevice has a maximum width and depth. Once the crevice has reached it's maximum " + + "width, Sneak while looking at the crevice to close it!"); + config.addDefault("Abilities.Earth.Fissure.Cooldown", 20000); + config.addDefault("Abilities.Earth.Fissure.Duration", 15000); + config.addDefault("Abilities.Earth.Fissure.MaxWidth", 3); + config.addDefault("Abilities.Earth.Fissure.SlapRange", 12); + config.addDefault("Abilities.Earth.Fissure.SlapDelay", 50); + + config.addDefault("Abilities.Earth.LavaDisc.Enabled", true); + config.addDefault("Abilities.Earth.LavaDisc.Description", "Hold Sneak (Default: Shift) on a lava source " + + "block to generate a disc of lava at your finger tips. Releasing " + + "Sneak will shoot the disc off in the direction " + + "you are looking! If you tap or hold Sneak again, " + + "the disc will attempt to return to you!"); + String[] meltable = { + Material.COBBLESTONE.name(), Material.OAK_LOG.name(), Material.SPRUCE_LOG.name(), + Material.JUNGLE_LOG.name(), Material.DARK_OAK_LOG.name(), Material.BIRCH_LOG.name(), + Material.ACACIA_LOG.name() + }; + config.addDefault("Abilities.Earth.LavaDisc.Cooldown", 7000); + config.addDefault("Abilities.Earth.LavaDisc.Duration", 1000); + config.addDefault("Abilities.Earth.LavaDisc.Damage", 4.0); + config.addDefault("Abilities.Earth.LavaDisc.Particles", 3); + config.addDefault("Abilities.Earth.LavaDisc.ContinueAfterEntityHit", false); + config.addDefault("Abilities.Earth.LavaDisc.RecallLimit", 3); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.RegenTime", 5000); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.BlockDamage", true); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks", meltable); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.LavaTrail", true); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.TrailFlow", false); + config.addDefault("Abilities.Earth.LavaDisc.Source.RegenTime", 10000); + config.addDefault("Abilities.Earth.LavaDisc.Source.LavaOnly", false); + config.addDefault("Abilities.Earth.LavaDisc.Source.Range", 4.0); + config.addDefault("Abilities.Earth.LavaDisc.RemovalPolicy.SwappedSlots.Enabled", true); + + config.addDefault("Abilities.Earth.LavaFlux.Enabled", true); + config.addDefault("Abilities.Earth.LavaFlux.Description", "This offensive ability enables a Lavabender to create a wave of lava, " + + "swiftly progressing forward and hurting/burning anything in its way. To use, " + + "simply swing your arm towards a target and the ability will activate."); + config.addDefault("Abilities.Earth.LavaFlux.Range", 12); + config.addDefault("Abilities.Earth.LavaFlux.Cooldown", 8000); + config.addDefault("Abilities.Earth.LavaFlux.Duration", 4000); + config.addDefault("Abilities.Earth.LavaFlux.Cleanup", 1000); + config.addDefault("Abilities.Earth.LavaFlux.Damage", 1.0); + config.addDefault("Abilities.Earth.LavaFlux.Speed", 1); + config.addDefault("Abilities.Earth.LavaFlux.Wave", true); + config.addDefault("Abilities.Earth.LavaFlux.KnockUp", 1.0); + config.addDefault("Abilities.Earth.LavaFlux.KnockBack", 1.0); + + config.addDefault("Abilities.Earth.LavaThrow.Enabled", true); + config.addDefault("Abilities.Earth.LavaThrow.Description", "Throwing lava is a fundamental technique for the rare subskill. " + + "Use Sneak(Deafult: Shift) while looking at a pool of lava infront of you, then " + + "Left-Click to splash the lava at your target. " + + "It can be used in rapid succession to create multiple streams of lava!"); + config.addDefault("Abilities.Earth.LavaThrow.Cooldown", 7000); + config.addDefault("Abilities.Earth.LavaThrow.MaxShots", 6); + config.addDefault("Abilities.Earth.LavaThrow.Range", 20); + config.addDefault("Abilities.Earth.LavaThrow.Damage", 1.0); + config.addDefault("Abilities.Earth.LavaThrow.SourceGrabRange", 4); + config.addDefault("Abilities.Earth.LavaThrow.SourceRegenDelay", 10000); + config.addDefault("Abilities.Earth.LavaThrow.FireTicks", 80); + config.addDefault("Abilities.Earth.LavaThrow.CurveFactor", 0.5); + + config.addDefault("Abilities.Earth.MagnetShield.Enabled", true); + config.addDefault("Abilities.Earth.MagnetShield.Description", "Repel any metal projectiles using a strong magnetic shield. " + + "To activate, simply hold sneak with this ability bound."); + config.addDefault("Abilities.Earth.MagnetShield.Materials", Arrays.asList( + "IRON_INGOT", + "IRON_HELMET", + "IRON_CHESTPLATE", + "IRON_LEGGINGS", + "IRON_BOOTS", + "IRON_BLOCK", + "IRON_AXE", + "IRON_PICKAXE", + "IRON_SWORD", + "IRON_HOE", + "IRON_SHOVEL", + "IRON_DOOR", + "IRON_NUGGET", + "IRON_BARS", + "IRON_HORSE_ARMOR", + "IRON_TRAPDOOR", + "HEAVY_WEIGHTED_PRESSURE_PLATE", + "GOLD_INGOT", + "GOLDEN_HELMET", + "GOLDEN_CHESTPLATE", + "GOLDEN_LEGGINGS", + "GOLDEN_BOOTS", + "GOLD_BLOCK", + "GOLD_NUGGET", + "GOLDEN_AXE", + "GOLDEN_PICKAXE", + "GOLDEN_SHOVEL", + "GOLDEN_SWORD", + "GOLDEN_HOE", + "GOLDEN_HORSE_ARMOR", + "LIGHT_WEIGHTED_PRESSURE_PLATE", + "CLOCK", + "COMPASS", + "RAW_GOLD_BLOCK", + "RAW_IRON_BLOCK", + "RAW_IRON", + "RAW_GOLD", + "ANVIL", + "CHIPPED_ANVIL", + "DAMAGED_ANVIL", + "IRON_ORE", + "GOLD_ORE", + "DEEPSLATE_IRON_ORE", + "DEEPSLATE_GOLD_ORE", + "SHIELD" + )); + config.addDefault("Abilities.Earth.MagnetShield.Duration", 6000); + config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Shift", 5000); + config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Click", 5000); + config.addDefault("Abilities.Earth.MagnetShield.Range", 5.0); + config.addDefault("Abilities.Earth.MagnetShield.RepelArrows", true); + config.addDefault("Abilities.Earth.MagnetShield.RepelLivingEntities", true); + config.addDefault("Abilities.Earth.MagnetShield.Velocity", 0.1); + + config.addDefault("Abilities.Earth.MetalFragments.Enabled", true); + config.addDefault("Abilities.Earth.MetalFragments.Description", "MetalFragments allows you to select a source and shoot " + + "multiple fragments of metal out of that source " + + "block towards your target, injuring them on impact. " + + "To use, tap Sneak (Default: Shift) at a metal " + + "source block and it will float up. Then, turn around " + + "and click at your target to fling metal fragments at them."); + config.addDefault("Abilities.Earth.MetalFragments.Cooldown", 5000); + config.addDefault("Abilities.Earth.MetalFragments.MaxSources", 3); + config.addDefault("Abilities.Earth.MetalFragments.SourceRange", 5); + config.addDefault("Abilities.Earth.MetalFragments.MaxFragments", 10); + config.addDefault("Abilities.Earth.MetalFragments.Damage", 4.0); + config.addDefault("Abilities.Earth.MetalFragments.Velocity", 2.0); + + config.addDefault("Abilities.Earth.MetalHook.Enabled", true); + config.addDefault("Abilities.Earth.MetalHook.Description", "This ability lets a Metalbender bend metal into " + + "grappling hooks, allowing them to easily manouver terrain. " + + "To use this ability, the user must either have Iron in their inventory " + + "or be wearing an Iron/Chainmail Chestplate. Left-Click in the direction " + + "you are looking to fire a grappling hook, several hooks can be active at once, " + + "allowing the bender to 'hang' in locations. To disengage the hooks, hold Shift (Default: Sneak) or Sprint."); + config.addDefault("Abilities.Earth.MetalHook.Cooldown", 3000); + config.addDefault("Abilities.Earth.MetalHook.Range", 30); + config.addDefault("Abilities.Earth.MetalHook.MaxHooks", 3); + config.addDefault("Abilities.Earth.MetalHook.TotalHooks", 0); + config.addDefault("Abilities.Earth.MetalHook.RequireItems", true); + config.addDefault("Abilities.Earth.MetalHook.BarrierHooking", true); + + config.addDefault("Abilities.Earth.MetalShred.Enabled", true); + config.addDefault("Abilities.Earth.MetalShred.Description", "MetalShred allows you to tear a metal surface allowing you to sneak in to the other side." + + "To use, you must find a flat metal surface. Then, Sneak(Default: Shift) " + + "at a piece of metal on that surface, and two pieces of metal " + + "will be pulled toward you. Finally, run alongside the surface to coil " + + "the metal around those two pieces. The way will be open, and the blocks " + + "will not reset until you either select a new source or you switch " + + "abilities. If you click after having torn a hole in a vertical surface, " + + "you can Left-Click in any direction and the metal will unfold in that " + + "direction. If you are fast and precise enough, the metal can bend in " + + "any shape. The length of this sheet of metal depends on how much was " + + "coiled in the first place."); + config.addDefault("Abilities.Earth.MetalShred.SourceRange", 5); + config.addDefault("Abilities.Earth.MetalShred.ExtendTick", 80); + config.addDefault("Abilities.Earth.MetalShred.Damage", 6.0); + + config.addDefault("Abilities.Earth.MudSurge.Enabled", true); + config.addDefault("Abilities.Earth.MudSurge.Description", "This ability lets an earthbender send a surge of mud " + + "in any direction, knocking back enemies and " + + "dealing moderate damage. This ability has a chance " + + "of blinding the target. To use, select " + + "a source of earth and click in any direction."); + config.addDefault("Abilities.Earth.MudSurge.Cooldown", 6000); + config.addDefault("Abilities.Earth.MudSurge.Damage", 1.0); + config.addDefault("Abilities.Earth.MudSurge.Waves", 5); + config.addDefault("Abilities.Earth.MudSurge.SourceRange", 7); + config.addDefault("Abilities.Earth.MudSurge.BlindChance", 10); + config.addDefault("Abilities.Earth.MudSurge.WetSourceOnly", false); + config.addDefault("Abilities.Earth.MudSurge.WaterSearchRadius", 5); + config.addDefault("Abilities.Earth.MudSurge.BlindTicks", 60); + config.addDefault("Abilities.Earth.MudSurge.CollisionRadius", 2.0); + config.addDefault("Abilities.Earth.MudSurge.MultipleHits", true); + config.addDefault("Abilities.Earth.MudSurge.AllowFallDamage", false); + config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.SwappedSlots.Enabled", true); + config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Enabled", true); + config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Range", 25.0); + + config.addDefault("Abilities.Earth.SandBlast.Enabled", true); + config.addDefault("Abilities.Earth.SandBlast.Description", "This ability lets an earthbender blast a bunch of sand at an enemy " + + "damaging them and temporarily blinding them! Just Sneak (Default: Shift) " + + "on a sand bendable block, then Left-Click in a direction to shoot a " + + "blast of sand!"); + config.addDefault("Abilities.Earth.SandBlast.Cooldown", 3000); + config.addDefault("Abilities.Earth.SandBlast.Damage", 3.0); + config.addDefault("Abilities.Earth.SandBlast.SourceRange", 8); + config.addDefault("Abilities.Earth.SandBlast.Range", 30); + config.addDefault("Abilities.Earth.SandBlast.MaxSandBlocks", 10); + + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Enabled", true); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Description", "Create a Crevice in the ground! Once opened, " + + "anyone can Tap Sneak with Shockwave to close the Crevice!"); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Range", 50); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.RevertDelay", 7500); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Depth", 5); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth", 8); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Cooldown", 10000); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Combination", Arrays.asList("Collapse:RIGHT_CLICK_BLOCK", "Shockwave:SHIFT_DOWN", "Shockwave:SHIFT_UP", "Shockwave:SHIFT_DOWN")); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Instructions", "Collapse (Right-click a block) > Shockwave (Tap sneak) > Shockwave (Tap sneak)"); + + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Enabled", true); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Description", "Fire balls of magma at your enemy!"); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots", 3); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage", 2.0); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange", 4); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown", 6000); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown", 1500); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow", false); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions", true); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection", true); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange", 30.0); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius", 2.0); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed", 1.5); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration", 15000); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources", 15); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Combination", Arrays.asList("EarthBlast:SHIFT_DOWN", "LavaFlow:SHIFT_UP", "LavaFlow:SHIFT_DOWN", "LavaFlow:RIGHT_CLICK_BLOCK")); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Instructions", "EarthBlast (Hold sneak) > LavaFlow (Release sneak) > LavaFlow (Hold sneak) > LavaFlow (Right-click a block) > LavaFlow (Left-click multiple times)"); + + ArrayList combustionSkipMaterials = new ArrayList<>(); + combustionSkipMaterials.add("#bee_growables"); + combustionSkipMaterials.add("#cave_vines"); + combustionSkipMaterials.add("#crops"); + combustionSkipMaterials.add("#flowers"); + combustionSkipMaterials.add("vine"); + combustionSkipMaterials.add("pale_hanging_moss"); + + config.addDefault("Abilities.Fire.Combustion.Enabled", true); + config.addDefault("Abilities.Fire.Combustion.Description", "Hold Shift to focus large amounts of energy into your body, " + + "Release Shift to fire Combustion. Move your mouse to " + + "direct where the beam travels. Left-Click to detonate " + + "the beam manually"); + config.addDefault("Abilities.Fire.Combustion.Damage", 4.0); + config.addDefault("Abilities.Fire.Combustion.FireTick", 100); + config.addDefault("Abilities.Fire.Combustion.MisfireModifier", -1); + config.addDefault("Abilities.Fire.Combustion.Power", 3); + config.addDefault("Abilities.Fire.Combustion.Range", 100); + config.addDefault("Abilities.Fire.Combustion.Speed", 0.65); + config.addDefault("Abilities.Fire.Combustion.Warmup", 1500); + config.addDefault("Abilities.Fire.Combustion.Cooldown", 5000); + config.addDefault("Abilities.Fire.Combustion.RegenTime", 10000); + config.addDefault("Abilities.Fire.Combustion.EntityCollisionRadius", 1.3); + config.addDefault("Abilities.Fire.Combustion.AbilityCollisionRadius", 1.3); + config.addDefault("Abilities.Fire.Combustion.DamageBlocks", true); + config.addDefault("Abilities.Fire.Combustion.RegenBlocks", true); + config.addDefault("Abilities.Fire.Combustion.WaitForRegen", true); + config.addDefault("Abilities.Fire.Combustion.InstantExplodeIfHit", true); + config.addDefault("Abilities.Fire.Combustion.ExplodeOnDeath", true); + config.addDefault("Abilities.Fire.Combustion.RemovalPolicy.SwappedSlots.Enabled", false); + config.addDefault("Abilities.Fire.Combustion.SkipMaterials", combustionSkipMaterials); + + config.addDefault("Abilities.Fire.Discharge.Enabled", true); + config.addDefault("Abilities.Fire.Discharge.Description", "Left-Click to shoot bolts of electricity out " + + "of your fingertips zapping what ever it hits!"); + config.addDefault("Abilities.Fire.Discharge.Damage", 3.0); + config.addDefault("Abilities.Fire.Discharge.Cooldown", 5000); + config.addDefault("Abilities.Fire.Discharge.AvatarCooldown", 500); + config.addDefault("Abilities.Fire.Discharge.Duration", 1000); + config.addDefault("Abilities.Fire.Discharge.SlotSwapping", false); + config.addDefault("Abilities.Fire.Discharge.EntityCollisionRadius", 1.0); + config.addDefault("Abilities.Fire.Discharge.AbilityCollisionRadius", 1.0); + config.addDefault("Abilities.Fire.Discharge.Sound.Volume", 0.6); + config.addDefault("Abilities.Fire.Discharge.Sound.Interval", 6); + + config.addDefault("Abilities.Fire.FireBall.Enabled", true); + config.addDefault("Abilities.Fire.FireBall.Description", "To use, simply Left-Click to shoot a fireball at your target!"); + config.addDefault("Abilities.Fire.FireBall.Cooldown", 3000); + config.addDefault("Abilities.Fire.FireBall.Range", 50); + config.addDefault("Abilities.Fire.FireBall.Damage", 3.0); + config.addDefault("Abilities.Fire.FireBall.FireDuration", 2000); + config.addDefault("Abilities.Fire.FireBall.Controllable", false); + config.addDefault("Abilities.Fire.FireBall.FireTrail", true); + config.addDefault("Abilities.Fire.FireBall.CollisionRadius", 1.1); + config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.Enabled", true); + config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveFirst", true); + config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Enabled", true); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveFirst", false); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Reflect", true); + + config.addDefault("Abilities.Fire.FireBreath.Enabled", true); + config.addDefault("Abilities.Fire.FireBreath.Description", "To use, hold Sneak (Default: Shift) to start breathing " + + "fire! Some Firebenders possess the power to infuse color " + + "when they breathe, it's unclear how they do this, but some suggest " + + "it can be obtained by saying \"Bring fire and light together as one and allow the breath of color\" " + + "and can be brought back to normal by saying \"Split the bond of fire " + + "and light and set the color free\"."); + config.addDefault("Abilities.Fire.FireBreath.Cooldown", 5000); + config.addDefault("Abilities.Fire.FireBreath.Duration", 3000); + config.addDefault("Abilities.Fire.FireBreath.Particles", 3); + config.addDefault("Abilities.Fire.FireBreath.Damage.Player", 1.0); + config.addDefault("Abilities.Fire.FireBreath.Damage.Mob", 2.0); + config.addDefault("Abilities.Fire.FireBreath.FireDuration", 3000); + config.addDefault("Abilities.Fire.FireBreath.Range", 10); + config.addDefault("Abilities.Fire.FireBreath.Avatar.FireEnabled", true); + config.addDefault("Abilities.Fire.FireBreath.Melt.Enabled", true); + config.addDefault("Abilities.Fire.FireBreath.Melt.Chance", 3); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.Enabled", true); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "You have bonded fire with light and can now breathe pure color."); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "You have split your bond of color and light."); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "You don't possess the power to bond light with fire."); + + config.addDefault("Abilities.Fire.FireComet.Enabled", true); + config.addDefault("Abilities.Fire.FireComet.Description", "Harnessing the power of Sozin's Comet, a firebender can create a great " + + "ball of fire, with much destructive power. Only useable during Sozin's Comet or while in the AvatarState, hold Sneak (Default: Shift) " + + "to start charging the ability up. Once the ability is charged, a large mass of particles will follow your cursor, until you release sneak, " + + "launching the great ball of fire in the direction you are looking."); + config.addDefault("Abilities.Fire.FireComet.Cooldown", 45000); + config.addDefault("Abilities.Fire.FireComet.ChargeUp", 7000); + config.addDefault("Abilities.Fire.FireComet.Damage", 6.0); + config.addDefault("Abilities.Fire.FireComet.BlastRadius", 3.0); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.Cooldown", 30000); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.ChargeUp", 5000); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.Damage", 12.0); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.BlastRadius", 5.0); + config.addDefault("Abilities.Fire.FireComet.Range", 50); + config.addDefault("Abilities.Fire.FireComet.RegenDelay", 15000); + config.addDefault("Abilities.Fire.FireComet.SozinsCometOnly", true); + config.addDefault("Abilities.Fire.FireComet.AvatarStateBypassComet", true); + + config.addDefault("Abilities.Fire.FirePunch.Enabled", true); + config.addDefault("Abilities.Fire.FirePunch.Description", "This basic ability allows a Firebender to channel their energies into a " + + "single punch, igniting and damaging the victim."); + config.addDefault("Abilities.Fire.FirePunch.Cooldown", 4000); + config.addDefault("Abilities.Fire.FirePunch.FireTicks", 2000); + config.addDefault("Abilities.Fire.FirePunch.Damage", 2.0); + + config.addDefault("Abilities.Fire.FireShots.Enabled", true); + config.addDefault("Abilities.Fire.FireShots.Description", "To use, tap Sneak (Default: Shift) to summon a " + + "FireBalls at your hand, then Left Click to shoot off each ball! " + + "Each shot will follow the cursor until it runs out or hits something! " + + "Tap Sneak again to switch your main hand."); + config.addDefault("Abilities.Fire.FireShots.Cooldown", 3000); + config.addDefault("Abilities.Fire.FireShots.Range", 50); + config.addDefault("Abilities.Fire.FireShots.FireBalls", 4); + config.addDefault("Abilities.Fire.FireShots.FireDuration", 3000); + config.addDefault("Abilities.Fire.FireShots.Damage", 2.0); + config.addDefault("Abilities.Fire.FireShots.CollisionRadius", 0.9); + config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.Enabled", true); + config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveFirst", true); + config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Enabled", true); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveFirst", false); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); + + config.addDefault("Abilities.Fire.FireSki.Enabled", true); + config.addDefault("Abilities.Fire.FireSki.Cooldown", 6000); + config.addDefault("Abilities.Fire.FireSki.Duration", 6000); + config.addDefault("Abilities.Fire.FireSki.Speed", 0.7); + config.addDefault("Abilities.Fire.FireSki.IgniteEntities", true); + config.addDefault("Abilities.Fire.FireSki.FireTicks", 60); + config.addDefault("Abilities.Fire.FireSki.RequiredHeight", 0.7); + config.addDefault("Abilities.Fire.FireSki.PunchActivated", false); + + config.addDefault("Abilities.Fire.LightningBurst.Enabled", true); + config.addDefault("Abilities.Fire.LightningBurst.Description", "To use the most explosive lightning move available to a firebender, hold " + + "Sneak (Default: Shift) until blue sparks appear in front of you. Upon releasing, " + + "you will unleash an electrical sphere, shocking anyone who gets too close"); + config.addDefault("Abilities.Fire.LightningBurst.Cooldown", 25000); + config.addDefault("Abilities.Fire.LightningBurst.ChargeUp", 4000); + config.addDefault("Abilities.Fire.LightningBurst.AvatarCooldown", 1000); + config.addDefault("Abilities.Fire.LightningBurst.AvatarChargeUp", 1000); + config.addDefault("Abilities.Fire.LightningBurst.Radius", 12); + config.addDefault("Abilities.Fire.LightningBurst.Damage", 9.0); + config.addDefault("Abilities.Fire.LightningBurst.Sound.Volume", 0.6); + config.addDefault("Abilities.Fire.LightningBurst.Sound.Interval", 6); + + config.addDefault("Abilities.Water.Bloodbending.Enabled", true); + config.addDefault("Abilities.Water.Bloodbending.Description", "This ability allows a skilled waterbender " + + "to bend the water within an enemy's blood, granting them full " + + "control over the enemy's limbs. This ability is extremely dangerous " + + "and is to be used carefully. To use, sneak while looking at an entity " + + "and its body will follow your movement. If you click, you will launch " + + "the entity towards whatever you were looking at when you clicked. The " + + "entity may collide with others, injuring them and the other one further."); + config.addDefault("Abilities.Water.Bloodbending.NightOnly", false); + config.addDefault("Abilities.Water.Bloodbending.FullMoonOnly", false); + config.addDefault("Abilities.Water.Bloodbending.UndeadMobs", true); + config.addDefault("Abilities.Water.Bloodbending.IgnoreWalls", false); + config.addDefault("Abilities.Water.Bloodbending.RequireBound", false); + config.addDefault("Abilities.Water.Bloodbending.Distance", 6); + config.addDefault("Abilities.Water.Bloodbending.HoldTime", 10000); + config.addDefault("Abilities.Water.Bloodbending.Cooldown", 4000); + + config.addDefault("Abilities.Water.BloodPuppet.Enabled", true); + config.addDefault("Abilities.Water.BloodPuppet.Description", "This very high-level bloodbending ability lets " + + "a master control entities' limbs, forcing them to " + + "attack the master's target. To use this ability, you must " + + "be a bloodbender. Next, sneak while targeting " + + "a mob or player and you will start controlling them. To " + + "make the entity hit another, click. To release your " + + "target, stop sneaking. This ability has NO cooldown, but " + + "may only be usable during the night depending on the " + + "server configuration."); + config.addDefault("Abilities.Water.BloodPuppet.NightOnly", false); + config.addDefault("Abilities.Water.BloodPuppet.FullMoonOnly", false); + config.addDefault("Abilities.Water.BloodPuppet.UndeadMobs", true); + config.addDefault("Abilities.Water.BloodPuppet.IgnoreWalls", false); + config.addDefault("Abilities.Water.BloodPuppet.RequireBound", false); + config.addDefault("Abilities.Water.BloodPuppet.Distance", 6); + config.addDefault("Abilities.Water.BloodPuppet.HoldTime", 10000); + config.addDefault("Abilities.Water.BloodPuppet.Cooldown", 4000); + config.addDefault(path + "Enabled", true); + config.addDefault(path + "Cooldown", 10000); + config.addDefault(path + "Damage", 6.0); + config.addDefault(path + "Range", 12); + config.addDefault(path + "Hitradius", 3.0); + config.addDefault(path + "SelfDamage", 2.0); + config.addDefault(path + "Speed", 1.0); + + config.addDefault("Abilities.Water.Drain.Enabled", true); + config.addDefault("Abilities.Water.Drain.Description", "Inspired by how Hama drained water from the fire lilies, many benders " + + "have practiced in the skill of draining water from plants! With this ability bound, " + + "Sneak (Default: Shift) near/around plant sources to drain the water out of them to fill up any " + + "bottles/buckets in your inventory! Alternatively, if you have nothing to fill" + + " and blasts are enabled in the config, you will be able to create mini blasts " + + "of water to shoot at your targets! Aleternatively, this ability can also be used to quickly fill up " + + "bottles from straight water sources or from falling rain!"); + config.addDefault("Abilities.Water.Drain.RegenDelay", 15000); + config.addDefault("Abilities.Water.Drain.Duration", 2000); + config.addDefault("Abilities.Water.Drain.Cooldown", 2000); + config.addDefault("Abilities.Water.Drain.AbsorbSpeed", 0.1); + config.addDefault("Abilities.Water.Drain.AbsorbChance", 20); + config.addDefault("Abilities.Water.Drain.AbsorbRate", 6); + config.addDefault("Abilities.Water.Drain.Radius", 6); + config.addDefault("Abilities.Water.Drain.HoldRange", 2); + config.addDefault("Abilities.Water.Drain.AllowRainSource", true); + config.addDefault("Abilities.Water.Drain.BlastsEnabled", true); + config.addDefault("Abilities.Water.Drain.KeepSource", false); + config.addDefault("Abilities.Water.Drain.BlastSpeed", 1); + config.addDefault("Abilities.Water.Drain.BlastDamage", 1.5); + config.addDefault("Abilities.Water.Drain.BlastRange", 20); + config.addDefault("Abilities.Water.Drain.MaxBlasts", 4); + config.addDefault("Abilities.Water.Drain.DrainTempBlocks", true); + + config.addDefault("Abilities.Water.FrostBreath.Enabled", true); + config.addDefault("Abilities.Water.FrostBreath.Description", "As demonstrated by Katara, a Waterbender is able to freeze their breath, " + + "causing anything it touches to be frozen! With this ability bound, simply hold " + + "Sneak (Default: Shift) to start breathing frost!"); + config.addDefault("Abilities.Water.FrostBreath.Cooldown", 15000); + config.addDefault("Abilities.Water.FrostBreath.Duration", 3000); + config.addDefault("Abilities.Water.FrostBreath.Particles", 3); + config.addDefault("Abilities.Water.FrostBreath.FrostDuration", 5000); + config.addDefault("Abilities.Water.FrostBreath.FrozenWaterDuration", 10000); + config.addDefault("Abilities.Water.FrostBreath.Range", 10); + config.addDefault("Abilities.Water.FrostBreath.Snow", true); + config.addDefault("Abilities.Water.FrostBreath.SnowDuration", 5000); + config.addDefault("Abilities.Water.FrostBreath.BendableSnow", false); + config.addDefault("Abilities.Water.FrostBreath.Damage.Enabled", false); + config.addDefault("Abilities.Water.FrostBreath.Damage.Player", 1.0); + config.addDefault("Abilities.Water.FrostBreath.Damage.Mob", 2.0); + config.addDefault("Abilities.Water.FrostBreath.Slow.Enabled", true); + config.addDefault("Abilities.Water.FrostBreath.Slow.Duration", 4000); + config.addDefault("Abilities.Water.FrostBreath.RestrictBiomes", true); + + config.addDefault("Abilities.Water.HealingWaters.Enabled", true); + config.addDefault("Abilities.Water.HealingWaters.Description", "To use this ability, the bender has to be partially submerged " + + "in water, OR be holding either a bottle of water or a water bucket." + + " This move will heal the player automatically if they have it equipped " + + "and are standing in water. If the player sneaks while in water and is targeting" + + " another entity, the bender will heal the targeted entity. The alternate " + + "healing method requires the bender to be holding a bottle of water or a water" + + " bucket. To start healing simply sneak, however if the bender is targeting " + + "a mob while sneaking, the bender will heal the targeted mob."); + config.addDefault("Abilities.Water.HealingWaters.Power", 1); + config.addDefault("Abilities.Water.HealingWaters.Range", 5); + config.addDefault("Abilities.Water.HealingWaters.DrainChance", 5); + config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Enabled", true); + config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Brightness", 10); + config.addDefault("Abilities.Water.HealingWaters.DynamicLight.KeepAlive", 1500); + + config.addDefault("Abilities.Water.IceClaws.Enabled", true); + config.addDefault("Abilities.Water.IceClaws.Description", "As demonstrated by Hama, a Waterbender can pull water out of thin air to create claws " + + "at the tips of their fingers. With IceClaws bound, hold Sneak (Default: Shift) to " + + "start pulling water out the air until you form claws at your finger " + + "tips, then attack an enemy to slow them down and do a bit of damage!"); + config.addDefault("Abilities.Water.IceClaws.Cooldown", 6000); + config.addDefault("Abilities.Water.IceClaws.ChargeTime", 1000); + config.addDefault("Abilities.Water.IceClaws.SlowDuration", 5000); + config.addDefault("Abilities.Water.IceClaws.Damage", 3.0); + config.addDefault("Abilities.Water.IceClaws.Range", 10); + config.addDefault("Abilities.Water.IceClaws.Throwable", true); + + config.addDefault("Abilities.Water.IceWall.Enabled", true); + config.addDefault("Abilities.Water.IceWall.Description", "IceWall allows an icebender to create a wall of ice, similar to " + + "raiseearth. To use, simply sneak while targeting either water, ice, or snow. " + + "To break the wall, you must sneak again while targeting it. Be aware that " + + "other icebenders can break your own shields, and if you are too close you " + + "can get hurt by the shards."); + config.addDefault("Abilities.Water.IceWall.Cooldown", 4000); + config.addDefault("Abilities.Water.IceWall.Width", 6); + config.addDefault("Abilities.Water.IceWall.MaxHeight", 5); + config.addDefault("Abilities.Water.IceWall.MinHeight", 3); + config.addDefault("Abilities.Water.IceWall.MaxWallHealth", 12); + config.addDefault("Abilities.Water.IceWall.MinWallHealth", 8); + config.addDefault("Abilities.Water.IceWall.Range", 8); + config.addDefault("Abilities.Water.IceWall.Damage", 4.0); + config.addDefault("Abilities.Water.IceWall.CanBreak", true); + config.addDefault("Abilities.Water.IceWall.Stackable", false); + config.addDefault("Abilities.Water.IceWall.LifeTime.Enabled", false); + config.addDefault("Abilities.Water.IceWall.LifeTime.Duration", 10000); + config.addDefault("Abilities.Water.IceWall.WallDamage", true); + config.addDefault("Abilities.Water.IceWall.WallDamage.Torrent", 5); + config.addDefault("Abilities.Water.IceWall.WallDamage.TorrentFreeze", 9); + config.addDefault("Abilities.Water.IceWall.WallDamage.IceBlast", 8); + config.addDefault("Abilities.Water.IceWall.WallDamage.Fireblast", 3); + config.addDefault("Abilities.Water.IceWall.WallDamage.FireblastCharged", 5); + config.addDefault("Abilities.Water.IceWall.WallDamage.Lightning", 12); + config.addDefault("Abilities.Water.IceWall.WallDamage.Combustion", 12); + config.addDefault("Abilities.Water.IceWall.WallDamage.EarthSmash", 8); + config.addDefault("Abilities.Water.IceWall.WallDamage.AirBlast", 2); + + config.addDefault("Abilities.Water.WakeFishing.Enabled", true); + config.addDefault("Abilities.Water.WakeFishing.Description", "With this ability bound, hold Sneak (Default: Shift) at a water block and " + + "don't lose focus of that block. Eventually some fish will investigate " + + "the wake and swim out at you!"); + config.addDefault("Abilities.Water.WakeFishing.Cooldown", 10000); + config.addDefault("Abilities.Water.WakeFishing.Duration", 20000); + config.addDefault("Abilities.Water.WakeFishing.Range", 5); + + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Description", "Create a swirling mass of water that drags any entity that enters it to the bottom " + + "of the whirlpool."); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Cooldown", 25000); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Duration", 15000); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.MaxDepth", 5); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Range", 10); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Combination", Arrays.asList("PhaseChange:SHIFT_DOWN", "Torrent:LEFT_CLICK", "Torrent:LEFT_CLICK")); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Instructions", "PhaseChange (Hold sneak) > Torrent (Left-click) > Torrent (Left-click)"); + + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Description", "Some Waterbenders have managed to create torrents of water much stronger than a regular torrent, " + + "that can carry them selves and others, as well as being able to freeze the entire stream whenever. The bender must stay focused on the flow or else the flow will stop." + + " If you Sneak (Default: Shift) while controlling the stream, the stream will return to you."); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Cooldown", 8000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Duration", 8000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MeltDelay", 5000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.SourceRange", 10); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxRange", 40); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MinRange", 8); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Trail", 80); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.BottleSource", false); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlantSource", false); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.RemoveOnAnyDamage", false); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.Normal", 1); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.AvatarState", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonSmall", 2); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonLarge", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.IsAvatarStateToggle", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.AvatarStateDuration", 60000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerStayNearSource", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxDistanceFromSource", 100); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Cooldown", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Duration", 2); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerRideOwnFlow", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Combination", Arrays.asList("WaterManipulation:SHIFT_DOWN", "WaterManipulation:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "WaterManipulation:SHIFT_UP")); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Instructions", "WaterManipulation (Tap sneak) > Torrent (Tap sneak) > Torrent (Hold sneak) > WaterManipulation (Release sneak)"); + + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Description", "Skilled Waterbenders are able to create two spinning rings of water around their bodies, " + + "which can be used as a defensive ability or for an offensive attack."); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Cooldown", 7000); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Damage", 3.0); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RingSize", 3.5); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Range", 40); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SourceRange", 10); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Speed", 2); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AnimationSpeed", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.PlantSource", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SnowSource", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RequireAdjacentPlants", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.BottleSource", false); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AbilityCollisionRadius", 1.6); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.EntityCollisionRadius", 1.6); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.Enabled", false); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveFirst", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveSecond", false); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Combination", Arrays.asList("Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "WaterManipulation:SHIFT_DOWN")); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Instructions", "Torrent (Tap sneak) > Torrent (Tap sneak) > WaterManipulation (Hold sneak) > WaterManipulation (Left-click multiple times)"); + + config.addDefault("Abilities.Water.Ice.Passive.Skate.Enabled", true); + config.addDefault("Abilities.Water.Ice.Passive.Skate.SpeedFactor", 4); + + config.addDefault("Abilities.Chi.Backstab.Enabled", true); + config.addDefault("Abilities.Chi.Backstab.Description", "Strike your foe in the back with a hard jab, temporariliy blocking their Chi, and " + + "inflicting a lot of damage! This ability has a long cooldown. You must hit the target in the back or this ability won't work!"); + config.addDefault("Abilities.Chi.Backstab.Cooldown", 8500); + config.addDefault("Abilities.Chi.Backstab.Damage", 6.0); + config.addDefault("Abilities.Chi.Backstab.MaxActivationAngle", 90); + + config.addDefault("Abilities.Chi.DaggerThrow.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.Description", "With this ability bound, Left-Click in " + + "rapid succession to shoot arrows out of your inventory at your target!"); + config.addDefault("Abilities.Chi.DaggerThrow.Cooldown", 3000); + config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Amount", 6); + config.addDefault("Abilities.Chi.DaggerThrow.Damage", 1.0); + config.addDefault("Abilities.Chi.DaggerThrow.ParticleTrail", true); + config.addDefault("Abilities.Chi.DaggerThrow.RequireArrows", false); + config.addDefault("Abilities.Chi.DaggerThrow.AllowPickup", false); + config.addDefault("Abilities.Chi.DaggerThrow.AbilityCollisionRadius", 0.5); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Cooldown", 1000); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.HitsRequired", 1); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Cooldown", 1000); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.HitsRequired", 1); + + String[] invalidWallRun = {Material.BARRIER.name()}; + config.addDefault("Abilities.Passives.WallRun.Enabled", true); + config.addDefault("Abilities.Passives.WallRun.Cooldown", 6000); + config.addDefault("Abilities.Passives.WallRun.Duration", 20000); + config.addDefault("Abilities.Passives.WallRun.Particles", true); + config.addDefault("Abilities.Passives.WallRun.Air", true); + config.addDefault("Abilities.Passives.WallRun.Earth", false); + config.addDefault("Abilities.Passives.WallRun.Water", false); + config.addDefault("Abilities.Passives.WallRun.Fire", true); + config.addDefault("Abilities.Passives.WallRun.Chi", true); + config.addDefault("Abilities.Passives.WallRun.InvalidBlocks", invalidWallRun); + + config.options().copyDefaults(true); + plugin.saveConfig(); + } + + private void addDeathMessages() { + FileConfiguration lang = ConfigManager.languageConfig.get(); + + //Fire + lang.addDefault("Abilities.Fire.FireComet.DeathMessage", "{victim} was squashed under the pressure of {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FireBall.DeathMessage", "{victim} burst from {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FireBreath.DeathMessage", "{victim} was consumed {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.Discharge.DeathMessage", "{victim} couldn't take {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FirePunch.DeathMessage", "{victim} punched out from {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FireShots.DeathMessage", "{victim} was shot by {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.LightningBurst.DeathMessage", "{victim} crackled out of existence from {attacker}'s {ability}"); + + //Water + lang.addDefault("Abilities.Water.Drain.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.FrostBreath.DeathMessage", "{victim} shattered from {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.IceClaws.DeathMessage", "{victim} was ripped to shreds by {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.IceWall.DeathMessage", "{victim} was collateral to {attacker}'s exploding {ability}"); + lang.addDefault("Abilities.Water.WaterBlast.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.Combo.WaterGimbal.DeathMessage", "{victim} was ripped apart by {attacker}'s {ability}"); + + //Earth + lang.addDefault("Abilities.Earth.EarthKick.DeathMessage", "{victim} got too much dirt in their eye from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.EarthLine.DeathMessage", "{victim} lost their footing from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.EarthShard.DeathMessage", "{victim} got blasted apart {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.LavaDisc.DeathMessage", "{victim} sliced in half by {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.LavaFlux.DeathMessage", "{victim} couldn't take the heat from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.LavaThrow.DeathMessage", "{victim} melted from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.MetalFragments.DeathMessage", "{victim} was shredded apart from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.MetalShred.DeathMessage", "{victim} was in the way of {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.MudSurge.DeathMessage", "{victim} drowned in mud from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.SandBlast.DeathMessage", "{victim} was sandblasted to oblivion from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.Combo.MagmaBlast.DeathMessage", "{victim} was obliterated by {attacker}'s {ability}"); + + //Air + lang.addDefault("Abilities.Air.AirBlade.DeathMessage", "{victim} was sliced in two by {attacker}'s {ability}"); + lang.addDefault("Abilities.Air.AirPunch.DeathMessage", "{victim} was exploded by {attacker}'s {ability}"); + lang.addDefault("Abilities.Air.SonicBlast.DeathMessage", "{victim}'s ears burst after {attacker}'s {ability}"); + + //Chi + lang.addDefault("Abilities.Chi.DaggerThrow.DeathMessage", "{victim} got stabbed too many times from {attacker}'s {ability}"); + lang.addDefault("Abilities.Chi.Backstab.DeathMessage", "{victim} fell victim to {attacker}'s {ability}"); + + //Avatar + lang.addDefault("Abilities.Avatar.SpiritBeam.DeathMessage", "{victim} was erased from existence by {attacker}'s {ability}"); + lang.addDefault("Abilities.Avatar.ElementSphereAir.DeathMessage", "{victim} was blasted apart by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereFire.DeathMessage", "{victim} was burnt to cinders by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereEarth.DeathMessage", "{victim} was crushed by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereWater.DeathMessage", "{victim} was sliced apart by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereStream.DeathMessage", "{victim} took the full force of {attacker}'s \u00A75ElementSphere"); + + ConfigManager.languageConfig.save(); + } + + private void setupElementSphereNames() { + FileConfiguration lang = ConfigManager.languageConfig.get(); + + lang.addDefault("Abilities.Avatar.ElementSphereAir.Name", "Air"); + lang.addDefault("Abilities.Avatar.ElementSphereFire.Name", "Fire"); + lang.addDefault("Abilities.Avatar.ElementSphereEarth.Name", "Earth"); + lang.addDefault("Abilities.Avatar.ElementSphereWater.Name", "Water"); + lang.addDefault("Abilities.Avatar.ElementSphereStream.Name", "Stream"); + + ConfigManager.languageConfig.save(); + } + + public static ConfigurationSection getConfig(Player player) { + if (player == null) + return getConfig((World)null); + return getConfig(player.getWorld()); + } + + public static ConfigurationSection getConfig(World world) { + boolean perWorldConfig = plugin.getConfig().getBoolean("Properties.PerWorldConfig"); + + if (world == null || !perWorldConfig) { + return plugin.getConfig(); + } + + String prefix = "Worlds." + world.getName(); + return new SubsectionConfigurationDecorator(plugin.getConfig(), prefix); + } +} diff --git a/src/configuration/SubsectionConfigurationDecorator.java b/src/configuration/SubsectionConfigurationDecorator.java new file mode 100644 index 0000000..a3b76ca --- /dev/null +++ b/src/configuration/SubsectionConfigurationDecorator.java @@ -0,0 +1,668 @@ +package com.jedk1.jedcore.configuration; + +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.Configuration; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +// ConfigurationSection decorator that tries to fetch with a prefix prepended to the path. +// If that section doesn't exist, then it falls back to the parent. +public class SubsectionConfigurationDecorator implements ConfigurationSection { + private ConfigurationSection parent; + private String prefix; + + public SubsectionConfigurationDecorator(ConfigurationSection parent, String prefix) { + this.parent = parent; + this.prefix = prefix; + + if (!this.prefix.endsWith(".")) { + this.prefix += "."; + } + } + + public String getPrefix() { + return this.prefix; + } + + @Override + public Set getKeys(boolean deep) { + return parent.getKeys(deep); + } + + @Override + public Map getValues(boolean deep) { + return parent.getValues(deep); + } + + @Override + public boolean contains(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return true; + } + + return parent.contains(path); + } + + @Override + public boolean contains(String path, boolean ignoreDefault) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath, ignoreDefault)) { + return true; + } + + return parent.contains(path, ignoreDefault); + } + + @Override + public boolean isSet(String path) { + String newPath = getPrefix() + path; + + if (parent.isSet(newPath)) { + return true; + } + + return parent.isSet(path); + } + + @Override + public String getCurrentPath() { + return parent.getCurrentPath(); + } + + @Override + public String getName() { + return parent.getName(); + } + + @Override + public Configuration getRoot() { + return parent.getRoot(); + } + + @Override + public ConfigurationSection getParent() { + return parent.getParent(); + } + + @Override + public Object get(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.get(newPath); + } + + return parent.get(path); + } + + @Override + public Object get(String path, Object def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.get(newPath, def); + } + + return parent.get(path, def); + } + + @Override + public void set(String path, Object value) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + parent.set(newPath, value); + return; + } + + parent.set(path, value); + } + + @Override + public ConfigurationSection createSection(String path) { + return parent.createSection(getPrefix() + path); + } + + @Override + public ConfigurationSection createSection(String path, Map map) { + return parent.createSection(getPrefix() + path, map); + } + + @Override + public String getString(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getString(newPath); + } + + return parent.getString(path); + } + + @Override + public String getString(String path, String def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getString(newPath, def); + } + + return parent.getString(path, def); + } + + @Override + public boolean isString(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isString(newPath); + } + + return parent.isString(path); + } + + @Override + public int getInt(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getInt(newPath); + } + + return parent.getInt(path); + } + + @Override + public int getInt(String path, int def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getInt(newPath, def); + } + + return parent.getInt(path, def); + } + + @Override + public boolean isInt(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isInt(newPath); + } + + return parent.isInt(path); + } + + @Override + public boolean getBoolean(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getBoolean(newPath); + } + + return parent.getBoolean(path); + } + + @Override + public boolean getBoolean(String path, boolean def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getBoolean(newPath, def); + } + + return parent.getBoolean(path, def); + } + + @Override + public boolean isBoolean(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isBoolean(newPath); + } + + return parent.isBoolean(path); + } + + @Override + public double getDouble(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getDouble(newPath); + } + + return parent.getDouble(path); + } + + @Override + public double getDouble(String path, double def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getDouble(newPath, def); + } + + return parent.getDouble(path, def); + } + + @Override + public boolean isDouble(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isDouble(newPath); + } + + return parent.isDouble(path); + } + + @Override + public long getLong(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getLong(newPath); + } + + return parent.getLong(path); + } + + @Override + public long getLong(String path, long def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getLong(newPath, def); + } + + return parent.getLong(path, def); + } + + @Override + public boolean isLong(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isLong(newPath); + } + + return parent.isLong(path); + } + + @Override + public List getList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getList(newPath); + } + + return parent.getList(path); + } + + @Override + public List getList(String path, List def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getList(newPath, def); + } + + return parent.getList(path, def); + } + + @Override + public boolean isList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isList(newPath); + } + + return parent.isList(path); + } + + @Override + public List getStringList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getStringList(newPath); + } + + return parent.getStringList(path); + } + + @Override + public List getIntegerList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getIntegerList(newPath); + } + + return parent.getIntegerList(path); + } + + @Override + public List getBooleanList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getBooleanList(newPath); + } + + return parent.getBooleanList(path); + } + + @Override + public List getDoubleList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getDoubleList(newPath); + } + + return parent.getDoubleList(path); + } + + @Override + public List getFloatList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getFloatList(newPath); + } + + return parent.getFloatList(path); + } + + @Override + public List getLongList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getLongList(newPath); + } + + return parent.getLongList(path); + } + + @Override + public List getByteList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getByteList(newPath); + } + + return parent.getByteList(path); + } + + @Override + public List getCharacterList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getCharacterList(newPath); + } + + return parent.getCharacterList(path); + } + + @Override + public List getShortList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getShortList(newPath); + } + + return parent.getShortList(path); + } + + @Override + public List> getMapList(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getMapList(newPath); + } + + return parent.getMapList(path); + } + + @Override + public T getSerializable(String s, Class aClass) { + return parent.getSerializable(s, aClass); + } + + @Override + public T getSerializable(String s, Class aClass, T t) { + return parent.getSerializable(s, aClass, t); + } + + @Override + public T getObject(String s, Class aClass) { + return parent.getObject(s, aClass); + } + + @Override + public T getObject(String s, Class aClass, T t) { + return parent.getObject(s, aClass, t); + } + + @Override + public Vector getVector(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getVector(newPath); + } + + return parent.getVector(path); + } + + @Override + public Vector getVector(String path, Vector def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getVector(newPath, def); + } + + return parent.getVector(path, def); + } + + @Override + public boolean isVector(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isVector(newPath); + } + + return parent.isVector(path); + } + + @Override + public OfflinePlayer getOfflinePlayer(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getOfflinePlayer(newPath); + } + + return parent.getOfflinePlayer(path); + } + + @Override + public OfflinePlayer getOfflinePlayer(String path, OfflinePlayer def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getOfflinePlayer(newPath, def); + } + + return parent.getOfflinePlayer(path, def); + } + + @Override + public boolean isOfflinePlayer(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isOfflinePlayer(newPath); + } + + return parent.isOfflinePlayer(path); + } + + @Override + public ItemStack getItemStack(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getItemStack(newPath); + } + + return parent.getItemStack(path); + } + + @Override + public ItemStack getItemStack(String path, ItemStack def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getItemStack(newPath, def); + } + + return parent.getItemStack(path, def); + } + + @Override + public boolean isItemStack(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isItemStack(newPath); + } + + return parent.isItemStack(path); + } + + @Override + public Color getColor(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getColor(newPath); + } + + return parent.getColor(path); + } + + @Override + public Color getColor(String path, Color def) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getColor(newPath, def); + } + + return parent.getColor(path, def); + } + + @Override + public boolean isColor(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isColor(newPath); + } + + return parent.isColor(path); + } + + @Override + public Location getLocation(String s) { + return parent.getLocation(s); + } + + @Override + public Location getLocation(String s, Location location) { + return parent.getLocation(s, location); + } + + @Override + public boolean isLocation(String s) { + return parent.isLocation(s); + } + + @Override + public ConfigurationSection getConfigurationSection(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.getConfigurationSection(newPath); + } + + return parent.getConfigurationSection(path); + } + + @Override + public boolean isConfigurationSection(String path) { + String newPath = getPrefix() + path; + + if (parent.contains(newPath)) { + return parent.isConfigurationSection(newPath); + } + + return parent.isConfigurationSection(path); + } + + @Override + public ConfigurationSection getDefaultSection() { + return parent.getDefaultSection(); + } + + @Override + public void addDefault(String path, Object value) { + parent.addDefault(path, value); + } + + @Override + public List getComments(String s) { + return List.of(); + } + + @Override + public List getInlineComments(String s) { + return List.of(); + } + + @Override + public void setComments(String s, List list) { + + } + + @Override + public void setInlineComments(String s, List list) { + + } +} diff --git a/src/event/PKCommandEvent.java b/src/event/PKCommandEvent.java new file mode 100644 index 0000000..3886951 --- /dev/null +++ b/src/event/PKCommandEvent.java @@ -0,0 +1,69 @@ +package com.jedk1.jedcore.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class PKCommandEvent extends Event{ + + public enum CommandType { + ADD, + BIND, + CHECK, + CHOOSE, + CLEAR, + DISPLAY, + GIVE, + HELP, + IMPORT, + INVINCIBLE, + PERMREMOVE, + PRESET, + RELOAD, + REMOVE, + TOGGLE, + VERSION, + WHO, + JEDCORE; + + public static CommandType getType(String string) { + for (CommandType element : CommandType.values()) { + if (element.toString().equalsIgnoreCase(string)) { + return element; + } + } + return null; + } + } + + public static final HandlerList handlers = new HandlerList(); + private Player sender; + private CommandType type; + private String[] args; + + public PKCommandEvent(Player sender, String[] args, CommandType type) { + this.sender = sender; + this.type = type; + this.args = args; + } + + public Player getSender() { + return sender; + } + + public CommandType getType() { + return type; + } + + public String[] getArgs() { + return args; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/listener/AbilityListener.java b/src/listener/AbilityListener.java new file mode 100644 index 0000000..91d7590 --- /dev/null +++ b/src/listener/AbilityListener.java @@ -0,0 +1,569 @@ +package com.jedk1.jedcore.listener; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.ability.airbending.AirBlade; +import com.jedk1.jedcore.ability.airbending.AirBreath; +import com.jedk1.jedcore.ability.airbending.AirGlide; +import com.jedk1.jedcore.ability.airbending.AirPunch; +import com.jedk1.jedcore.ability.airbending.Meditate; +import com.jedk1.jedcore.ability.airbending.SonicBlast; +import com.jedk1.jedcore.ability.avatar.SpiritBeam; +import com.jedk1.jedcore.ability.avatar.elementsphere.ElementSphere; +import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; +import com.jedk1.jedcore.ability.earthbending.EarthKick; +import com.jedk1.jedcore.ability.earthbending.EarthLine; +import com.jedk1.jedcore.ability.earthbending.EarthPillar; +import com.jedk1.jedcore.ability.earthbending.EarthShard; +import com.jedk1.jedcore.ability.earthbending.EarthSurf; +import com.jedk1.jedcore.ability.earthbending.Fissure; +import com.jedk1.jedcore.ability.earthbending.LavaDisc; +import com.jedk1.jedcore.ability.earthbending.LavaFlux; +import com.jedk1.jedcore.ability.earthbending.LavaThrow; +import com.jedk1.jedcore.ability.earthbending.MagnetShield; +import com.jedk1.jedcore.ability.earthbending.MetalArmor; +import com.jedk1.jedcore.ability.earthbending.MetalFragments; +import com.jedk1.jedcore.ability.earthbending.MetalHook; +import com.jedk1.jedcore.ability.earthbending.MetalShred; +import com.jedk1.jedcore.ability.earthbending.MudSurge; +import com.jedk1.jedcore.ability.earthbending.SandBlast; +import com.jedk1.jedcore.ability.earthbending.combo.Crevice; +import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; +import com.jedk1.jedcore.ability.firebending.Combustion; +import com.jedk1.jedcore.ability.firebending.Discharge; +import com.jedk1.jedcore.ability.firebending.FireBall; +import com.jedk1.jedcore.ability.firebending.FireBreath; +import com.jedk1.jedcore.ability.firebending.FireComet; +import com.jedk1.jedcore.ability.firebending.FirePunch; +import com.jedk1.jedcore.ability.firebending.FireShots; +import com.jedk1.jedcore.ability.firebending.FireSki; +import com.jedk1.jedcore.ability.firebending.LightningBurst; +import com.jedk1.jedcore.ability.passive.WallRun; +import com.jedk1.jedcore.ability.waterbending.*; +import com.jedk1.jedcore.ability.waterbending.combo.WaterFlow; +import com.jedk1.jedcore.ability.waterbending.combo.WaterGimbal; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ProjectKorra; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.ability.ChiAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; +import com.projectkorra.projectkorra.airbending.Suffocate; +import com.projectkorra.projectkorra.earthbending.EarthArmor; +import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; +import com.projectkorra.projectkorra.firebending.FireJet; +import com.projectkorra.projectkorra.util.MovementHandler; +import com.projectkorra.projectkorra.waterbending.blood.Bloodbending; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerAnimationEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerToggleSneakEvent; +import org.bukkit.inventory.EquipmentSlot; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class AbilityListener implements Listener { + + JedCore plugin; + + public AbilityListener(JedCore plugin) { + this.plugin = plugin; + } + + private final List recentlyDropped = new ArrayList<>(); + + @EventHandler(priority = EventPriority.LOWEST) + // Abilities that should bypass punch cancels should be handled here. + public void onPlayerSwingBypassCancel(PlayerInteractEvent event) { + Player player = event.getPlayer(); + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { + return; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null) { + return; + } + + if (Suffocate.isBreathbent(player) || bPlayer.isChiBlocked()) { + return; + } + + if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { + return; + } + + CoreAbility coreAbil = bPlayer.getBoundAbility(); + if (coreAbil == null) { + return; + } + + if (!bPlayer.canBendIgnoreCooldowns(coreAbil)) { + return; + } + + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { + return; + } + + // FireSki bypasses punch cancel because the normal version is activated from sneaking alone. + // The punch activation exists just so people don't accidentally activate it, so they should have the same + // requirements for activation. + if (coreAbil instanceof FireJet && FireSki.isPunchActivated(player.getWorld())) { + if (player.isSneaking()) { + FireSki ski = new FireSki(player); + if (ski.isStarted() && !bPlayer.isOnCooldown("FireJet")) { + // The event only needs to be cancelled when FireSki is set to have no cooldown. + // This is to prevent FireJet from activating from the same swing event. + event.setCancelled(true); + } + } + } + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerDropItemEvent(PlayerDropItemEvent event) { + recentlyDropped.add(event.getPlayer().getUniqueId()); + Bukkit.getScheduler().runTaskLater(ProjectKorra.plugin, () -> recentlyDropped.remove(event.getPlayer().getUniqueId()), 2L); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerInventoryInteract(InventoryClickEvent event) { + InventoryAction action = event.getAction(); + if (action == InventoryAction.DROP_ALL_CURSOR || + action == InventoryAction.DROP_ALL_SLOT || + action == InventoryAction.DROP_ONE_CURSOR || + action == InventoryAction.DROP_ONE_SLOT || + action == InventoryAction.UNKNOWN) { + + recentlyDropped.add(event.getWhoClicked().getUniqueId()); + + Bukkit.getScheduler().runTaskLater(ProjectKorra.plugin, () -> { + recentlyDropped.remove(event.getWhoClicked().getUniqueId()); + }, 2L); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerSwing(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (recentlyDropped.contains(player.getUniqueId())) return; + + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { + return; + } + if (event.getAction() == Action.LEFT_CLICK_BLOCK && event.isCancelled()){ + return; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null) { + return; + } + + if (Suffocate.isBreathbent(player)) { + event.setCancelled(true); + return; + } else if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { + event.setCancelled(true); + return; + } else if (bPlayer.isChiBlocked()) { + event.setCancelled(true); + return; + } else if (GeneralMethods.isInteractable(player.getTargetBlock((Set)null, 5))) { + return; + } + + if (bPlayer.isToggled()) { + new WallRun(player); + } + + CoreAbility coreAbil = bPlayer.getBoundAbility(); + if (coreAbil == null) { + if (MultiAbilityManager.hasMultiAbilityBound(player)){ + String abil = MultiAbilityManager.getBoundMultiAbility(player); + if (abil.equalsIgnoreCase("elementsphere")) { + new ElementSphere(player); + } + } + return; + } + + String abilName = bPlayer.getBoundAbilityName(); + Class abilClass = coreAbil.getClass(); + + if (bPlayer.canBendIgnoreCooldowns(coreAbil)) { + + if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(AirBlade.class)) { + new AirBlade(player); + } + if (abilClass.equals(AirPunch.class)) { + new AirPunch(player); + } + } + + if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(EarthArmor.class)) { + new MetalArmor(player); + } + if (abilClass.equals(EarthLine.class)) { + EarthLine.shootLine(player); + } + if (abilClass.equals(EarthShard.class)) { + for (EarthShard shard : CoreAbility.getAbilities(player, EarthShard.class)) { + shard.throwShard(); // call the instance method + } + } + if (abilClass.equals(EarthSurf.class)) { + new EarthSurf(player); + } + if (abilClass.equals(Fissure.class)) { + new Fissure(player); + } + if (abilClass.equals(LavaFlux.class)) { + new LavaFlux(player); + } + if (abilClass.equals(LavaThrow.class)) { + LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); + if (lt != null) { + lt.createBlast(); + } + } + if (abilClass.equals(MetalFragments.class)) { + MetalFragments.shootFragment(player); + } + if (abilClass.equals(MetalHook.class)) { + new MetalHook(player); + } + if (abilClass.equals(MetalShred.class)) { + MetalShred.extend(player); + } + if (abilClass.equals(MudSurge.class)) { + MudSurge.mudSurge(player); + } + if (abilClass.equals(SandBlast.class)) { + SandBlast.blastSand(player); + } + if (abilClass.equals(LavaFlow.class)) { + MagmaBlast.performAction(player); + } + if (abilClass.equals(MagnetShield.class)) { + new MagnetShield(player, true); + } + } + + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(Combustion.class)) { + Combustion.combust(player); + } + if (abilClass.equals(Discharge.class)) { + new Discharge(player); + } + if (abilClass.equals(FireBall.class)) { + new FireBall(player); + } + if (abilClass.equals(FirePunch.class)) { + new FirePunch(player); + } + if (abilClass.equals(FireShots.class)) { + FireShots.fireShot(player); + } + } + + if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.WATER.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { + com.jedk1.jedcore.ability.waterbending.Bloodbending.launch(player); + } + if (abilClass.equals(BloodPuppet.class)) { + BloodPuppet.attack(player); + } + if (abilClass.equals(BloodShot.class)) { + new BloodShot(player); + } + if (abilClass.equals(IceClaws.class)) { + IceClaws.throwClaws(player); + } + if (abilName.equals("Drain")) { + Drain.fireBlast(player); + } + if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { + WaterGimbal.prepareBlast(player); + } + if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { + WaterFlow.freeze(player); + } + } + if (coreAbil instanceof ChiAbility && bPlayer.isElementToggled(Element.CHI)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Chi.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(DaggerThrow.class)) { + new DaggerThrow(player); + } + } + + if (coreAbil instanceof AvatarAbility) { + if (abilClass.equals(ElementSphere.class)) { + new ElementSphere(player); + } + } + } + } + + public static ConcurrentHashMap recent = new ConcurrentHashMap(); + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerSneak(PlayerToggleSneakEvent event) { + Player player = event.getPlayer(); + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + + if (event.isCancelled() || bPlayer == null) { + return; + } + + String abilName = bPlayer.getBoundAbilityName(); + if (Suffocate.isBreathbent(player)) { + if (!abilName.equalsIgnoreCase("AirSwipe") + && !abilName.equalsIgnoreCase("FireBlast") + && !abilName.equalsIgnoreCase("EarthBlast") + && !abilName.equalsIgnoreCase("WaterManipulation")) { + if(!player.isSneaking()) { + event.setCancelled(true); + } + } + } + + if (MovementHandler.isStopped(player) || Bloodbending.isBloodbent(player)) { + event.setCancelled(true); + return; + } + + CoreAbility coreAbil = bPlayer.getBoundAbility(); + if (coreAbil == null) { + return; + } + + Class abilClass = coreAbil.getClass(); + + if (bPlayer.isChiBlocked()) { + event.setCancelled(true); + return; + } + + if (player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (abilClass.equals(FireShots.class)) { + FireShots.swapHands(player); + } + + if (abilClass.equals(FirePunch.class)) { + FirePunch.swapHands(player); + } + } + } + + if (!player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { + if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(AirBreath.class)) { + new AirBreath(player); + } + if (abilClass.equals(AirGlide.class)) { + new AirGlide(player); + } + if (abilClass.equals(Meditate.class)) { + new Meditate(player); + } + if (abilClass.equals(SonicBlast.class)) { + new SonicBlast(player); + } + } + + if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(EarthKick.class)) { + new EarthKick(player); + } + if (abilClass.equals(EarthLine.class)) { + new EarthLine(player); + } + if (abilClass.equals(EarthPillar.class)) { + new EarthPillar(player); + } + if (abilClass.equals(EarthShard.class)) { + new EarthShard(player); + } + if (abilClass.equals(Fissure.class)) { + Fissure.performAction(player); + } + if (abilClass.equals(LavaDisc.class)) { + new LavaDisc(player); + } + if (abilClass.equals(MagnetShield.class)) { + new MagnetShield(player, false); + } + if (abilClass.equals(MetalFragments.class)) { + new MetalFragments(player); + } + if (abilClass.equals(MetalShred.class)) { + new MetalShred(player); + } + if (abilClass.equals(MudSurge.class)) { + new MudSurge(player); + } + if (abilClass.equals(SandBlast.class)) { + new SandBlast(player); + } + if (abilClass.equals(Crevice.class)) { + Crevice.closeCrevice(player); + } + if (abilClass.equals(LavaThrow.class)) { + LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); + if (lt == null) { + new LavaThrow(player); + } + } + } + + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(Combustion.class)) { + new Combustion(event.getPlayer()); + } + if (abilClass.equals(FireBreath.class)) { + new FireBreath(player); + } + if (abilClass.equals(FireComet.class)) { + new FireComet(player); + } + if (abilClass.equals(FireJet.class)) { + if (FireSki.isPunchActivated(player.getWorld())) { + FireSki fs = CoreAbility.getAbility(player, FireSki.class); + + if (fs != null) { + fs.remove(); + } + } else { + new FireSki(player); + } + } + if (abilClass.equals(FireShots.class)) { + new FireShots(player); + } + if (abilClass.equals(LightningBurst.class)) { + new LightningBurst(player); + } + } + + if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Water.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { + new com.jedk1.jedcore.ability.waterbending.Bloodbending(player); + } + if (abilClass.equals(BloodPuppet.class)) { + new BloodPuppet(player); + } + if (abilClass.equals(FrostBreath.class)) { + new FrostBreath(player); + } + if (abilClass.equals(IceClaws.class)) { + new IceClaws(player); + IceClaws.swapHands(player); + } + if (abilClass.equals(IceWall.class)) { + new IceWall(player); + } + if (abilName.equals("Drain")) { + new Drain(player); + } + if (abilClass.equals(WakeFishing.class)) { + new WakeFishing(player); + } + } + + if (coreAbil instanceof AvatarAbility) { + if (abilClass.equals(SpiritBeam.class)) { + new SpiritBeam(player); + } + } + } + } + + @EventHandler + public void onArrowHit(EntityDamageByEntityEvent event) { + if (event.getDamager().getType() == EntityType.ARROW) { + Arrow arrow = (Arrow) event.getDamager(); + if (arrow.getShooter() instanceof Player && arrow.hasMetadata("daggerthrow")) { + Player player = (Player) arrow.getShooter(); + event.setDamage(0.0D); + player.playSound(player.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 1.0f); + } + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerInteraction(PlayerInteractEvent event) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + MetalFragments.shootFragment(event.getPlayer()); + } + } + + @EventHandler + public void onChange(EntityChangeBlockEvent event) { + if (event.getEntity() instanceof FallingBlock) { + if (event.getEntity().hasMetadata("magmablast")) event.setCancelled(true); + } + } +} diff --git a/src/listener/CommandListener.java b/src/listener/CommandListener.java new file mode 100644 index 0000000..1bfb5a2 --- /dev/null +++ b/src/listener/CommandListener.java @@ -0,0 +1,76 @@ +package com.jedk1.jedcore.listener; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.command.JedCoreCommand; +import com.jedk1.jedcore.event.PKCommandEvent; +import com.jedk1.jedcore.event.PKCommandEvent.CommandType; +import com.projectkorra.projectkorra.command.PKCommand; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import java.util.Arrays; +import java.util.Objects; +import java.util.UUID; + +public class CommandListener implements Listener { + + private final JedCore plugin; + private static final String[] CMD_ALIASES = { + "/bending", "/bend", "/b", "/pk", "/projectkorra", "/korra", "/mtla", "/tla" + }; + public static final String[] DEVELOPERS = { + "4eb6315e-9dd1-49f7-b582-c1170e497ab0", // jedk1 + "d57565a5-e6b0-44e3-a026-979d5de10c4d", // s3xi + "e98a2f7d-d571-4900-a625-483cbe6774fe", // Aztl + "b6bd2ceb-4922-4707-9173-8a02044e9069", // Cozmyc + "b1318b21-5956-445c-a328-bad3175c1c7a" // Hihelloy + }; + + public CommandListener(JedCore plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerCommand(PlayerCommandPreprocessEvent event) { + String cmd = event.getMessage().toLowerCase(); + String[] args = cmd.split("\\s+"); + if (Arrays.asList(CMD_ALIASES).contains(args[0]) && args.length >= 2) { + PKCommandEvent newEvent = new PKCommandEvent(event.getPlayer(), args, null); + for (PKCommand command : PKCommand.instances.values()) { + if (Arrays.asList(command.getAliases()).contains(args[1].toLowerCase())) { + newEvent = new PKCommandEvent(event.getPlayer(), args, CommandType.getType(command.getName())); + break; + } + } + Bukkit.getServer().getPluginManager().callEvent(newEvent); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPKCommand(final PKCommandEvent event) { + // Run task using Paper/Folia-compatible scheduler API + plugin.getServer().getScheduler().runTask(plugin, () -> { + if (event.getType() != null) { + if (event.getType().equals(CommandType.WHO) && event.getSender().hasPermission("bending.command.who")) { + if (event.getArgs().length == 3) { + if (Bukkit.getPlayer(event.getArgs()[2]) != null) { + UUID uuid = Objects.requireNonNull(Bukkit.getPlayer(event.getArgs()[2])).getUniqueId(); + if (Arrays.asList(DEVELOPERS).contains(uuid.toString())) { + event.getSender().sendMessage(ChatColor.DARK_AQUA + "JedCore Developer"); + } + } + } + return; + } + if (event.getType().equals(CommandType.VERSION) && event.getSender().hasPermission("bending.command.version")) { + JedCoreCommand.sendBuildInfo(event.getSender()); + } + } + }); + } +} diff --git a/src/listener/JCListener.java b/src/listener/JCListener.java new file mode 100644 index 0000000..4ac8166 --- /dev/null +++ b/src/listener/JCListener.java @@ -0,0 +1,237 @@ +package com.jedk1.jedcore.listener; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.ability.chiblocking.Backstab; +import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; +import com.jedk1.jedcore.ability.earthbending.*; +import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; +import com.jedk1.jedcore.ability.firebending.FireBreath; +import com.jedk1.jedcore.ability.firebending.FirePunch; +import com.jedk1.jedcore.ability.firebending.FireSki; +import com.jedk1.jedcore.ability.waterbending.IceClaws; +import com.jedk1.jedcore.ability.waterbending.IceWall; +import com.jedk1.jedcore.util.LightManager; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.ProjectKorra; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.IceAbility; +import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; +import com.projectkorra.projectkorra.event.*; + +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.event.player.*; +import org.bukkit.scheduler.BukkitRunnable; + +public class JCListener implements Listener { + + JedCore plugin; + + public JCListener(JedCore plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onAbilityStart(AbilityStartEvent event) { + if (event.isCancelled()) return; + + if (event.getAbility() instanceof LavaFlow) { + Player player = event.getAbility().getPlayer(); + MagmaBlast mb = CoreAbility.getAbility(player, MagmaBlast.class); + + if (mb != null && (mb.hasBlocks() || mb.shouldBlockLavaFlow())) { + event.setCancelled(true); + LavaFlow flow = (LavaFlow) event.getAbility(); + + // Reset the cooldown of LavaFlow that was set before the call to start(). + flow.getBendingPlayer().removeCooldown(flow); + } + } else if (event.getAbility() instanceof PlantRegrowth) { + PlantRegrowth regrowth = (PlantRegrowth)event.getAbility(); + + // Stop PlantRegrowth from creating permanent snow when used against FrostBreath snow. + if (regrowth.getType() == Material.SNOW && TempBlock.isTempBlock(regrowth.getBlock())) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onFlow(BlockFromToEvent event) { + if (!LavaDisc.canFlowFrom(event.getBlock())) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onPlayerFallDamage(EntityDamageEvent event) { + if (event.isCancelled() || event.getCause() != DamageCause.FALL || !(event.getEntity() instanceof Player)) { + return; + } + + Player player = (Player)event.getEntity(); + + if (MudSurge.onFallDamage(player)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onEntityDamage(EntityDamageEvent event) { + if (event.getCause().equals(DamageCause.SUFFOCATION)) { + if (event.getEntity() instanceof LivingEntity) { + LivingEntity entity = (LivingEntity) event.getEntity(); + Block block = entity.getEyeLocation().getBlock(); + if (RegenTempBlock.blocks.containsKey(block) && IceAbility.isIce(block)) { + event.setCancelled(true); + return; + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getDamager() instanceof Player && event.getEntity() instanceof LivingEntity) { + if (event.getCause() == DamageCause.ENTITY_ATTACK && event.getDamager().getWorld().equals(event.getEntity().getWorld())) { + double distSq = event.getDamager().getLocation().distanceSquared(event.getEntity().getLocation()); + + // Only activate these in melee range + if (distSq <= 5 * 5) { + FirePunch fp = CoreAbility.getAbility((Player) event.getDamager(), FirePunch.class); + if (fp != null) { + fp.punch((LivingEntity) event.getEntity()); + event.setCancelled(true); + return; + } + + if (Backstab.punch((Player) event.getDamager(), (LivingEntity) event.getEntity())) { + event.setCancelled(true); + double damage = Backstab.getDamage(event.getDamager().getWorld()); + DamageHandler.damageEntity(event.getEntity(), (Player) event.getDamager(), damage, CoreAbility.getAbility("BackStab")); + return; + } + } + } + + if (IceClaws.freezeEntity((Player) event.getDamager(), (LivingEntity) event.getEntity())) { + event.setCancelled(true); + return; + } + } + + if (event.getDamager() instanceof Arrow arrow) { + if (event.getEntity() instanceof LivingEntity) { + if (arrow.hasMetadata("daggerthrow")) { + event.setDamage(0); + if (!(arrow.getShooter() instanceof Player shooter)) return; + if (!CoreAbility.hasAbility(shooter, DaggerThrow.class)) return; + DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); + if (daggerThrow != null) { + daggerThrow.damageEntityFromArrow(((LivingEntity) event.getEntity()), arrow); + arrow.remove(); + event.setCancelled(true); + } + } + if (arrow.hasMetadata("metalhook")) { + event.setDamage(0); + arrow.remove(); + event.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onBlockBreak(BlockBreakEvent event) { + MetalFragments.remove(event.getPlayer(), event.getBlock()); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onEntityExplode(EntityExplodeEvent event){ + if (IceWall.checkExplosions(event.getLocation(), event.getEntity())) { + event.blockList().clear(); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onCollisionWithEntity(HorizontalVelocityChangeEvent event) { + if (event.getEntity().getWorld() != event.getInstigator().getWorld()) { + return; + } + IceWall.collisionDamage(event.getEntity(), event.getDistanceTraveled(), event.getDifference(), event.getInstigator()); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerSprint(PlayerToggleSprintEvent event) { + if (!event.isSprinting()) + return; + + if (CoreAbility.hasAbility(event.getPlayer(), EarthSurf.class)) { + event.setCancelled(true); + return; + } + + if (CoreAbility.hasAbility(event.getPlayer(), FireSki.class)) { + event.setCancelled(true); + return; + } + + MetalShred.startShred(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void projectKorraReload(BendingReloadEvent event) { + final CommandSender sender = event.getSender(); + LightManager.get().restart(); + // There's a PK bug where a new collision manager is set on reload without stopping the old task. + ProjectKorra.getCollisionManager().stopCollisionDetection(); + new BukkitRunnable() { + public void run() { + JCMethods.reload(); + sender.sendMessage(ChatColor.DARK_AQUA + "JedCore config reloaded."); + } + }.runTaskLater(JedCore.plugin, 1); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onChat(AsyncPlayerChatEvent event){ + Player player = event.getPlayer(); + String msg = event.getMessage(); + + if (msg.toLowerCase().contains("bring fire and light together as one and allow the breath of color")) { + FireBreath.toggleRainbowBreath(player, true); + event.setCancelled(true); + } + + if (msg.toLowerCase().contains("split the bond of fire and light and set the color free")) { + FireBreath.toggleRainbowBreath(player, false); + event.setCancelled(true); + } + + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onItemPickup(InventoryPickupItemEvent event) { + if (event.getItem().getPickupDelay() >= Short.MAX_VALUE) { + event.setCancelled(true); + } + } +} diff --git a/src/policies/removal/CannotBendRemovalPolicy.java b/src/policies/removal/CannotBendRemovalPolicy.java new file mode 100644 index 0000000..270037c --- /dev/null +++ b/src/policies/removal/CannotBendRemovalPolicy.java @@ -0,0 +1,44 @@ +package com.jedk1.jedcore.policies.removal; + +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.CoreAbility; + +public class CannotBendRemovalPolicy implements RemovalPolicy { + private BendingPlayer bPlayer; + private boolean ignoreBinds; + private boolean ignoreCooldowns; + private CoreAbility ability; + + public CannotBendRemovalPolicy(BendingPlayer bPlayer, CoreAbility ability) { + this(bPlayer, ability, false, false); + } + + public CannotBendRemovalPolicy(BendingPlayer bPlayer, CoreAbility ability, boolean ignoreBinds, boolean ignoreCooldowns) { + this.bPlayer = bPlayer; + this.ability = ability; + this.ignoreBinds = ignoreBinds; + this.ignoreCooldowns = ignoreCooldowns; + } + + @Override + public boolean shouldRemove() { + if (this.ignoreBinds && this.ignoreCooldowns) { + return !this.bPlayer.canBendIgnoreBindsCooldowns(ability); + } + + if (this.ignoreBinds) { + return !this.bPlayer.canBendIgnoreBinds(ability); + } + + if (this.ignoreCooldowns) { + return !this.bPlayer.canBendIgnoreCooldowns(ability); + } + + return !this.bPlayer.canBend(ability); + } + + @Override + public String getName() { + return "CannotBend"; + } +} diff --git a/src/policies/removal/CompositeRemovalPolicy.java b/src/policies/removal/CompositeRemovalPolicy.java new file mode 100644 index 0000000..f9dbebf --- /dev/null +++ b/src/policies/removal/CompositeRemovalPolicy.java @@ -0,0 +1,102 @@ +package com.jedk1.jedcore.policies.removal; + +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.ability.CoreAbility; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +public class CompositeRemovalPolicy implements RemovalPolicy { + private final List policies = new ArrayList<>(); + private final CoreAbility ability; + + public CompositeRemovalPolicy(CoreAbility ability, List policies) { + if (policies != null) { + this.policies.addAll(policies); + } + this.ability = ability; + } + + public CompositeRemovalPolicy(CoreAbility ability, RemovalPolicy... policies) { + if (policies != null) { + this.policies.addAll(Arrays.asList(policies)); + } + this.ability = ability; + } + + @Override + public boolean shouldRemove() { + if (policies.isEmpty()) return false; + + for (RemovalPolicy policy : policies) { + if (policy.shouldRemove()) { + return true; + } + } + return false; + } + + /** + * Loads each policy’s configuration. + * Policies with no config or disabled ones are removed. + */ + public void load(ConfigurationSection config, String prefix) { + if (policies.isEmpty() || config == null) return; + + String pathPrefix = prefix + ".RemovalPolicy."; + + Iterator iterator = policies.iterator(); + while (iterator.hasNext()) { + RemovalPolicy policy = iterator.next(); + ConfigurationSection section = config.getConfigurationSection(pathPrefix + policy.getName()); + + if (section == null) { + iterator.remove(); + continue; + } + + if (!section.getBoolean("Enabled", true)) { + iterator.remove(); + continue; + } + + policy.load(section); + } + } + + /** + * Loads policy config using a convention: "Abilities.[Element].[AbilityName]" + */ + @Override + public void load(ConfigurationSection config) { + if (config == null || this.policies.isEmpty()) return; + + Element element = ability.getElement(); + if (element instanceof Element.SubElement) { + element = ((Element.SubElement) element).getParentElement(); + } + + String abilityName = ability.getName(); + String prefix = "Abilities." + element.getName() + "." + abilityName; + + load(config, prefix); + } + + public void addPolicy(RemovalPolicy policy) { + if (policy != null) { + this.policies.add(policy); + } + } + + public void removePolicyType(Class type) { + policies.removeIf(policy -> type.isAssignableFrom(policy.getClass())); + } + + @Override + public String getName() { + return "Composite"; + } +} diff --git a/src/policies/removal/IsDeadRemovalPolicy.java b/src/policies/removal/IsDeadRemovalPolicy.java new file mode 100644 index 0000000..81c98cb --- /dev/null +++ b/src/policies/removal/IsDeadRemovalPolicy.java @@ -0,0 +1,21 @@ +package com.jedk1.jedcore.policies.removal; + +import org.bukkit.entity.Player; + +public class IsDeadRemovalPolicy implements RemovalPolicy { + private Player player; + + public IsDeadRemovalPolicy(Player player) { + this.player = player; + } + + @Override + public boolean shouldRemove() { + return this.player == null || !this.player.isOnline() || this.player.isDead(); + } + + @Override + public String getName() { + return "IsDead"; + } +} diff --git a/src/policies/removal/IsOfflineRemovalPolicy.java b/src/policies/removal/IsOfflineRemovalPolicy.java new file mode 100644 index 0000000..9443215 --- /dev/null +++ b/src/policies/removal/IsOfflineRemovalPolicy.java @@ -0,0 +1,21 @@ +package com.jedk1.jedcore.policies.removal; + +import org.bukkit.entity.Player; + +public class IsOfflineRemovalPolicy implements RemovalPolicy { + private Player player; + + public IsOfflineRemovalPolicy(Player player) { + this.player = player; + } + + @Override + public boolean shouldRemove() { + return this.player == null || !this.player.isOnline(); + } + + @Override + public String getName() { + return "IsOffline"; + } +} diff --git a/src/policies/removal/OutOfRangeRemovalPolicy.java b/src/policies/removal/OutOfRangeRemovalPolicy.java new file mode 100644 index 0000000..ee5c394 --- /dev/null +++ b/src/policies/removal/OutOfRangeRemovalPolicy.java @@ -0,0 +1,37 @@ +package com.jedk1.jedcore.policies.removal; + +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +import java.util.function.Supplier; + +public class OutOfRangeRemovalPolicy implements RemovalPolicy { + private Supplier fromSupplier; + private Player player; + private double range; + + public OutOfRangeRemovalPolicy(Player player, double range, Supplier from) { + this.player = player; + this.range = range; + this.fromSupplier = from; + } + + @Override + public boolean shouldRemove() { + if (this.range == 0) return false; + + Location from = this.fromSupplier.get(); + return from.distanceSquared(this.player.getLocation()) >= (this.range * this.range); + } + + @Override + public void load(ConfigurationSection config) { + this.range = config.getDouble("Range"); + } + + @Override + public String getName() { + return "OutOfRange"; + } +} diff --git a/src/policies/removal/RemovalPolicy.java b/src/policies/removal/RemovalPolicy.java new file mode 100644 index 0000000..d240687 --- /dev/null +++ b/src/policies/removal/RemovalPolicy.java @@ -0,0 +1,11 @@ +package com.jedk1.jedcore.policies.removal; + +import org.bukkit.configuration.ConfigurationSection; + +public interface RemovalPolicy { + boolean shouldRemove(); + + default void load(ConfigurationSection config) { } + String getName(); +} + diff --git a/src/policies/removal/SwappedSlotsRemovalPolicy.java b/src/policies/removal/SwappedSlotsRemovalPolicy.java new file mode 100644 index 0000000..e822dd1 --- /dev/null +++ b/src/policies/removal/SwappedSlotsRemovalPolicy.java @@ -0,0 +1,26 @@ +package com.jedk1.jedcore.policies.removal; + +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.CoreAbility; + +public class SwappedSlotsRemovalPolicy implements RemovalPolicy { + private BendingPlayer bPlayer; + private Class type; + + public SwappedSlotsRemovalPolicy(BendingPlayer bPlayer, Class type) { + this.bPlayer = bPlayer; + this.type = type; + } + + @Override + public boolean shouldRemove() { + CoreAbility bound = this.bPlayer.getBoundAbility(); + + return bound == null || !bound.getClass().isAssignableFrom(type); + } + + @Override + public String getName() { + return "SwappedSlots"; + } +} diff --git a/src/util/AbilitySelector.java b/src/util/AbilitySelector.java new file mode 100644 index 0000000..6b3ca40 --- /dev/null +++ b/src/util/AbilitySelector.java @@ -0,0 +1,54 @@ +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.ability.waterbending.BloodShot; +import com.jedk1.jedcore.ability.waterbending.WaterBlast; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.earthbending.*; +import com.projectkorra.projectkorra.firebending.*; +import com.projectkorra.projectkorra.waterbending.*; +import com.projectkorra.projectkorra.waterbending.ice.*; + +import java.util.HashMap; +import java.util.Map; + +public class AbilitySelector { + private static Map specialAbilities = new HashMap<>(); + + static { + specialAbilities.put("FireBlast", CoreAbility.getAbility(FireBlast.class)); + specialAbilities.put("FireBlastCharged", CoreAbility.getAbility(FireBlastCharged.class)); + specialAbilities.put("Blaze", CoreAbility.getAbility(Blaze.class)); + specialAbilities.put("BlazeArc", CoreAbility.getAbility(BlazeArc.class)); + specialAbilities.put("BlazeRing", CoreAbility.getAbility(BlazeRing.class)); + + specialAbilities.put("WaterSpout", CoreAbility.getAbility(WaterSpout.class)); + specialAbilities.put("WaterSpoutWave", CoreAbility.getAbility(WaterSpoutWave.class)); + specialAbilities.put("Torrent", CoreAbility.getAbility(Torrent.class)); + specialAbilities.put("TorrentWave", CoreAbility.getAbility(TorrentWave.class)); + specialAbilities.put("SurgeWall", CoreAbility.getAbility(SurgeWall.class)); + specialAbilities.put("SurgeWave", CoreAbility.getAbility(SurgeWave.class)); + specialAbilities.put("IceSpike", CoreAbility.getAbility(IceSpikeBlast.class)); + specialAbilities.put("IceSpikeBlast", CoreAbility.getAbility(IceSpikeBlast.class)); + specialAbilities.put("IceSpikePillar", CoreAbility.getAbility(IceSpikePillar.class)); + specialAbilities.put("IceSpikePillarField", CoreAbility.getAbility(IceSpikePillarField.class)); + + specialAbilities.put("Shockwave", CoreAbility.getAbility(Shockwave.class)); + specialAbilities.put("Ripple", CoreAbility.getAbility(Ripple.class)); + specialAbilities.put("RaiseEarth", CoreAbility.getAbility(RaiseEarth.class)); + specialAbilities.put("RaiseEarthWall", CoreAbility.getAbility(RaiseEarthWall.class)); + specialAbilities.put("Collapse", CoreAbility.getAbility(Collapse.class)); + specialAbilities.put("CollapseWall", CoreAbility.getAbility(CollapseWall.class)); + + specialAbilities.put("WaterGimbal", CoreAbility.getAbility(WaterBlast.class)); + specialAbilities.put("BloodShot", CoreAbility.getAbility(BloodShot.class)); + } + + public static CoreAbility getAbility(String abilityName) { + CoreAbility ability = specialAbilities.get(abilityName); + + if (ability != null) + return ability; + + return CoreAbility.getAbility(abilityName); + } +} diff --git a/src/util/AirShieldReflector.java b/src/util/AirShieldReflector.java new file mode 100644 index 0000000..5b589a3 --- /dev/null +++ b/src/util/AirShieldReflector.java @@ -0,0 +1,28 @@ +package com.jedk1.jedcore.util; + +import com.projectkorra.projectkorra.airbending.AirShield; +import org.bukkit.Location; +import org.bukkit.util.Vector; + +public class AirShieldReflector { + public static void reflect(AirShield shield, Location location, Vector direction) { + Location shieldLocation = shield.getPlayer().getEyeLocation().clone(); + double radius = shield.getRadius(); + + if (shieldLocation.distanceSquared(location) > radius * radius) + return; + + Vector normal = location.toVector().subtract(shieldLocation.toVector()).normalize(); + // Move this instance so it's at the edge of the shield. + Location newLocation = shieldLocation.clone().add(normal.clone().multiply(radius)); + + location.setX(newLocation.getX()); + location.setY(newLocation.getY()); + location.setZ(newLocation.getZ()); + + // Reflect the direction about the normal. + direction.subtract(normal.clone().multiply(2 * direction.dot(normal))).normalize(); + } + + private AirShieldReflector() { } +} diff --git a/src/util/BlockUtil.java b/src/util/BlockUtil.java new file mode 100644 index 0000000..8a34f6f --- /dev/null +++ b/src/util/BlockUtil.java @@ -0,0 +1,19 @@ +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.collision.AABB; +import org.bukkit.Location; +import org.bukkit.entity.FallingBlock; + +public final class BlockUtil { + private BlockUtil() { + + } + + public static AABB getFallingBlockBoundsFull(FallingBlock fb) { + Location loc = fb.getLocation(); + + // Subtract to line the bounding box up with the corner of the box. + // The FallingBlock#getLocation returns the center of the block at the bottom. + return AABB.BlockBounds.at(loc.subtract(0.5, 0, 0.5)); + } +} diff --git a/src/util/ChiRestrictor.java b/src/util/ChiRestrictor.java new file mode 100644 index 0000000..8869cc8 --- /dev/null +++ b/src/util/ChiRestrictor.java @@ -0,0 +1,136 @@ +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.ChiAbility; +import com.projectkorra.projectkorra.event.AbilityStartEvent; +import com.projectkorra.projectkorra.event.BendingReloadEvent; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +// Stops chi abilities from being activated from ranged attacks. +// Only works on Chi abilities that have a public method with the signature "Entity getTarget()". +public class ChiRestrictor implements Listener { + private static Map, Method> cache = new HashMap<>(); + private static Set whitelist = new HashSet<>(); + + private static boolean enabled; + private static boolean resetCooldown; + private static double meleeDistanceSq; + + static { + reloadConfig(); + } + + @EventHandler + public void onBendingReload(BendingReloadEvent event) { + new BukkitRunnable() { + public void run() { + reloadConfig(); + } + }.runTaskLater(JedCore.plugin, 1); + } + + public static void reloadConfig() { + whitelist.clear(); + + ConfigurationSection config = JedCoreConfig.getConfig((Player)null); + + enabled = config.getBoolean("Properties.ChiRestrictor.Enabled"); + resetCooldown = config.getBoolean("Properties.ChiRestrictor.ResetCooldown"); + double meleeDistance = config.getDouble("Properties.ChiRestrictor.MeleeDistance"); + + meleeDistanceSq = meleeDistance * meleeDistance; + + for (String abilityName : config.getStringList("Properties.ChiRestrictor.Whitelist")) { + whitelist.add(abilityName.toLowerCase()); + } + } + + @EventHandler + public void onAbilityStart(AbilityStartEvent event) { + if (!enabled || event.isCancelled() || !(event.getAbility() instanceof ChiAbility)) { + return; + } + + ChiAbility ability = (ChiAbility)event.getAbility(); + if (isWhitelisted(ability.getName())) { + return; + } + + Entity target = getTarget(ability); + if (target == null) { + return; + } + + Player player = event.getAbility().getPlayer(); + + if (player.getWorld() != target.getWorld()) { + return; + } + + double distanceSq = target.getLocation().distanceSquared(player.getLocation()); + if (distanceSq > meleeDistanceSq) { + event.setCancelled(true); + + if (resetCooldown) { + ability.getBendingPlayer().removeCooldown(ability); + } + } + } + + private static boolean isWhitelisted(String name) { + return whitelist.contains(name.toLowerCase()); + } + + private static Entity getTarget(ChiAbility ability) { + Class clazz = ability.getClass(); + + Method method; + + // Check to see if this class was stored in cache to minimize reflection usage. + if (cache.containsKey(clazz)) { + method = cache.get(clazz); + + // method will be null when the class has already been checked and didn't have getTarget. + if (method == null) { + return null; + } + } else { + // Use reflection to see if the ability has getTarget method. + // Store this in a map to minimize reflection usage. + try { + method = clazz.getDeclaredMethod("getTarget"); + + cache.put(clazz, method); + } catch (NoSuchMethodException e) { + cache.put(clazz, null); + return null; + } + } + + // Call the getTarget method if it exists and return the Entity. + try { + Object entity = method.invoke(ability); + + if (entity instanceof Entity) { + return (Entity)entity; + } + + return null; + } catch (IllegalAccessException|InvocationTargetException e) { + return null; + } + } +} diff --git a/src/util/CollisionInitializer.java b/src/util/CollisionInitializer.java new file mode 100644 index 0000000..403baf9 --- /dev/null +++ b/src/util/CollisionInitializer.java @@ -0,0 +1,96 @@ +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.ProjectKorra; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import org.bukkit.configuration.ConfigurationSection; + +import java.util.HashMap; +import java.util.Map; + +public class CollisionInitializer { + // This is used for special mappings where collisions are stored in a separate place. + public static Map abilityMap = new HashMap<>(); + private Class type; + + public CollisionInitializer(Class type) { + this.type = type; + } + + public boolean initialize() { + CoreAbility ability = CoreAbility.getAbility(type); + + if (ability == null) return false; + + String abilityName = ability.getName(); + + Element element = ability.getElement(); + if (element instanceof Element.SubElement) { + element = ((Element.SubElement) element).getParentElement(); + if (element == null) { + element = ability.getElement(); + } + } + + if (abilityMap.containsKey(abilityName)) { + abilityName = abilityMap.get(abilityName); + } + + String collisionPath = getCollisionPath(abilityName, element); + + ConfigurationSection section = JedCore.plugin.getConfig().getConfigurationSection(collisionPath); + for (String key : section.getKeys(false)) { + ConfigurationSection abilityConfig = section.getConfigurationSection(key); + + boolean enabled = abilityConfig.getBoolean("Enabled"); + if (!enabled) continue; + + if (key.equalsIgnoreCase("-small-")) { + JedCore.logDebug("Initializing small collision for " + abilityName + "."); + ProjectKorra.getCollisionInitializer().addSmallAbility(ability); + + continue; + } else if (key.equalsIgnoreCase("-large-")) { + JedCore.logDebug("Initializing large collision for " + abilityName + "."); + ProjectKorra.getCollisionInitializer().addLargeAbility(ability); + + continue; + } + + boolean removeFirst = abilityConfig.getBoolean("RemoveFirst"); + boolean removeSecond = abilityConfig.getBoolean("RemoveSecond"); + + CoreAbility secondAbility = AbilitySelector.getAbility(key); + + if (secondAbility != null) { + JedCore.logDebug("Initializing collision for " + abilityName + " => " + key); + + ProjectKorra.getCollisionManager().addCollision(new Collision(ability, secondAbility, removeFirst, removeSecond)); + } + } + + return true; + } + + private String getCollisionPath(String abilityName, Element element) { + CoreAbility ability = CoreAbility.getAbility(abilityName); + if (ability == null) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + + sb.append("Abilities.").append(element.getName()).append("."); + + if (ability instanceof ComboAbility) { + sb.append(element.getName()).append("Combo."); + } + + sb.append(abilityName).append(".Collisions"); + + return sb.toString(); + } +} diff --git a/src/util/FireTick.java b/src/util/FireTick.java new file mode 100644 index 0000000..adb9e53 --- /dev/null +++ b/src/util/FireTick.java @@ -0,0 +1,65 @@ +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.JedCore; +import org.bukkit.entity.Entity; + +import java.util.HashMap; +import java.util.Map; + +public class FireTick { + private static Map methods = new HashMap<>(); + private static FireTickMethod method = new OverwriteFireTickMethod(); + + static { + methods.put("overwrite", new OverwriteFireTickMethod()); + methods.put("larger", new LargerFireTickMethod()); + methods.put("accumulate", new AccumulateFireTickMethod()); + } + + public static void set(Entity target, int amount) { + method.set(target, amount); + } + + public static void loadMethod() { + String methodName = JedCore.plugin.getConfig().getString("Properties.FireTickMethod"); + + FireTickMethod newMethod = methods.get(methodName.toLowerCase()); + if (newMethod != null) { + JedCore.logDebug("Using " + methodName + " as FireTickMethod."); + method = newMethod; + } else { + JedCore.plugin.getLogger().warning(methodName + " not a known FireTickMethod. Defaulting to larger method."); + method = new LargerFireTickMethod(); + } + } + + private interface FireTickMethod { + void set(Entity entity, int amount); + } + + // Always set the target's fire tick to the new amount. + private static class OverwriteFireTickMethod implements FireTickMethod { + @Override + public void set(Entity entity, int amount) { + entity.setFireTicks(amount); + } + } + + // Only overwrite target's fire tick if the new fire tick is larger. + private static class LargerFireTickMethod implements FireTickMethod { + @Override + public void set(Entity entity, int amount) { + if (entity.getFireTicks() < amount) { + entity.setFireTicks(amount); + } + } + } + + // Increase the target's fire tick instead of overwriting. + private static class AccumulateFireTickMethod implements FireTickMethod { + @Override + public void set(Entity entity, int amount) { + entity.setFireTicks(entity.getFireTicks() + amount); + } + } +} diff --git a/src/util/LightManager.java b/src/util/LightManager.java new file mode 100644 index 0000000..a48727d --- /dev/null +++ b/src/util/LightManager.java @@ -0,0 +1,443 @@ +package com.jedk1.jedcore.util; + +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ProjectKorra; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Levelled; +import org.bukkit.block.data.Waterlogged; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.concurrent.*; + +public class LightManager { + + // Our LightManager instance + private static final LightManager INSTANCE = new LightManager(); + // If the MC version is pre-LIGHT (< 1.17) this class basically does nothing + private final boolean modern; + // Striped Lock set at number of processors * 2 + private final Object[] locks; + // A map containing all active lights + private final ConcurrentHashMap> lightMap = new ConcurrentHashMap<>(); + // A queue for handling individual reversions + private final ConcurrentLinkedQueue blockChangeQueue = new ConcurrentLinkedQueue<>(); + + // Default LIGHT BlockData + private final Map lightDataMap = new HashMap<>(); + private final Map waterloggedLightDataMap = new HashMap<>(); + + // Scheduler with threads equal to the number of available processors, this handles reverting expired lights + private ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors()); + + /** + * Creates a new LightManager instance. Initializes default BlockData for LIGHT and waterlogged LIGHT, + * sets up locks based on the number of available processors * 2, and schedules the reverter task to run periodically + * using a ScheduledThreadPoolExecutor. + */ + private LightManager() { + modern = GeneralMethods.getMCVersion() >= 1170; + + int numLocks = Runtime.getRuntime().availableProcessors() * 2; + locks = new Object[numLocks]; + for (int i = 0; i < numLocks; i++) { + locks[i] = new Object(); + } + + if (modern) { + precomputeLightData(); + startLightReverter(); + } + } + + /** + * Retrieves the current time and iterates over all light data in the light map. If the current time is greater + * than or equal to the expiry time of a light data, it fades the light out and removes the light data from the map. + * This is running periodically, or every 50ms, via the scheduled thread pool executor. + */ + private void revertExpiredLights() { + long currentTime = System.currentTimeMillis(); + List lightsToRevert = new ArrayList<>(); + + lightMap.forEach((location, lightDataSet) -> { + Iterator iterator = lightDataSet.iterator(); + while (iterator.hasNext()) { + LightData lightData = iterator.next(); + if (currentTime >= lightData.expiryTime) { + lightsToRevert.add(lightData); + iterator.remove(); + } + } + if (lightDataSet.isEmpty()) { + lightMap.remove(location); + } + }); + + for (LightData lightData : lightsToRevert) { + fadeLight(lightData); + } + } + + /** + * Precomputes light data for levels 1 through 15 by creating a BlockData object for each level + * with the "LIGHT" material and setting the level using the Levelled interface. It also + * creates a waterlogged version of each light data object using the Waterlogged interface. + * The resulting objects are stored in the lightDataMap and waterloggedLightDataMap maps + * respectively. This cuts down on computation time constantly manipulating BlockData. + */ + private void precomputeLightData() { + BlockData lightData = Bukkit.createBlockData(Material.valueOf("LIGHT")); + + for (int level = 1; level <= 15; level++) { + ((Levelled) lightData).setLevel(level); + lightDataMap.put(level, lightData.clone()); + + BlockData waterloggedLightData = lightData.clone(); + ((Waterlogged) waterloggedLightData).setWaterlogged(true); + waterloggedLightDataMap.put(level, waterloggedLightData); + } + } + + /** + * Starts the light reverter task by scheduling it to run at a fixed rate of 50 milliseconds, or 1 tick. + * If the scheduler is already shut down, a new ScheduledThreadPoolExecutor is created with the number of available processors. + */ + private void startLightReverter() { + if (scheduler.isShutdown()) { + scheduler = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors()); + } + + scheduler.scheduleAtFixedRate(this::revertExpiredLights, 0, 50, TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate(this::processBlockChanges, 0, 50, TimeUnit.MILLISECONDS); + } + + /** + * Fades out a light by decrementing its brightness by 1. The light will stop fading when its brightness + * reaches 0. The fade process is scheduled to run every 50 milliseconds, or 1 tick. + * + * @param lightData the LightData object containing the light's brightness, location, UUID, and ephemeral flag + */ + private void fadeLight(LightData lightData) { + int brightness = lightData.brightness; + + class TaskHolder { + ScheduledFuture future; + } + TaskHolder taskHolder = new TaskHolder(); + + Runnable task = new Runnable() { + private int currentBrightness = brightness; + + @Override + public void run() { + currentBrightness--; + if (currentBrightness > 0) { + sendLightChange(lightData.location, currentBrightness, lightData.observers); + } else { + revertLight(lightData); + taskHolder.future.cancel(false); + } + } + }; + + taskHolder.future = scheduler.scheduleAtFixedRate(task, 0, 50, TimeUnit.MILLISECONDS); + } + + /** + * Sends a block change to the specified location. Brightness of 0 indicates that the light should be reverted. + * + * @param location the location where the light change is to be sent + * @param brightness the brightness level of the light + * @param observers the list of players who can see the light + */ + private void sendLightChange(Location location, int brightness, Collection observers) { + BlockData lightData = brightness > 0 ? getLightData(location, brightness) : getCurrentBlockData(location); + World targetWorld = location.getWorld(); + double maxDistanceSquared = Math.pow(Bukkit.getServer().getViewDistance() * 16, 2); + + observers.stream() + .filter(player -> player != null && player.isOnline() && !player.isDead() && player.getWorld().equals(targetWorld)) + .filter(player -> player.getLocation().distanceSquared(location) <= maxDistanceSquared) + .forEach(player -> blockChangeQueue.add(new BlockChange(player, location, lightData))); + } + + private void processBlockChanges() { + BlockChange blockChange; + while ((blockChange = blockChangeQueue.poll()) != null) { + Player player = blockChange.getPlayer(); + BlockChange finalBlockChange = blockChange; + Bukkit.getScheduler().runTaskAsynchronously(ProjectKorra.plugin, () -> { + player.sendBlockChange(finalBlockChange.getLocation(), finalBlockChange.getBlockData()); + }); + } + } + + /** + * Helper method to revert a light at the specified location by calling sendLightChange with a brightness of 0. + * + * @param lightData the LightData object containing the location, brightness, UUID, and ephemeral flag of the light to be reverted + */ + private void revertLight(LightData lightData) { + sendLightChange(lightData.location, 0, lightData.observers); + } + + /** + * Returns the BlockData as light for the given Location, based on whether the block is water or air. + * + * @param location the Location to get the BlockData for + * @param lightLevel the light level to set for the BlockData + * @return the BlockData for the given Location + */ + private BlockData getLightData(Location location, int lightLevel) { + if (location.getBlock().getType() == Material.WATER) { + return waterloggedLightDataMap.get(lightLevel); + } else { + return lightDataMap.get(lightLevel); + } + } + + /** + * Returns the BlockData for the given Location, based on the current state of the block. + * Used to revert lights that have expired. + * + * @param location the Location to get the BlockData for + * @return the BlockData for the given Location + */ + private BlockData getCurrentBlockData(Location location) { + return location.getBlock().getBlockData(); + } + + public static LightManager get() { + return INSTANCE; + } + + /** + * Creates a new LightBuilder instance with the given location. + * + * @param location the location where the light will be created + * @return a new LightBuilder instance + */ + public static LightBuilder createLight(Location location) { + return new LightBuilder(location); + } + + /** + * Adds a light at the specified location with the given brightness and expiry. + * Visible for the specified observers. + * Subsequent calls to a location with an active light extends the expiration time for the relevant observers. + * + * @param location the location where the light should be added + * @param brightness the brightness of the light, 1-15 + * @param expiry the time in milliseconds before the light fades out + * @param observers the list of players who can see the light + */ + private void addLight(Location location, int brightness, long expiry, Collection observers) { + if (!modern) return; + + location = location.getBlock().getLocation(); + long expiryTime = System.currentTimeMillis() + expiry; + + if (location.getBlock().getLightLevel() >= brightness || + (!location.getBlock().isEmpty() && !location.getBlock().getType().equals(Material.WATER))) return; + + LightData newLightData = new LightData(location, brightness, observers, expiryTime); + + Object lock = getLockForLocation(location); + synchronized (lock) { + ConcurrentSkipListSet existingSet = lightMap.computeIfAbsent(location, loc -> new ConcurrentSkipListSet<>()); + existingSet.removeIf(lightData -> lightData.observers.equals(observers)); + existingSet.add(newLightData); + } + + sendLightChange(location, brightness, observers); + } + + /** + * Returns the lock object associated with the given location. The lock object + * is used to synchronize access to the light data for the location. The + * function calculates the hash code of the location and uses it to determine + * the index of the lock object in the locks array. The locks array is + * initialized with a fixed number of objects based on the number of available + * processors * 2. + * + * @param location the location for which the lock object is requested + * @return the lock object associated with the location + */ + private Object getLockForLocation(Location location) { + return locks[(location.hashCode() & 0x7FFFFFFF) % locks.length]; + } + + /** + * Reverts all active lights immediately with no fade-out, then restarts the revert scheduler. + * This does not normally need to be used as it's already called when ProjectKorra is reloaded. + */ + public void restart() { + if (!modern) return; + + lightMap.values().forEach(set -> set.forEach(this::revertLight)); + lightMap.clear(); + + scheduler.shutdown(); + + try { + if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { + scheduler.shutdownNow(); + } + } catch (InterruptedException e) { + scheduler.shutdownNow(); + Thread.currentThread().interrupt(); + } + + startLightReverter(); + } + + private static class LightData implements Comparable { + private final Location location; + private final int brightness; + private final Collection observers; + private final long expiryTime; + + private LightData(Location location, int brightness, Collection observers, long expiryTime) { + this.location = location; + this.brightness = brightness; + this.observers = observers; + this.expiryTime = expiryTime; + } + + /** + * Calculates the hash code for this object. The hash code is based on the + * values of the location, brightness, observers, and expiryTime fields. + * + * @return the hash code of this object + */ + @Override + public int hashCode() { + return Objects.hash(location, brightness, observers, expiryTime); + } + + /** + * Checks if this LightData object is equal to another object. Two LightData objects are considered + * equal if they have the same brightness, expiryTime, location, and observers. + * + * @param obj the object to compare this LightData object to + * @return true if the objects are equal, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + LightData that = (LightData) obj; + return brightness == that.brightness && + expiryTime == that.expiryTime && + location.equals(that.location) && + observers.equals(that.observers); + } + + /** + * Returns a string representation of the LightData object. + * + * @return a string in the format "LightData{location=..., brightness=..., observers=..., expiryTime=...}" + */ + @Override + public String toString() { + return "LightData{" + + "location=" + location + + ", brightness=" + brightness + + ", observers=" + observers + + ", expiryTime=" + expiryTime + + '}'; + } + + /** + * Compares this LightData object with another LightData object based on their expiryTime. + * + * @param other the LightData object to compare to + * @return a negative integer, zero, or a positive integer as this object's + * expiryTime is less than, equal to, or greater than the other object's + * expiryTime. + */ + @Override + public int compareTo(LightData other) { + return Long.compare(this.expiryTime, other.expiryTime); + } + } + + public static class LightBuilder { + private final Location location; + private int brightness = 15; // default brightness + private long timeUntilFade = 50; // default expiry time in ms + private Collection observers = Bukkit.getOnlinePlayers(); // default to all players + + public LightBuilder(Location location) { + this.location = location; + } + + /** + * Sets the brightness value, 1-15, for this light. + * + * @param brightness the new brightness value, a value 1-15. + * @return the current instance of the LightBuilder + */ + public LightBuilder brightness(int brightness) { + this.brightness = Math.max(1, Math.min(15, brightness)); + return this; + } + + /** + * Sets the expiry time in ms for this light, defaults to 50ms. + * + * @param expiry the new expiry time in milliseconds + * @return the current instance of the LightBuilder + */ + public LightBuilder timeUntilFadeout(long expiry) { + this.timeUntilFade = expiry; + return this; + } + + /** + * Sets the collection of observers for this light, defaults to everybody. + * + * @param observers the collection of observers to set + * @return the current instance of the LightBuilder + */ + public LightBuilder observers(Collection observers) { + this.observers = observers; + return this; + } + + /** + * Emits this light at the specified location with the given brightness, expiry time, and observers. + */ + public void emit() { + LightManager.get().addLight(location, brightness, timeUntilFade, observers); + } + } + + private static class BlockChange { + private final Player player; + private final Location location; + private final BlockData blockData; + + public BlockChange(Player player, Location location, BlockData blockData) { + this.player = player; + this.location = location; + this.blockData = blockData; + } + + public Player getPlayer() { + return player; + } + + public Location getLocation() { + return location; + } + + public BlockData getBlockData() { + return blockData; + } + } +} \ No newline at end of file diff --git a/src/util/MaterialUtil.java b/src/util/MaterialUtil.java new file mode 100644 index 0000000..25d74c7 --- /dev/null +++ b/src/util/MaterialUtil.java @@ -0,0 +1,48 @@ +package com.jedk1.jedcore.util; + +import com.projectkorra.projectkorra.GeneralMethods; + +import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.block.Block; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MaterialUtil { + + // todo: use the registry/tags (with config) or grab directly from PKs config maybe? + private static final List TRANSPARENT_MATERIALS = new ArrayList(){{ + addAll(Arrays.asList( + Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.OAK_SAPLING, Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, + Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, Material.DARK_OAK_SAPLING, Material.WATER, + Material.LAVA, Material.COBWEB, Material.TALL_GRASS, Material.GRASS, Material.FERN, Material.DEAD_BUSH, + Material.DANDELION, Material.POPPY, Material.BLUE_ORCHID, Material.ALLIUM, + Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, + Material.OXEYE_DAISY, Material.BROWN_MUSHROOM, Material.RED_MUSHROOM, Material.TORCH, Material.FIRE, + Material.WHEAT, Material.SNOW, Material.SUGAR_CANE, Material.VINE, Material.SUNFLOWER, Material.LILAC, + Material.LARGE_FERN, Material.ROSE_BUSH, Material.PEONY)); + if (GeneralMethods.getMCVersion() >= 1170) { + add(Material.getMaterial("LIGHT")); + } + }}; + + public static boolean isSign(Material material) { + return Tag.SIGNS.isTagged(material); + } + + public static boolean isSign(Block block) { + return isSign(block.getType()); + } + + // Do a fast lookup by avoiding the region protection check. + public static boolean isTransparent(Block block) { + return isTransparent(block.getType()); + } + + // Do a fast lookup by avoiding the region protection check. + public static boolean isTransparent(Material material) { + return TRANSPARENT_MATERIALS.contains(material); + } +} diff --git a/src/util/MetricsLite.java b/src/util/MetricsLite.java new file mode 100644 index 0000000..b93fb90 --- /dev/null +++ b/src/util/MetricsLite.java @@ -0,0 +1,535 @@ +/* + * Copyright 2011-2013 Tyler Blair. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and contributors and should not be interpreted as representing official policies, + * either expressed or implied, of anybody else. + */ + +package com.jedk1.jedcore.util; + +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.scheduler.BukkitTask; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Method; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.UUID; +import java.util.logging.Level; +import java.util.zip.GZIPOutputStream; + +public class MetricsLite { + + /** + * The current revision number + */ + private final static int REVISION = 7; + + /** + * The base url of the metrics domain + */ + private static final String BASE_URL = "http://report.mcstats.org"; + + /** + * The url used to report a server's status + */ + private static final String REPORT_URL = "/plugin/%s"; + + /** + * Interval of time to ping (in minutes) + */ + private final static int PING_INTERVAL = 15; + + /** + * The plugin this metrics submits for + */ + private final Plugin plugin; + + /** + * The plugin configuration file + */ + private final YamlConfiguration configuration; + + /** + * The plugin configuration file + */ + private final File configurationFile; + + /** + * Unique server id + */ + private final String guid; + + /** + * Debug mode + */ + private final boolean debug; + + /** + * Lock for synchronization + */ + private final Object optOutLock = new Object(); + + /** + * Id of the scheduled task + */ + private volatile BukkitTask task = null; + + public MetricsLite(Plugin plugin) throws IOException { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } + + this.plugin = plugin; + + // load the config + configurationFile = getConfigFile(); + configuration = YamlConfiguration.loadConfiguration(configurationFile); + + // add some defaults + configuration.addDefault("opt-out", false); + configuration.addDefault("guid", UUID.randomUUID().toString()); + configuration.addDefault("debug", false); + + // Do we need to create the file? + if (configuration.get("guid", null) == null) { + configuration.options().header("http://mcstats.org").copyDefaults(true); + configuration.save(configurationFile); + } + + // Load the guid then + guid = configuration.getString("guid"); + debug = configuration.getBoolean("debug", false); + } + + /** + * Start measuring statistics. This will immediately create an async repeating task as the plugin and send + * the initial data to the metrics backend, and then after that it will post in increments of + * PING_INTERVAL * 1200 ticks. + * + * @return True if statistics measuring is running, otherwise false. + */ + public boolean start() { + synchronized (optOutLock) { + // Did we opt out? + if (isOptOut()) { + return false; + } + + // Is metrics already running? + if (task != null) { + return true; + } + + // Begin hitting the server with glorious data + task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { + + private boolean firstPost = true; + + public void run() { + try { + // This has to be synchronized or it can collide with the disable method. + synchronized (optOutLock) { + // Disable Task, if it is running and the server owner decided to opt-out + if (isOptOut() && task != null) { + task.cancel(); + task = null; + } + } + + // We use the inverse of firstPost because if it is the first time we are posting, + // it is not a interval ping, so it evaluates to FALSE + // Each time thereafter it will evaluate to TRUE, i.e PING! + postPlugin(!firstPost); + + // After the first post we set firstPost to false + // Each post thereafter will be a ping + firstPost = false; + } catch (IOException e) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); + } + } + } + }, 0, PING_INTERVAL * 1200); + + return true; + } + } + + /** + * Has the server owner denied plugin metrics? + * + * @return true if metrics should be opted out of it + */ + public boolean isOptOut() { + synchronized (optOutLock) { + try { + // Reload the metrics file + configuration.load(getConfigFile()); + } catch (IOException | InvalidConfigurationException ex) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + } + return true; + } + return configuration.getBoolean("opt-out", false); + } + } + + /** + * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. + * + * @throws java.io.IOException + */ + public void enable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (isOptOut()) { + configuration.set("opt-out", false); + configuration.save(configurationFile); + } + + // Enable Task, if it is not running + if (task == null) { + start(); + } + } + } + + /** + * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. + * + * @throws java.io.IOException + */ + public void disable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (!isOptOut()) { + configuration.set("opt-out", true); + configuration.save(configurationFile); + } + + // Disable Task, if it is running + if (task != null) { + task.cancel(); + task = null; + } + } + } + + /** + * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status + * + * @return the File object for the config file + */ + public File getConfigFile() { + // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use + // is to abuse the plugin object we already have + // plugin.getDataFolder() => base/plugins/PluginA/ + // pluginsFolder => base/plugins/ + // The base is not necessarily relative to the startup directory. + File pluginsFolder = plugin.getDataFolder().getParentFile(); + + // return => base/plugins/PluginMetrics/config.yml + return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); + } + + /** + * Gets the online player (backwards compatibility) + * + * @return online player amount + */ + private int getOnlinePlayers() { + try { + Method onlinePlayerMethod = Server.class.getMethod("getOnlinePlayers"); + if(onlinePlayerMethod.getReturnType().equals(Collection.class)) { + return ((Collection)onlinePlayerMethod.invoke(Bukkit.getServer())).size(); + } else { + return ((Player[])onlinePlayerMethod.invoke(Bukkit.getServer())).length; + } + } catch (Exception ex) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + } + } + + return 0; + } + + /** + * Generic method that posts a plugin to the metrics website + */ + private void postPlugin(boolean isPing) throws IOException { + // Server software specific section + PluginDescriptionFile description = plugin.getDescription(); + String pluginName = description.getName(); + boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled + String pluginVersion = description.getVersion(); + String serverVersion = Bukkit.getVersion(); + int playersOnline = this.getOnlinePlayers(); + + // END server software specific section -- all code below does not use any code outside of this class / Java + + // Construct the post data + StringBuilder json = new StringBuilder(1024); + json.append('{'); + + // The plugin's description file containg all of the plugin data such as name, version, author, etc + appendJSONPair(json, "guid", guid); + appendJSONPair(json, "plugin_version", pluginVersion); + appendJSONPair(json, "server_version", serverVersion); + appendJSONPair(json, "players_online", Integer.toString(playersOnline)); + + // New data as of R6 + String osname = System.getProperty("os.name"); + String osarch = System.getProperty("os.arch"); + String osversion = System.getProperty("os.version"); + String java_version = System.getProperty("java.version"); + int coreCount = Runtime.getRuntime().availableProcessors(); + + // normalize os arch .. amd64 -> x86_64 + if (osarch.equals("amd64")) { + osarch = "x86_64"; + } + + appendJSONPair(json, "osname", osname); + appendJSONPair(json, "osarch", osarch); + appendJSONPair(json, "osversion", osversion); + appendJSONPair(json, "cores", Integer.toString(coreCount)); + appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); + appendJSONPair(json, "java_version", java_version); + + // If we're pinging, append it + if (isPing) { + appendJSONPair(json, "ping", "1"); + } + + // close json + json.append('}'); + + // Create the url + URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); + + // Connect to the website + URLConnection connection; + + // Mineshafter creates a socks proxy, so we can safely bypass it + // It does not reroute POST requests so we need to go around it + if (isMineshafterPresent()) { + connection = url.openConnection(Proxy.NO_PROXY); + } else { + connection = url.openConnection(); + } + + + byte[] uncompressed = json.toString().getBytes(); + byte[] compressed = gzip(json.toString()); + + // Headers + connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("Content-Encoding", "gzip"); + connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + + connection.setDoOutput(true); + + if (debug) { + System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); + } + + // Write the data + OutputStream os = connection.getOutputStream(); + os.write(compressed); + os.flush(); + + // Now read the response + final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String response = reader.readLine(); + + // close resources + os.close(); + reader.close(); + + if (response == null || response.startsWith("ERR") || response.startsWith("7")) { + if (response == null) { + response = "null"; + } else if (response.startsWith("7")) { + response = response.substring(response.startsWith("7,") ? 2 : 1); + } + + throw new IOException(response); + } + } + + /** + * GZip compress a string of bytes + * + * @param input + * @return + */ + public static byte[] gzip(String input) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream gzos = null; + + try { + gzos = new GZIPOutputStream(baos); + gzos.write(input.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (gzos != null) try { + gzos.close(); + } catch (IOException ignore) { + } + } + + return baos.toByteArray(); + } + + /** + * Check if mineshafter is present. If it is, we need to bypass it to send POST requests + * + * @return true if mineshafter is installed on the server + */ + private boolean isMineshafterPresent() { + try { + Class.forName("mineshafter.MineServer"); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Appends a json encoded key/value pair to the given string builder. + * + * @param json + * @param key + * @param value + * @throws UnsupportedEncodingException + */ + private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { + boolean isValueNumeric = false; + + try { + if (value.equals("0") || !value.endsWith("0")) { + Double.parseDouble(value); + isValueNumeric = true; + } + } catch (NumberFormatException e) { + isValueNumeric = false; + } + + if (json.charAt(json.length() - 1) != '{') { + json.append(','); + } + + json.append(escapeJSON(key)); + json.append(':'); + + if (isValueNumeric) { + json.append(value); + } else { + json.append(escapeJSON(value)); + } + } + + /** + * Escape a string to create a valid JSON string + * + * @param text + * @return + */ + private static String escapeJSON(String text) { + StringBuilder builder = new StringBuilder(); + + builder.append('"'); + for (int index = 0; index < text.length(); index++) { + char chr = text.charAt(index); + + switch (chr) { + case '"': + case '\\': + builder.append('\\'); + builder.append(chr); + break; + case '\b': + builder.append("\\b"); + break; + case '\t': + builder.append("\\t"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + default: + if (chr < ' ') { + String t = "000" + Integer.toHexString(chr); + builder.append("\\u" + t.substring(t.length() - 4)); + } else { + builder.append(chr); + } + break; + } + } + builder.append('"'); + + return builder.toString(); + } + + /** + * Encode text as UTF-8 + * + * @param text the text to encode + * @return the encoded text, as UTF-8 + */ + private static String urlEncode(final String text) throws UnsupportedEncodingException { + return URLEncoder.encode(text, "UTF-8"); + } + +} \ No newline at end of file diff --git a/src/util/PaperLib.java b/src/util/PaperLib.java new file mode 100644 index 0000000..1a00a91 --- /dev/null +++ b/src/util/PaperLib.java @@ -0,0 +1,96 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.JedCore; +import java.util.concurrent.CompletableFuture; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; + +public class PaperLib { + private static Environment ENVIRONMENT; + + public static CompletableFuture getChunkAtAsync(Location location) { + return ENVIRONMENT.getChunkAtAsync(location); + } + + public static CompletableFuture getChunkAtAsync(Block block) { + return ENVIRONMENT.getChunkAtAsync(block); + } + + public static CompletableFuture teleportAsync(Entity entity, Location location) { + return ENVIRONMENT.teleportAsync(entity, location); + } + + public static CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { + return ENVIRONMENT.teleportAsync(entity, location, cause); + } + + static { + if (JedCore.isFolia()) { + ENVIRONMENT = new Folia(); + } else if (JedCore.isPaper()) { + ENVIRONMENT = new Paper(); + } else { + ENVIRONMENT = new Spigot(); + } + + } + + private interface Environment { + default CompletableFuture getChunkAtAsync(Location location) { + return this.getChunkAtAsync(location.getBlock()); + } + + CompletableFuture getChunkAtAsync(Block var1); + + default CompletableFuture teleportAsync(Entity entity, Location location) { + return this.teleportAsync(entity, location, TeleportCause.PLUGIN); + } + + CompletableFuture teleportAsync(Entity var1, Location var2, PlayerTeleportEvent.TeleportCause var3); + } + + static class Spigot implements Environment { + public CompletableFuture getChunkAtAsync(Block block) { + return CompletableFuture.completedFuture(block.getChunk()); + } + + public CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { + entity.teleport(location, cause); + return CompletableFuture.completedFuture(true); + } + } + + static class Paper implements Environment { + public CompletableFuture getChunkAtAsync(Block block) { + return block.getWorld().getChunkAtAsync(block); + } + + public CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { + return entity.teleportAsync(location, cause); + } + } + + static class Folia implements Environment { + public CompletableFuture getChunkAtAsync(Block block) { + CompletableFuture future = new CompletableFuture(); + ThreadUtil.ensureLocation(block.getLocation(), () -> { + Chunk chunk = block.getWorld().getChunkAt(block); + future.complete(chunk); + }); + return future; + } + + public CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { + return entity.teleportAsync(location, cause); + } + } +} diff --git a/src/util/RegenTempBlock.java b/src/util/RegenTempBlock.java new file mode 100644 index 0000000..56794f6 --- /dev/null +++ b/src/util/RegenTempBlock.java @@ -0,0 +1,193 @@ +package com.jedk1.jedcore.util; + +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.util.TempBlock; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.BlockData; +import org.bukkit.inventory.InventoryHolder; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class RegenTempBlock { + + public static Map blocks = new HashMap<>(); + public static Map temps = new HashMap<>(); + public static Map states = new HashMap<>(); + + /** + * Creates a TempBlock that reverts after a delay. + * @param block Block to be updated/reverted. + * @param material Material to be changed. + * @param data Data to be changed. + * @param delay Delay until block regens. + */ + public RegenTempBlock(Block block, Material material, BlockData data, long delay) { + this(block, material, data, delay, true); + } + + /** + * Creates a TempBlock or a State of a block that reverts after a certain time. + * @param block Block to be updated/reverted. + * @param material Material to be changed. + * @param data Data to be changed. + * @param delay Delay until block regens. + * @param temp Use TempBlock or BlockState. + */ + @SuppressWarnings("deprecation") + public RegenTempBlock(Block block, Material material, BlockData data, long delay, boolean temp) { + this(block, material, data, delay, temp, null); + } + + public RegenTempBlock(Block block, Material material, BlockData data, long delay, boolean temp, RegenCallback callback) { + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + if (block.getState() instanceof InventoryHolder || block.getType() == Material.JUKEBOX) { + return; + } + if (blocks.containsKey(block)) { + blocks.replace(block, new RegenBlockData(System.currentTimeMillis() + delay, callback)); + block.setBlockData(data.clone()); + } else { + blocks.put(block, new RegenBlockData(System.currentTimeMillis() + delay, callback)); + if (TempBlock.isTempBlock(block)) { + TempBlock.get(block).revertBlock(); + } + if (temp) { + TempBlock tb = new TempBlock(block, data.clone()); + temps.put(block, tb); + } else { + states.put(block, block.getState()); + if (material != null) { + block.setBlockData(data.clone()); + } + } + } + } + + /** + * Manages blocks to be reverted. + */ + public static void manage() { + Iterator> iterator = blocks.entrySet().iterator(); + + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + + Block b = entry.getKey(); + RegenBlockData blockData = entry.getValue(); + + if (System.currentTimeMillis() >= blockData.endTime) { + TempBlock tb = temps.get(b); + if (tb != null) { + tb.revertBlock(); + temps.remove(b); + } + + BlockState bs = states.get(b); + if (bs != null) { + bs.update(true); + states.remove(b); + } + + iterator.remove(); + + if (blockData.callback != null) { + blockData.callback.onRegen(b); + } + } + } + } + + /** + * Reverts an individual block. + * @param block + */ + public static void revert(Block block) { + if (blocks.containsKey(block)) { + if (TempBlock.isTempBlock(block) && temps.containsKey(block)) { + TempBlock tb = TempBlock.get(block); + tb.revertBlock(); + temps.remove(block); + } + if (states.containsKey(block)) { + states.get(block).update(true); + states.remove(block); + } + blocks.remove(block); + } + } + + /** + * Reverts all blocks. + */ + public static void revertAll() { + for (Block b : blocks.keySet()) { + if (temps.containsKey(b)) { + TempBlock tb = temps.get(b); + tb.revertBlock(); + } + if (states.containsKey(b)) { + states.get(b).update(true); + } + } + temps.clear(); + states.clear(); + blocks.clear(); + } + + /** + * Returns true if the block is a RegenTempBlock. + * @param block + * @return + */ + public static boolean hasBlock(Block block) { + if (blocks.containsKey(block)) { + return true; + } + return false; + } + + /** + * Returns true if the block is stored as a temp block. + * @param block + * @return + */ + public static boolean isTempBlock(Block block) { + if (temps.containsKey(block)) { + return true; + } + return false; + } + + /** + * Returns true if the block is stored as a block state. + * @param block + * @return + */ + public static boolean isBlockState(Block block) { + if (states.containsKey(block)) { + return true; + } + return false; + } + + private static class RegenBlockData { + long endTime; + RegenCallback callback; + + public RegenBlockData(long endTime, RegenCallback callback) { + this.endTime = endTime; + this.callback = callback; + } + } + + public interface RegenCallback { + void onRegen(Block block); + } +} diff --git a/src/util/TempFallingBlock.java b/src/util/TempFallingBlock.java new file mode 100644 index 0000000..0590657 --- /dev/null +++ b/src/util/TempFallingBlock.java @@ -0,0 +1,151 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package com.jedk1.jedcore.util; + +import com.projectkorra.projectkorra.ability.CoreAbility; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.FallingBlock; +import org.bukkit.util.Vector; + +public class TempFallingBlock { + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap> instancesByAbility = new ConcurrentHashMap(); + private FallingBlock fallingblock; + private CoreAbility ability; + private long creation; + private boolean expire; + private Consumer onPlace; + + public TempFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability) { + this(location, data, velocity, ability, false); + } + + public TempFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability, boolean expire) { + this.fallingblock = location.getWorld().spawnFallingBlock(location, data.clone()); + this.fallingblock.setVelocity(velocity); + this.fallingblock.setDropItem(false); + this.ability = ability; + this.creation = System.currentTimeMillis(); + this.expire = expire; + instances.put(this.fallingblock, this); + if (!instancesByAbility.containsKey(ability)) { + instancesByAbility.put(ability, new HashSet()); + } + + ((Set)instancesByAbility.get(ability)).add(this); + } + + public static void manage() { + long time = System.currentTimeMillis(); + + for(TempFallingBlock tfb : instances.values()) { + if (tfb.canExpire() && time > tfb.getCreationTime() + 5000L) { + tfb.remove(); + } else if (time > tfb.getCreationTime() + 120000L) { + tfb.remove(); + } + } + + } + + public static TempFallingBlock get(FallingBlock fallingblock) { + return isTempFallingBlock(fallingblock) ? (TempFallingBlock)instances.get(fallingblock) : null; + } + + public static boolean isTempFallingBlock(FallingBlock fallingblock) { + return instances.containsKey(fallingblock); + } + + public static void removeFallingBlock(FallingBlock fallingblock) { + if (isTempFallingBlock(fallingblock)) { + TempFallingBlock tempFallingBlock = (TempFallingBlock)instances.get(fallingblock); + Objects.requireNonNull(fallingblock); + ThreadUtil.ensureEntity(fallingblock, fallingblock::remove); + instances.remove(fallingblock); + ((Set)instancesByAbility.get(tempFallingBlock.ability)).remove(tempFallingBlock); + if (((Set)instancesByAbility.get(tempFallingBlock.ability)).isEmpty()) { + instancesByAbility.remove(tempFallingBlock.ability); + } + } + + } + + public static void removeAllFallingBlocks() { + for(FallingBlock fallingblock : instances.keySet()) { + Objects.requireNonNull(fallingblock); + ThreadUtil.ensureEntity(fallingblock, fallingblock::remove); + } + + instances.clear(); + instancesByAbility.clear(); + } + + public static Set getFromAbility(CoreAbility ability) { + return (Set)instancesByAbility.getOrDefault(ability, new HashSet()); + } + + public void remove() { + FallingBlock var10000 = this.fallingblock; + FallingBlock var10001 = this.fallingblock; + Objects.requireNonNull(var10001); + ThreadUtil.ensureEntity(var10000, var10001::remove); + instances.remove(this.fallingblock); + } + + public FallingBlock getFallingBlock() { + return this.fallingblock; + } + + public CoreAbility getAbility() { + return this.ability; + } + + public Material getMaterial() { + return this.fallingblock.getBlockData().getMaterial(); + } + + public BlockData getMaterialData() { + return this.fallingblock.getBlockData(); + } + + public BlockData getData() { + return this.fallingblock.getBlockData(); + } + + public Location getLocation() { + return this.fallingblock.getLocation(); + } + + public long getCreationTime() { + return this.creation; + } + + public boolean canExpire() { + return this.expire; + } + + public void tryPlace() { + if (this.onPlace != null) { + this.onPlace.accept(this); + } + + } + + public Consumer getOnPlace() { + return this.onPlace; + } + + public void setOnPlace(Consumer onPlace) { + this.onPlace = onPlace; + } +} diff --git a/src/util/TemporaryFallingBlock.java b/src/util/TemporaryFallingBlock.java new file mode 100644 index 0000000..3a21650 --- /dev/null +++ b/src/util/TemporaryFallingBlock.java @@ -0,0 +1,29 @@ +package com.jedk1.jedcore.util; + +import com.projectkorra.projectkorra.ability.CoreAbility; +import org.bukkit.Location; +import org.bukkit.block.data.BlockData; +import org.bukkit.util.Vector; + +public class TemporaryFallingBlock extends TempFallingBlock { + + private final Location originalLocation; + + public TemporaryFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability) { + super(location, data, velocity, ability); + originalLocation = location.clone(); + } + + public Location getOriginalLocation() { + return originalLocation; + } + + public boolean hasMoved() { + Location currentLocation = getFallingBlock().getLocation(); + return currentLocation.getX() != originalLocation.getX() || currentLocation.getZ() != originalLocation.getZ(); + } + + public void resetToOriginalLocation() { + getFallingBlock().teleport(originalLocation); + } +} diff --git a/src/util/ThreadUtil.java b/src/util/ThreadUtil.java new file mode 100644 index 0000000..ffd46d7 --- /dev/null +++ b/src/util/ThreadUtil.java @@ -0,0 +1,209 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.JedCore; +import io.papermc.paper.threadedregions.scheduler.RegionScheduler; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; + +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; + +public class ThreadUtil { + + public static void ensureMainThread(Runnable runnable) { + if (Bukkit.isPrimaryThread()) { + runnable.run(); + } else { + throw new IllegalStateException("Runnable must be called from the main thread in Folia/Paper"); + } + } + + public static T EnsureMainThread(Callable supplier) { + if (Bukkit.isPrimaryThread()) { + try { + return supplier.call(); + } catch (Exception e) { + throw new RuntimeException("Failed to get value on main thread", e); + } + } else { + throw new IllegalStateException("Must be called from the main thread in Folia/Paper"); + } + } + + public static T ensureMainThread2(Supplier supplier) { + if (Bukkit.isPrimaryThread()) { + return supplier.get(); + } else { + throw new IllegalStateException("Operation must be performed on the main thread."); + } + } + + public static void ensureEntity(Entity entity, Runnable runnable) { + if (JedCore.isFolia()) { + if (Bukkit.isOwnedByCurrentRegion(entity) || Bukkit.isStopping()) { + runnable.run(); + return; + } + + entity.getScheduler().execute(JedCore.plugin, runnable, (Runnable)null, 1L); + } else { + if (Bukkit.isPrimaryThread()) { + runnable.run(); + return; + } + + Bukkit.getScheduler().runTask(JedCore.plugin, runnable); + } + + } + + public static void ensureEntityDelay(Entity entity, Runnable runnable, long delay) { + delay = Math.max(1L, delay); + if (JedCore.isFolia()) { + entity.getScheduler().execute(JedCore.plugin, runnable, (Runnable)null, delay); + } else { + Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); + } + + } + + public static Object ensureEntityTimer(Entity entity, Runnable runnable, long delay, long repeat) { + delay = Math.max(1L, delay); + return JedCore.isFolia() ? entity.getScheduler().runAtFixedRate(JedCore.plugin, (task) -> runnable.run(), (Runnable)null, delay, repeat) : Bukkit.getScheduler().runTaskTimer(JedCore.plugin, runnable, delay, repeat); + } + + public static void ensureLocation(Location location, Runnable runnable) { + if (JedCore.isFolia()) { + if (Bukkit.isOwnedByCurrentRegion(location) || Bukkit.isStopping()) { + runnable.run(); + return; + } + + RegionScheduler scheduler = Bukkit.getRegionScheduler(); + scheduler.execute(JedCore.plugin, location, runnable); + } else { + if (Bukkit.isPrimaryThread()) { + runnable.run(); + return; + } + + Bukkit.getScheduler().runTask(JedCore.plugin, runnable); + } + + } + + public static void ensureLocationDelay(@NotNull Location location, Runnable runnable, long delay) { + delay = Math.max(1L, delay); + if (JedCore.isFolia()) { + RegionScheduler scheduler = Bukkit.getRegionScheduler(); + scheduler.runDelayed(JedCore.plugin, location, (task) -> runnable.run(), delay); + } else { + Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); + } + + } + + public static Object ensureLocationTimer(Location location, Runnable runnable, long delay, long repeat) { + delay = Math.max(1L, delay); + if (JedCore.isFolia()) { + RegionScheduler scheduler = Bukkit.getRegionScheduler(); + return scheduler.runAtFixedRate(JedCore.plugin, location, (task) -> runnable.run(), delay, repeat); + } else { + return Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); + } + } + + public static void runAsync(Runnable runnable) { + if (JedCore.isFolia()) { + if (Bukkit.isStopping()) { + runnable.run(); + return; + } + + Bukkit.getAsyncScheduler().runNow(JedCore.plugin, (task) -> runnable.run()); + } else { + Bukkit.getScheduler().runTaskAsynchronously(JedCore.plugin, runnable); + } + + } + + public static void runAsyncLater(Runnable runnable, long delay) { + delay = Math.max(1L, delay); + if (JedCore.isFolia()) { + Bukkit.getAsyncScheduler().runDelayed(JedCore.plugin, (task) -> runnable.run(), delay * 50L, TimeUnit.MILLISECONDS); + } else { + Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); + } + + } + + public static Object runAsyncTimer(Runnable runnable, long delay, long repeat) { + delay = Math.max(1L, delay); + return JedCore.isFolia() ? Bukkit.getAsyncScheduler().runAtFixedRate(JedCore.plugin, (task) -> runnable.run(), delay * 50L, repeat * 50L, TimeUnit.MILLISECONDS) : Bukkit.getScheduler().runTaskTimerAsynchronously(JedCore.plugin, runnable, delay, repeat); + } + + public static void runSync(Runnable runnable) { + if (JedCore.isFolia()) { + if (Bukkit.isStopping()) { + runnable.run(); + return; + } + + Bukkit.getGlobalRegionScheduler().run(JedCore.plugin, (task) -> runnable.run()); + } else { + Bukkit.getScheduler().runTask(JedCore.plugin, runnable); + } + + } + + public static Object runSyncLater(Runnable runnable, long delay) { + delay = Math.max(1L, delay); + return JedCore.isFolia() ? Bukkit.getGlobalRegionScheduler().runDelayed(JedCore.plugin, (task) -> runnable.run(), delay) : Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); + } + + public static Object runSyncTimer(Runnable runnable, long delay, long repeat) { + delay = Math.max(1L, delay); + return JedCore.isFolia() ? Bukkit.getGlobalRegionScheduler().runAtFixedRate(JedCore.plugin, (task) -> runnable.run(), delay, repeat) : Bukkit.getScheduler().runTaskTimer(JedCore.plugin, runnable, delay, repeat); + } + + public static boolean cancelTimerTask(Object task) { + if (task == null) { + return false; + } else { + if (JedCore.isFolia()) { + if (task instanceof ScheduledTask) { + ((ScheduledTask)task).cancel(); + return true; + } + } else if (task instanceof BukkitTask) { + ((BukkitTask)task).cancel(); + return true; + } + + return false; + } + } + + public static boolean isTaskCancelled(Object task) { + if (JedCore.isFolia()) { + if (task instanceof ScheduledTask) { + return ((ScheduledTask)task).isCancelled(); + } + } else if (task instanceof BukkitTask) { + return ((BukkitTask)task).isCancelled(); + } + + return false; + } +} diff --git a/src/util/ThrownEntityTracker.java b/src/util/ThrownEntityTracker.java new file mode 100644 index 0000000..a2ac646 --- /dev/null +++ b/src/util/ThrownEntityTracker.java @@ -0,0 +1,93 @@ +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.Ability; +import com.projectkorra.projectkorra.util.DamageHandler; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class ThrownEntityTracker { + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static boolean collisions = JedCore.plugin.getConfig().getBoolean("Properties.MobCollisions.Enabled"); + private long delay; + private long fireTime; + private Entity entity; + private Player instigator; + private Vector thisVelocity; + private Ability ability; + + public ThrownEntityTracker(Ability ability, Entity e, Player instigator, long delay) { + entity = e; + this.instigator = instigator; + fireTime = System.currentTimeMillis(); + this.delay = delay; + thisVelocity = e.getVelocity(); + this.delay = delay; + instances.put(entity, this); + } + + public void update() { + if (System.currentTimeMillis() < fireTime + delay) { + return; + } + if (!collisions || entity.isOnGround()) { + remove(); + return; + } + thisVelocity = entity.getVelocity().clone(); + List nearby = GeneralMethods.getEntitiesAroundPoint(entity.getLocation(), 2D); + if (nearby.contains(entity)) { + nearby.remove(entity); + } + if (nearby.contains(instigator)) { + nearby.remove(instigator); + } + if (nearby.size() != 0) { + entity.setVelocity(thisVelocity.multiply(0.5D)); + for(Entity e : nearby){ + e.setVelocity(entity.getVelocity().multiply(0.25D).add(GeneralMethods.getDirection(entity.getLocation(), e.getLocation()).multiply(2))); + if (e instanceof LivingEntity) { + DamageHandler.damageEntity(e, 2D, ability); + } + if (entity instanceof LivingEntity) { + DamageHandler.damageEntity(entity, 1D, ability); + ((LivingEntity) entity).setNoDamageTicks(0); + } + } + remove(); + } + } + + public static void updateAll() { + for (Entity entity : instances.keySet()) { + if (entity == null) { + instances.remove(entity); + continue; + } + instances.get(entity).update(); + } + } + + public void remove() { + remove(entity); + } + + public static void remove(Entity entity) { + if (instances.containsKey(entity)) { + instances.remove(entity); + } + } + + public static void removeAll() { + instances.clear(); + } + +} diff --git a/src/util/versionadapter/ParticleAdapter.java b/src/util/versionadapter/ParticleAdapter.java new file mode 100644 index 0000000..45edae3 --- /dev/null +++ b/src/util/versionadapter/ParticleAdapter.java @@ -0,0 +1,8 @@ +package com.jedk1.jedcore.util.versionadapter; + +import org.bukkit.Location; + +public interface ParticleAdapter { + void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha); + void displayMagneticParticles(Location location); +} diff --git a/src/util/versionadapter/ParticleAdapterFactory.java b/src/util/versionadapter/ParticleAdapterFactory.java new file mode 100644 index 0000000..50284b7 --- /dev/null +++ b/src/util/versionadapter/ParticleAdapterFactory.java @@ -0,0 +1,25 @@ +package com.jedk1.jedcore.util.versionadapter; + +import com.projectkorra.projectkorra.GeneralMethods; +import org.bukkit.Bukkit; + +public class ParticleAdapterFactory { + + private ParticleAdapter adapter; + + public ParticleAdapterFactory() { + int serverVersion = GeneralMethods.getMCVersion(); + + if (serverVersion >= 1205) { + Bukkit.getLogger().info("[JedCore] Using 1.20.5+ ParticleAdapter"); + adapter = new ParticleAdapter_1_20_5(); + } else { + Bukkit.getLogger().info("[JedCore] Using 1.20.4- ParticleAdapter"); + adapter = new ParticleAdapter_1_20_4(); + } + } + + public ParticleAdapter getAdapter() { + return adapter; + } +} \ No newline at end of file diff --git a/src/util/versionadapter/ParticleAdapter_1_20_4.java b/src/util/versionadapter/ParticleAdapter_1_20_4.java new file mode 100644 index 0000000..4d29090 --- /dev/null +++ b/src/util/versionadapter/ParticleAdapter_1_20_4.java @@ -0,0 +1,30 @@ +package com.jedk1.jedcore.util.versionadapter; + +import org.bukkit.*; + +public class ParticleAdapter_1_20_4 implements ParticleAdapter { + + @Override + public void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { + if (location.getWorld() == null) return; + int[] color = hexToRgb(hex); + if (alpha < 255) { + location.getWorld().spawnParticle(Particle.valueOf("SPELL_MOB_AMBIENT"), location, 0, color[0] / 255D, color[1] / 255D, color[2] / 255D, 1); + } else { + location.getWorld().spawnParticle(Particle.valueOf("SPELL_MOB"), location, 0, color[0] / 255D, color[1] / 255D, color[2] / 255D, 1); + } + } + + @Override + public void displayMagneticParticles(Location location) { + location.getWorld().spawnParticle(Particle.valueOf("ASH"), location, 1, 0, 0, 0, 0.03); + } + + private int[] hexToRgb(String hex) { + return new int[] { + Integer.valueOf(hex.substring(1, 3), 16), + Integer.valueOf(hex.substring(3, 5), 16), + Integer.valueOf(hex.substring(5, 7), 16) + }; + } +} \ No newline at end of file diff --git a/src/util/versionadapter/ParticleAdapter_1_20_5.java b/src/util/versionadapter/ParticleAdapter_1_20_5.java new file mode 100644 index 0000000..0813924 --- /dev/null +++ b/src/util/versionadapter/ParticleAdapter_1_20_5.java @@ -0,0 +1,26 @@ +package com.jedk1.jedcore.util.versionadapter; + +import org.bukkit.*; + +public class ParticleAdapter_1_20_5 implements ParticleAdapter { + + @Override + public void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { + if (location.getWorld() == null) return; + int[] color = hexToRgb(hex); + location.getWorld().spawnParticle(Particle.valueOf("ENTITY_EFFECT"), location, amount, extra, offsetX, offsetY, offsetZ, Color.fromARGB(alpha, color[0], color[1], color[2])); + } + + @Override + public void displayMagneticParticles(Location location) { + location.getWorld().spawnParticle(Particle.valueOf("MYCELIUM"), location, 1, 0, 0, 0, 0.01); + } + + private int[] hexToRgb(String hex) { + return new int[] { + Integer.valueOf(hex.substring(1, 3), 16), + Integer.valueOf(hex.substring(3, 5), 16), + Integer.valueOf(hex.substring(5, 7), 16) + }; + } +} diff --git a/src/util/versionadapter/PotionEffectAdapter.java b/src/util/versionadapter/PotionEffectAdapter.java new file mode 100644 index 0000000..f4fbb53 --- /dev/null +++ b/src/util/versionadapter/PotionEffectAdapter.java @@ -0,0 +1,15 @@ +package com.jedk1.jedcore.util.versionadapter; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionType; + +public interface PotionEffectAdapter { + PotionType getHarmingPotionType(); + PotionEffect getSlownessEffect(int duration, int strength); + PotionEffect getResistanceEffect(int duration, int strength); + PotionEffect getNauseaEffect(int duration); + void applyJumpBoost(Player player, int duration, int strength); + boolean hasWaterPotion(Inventory inventory); +} diff --git a/src/util/versionadapter/PotionEffectAdapterFactory.java b/src/util/versionadapter/PotionEffectAdapterFactory.java new file mode 100644 index 0000000..e4b67c7 --- /dev/null +++ b/src/util/versionadapter/PotionEffectAdapterFactory.java @@ -0,0 +1,25 @@ +package com.jedk1.jedcore.util.versionadapter; + +import com.projectkorra.projectkorra.GeneralMethods; +import org.bukkit.Bukkit; + +public class PotionEffectAdapterFactory { + + private PotionEffectAdapter adapter; + + public PotionEffectAdapterFactory() { + int serverVersion = GeneralMethods.getMCVersion(); + + if (serverVersion >= 1205) { + Bukkit.getLogger().info("[JedCore] Using 1.20.5+ PotionEffectAdapter"); + adapter = new PotionEffectAdapter_1_20_5(); + } else { + Bukkit.getLogger().info("[JedCore] Using 1.20.4- PotionEffectAdapter"); + adapter = new PotionEffectAdapter_1_20_4(); + } + } + + public PotionEffectAdapter getAdapter() { + return adapter; + } +} diff --git a/src/util/versionadapter/PotionEffectAdapter_1_20_4.java b/src/util/versionadapter/PotionEffectAdapter_1_20_4.java new file mode 100644 index 0000000..b79e91e --- /dev/null +++ b/src/util/versionadapter/PotionEffectAdapter_1_20_4.java @@ -0,0 +1,55 @@ +package com.jedk1.jedcore.util.versionadapter; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionType; + +public class PotionEffectAdapter_1_20_4 implements PotionEffectAdapter { + + @Override + public PotionType getHarmingPotionType() { + return PotionType.valueOf("INSTANT_DAMAGE"); + } + + @Override + public PotionEffect getSlownessEffect(int duration, int strength) { + return new PotionEffect(PotionEffectType.getByName("SLOW"), duration / 50, strength); + } + + @Override + public PotionEffect getResistanceEffect(int duration, int strength) { + return new PotionEffect(PotionEffectType.getByName("DAMAGE_RESISTANCE"), duration / 50, strength - 1); + } + + @Override + public PotionEffect getNauseaEffect(int duration) { + return new PotionEffect(PotionEffectType.getByName("CONFUSION"), duration / 50, 1); + } + + @Override + public void applyJumpBoost(Player player, int duration, int strength) { + if (player.hasPotionEffect(PotionEffectType.getByName("JUMP"))) { + player.removePotionEffect(PotionEffectType.getByName("JUMP")); + } + player.addPotionEffect(new PotionEffect(PotionEffectType.getByName("JUMP"), duration / 50, strength - 1)); + } + + @Override + public boolean hasWaterPotion(Inventory inventory) { + if (inventory.contains(Material.POTION)) { + ItemStack item = inventory.getItem(inventory.first(Material.POTION)); + if (item == null) return false; + PotionMeta meta = (PotionMeta) item.getItemMeta(); + if (meta == null) return false; + + PotionType potionType = PotionMetaUtil.getPotionType(meta); + return potionType == PotionType.WATER; + } + return false; + } +} diff --git a/src/util/versionadapter/PotionEffectAdapter_1_20_5.java b/src/util/versionadapter/PotionEffectAdapter_1_20_5.java new file mode 100644 index 0000000..1ef51b1 --- /dev/null +++ b/src/util/versionadapter/PotionEffectAdapter_1_20_5.java @@ -0,0 +1,55 @@ +package com.jedk1.jedcore.util.versionadapter; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionType; + +public class PotionEffectAdapter_1_20_5 implements PotionEffectAdapter { + + @Override + public PotionType getHarmingPotionType() { + return PotionType.valueOf("HARMING"); + } + + @Override + public PotionEffect getSlownessEffect(int duration, int strength) { + return new PotionEffect(PotionEffectType.getByName("SLOWNESS"), duration / 50, strength - 1); + } + + @Override + public PotionEffect getResistanceEffect(int duration, int strength) { + return new PotionEffect(PotionEffectType.getByName("RESISTANCE"), duration / 50, strength - 1); + } + + @Override + public PotionEffect getNauseaEffect(int duration) { + return new PotionEffect(PotionEffectType.getByName("NAUSEA"), duration / 50, 1); + } + + @Override + public void applyJumpBoost(Player player, int duration, int strength) { + if (player.hasPotionEffect(PotionEffectType.getByName("JUMP_BOOST"))) { + player.removePotionEffect(PotionEffectType.getByName("JUMP_BOOST")); + } + player.addPotionEffect(new PotionEffect(PotionEffectType.getByName("JUMP_BOOST"), duration / 50, strength - 1)); + } + + @Override + public boolean hasWaterPotion(Inventory inventory) { + if (inventory.contains(Material.POTION)) { + ItemStack item = inventory.getItem(inventory.first(Material.POTION)); + if (item == null) return false; + PotionMeta meta = (PotionMeta) item.getItemMeta(); + if (meta == null) return false; + + PotionType potionType = PotionMetaUtil.getPotionType(meta); + return potionType == PotionType.WATER; + } + return false; + } +} \ No newline at end of file diff --git a/src/util/versionadapter/PotionMetaUtil.java b/src/util/versionadapter/PotionMetaUtil.java new file mode 100644 index 0000000..1d82431 --- /dev/null +++ b/src/util/versionadapter/PotionMetaUtil.java @@ -0,0 +1,29 @@ +package com.jedk1.jedcore.util.versionadapter; + +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionType; + +import java.lang.reflect.Method; + +public class PotionMetaUtil { + + public static PotionType getPotionType(PotionMeta meta) { + try { + Method getBasePotionType = PotionMeta.class.getMethod("getBasePotionType"); + return (PotionType) getBasePotionType.invoke(meta); + } catch (NoSuchMethodException e) { + try { + Method getBasePotionData = PotionMeta.class.getMethod("getBasePotionData"); + Object basePotionData = getBasePotionData.invoke(meta); + + Method getType = basePotionData.getClass().getMethod("getType"); + return (PotionType) getType.invoke(basePotionData); + } catch (Exception ex) { + ex.printStackTrace(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } +} \ No newline at end of file From 87f098af2e100a476f767e6a9832011dc294e375 Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 3 Aug 2025 19:21:01 -0700 Subject: [PATCH 48/61] Delete plugin.yml --- plugin.yml | 109 ----------------------------------------------------- 1 file changed, 109 deletions(-) delete mode 100644 plugin.yml diff --git a/plugin.yml b/plugin.yml deleted file mode 100644 index 5eb7f75..0000000 --- a/plugin.yml +++ /dev/null @@ -1,109 +0,0 @@ -name: JedCore -main: com.jedk1.jedcore.JedCore -version: ${project.version} -authors: ['jedk1'] -depend: [ProjectKorra] -folia-supported: true -api-version: '1.20' -load: POSTWORLD -description: "A cool ProjectKorra addon plugin" - -permissions: - # OP permissions - jedcore.admin: - default: op - description: Access to abilities and commands. - children: - jedcore.admin.notify: true - bending.ability.SwiftStream: true - bending.ability.BloodPuppet: true - bending.ability.PlantDrain: true - bending.ability.Fissure: true - bending.ability.LavaFlux: true - bending.ability.FireBreath.RainbowBreath: true - bending.ability.ElementSphere: true - bending.ability.ElementSphere.Air: true - bending.ability.ElementSphere.Earth: true - bending.ability.ElementSphere.Fire: true - bending.ability.ElementSphere.Water: true - bending.ability.ElementSphere.Stream: true - bending.ability.Maelstrom: true - bending.ability.SpiritBeam: true - - # Player Permissions - jedcore.commands: - default: true - description: Access to player commands. - children: - bending.command.jedcore: true - - jedcore.passive: - default: true - description: Access to passive abilities. - children: - bending.ability.WallRun: true - - jedcore.air: - default: true - description: Access to air abilities. - children: - bending.ability.AirBlade: true - bending.ability.AirBreath: true - bending.ability.AirPunch: true - bending.ability.AirGlide: true - bending.ability.Meditate: true - bending.ability.SonicBlast: true - bending.ability.AirSlam: true - - jedcore.water: - default: true - description: Access to water abilities. - children: - bending.ability.FrostBreath: true - bending.ability.IceClaws: true - bending.ability.IceSkate: true - bending.ability.IceWall: true - bending.ability.Drain: true - bending.ability.WakeFishing: true - bending.ability.WaterFlow: true - bending.ability.WaterGimbal: true - - jedcore.earth: - default: true - description: Access to earth abilities. - children: - bending.ability.Crevice: true - bending.ability.EarthKick: true - bending.ability.EarthLine: true - bending.ability.EarthPillar: true - bending.ability.EarthShard: true - bending.ability.EarthSurf: true - bending.ability.LavaDisc: true - bending.ability.LavaThrow: true - bending.ability.MagnetShield: true - bending.ability.MetalFragments: true - bending.ability.MetalHook: true - bending.ability.MetalShred: true - bending.ability.MudSurge: true - bending.ability.SandBlast: true - bending.ability.MagmaBlast: true - - jedcore.fire: - default: true - description: Access to fire abilities. - children: - bending.ability.Combustion: true - bending.ability.Discharge: true - bending.ability.FireBall: true - bending.ability.FireBreath: true - bending.ability.FireComet: true - bending.ability.FirePunch: true - bending.ability.FireShots: true - bending.ability.LightningBurst: true - - jedcore.chi: - default: true - description: Access to chi abilities. - children: - bending.ability.Backstab: true - bending.ability.DaggerThrow: true From c60e8a8e0cd4648c8e470dcbd07fde8d1c09b0df Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 3 Aug 2025 19:21:18 -0700 Subject: [PATCH 49/61] Update plugin.yml --- src/plugin.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/plugin.yml b/src/plugin.yml index acae96d..5eb7f75 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -2,10 +2,14 @@ name: JedCore main: com.jedk1.jedcore.JedCore version: ${project.version} authors: ['jedk1'] -depend: ['ProjectKorra'] -api-version: 1.20 +depend: [ProjectKorra] +folia-supported: true +api-version: '1.20' +load: POSTWORLD +description: "A cool ProjectKorra addon plugin" + permissions: - #OP permissions + # OP permissions jedcore.admin: default: op description: Access to abilities and commands. @@ -25,17 +29,20 @@ permissions: bending.ability.ElementSphere.Stream: true bending.ability.Maelstrom: true bending.ability.SpiritBeam: true - #Player Permissions + + # Player Permissions jedcore.commands: default: true description: Access to player commands. children: bending.command.jedcore: true + jedcore.passive: default: true description: Access to passive abilities. children: bending.ability.WallRun: true + jedcore.air: default: true description: Access to air abilities. @@ -47,6 +54,7 @@ permissions: bending.ability.Meditate: true bending.ability.SonicBlast: true bending.ability.AirSlam: true + jedcore.water: default: true description: Access to water abilities. @@ -59,6 +67,7 @@ permissions: bending.ability.WakeFishing: true bending.ability.WaterFlow: true bending.ability.WaterGimbal: true + jedcore.earth: default: true description: Access to earth abilities. @@ -78,6 +87,7 @@ permissions: bending.ability.MudSurge: true bending.ability.SandBlast: true bending.ability.MagmaBlast: true + jedcore.fire: default: true description: Access to fire abilities. @@ -90,9 +100,10 @@ permissions: bending.ability.FirePunch: true bending.ability.FireShots: true bending.ability.LightningBurst: true + jedcore.chi: default: true description: Access to chi abilities. children: bending.ability.Backstab: true - bending.ability.DaggerThrow: true \ No newline at end of file + bending.ability.DaggerThrow: true From 476f419d87e53308fe9743e7faeab95dd0caf70c Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 3 Aug 2025 19:35:37 -0700 Subject: [PATCH 50/61] Update README.md (added the correct discord hyper-link) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96909e1..36de89a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ # JedCore This is my fork of Cozymc's fork of plushmonkey's fork of jedk1's JedCore addon for ProjectKorra. Download releases [here](https://github.com/Hihelloy-main/JedCore/releases). -Join our [Discord]() to discuss the plugin, suggest changes, report bugs, etc (new Discord soon). +Join our [Discord](https://discord.gg/gh9MfDmwZm) to discuss the plugin, suggest changes, report bugs, etc. ## Changelog From 6460c3a2e3b2487b1d57971eeedc443ed65bb611 Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Mon, 4 Aug 2025 07:26:18 -0700 Subject: [PATCH 51/61] Update README.md Added the correct hyper-links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 36de89a..a4b8a39 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![GitHub Pre-Release](https://img.shields.io/github/release-pre/Hihelloy-main/JedCore.svg)](https://github.com/CozmycDev/JedCore/releases) -[![Github All Releases](https://img.shields.io/github/downloads/Hihelloy-main/JedCore/total.svg)](https://github.com/CozmycDev/JedCore/releases) +[![GitHub Pre-Release](https://img.shields.io/github/release-pre/Hihelloy-main/JedCore.svg)](https://github.com/Hihelloy-main/JedCore/releases) +[![Github All Releases](https://img.shields.io/github/downloads/Hihelloy-main/JedCore/total.svg)](https://github.com/Hihelloy-main/JedCore/releases) ![Size](https://img.shields.io/github/repo-size/Hihelloy-main/JedCore.svg) # JedCore From 78704de372acb1adb788800fe7ef98e3371aae1c Mon Sep 17 00:00:00 2001 From: Hihelloy-main Date: Thu, 23 Oct 2025 19:02:10 -0700 Subject: [PATCH 52/61] 2.15.1-PRE-RELEASE-3 Switches from Paper to Spigot and much more I am too lazy to get into right now. --- pom.xml | 74 +- src/JCManager.java | 27 - src/JCMethods.java | 356 ---------- src/ability/airbending/AirBlade.java | 276 -------- src/ability/avatar/elementsphere/ESEarth.java | 219 ------ .../avatar/elementsphere/ElementSphere.java | 523 -------------- src/ability/chiblocking/DaggerThrow.java | 348 --------- src/ability/earthbending/EarthKick.java | 336 --------- src/ability/earthbending/EarthLine.java | 492 ------------- src/ability/earthbending/EarthPillar.java | 216 ------ src/ability/earthbending/EarthShard.java | 274 -------- src/ability/earthbending/EarthSurf.java | 503 ------------- src/ability/earthbending/Fissure.java | 441 ------------ src/ability/earthbending/LavaDisc.java | 553 --------------- src/ability/earthbending/LavaFlux.java | 451 ------------ src/ability/earthbending/LavaThrow.java | 344 --------- src/ability/earthbending/MagnetShield.java | 281 -------- src/ability/earthbending/MetalArmor.java | 212 ------ src/ability/earthbending/MetalFragments.java | 430 ------------ src/ability/earthbending/MetalHook.java | 396 ----------- src/ability/earthbending/MetalShred.java | 483 ------------- src/ability/earthbending/MudSurge.java | 654 ----------------- src/ability/earthbending/SandBlast.java | 377 ---------- src/ability/earthbending/combo/Crevice.java | 370 ---------- .../earthbending/combo/MagmaBlast.java | 615 ---------------- src/ability/firebending/Combustion.java | 629 ----------------- src/ability/firebending/FireBreath.java | 427 ----------- src/ability/firebending/FireShots.java | 416 ----------- src/ability/firebending/LightningBurst.java | 370 ---------- src/ability/waterbending/BloodPuppet.java | 511 -------------- src/ability/waterbending/BloodShot.java | 131 ---- src/ability/waterbending/Bloodbending.java | 377 ---------- src/ability/waterbending/Drain.java | 605 ---------------- src/ability/waterbending/FrostBreath.java | 440 ------------ src/ability/waterbending/HealingWaters.java | 267 ------- src/ability/waterbending/IceClaws.java | 299 -------- src/com/jedk1/jedcore/JCManager.java | 29 + src/com/jedk1/jedcore/JCMethods.java | 356 ++++++++++ src/{ => com/jedk1/jedcore}/JedCore.java | 53 +- .../jedcore/ability/airbending/AirBlade.java | 331 +++++++++ .../ability/airbending/AirBreath.java | 0 .../jedcore}/ability/airbending/AirGlide.java | 0 .../jedcore}/ability/airbending/AirPunch.java | 0 .../jedcore}/ability/airbending/Meditate.java | 0 .../ability/airbending/SonicBlast.java | 0 .../ability/airbending/combo/AirSlam.java | 0 .../ability/airbending/combo/SwiftStream.java | 0 .../jedcore}/ability/avatar/SpiritBeam.java | 0 .../ability/avatar/elementsphere/ESAir.java | 0 .../ability/avatar/elementsphere/ESEarth.java | 215 ++++++ .../ability/avatar/elementsphere/ESFire.java | 0 .../avatar/elementsphere/ESStream.java | 0 .../ability/avatar/elementsphere/ESWater.java | 0 .../avatar/elementsphere/ElementSphere.java | 520 ++++++++++++++ .../ability/chiblocking/Backstab.java | 11 +- .../ability/chiblocking/DaggerThrow.java | 351 ++++++++++ .../ability/earthbending/EarthKick.java | 343 +++++++++ .../ability/earthbending/EarthLine.java | 490 +++++++++++++ .../ability/earthbending/EarthPillar.java | 215 ++++++ .../ability/earthbending/EarthShard.java | 528 ++++++++++++++ .../ability/earthbending/EarthSurf.java | 505 ++++++++++++++ .../jedcore/ability/earthbending/Fissure.java | 439 ++++++++++++ .../ability/earthbending/LavaDisc.java | 555 +++++++++++++++ .../ability/earthbending/LavaFlux.java | 445 ++++++++++++ .../ability/earthbending/LavaThrow.java | 340 +++++++++ .../ability/earthbending/MagnetShield.java | 274 ++++++++ .../ability/earthbending/MetalArmor.java | 211 ++++++ .../ability/earthbending/MetalFragments.java | 426 +++++++++++ .../ability/earthbending/MetalHook.java | 395 +++++++++++ .../ability/earthbending/MetalShred.java | 486 +++++++++++++ .../ability/earthbending/MudSurge.java | 660 ++++++++++++++++++ .../ability/earthbending/SandBlast.java | 376 ++++++++++ .../ability/earthbending/combo/Crevice.java | 374 ++++++++++ .../earthbending/combo/MagmaBlast.java | 617 ++++++++++++++++ .../ability/firebending/Combustion.java | 622 +++++++++++++++++ .../ability/firebending/Discharge.java | 1 - .../ability/firebending/FireBall.java | 21 +- .../ability/firebending/FireBreath.java | 422 +++++++++++ .../ability/firebending/FireComet.java | 1 - .../ability/firebending/FirePunch.java | 9 +- .../ability/firebending/FireShots.java | 411 +++++++++++ .../jedcore}/ability/firebending/FireSki.java | 1 - .../ability/firebending/LightningBurst.java | 369 ++++++++++ .../jedcore}/ability/passive/WallRun.java | 1 - .../ability/waterbending/BloodPuppet.java | 512 ++++++++++++++ .../ability/waterbending/Bloodbending.java | 376 ++++++++++ .../jedcore/ability/waterbending/Drain.java | 598 ++++++++++++++++ .../ability/waterbending/DrainBlast.java | 1 - .../ability/waterbending/FrostBreath.java | 439 ++++++++++++ .../ability/waterbending/HealingWaters.java | 268 +++++++ .../ability/waterbending/IceClaws.java | 330 +++++++++ .../ability/waterbending/IcePassive.java | 2 - .../jedcore/ability/waterbending/IceWall.java | 610 ++++++++++++++++ .../ability/waterbending/WakeFishing.java | 235 +++++++ .../ability/waterbending/WaterBlast.java | 244 +++++++ .../ability/waterbending/combo/Maelstrom.java | 1 - .../ability/waterbending/combo/WaterFlow.java | 6 +- .../waterbending/combo/WaterGimbal.java | 3 +- src/com/jedk1/jedcore/collision/AABB.java | 183 +++++ src/com/jedk1/jedcore/collision/Collider.java | 12 + .../jedcore/collision/CollisionDetector.java | 127 ++++ .../jedcore/collision/CollisionUtil.java | 34 + src/com/jedk1/jedcore/collision/Ray.java | 38 + src/com/jedk1/jedcore/collision/Sphere.java | 53 ++ .../jedk1/jedcore}/command/Commands.java | 0 .../jedcore}/command/JedCoreCommand.java | 11 +- .../jedk1/jedcore}/configuration/Config.java | 1 - .../jedcore}/configuration/JedCoreConfig.java | 0 .../SubsectionConfigurationDecorator.java | 0 .../jedk1/jedcore}/event/PKCommandEvent.java | 0 .../jedcore/listener/AbilityListener.java | 545 +++++++++++++++ .../jedcore/listener/CommandListener.java | 73 ++ .../jedk1/jedcore/listener/JCListener.java | 239 +++++++ .../removal/CannotBendRemovalPolicy.java | 0 .../removal/CompositeRemovalPolicy.java | 0 .../policies/removal/IsDeadRemovalPolicy.java | 0 .../removal/IsOfflineRemovalPolicy.java | 0 .../removal/OutOfRangeRemovalPolicy.java | 0 .../policies/removal/RemovalPolicy.java | 0 .../removal/SwappedSlotsRemovalPolicy.java | 0 .../jedk1/jedcore}/util/AbilitySelector.java | 8 +- .../jedcore}/util/AirShieldReflector.java | 0 .../jedk1/jedcore}/util/BlockUtil.java | 0 .../jedk1/jedcore}/util/ChiRestrictor.java | 12 +- .../jedcore}/util/CollisionInitializer.java | 0 .../jedk1/jedcore}/util/FireTick.java | 0 .../jedk1/jedcore}/util/LightManager.java | 47 +- .../jedk1/jedcore/util/LightManagerUtil.java | 108 +++ .../jedk1/jedcore}/util/MaterialUtil.java | 1 - .../jedk1/jedcore}/util/MetricsLite.java | 16 +- .../jedk1/jedcore}/util/RegenTempBlock.java | 1 - .../jedk1/jedcore}/util/TempFallingBlock.java | 303 ++++---- .../jedcore}/util/TemporaryFallingBlock.java | 0 src/com/jedk1/jedcore/util/ThreadUtil.java | 375 ++++++++++ .../jedcore}/util/ThrownEntityTracker.java | 1 - .../util/versionadapter/ParticleAdapter.java | 0 .../ParticleAdapterFactory.java | 0 .../ParticleAdapter_1_20_4.java | 3 +- .../ParticleAdapter_1_20_5.java | 6 +- .../versionadapter/PotionEffectAdapter.java | 0 .../PotionEffectAdapterFactory.java | 0 .../PotionEffectAdapter_1_20_4.java | 0 .../PotionEffectAdapter_1_20_5.java | 0 .../util/versionadapter/PotionMetaUtil.java | 0 src/listener/AbilityListener.java | 569 --------------- src/listener/CommandListener.java | 76 -- src/listener/JCListener.java | 237 ------- src/plugin.yml | 1 - src/util/PaperLib.java | 96 --- src/util/ThreadUtil.java | 209 ------ 150 files changed, 17018 insertions(+), 15118 deletions(-) delete mode 100644 src/JCManager.java delete mode 100644 src/JCMethods.java delete mode 100644 src/ability/airbending/AirBlade.java delete mode 100644 src/ability/avatar/elementsphere/ESEarth.java delete mode 100644 src/ability/avatar/elementsphere/ElementSphere.java delete mode 100644 src/ability/chiblocking/DaggerThrow.java delete mode 100644 src/ability/earthbending/EarthKick.java delete mode 100644 src/ability/earthbending/EarthLine.java delete mode 100644 src/ability/earthbending/EarthPillar.java delete mode 100644 src/ability/earthbending/EarthShard.java delete mode 100644 src/ability/earthbending/EarthSurf.java delete mode 100644 src/ability/earthbending/Fissure.java delete mode 100644 src/ability/earthbending/LavaDisc.java delete mode 100644 src/ability/earthbending/LavaFlux.java delete mode 100644 src/ability/earthbending/LavaThrow.java delete mode 100644 src/ability/earthbending/MagnetShield.java delete mode 100644 src/ability/earthbending/MetalArmor.java delete mode 100644 src/ability/earthbending/MetalFragments.java delete mode 100644 src/ability/earthbending/MetalHook.java delete mode 100644 src/ability/earthbending/MetalShred.java delete mode 100644 src/ability/earthbending/MudSurge.java delete mode 100644 src/ability/earthbending/SandBlast.java delete mode 100644 src/ability/earthbending/combo/Crevice.java delete mode 100644 src/ability/earthbending/combo/MagmaBlast.java delete mode 100644 src/ability/firebending/Combustion.java delete mode 100644 src/ability/firebending/FireBreath.java delete mode 100644 src/ability/firebending/FireShots.java delete mode 100644 src/ability/firebending/LightningBurst.java delete mode 100644 src/ability/waterbending/BloodPuppet.java delete mode 100644 src/ability/waterbending/BloodShot.java delete mode 100644 src/ability/waterbending/Bloodbending.java delete mode 100644 src/ability/waterbending/Drain.java delete mode 100644 src/ability/waterbending/FrostBreath.java delete mode 100644 src/ability/waterbending/HealingWaters.java delete mode 100644 src/ability/waterbending/IceClaws.java create mode 100644 src/com/jedk1/jedcore/JCManager.java create mode 100644 src/com/jedk1/jedcore/JCMethods.java rename src/{ => com/jedk1/jedcore}/JedCore.java (82%) create mode 100644 src/com/jedk1/jedcore/ability/airbending/AirBlade.java rename src/{ => com/jedk1/jedcore}/ability/airbending/AirBreath.java (100%) rename src/{ => com/jedk1/jedcore}/ability/airbending/AirGlide.java (100%) rename src/{ => com/jedk1/jedcore}/ability/airbending/AirPunch.java (100%) rename src/{ => com/jedk1/jedcore}/ability/airbending/Meditate.java (100%) rename src/{ => com/jedk1/jedcore}/ability/airbending/SonicBlast.java (100%) rename src/{ => com/jedk1/jedcore}/ability/airbending/combo/AirSlam.java (100%) rename src/{ => com/jedk1/jedcore}/ability/airbending/combo/SwiftStream.java (100%) rename src/{ => com/jedk1/jedcore}/ability/avatar/SpiritBeam.java (100%) rename src/{ => com/jedk1/jedcore}/ability/avatar/elementsphere/ESAir.java (100%) create mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java rename src/{ => com/jedk1/jedcore}/ability/avatar/elementsphere/ESFire.java (100%) rename src/{ => com/jedk1/jedcore}/ability/avatar/elementsphere/ESStream.java (100%) rename src/{ => com/jedk1/jedcore}/ability/avatar/elementsphere/ESWater.java (100%) create mode 100644 src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java rename src/{ => com/jedk1/jedcore}/ability/chiblocking/Backstab.java (99%) create mode 100644 src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthKick.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthLine.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthShard.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/Fissure.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalHook.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/MetalShred.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/MudSurge.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/SandBlast.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java create mode 100644 src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java create mode 100644 src/com/jedk1/jedcore/ability/firebending/Combustion.java rename src/{ => com/jedk1/jedcore}/ability/firebending/Discharge.java (99%) rename src/{ => com/jedk1/jedcore}/ability/firebending/FireBall.java (99%) create mode 100644 src/com/jedk1/jedcore/ability/firebending/FireBreath.java rename src/{ => com/jedk1/jedcore}/ability/firebending/FireComet.java (99%) rename src/{ => com/jedk1/jedcore}/ability/firebending/FirePunch.java (99%) create mode 100644 src/com/jedk1/jedcore/ability/firebending/FireShots.java rename src/{ => com/jedk1/jedcore}/ability/firebending/FireSki.java (99%) create mode 100644 src/com/jedk1/jedcore/ability/firebending/LightningBurst.java rename src/{ => com/jedk1/jedcore}/ability/passive/WallRun.java (99%) create mode 100644 src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java create mode 100644 src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java create mode 100644 src/com/jedk1/jedcore/ability/waterbending/Drain.java rename src/{ => com/jedk1/jedcore}/ability/waterbending/DrainBlast.java (99%) create mode 100644 src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java create mode 100644 src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java create mode 100644 src/com/jedk1/jedcore/ability/waterbending/IceClaws.java rename src/{ => com/jedk1/jedcore}/ability/waterbending/IcePassive.java (98%) create mode 100644 src/com/jedk1/jedcore/ability/waterbending/IceWall.java create mode 100644 src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java create mode 100644 src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java rename src/{ => com/jedk1/jedcore}/ability/waterbending/combo/Maelstrom.java (99%) rename src/{ => com/jedk1/jedcore}/ability/waterbending/combo/WaterFlow.java (98%) rename src/{ => com/jedk1/jedcore}/ability/waterbending/combo/WaterGimbal.java (99%) create mode 100644 src/com/jedk1/jedcore/collision/AABB.java create mode 100644 src/com/jedk1/jedcore/collision/Collider.java create mode 100644 src/com/jedk1/jedcore/collision/CollisionDetector.java create mode 100644 src/com/jedk1/jedcore/collision/CollisionUtil.java create mode 100644 src/com/jedk1/jedcore/collision/Ray.java create mode 100644 src/com/jedk1/jedcore/collision/Sphere.java rename src/{ => com/jedk1/jedcore}/command/Commands.java (100%) rename src/{ => com/jedk1/jedcore}/command/JedCoreCommand.java (99%) rename src/{ => com/jedk1/jedcore}/configuration/Config.java (99%) rename src/{ => com/jedk1/jedcore}/configuration/JedCoreConfig.java (100%) rename src/{ => com/jedk1/jedcore}/configuration/SubsectionConfigurationDecorator.java (100%) rename src/{ => com/jedk1/jedcore}/event/PKCommandEvent.java (100%) create mode 100644 src/com/jedk1/jedcore/listener/AbilityListener.java create mode 100644 src/com/jedk1/jedcore/listener/CommandListener.java create mode 100644 src/com/jedk1/jedcore/listener/JCListener.java rename src/{ => com/jedk1/jedcore}/policies/removal/CannotBendRemovalPolicy.java (100%) rename src/{ => com/jedk1/jedcore}/policies/removal/CompositeRemovalPolicy.java (100%) rename src/{ => com/jedk1/jedcore}/policies/removal/IsDeadRemovalPolicy.java (100%) rename src/{ => com/jedk1/jedcore}/policies/removal/IsOfflineRemovalPolicy.java (100%) rename src/{ => com/jedk1/jedcore}/policies/removal/OutOfRangeRemovalPolicy.java (100%) rename src/{ => com/jedk1/jedcore}/policies/removal/RemovalPolicy.java (100%) rename src/{ => com/jedk1/jedcore}/policies/removal/SwappedSlotsRemovalPolicy.java (100%) rename src/{ => com/jedk1/jedcore}/util/AbilitySelector.java (92%) rename src/{ => com/jedk1/jedcore}/util/AirShieldReflector.java (100%) rename src/{ => com/jedk1/jedcore}/util/BlockUtil.java (100%) rename src/{ => com/jedk1/jedcore}/util/ChiRestrictor.java (94%) rename src/{ => com/jedk1/jedcore}/util/CollisionInitializer.java (100%) rename src/{ => com/jedk1/jedcore}/util/FireTick.java (100%) rename src/{ => com/jedk1/jedcore}/util/LightManager.java (92%) create mode 100644 src/com/jedk1/jedcore/util/LightManagerUtil.java rename src/{ => com/jedk1/jedcore}/util/MaterialUtil.java (99%) rename src/{ => com/jedk1/jedcore}/util/MetricsLite.java (98%) rename src/{ => com/jedk1/jedcore}/util/RegenTempBlock.java (99%) rename src/{ => com/jedk1/jedcore}/util/TempFallingBlock.java (97%) rename src/{ => com/jedk1/jedcore}/util/TemporaryFallingBlock.java (100%) create mode 100644 src/com/jedk1/jedcore/util/ThreadUtil.java rename src/{ => com/jedk1/jedcore}/util/ThrownEntityTracker.java (99%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/ParticleAdapter.java (100%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/ParticleAdapterFactory.java (100%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/ParticleAdapter_1_20_4.java (95%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/ParticleAdapter_1_20_5.java (92%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/PotionEffectAdapter.java (100%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/PotionEffectAdapterFactory.java (100%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/PotionEffectAdapter_1_20_4.java (100%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/PotionEffectAdapter_1_20_5.java (100%) rename src/{ => com/jedk1/jedcore}/util/versionadapter/PotionMetaUtil.java (100%) delete mode 100644 src/listener/AbilityListener.java delete mode 100644 src/listener/CommandListener.java delete mode 100644 src/listener/JCListener.java delete mode 100644 src/util/PaperLib.java delete mode 100644 src/util/ThreadUtil.java diff --git a/pom.xml b/pom.xml index 06eff36..9121837 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.jedk1 jedcore - 2.15.1-PRE-RELEASE-1-PK1.12.0 + 2.15.1-PRE-RELEASE-3-PK1.12.1 jar JedCore @@ -25,15 +25,32 @@ com.projectkorra projectkorra - 1.12.0 + 1.12.1-PRE-RELEASE-1 + provided - - io.papermc.paper - paper-api - 1.20.2-R0.1-SNAPSHOT - provided - + + org.spigotmc + spigot-api + 1.20.2-R0.1-SNAPSHOT + provided + + + + com.google.guava + guava + 33.5.0-jre + + + com.cjcrafter + foliascheduler + 0.7.2 + + + org.jetbrains + annotations + 26.0.2-1 + @@ -68,6 +85,47 @@ ${dir} + + org.apache.maven.plugins + maven-shade-plugin + 3.4.1 + + + package + shade + + + + com.google.guava + com.jedk1.jedcore.libs.googleguava + + + org.jetbrains.annotations + com.jedk1.jedcore.libs.jetbrains + + + com.cjcrafter.foliascheduler + com.jedk1.jedcore.libs.foliascheduler + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + META-INF/versions/** + META-INF/*.kotlin_module + + + + false + + + + diff --git a/src/JCManager.java b/src/JCManager.java deleted file mode 100644 index 5fda987..0000000 --- a/src/JCManager.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.jedk1.jedcore; - -import org.bukkit.Bukkit; - - import com.jedk1.jedcore.ability.firebending.LightningBurst; - import com.jedk1.jedcore.ability.waterbending.HealingWaters; - import com.jedk1.jedcore.ability.waterbending.IcePassive; - import com.jedk1.jedcore.util.RegenTempBlock; - -public class JCManager implements Runnable { - - public JedCore plugin; - - public JCManager(JedCore plugin) { - this.plugin = plugin; - } - - public void run() { - LightningBurst.progressAll(); - - HealingWaters.heal(Bukkit.getServer()); - IcePassive.handleSkating(); -// IceWall.progressAll(); - - RegenTempBlock.manage(); - } -} \ No newline at end of file diff --git a/src/JCMethods.java b/src/JCMethods.java deleted file mode 100644 index d1a802f..0000000 --- a/src/JCMethods.java +++ /dev/null @@ -1,356 +0,0 @@ -package com.jedk1.jedcore; - -import java.util.*; - -import com.jedk1.jedcore.util.*; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.region.RegionProtection; -import org.bukkit.*; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ProjectKorra; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager; -import com.projectkorra.projectkorra.util.TempBlock; - -public class JCMethods { - - // todo: either use PKs isPlant or the registry/tags (with config) - private static final ArrayList SMALL_PLANTS = new ArrayList(){{ - addAll(Arrays.asList(Material.GRASS, Material.FERN, Material.POPPY, Material.DANDELION, Material.OAK_SAPLING, - Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, - Material.DARK_OAK_SAPLING, Material.ALLIUM, Material.ORANGE_TULIP, Material.PINK_TULIP, Material.RED_TULIP, - Material.WHITE_TULIP, Material.ROSE_BUSH, Material.BLUE_ORCHID, Material.LILAC, Material.OXEYE_DAISY, - Material.AZURE_BLUET, Material.PEONY, Material.SUNFLOWER, Material.LARGE_FERN, Material.RED_MUSHROOM, - Material.BROWN_MUSHROOM, Material.PUMPKIN_STEM, Material.MELON_STEM, Material.WHEAT, Material.TALL_GRASS, - Material.BEETROOTS, Material.CARROTS, Material.POTATOES, Material.CRIMSON_FUNGUS, Material.WARPED_FUNGUS, - Material.BAMBOO, Material.BAMBOO_SAPLING)); - - int serverVersion = GeneralMethods.getMCVersion(); - if (serverVersion >= 1170) { - add(Material.getMaterial("AZALEA")); - add(Material.getMaterial("FLOWERING_AZALEA")); - add(Material.getMaterial("FLOWERING_AZALEA_LEAVES")); - add(Material.getMaterial("AZALEA_LEAVES")); - add(Material.getMaterial("BIG_DRIPLEAF")); - add(Material.getMaterial("BIG_DRIPLEAF_STEM")); - add(Material.getMaterial("SMALL_DRIPLEAF")); - add(Material.getMaterial("HANGING_ROOTS")); - add(Material.getMaterial("GLOW_LICHEN")); - add(Material.getMaterial("CAVE_VINES")); - add(Material.getMaterial("CAVE_VINES_PLANT")); - } - }}; - - private static List worlds = new ArrayList<>(); - private static List combos = new ArrayList<>(); - - public static List getDisabledWorlds() { - return JCMethods.worlds; - } - - public static void registerDisabledWorlds() { - worlds.clear(); - List registeredworlds = ProjectKorra.plugin.getConfig().getStringList("Properties.DisabledWorlds"); - if (!registeredworlds.isEmpty()) { - worlds.addAll(registeredworlds); - } - } - - public static boolean isDisabledWorld(World world) { - return getDisabledWorlds().contains(world.getName()); - } - - public static List getCombos() { - return JCMethods.combos; - } - - public static void registerCombos() { - combos.clear(); - combos.addAll(ComboManager.getComboAbilities().keySet()); - } - - /** - * Gets the points of a line between two points. - * @param startLoc - * @param endLoc - * @param points - * @return locations - */ - public static List getLinePoints(Location startLoc, Location endLoc, int points){ - List locations = new ArrayList(); - Location diff = endLoc.subtract(startLoc); - double diffX = diff.getX() / points; - double diffY = diff.getY() / points; - double diffZ = diff.getZ() / points; - Location loc = startLoc; - for(int i = 0; i < points; i++){ - loc.add(new Location(startLoc.getWorld(), diffX, diffY, diffZ)); - locations.add(loc.clone()); - } - return locations; - } - - public static List getCirclePoints(Location location, int points, double size) { - return getCirclePoints(location, points, size, 0); - } - - /** - * Gets points in a circle. - * @param location - * @param points - * @param size - * @return - */ - public static List getCirclePoints(Location location, int points, double size, double startangle){ - List locations = new ArrayList(); - for(int i = 0; i < 360; i += 360/points){ - double angle = (i * Math.PI / 180); - double x = size * Math.cos(angle + startangle); - double z = size * Math.sin(angle + startangle); - Location loc = location.clone(); - loc.add(x, 0, z); - locations.add(loc); - } - return locations; - } - - /** - * Gets points in a vertical circle. - * @param location - * @param points - * @param size - * @param yawOffset - * @return - */ - public static List getVerticalCirclePoints(Location location, int points, double size, float yawOffset) { - List locations = new ArrayList<>(); - Location fakeLoc = location.clone(); - fakeLoc.setPitch(0); - fakeLoc.setYaw(yawOffset); - Vector direction = fakeLoc.getDirection(); - - for(double j = -180; j <= 180; j += points){ - Location tempLoc = fakeLoc.clone(); - Vector newDir = direction.clone().multiply(size * Math.cos(Math.toRadians(j))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + size + (size * Math.sin(Math.toRadians(j)))); - locations.add(tempLoc.clone()); - } - return locations; - } - - /** - * Remove an item from a players inventory. - * @param player - * @param material - * @param amount - * @return - */ - public static boolean removeItemFromInventory(Player player, Material material, int amount) { - for (ItemStack item : player.getInventory().getContents()) { - if (item != null && item.getType() == material) { - if (item.getAmount() == amount) { - Map remaining = player.getInventory().removeItem(item); - - if (!remaining.isEmpty()) { - ItemStack offhand = player.getInventory().getItemInOffHand(); - - // Spigot seems to not handle offhand correctly with removeItem, so try to manually remove it. - if (offhand != null && offhand.getType() == material && offhand.getAmount() == amount) { - player.getInventory().setItemInOffHand(null); - } - } - } else if (item.getAmount() > amount) { - item.setAmount(item.getAmount() - amount); - } - - return true; - } - } - - return false; - } - - /** - * Gets points in a spiral shape. - * @param location - * @param points - * @param spiralCount - * @param startAngle - * @param startSize - * @param finalSize - * @param noClip - * @return - */ - public static List getSpiralPoints(Location location, int points, int spiralCount, int startAngle, double startSize, double finalSize, boolean noClip){ - return getSpiralPoints(location, points, spiralCount, 0.0D, startAngle, startSize, finalSize, noClip); - } - - /** - * Gets points in a vertical spiral shape, could be used for a tornado. - * @param location - * @param points - * @param spiralCount - * @param height - * @param startAngle - * @param startSize - * @param finalSize - * @param noClip - * @return - */ - public static List getSpiralPoints(Location location, int points, int spiralCount, double height, int startAngle, double startSize, double finalSize, boolean noClip){ - List locations = new ArrayList(); - - points = points/spiralCount; - double sizeIncr = ((finalSize - startSize) / points)/spiralCount; - double hightIncr = (height/points)/spiralCount; - double size = startSize; - for(int i = 0; i < spiralCount; i++){ - for(int j = 0; j < 360; j += 360/points){ - hightIncr = hightIncr + ((height/points)/spiralCount); - size = size + sizeIncr; - double angle = (j * Math.PI / 180); - double x = size * Math.cos(angle + startAngle); - double z = size * Math.sin(angle + startAngle); - Location loc = location.clone(); - loc.add(x, hightIncr, z); - if(!noClip && ElementalAbility.isAir(loc.getBlock().getType())) - locations.add(loc); - else if(noClip) - locations.add(loc); - } - } - - return locations; - } - - public static void extinguishBlocks(Player player, String ability, int range, int radius, boolean fire, boolean lava){ - for (Block block : GeneralMethods.getBlocksAroundPoint(player.getTargetBlock(null, range).getLocation(), radius)) { - Material mat = block.getType(); - if(mat != Material.FIRE && mat != Material.LAVA && mat != Material.SOUL_FIRE) - continue; - if (RegionProtection.isRegionProtected(player, block.getLocation(), ability)) - continue; - if (((mat == Material.FIRE || mat == Material.SOUL_FIRE) && fire)||(mat == Material.LAVA && lava)) { - block.setType(mat != Material.LAVA ? Material.AIR : isLiquidSource(block) ? Material.OBSIDIAN : Material.COBBLESTONE); - block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0); - } - } - } - - /** - * Checks if 3 blocks around the block are of the required type. - * @param block - * @param type - * @return - */ - public static boolean isAdjacentToThreeOrMoreSources(Block block, Material type) { - if (TempBlock.isTempBlock(block)) { - return false; - } - int sources = 0; - BlockFace[] faces = { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN }; - for (BlockFace face : faces) { - Block blocki = block.getRelative(face); - if ((blocki.getType() == type)) { - sources++; - } - } - if (sources >= 2) - return true; - return false; - } - - static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, - Material.NETHER_PORTAL, Material.END_PORTAL, - Material.END_PORTAL_FRAME, Material.OBSIDIAN}; - - public static boolean isUnbreakable(Block block) { - if (block.getState() instanceof InventoryHolder) { - return true; - } - if (Arrays.asList(unbreakables).contains(block.getType())) - return true; - return false; - } - - public static boolean isLiquidSource(Block block) { - if (!block.isLiquid()) { - return false; - } - - if (!(block.getBlockData() instanceof Levelled)) { - return false; - } - - Levelled levelData = (Levelled) block.getBlockData(); - - return levelData.getLevel() == 0; - } - - // TODO: Should this be reimplemented or has the rpg plugin been abandoned? - public static boolean isSozinsComet(World world) { - return false; - } - - // TODO: Should this be reimplemented or has the rpg plugin been abandoned? - public static boolean isLunarEclipse(World world) { - return false; - } - - // todo: see SMALL_PLANTS - public static boolean isDoublePlant(Material material) { - return material == Material.SUNFLOWER || material == Material.LILAC || material == Material.TALL_GRASS || - material == Material.LARGE_FERN || material == Material.ROSE_BUSH || material == Material.PEONY; - } - - public static boolean isSmallPlant(Block block) { - return isSmallPlant(block.getType()); - } - - public static boolean isSmallPlant(Material material) { - return WaterAbility.isPlant(material); - //return SMALL_PLANTS.contains(material); - } - - public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra) { - displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, 255); - } - - public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { - JedCore.plugin.getParticleAdapter().displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, alpha); - } - - public static void emitLight(Location loc) { - ConfigurationSection config = JedCoreConfig.getConfig((Player)null); - if (config.getBoolean("Properties.Fire.DynamicLight.Enabled")) { - int brightness = config.getInt("Properties.Fire.DynamicLight.Brightness"); - long keepAlive = config.getLong("Properties.Fire.DynamicLight.KeepAlive"); - - LightManager.createLight(loc).brightness(brightness).timeUntilFadeout(keepAlive).emit(); - } - } - - public static void reload() { - JedCore.log.info("JedCore Reloaded."); - JedCore.plugin.reloadConfig(); - JedCore.logDebug = JedCoreConfig.getConfig((World)null).getBoolean("Properties.LogDebug"); - CoreAbility.registerPluginAbilities(JedCore.plugin, "com.jedk1.jedcore.ability"); - registerDisabledWorlds(); - registerCombos(); - RegenTempBlock.revertAll(); - JedCore.plugin.initializeCollisions(); - FireTick.loadMethod(); - } -} diff --git a/src/ability/airbending/AirBlade.java b/src/ability/airbending/AirBlade.java deleted file mode 100644 index f0a6d9b..0000000 --- a/src/ability/airbending/AirBlade.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.jedk1.jedcore.ability.airbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; - -public class AirBlade extends AirAbility implements AddonAbility { - - private Location location; - private Vector direction; - private double travelled; - - @Attribute("Growth") - private double growth = 1; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute("CollisionRadius") - private double entityCollisionRadius; - - public AirBlade(Player player) { - super(player); - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - this.location = player.getEyeLocation().clone(); - this.direction = player.getEyeLocation().getDirection().clone(); - - start(); - if (!isRemoved()) - bPlayer.addCooldown(this); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Air.AirBlade.Cooldown"); - range = config.getDouble("Abilities.Air.AirBlade.Range"); - damage = config.getDouble("Abilities.Air.AirBlade.Damage"); - entityCollisionRadius = config.getDouble("Abilities.Air.AirBlade.EntityCollisionRadius"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (travelled >= range) { - remove(); - return; - } - - progressBlade(); - } - - private void progressBlade() { - for (int j = 0; j < 2; j++) { - if (!moveAndCheckCollision()) { - return; - } - - double pitch = -location.getPitch(); - Location lastLoc = location.clone(); - - for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { - Location tempLoc = calculateParticleLocation(i); - playAirbendingParticles(tempLoc, 1, (float) Math.random() / 2, (float) Math.random() / 2, (float) Math.random() / 2); - - if (j == 0 && !lastLoc.getBlock().getLocation().equals(tempLoc.getBlock().getLocation())) { - if (handleEntityCollision(tempLoc)) { - return; - } - lastLoc = tempLoc; - } - } - } - } - - private boolean moveAndCheckCollision() { - location = location.add(direction.multiply(1)); - playAirbendingSound(location); - travelled++; - growth += 0.125; - - if (travelled >= range || - !isTransparent(location.getBlock()) || - RegionProtection.isRegionProtected(player, player.getLocation(), this)) { - remove(); - return false; - } - return true; - } - - private Location calculateParticleLocation(double angle) { - Location tempLoc = location.clone(); - tempLoc.setPitch(0); - Vector tempDir = tempLoc.getDirection().clone(); - tempDir.setY(0); - Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(angle))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(angle)))); - return tempLoc; - } - - private boolean handleEntityCollision(Location tempLoc) { - boolean hit = CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), entity -> { - DamageHandler.damageEntity(entity, damage, this); - remove(); - return true; - }); - if (hit) { - remove(); - return true; - } - return false; - } - - @Override - public Player getPlayer() { - return player; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public List getLocations() { - List locations = new ArrayList<>(); - - double pitch = -location.getPitch(); - - for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { - Location tempLoc = location.clone(); - tempLoc.setPitch(0); - - Vector tempDir = tempLoc.getDirection().clone(); - tempDir.setY(0); - - Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(i))); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(i)))); - - locations.add(tempLoc); - } - - return locations; - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Air.AirBlade.AbilityCollisionRadius"); - } - - public long getCooldown() { - return cooldown; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - @Override - public String getName() { - return "AirBlade"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirBlade.Description"); - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getTravelled() { - return travelled; - } - - public void setTravelled(double travelled) { - this.travelled = travelled; - } - - public double getGrowth() { - return growth; - } - - public void setGrowth(double growth) { - this.growth = growth; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Air.AirBlade.Enabled"); - } -} diff --git a/src/ability/avatar/elementsphere/ESEarth.java b/src/ability/avatar/elementsphere/ESEarth.java deleted file mode 100644 index c4517b8..0000000 --- a/src/ability/avatar/elementsphere/ESEarth.java +++ /dev/null @@ -1,219 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - -import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; - -public class ESEarth extends AvatarAbility implements AddonAbility { - - static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, Material.NETHER_PORTAL, Material.END_PORTAL, - Material.END_PORTAL_FRAME, Material.ENDER_CHEST, Material.CHEST, Material.TRAPPED_CHEST }; - - private TempFallingBlock tfb; - private long revertDelay; - - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute("Size") - private int impactSize; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - public ESEarth(Player player) { - super(player); - if (!hasAbility(player, ElementSphere.class)) { - return; - } - ElementSphere currES = getAbility(player, ElementSphere.class); - if (currES.getEarthUses() == 0) { - return; - } - if (bPlayer.isOnCooldown("ESEarth")) { - return; - } - if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), 40).getLocation())) { - return; - } - setFields(); - start(); - if (!isRemoved()) { - bPlayer.addCooldown("ESEarth", getCooldown()); - currES.setEarthUses(currES.getEarthUses() - 1); - Location location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); - tfb = new TempFallingBlock(location, Material.DIRT.createBlockData(), location.getDirection().multiply(3), this); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - revertDelay = config.getLong("Abilities.Avatar.ElementSphere.Earth.ImpactRevert"); - damage = config.getDouble("Abilities.Avatar.ElementSphere.Earth.Damage"); - impactSize = config.getInt("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize"); - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Earth.Cooldown"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline()) { - tfb.remove(); - remove(); - return; - } - if (tfb.getFallingBlock().isDead()) { - remove(); - return; - } - if (RegionProtection.isRegionProtected(this, tfb.getLocation())){ - remove(); - return; - } - - EarthAbility.playEarthbendingSound(tfb.getLocation()); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), 2.5)) { - if (entity instanceof LivingEntity && !(entity instanceof ArmorStand) && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player targetPlayer) && Commands.invincible.contains(targetPlayer.getName()))) { - DamageHandler.damageEntity(entity, damage, this); - } - } - } - - // Unused - public static void explodeEarth(TempFallingBlock tempfallingblock) { - FallingBlock fb = tempfallingblock.getFallingBlock(); - ESEarth es = (ESEarth) tempfallingblock.getAbility(); - Player player = es.getPlayer(); - - ParticleEffect.SMOKE_LARGE.display(fb.getLocation(), 0, 0, 0, 0.3F, 25); - fb.getWorld().playSound(fb.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 2f, 0.5f); - - ThreadLocalRandom rand = ThreadLocalRandom.current(); - - for (Location l : GeneralMethods.getCircle(fb.getLocation(), es.impactSize, 1, false, true, 0)) { - if (isBreakable(l.getBlock()) && !RegionProtection.isRegionProtected(player, l, "ElementSphere") && EarthAbility.isEarthbendable(player, l.getBlock())) { - ParticleEffect.SMOKE_LARGE.display(l, 0, 0, 0, 0.1F, 2); - new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000), false); - } - - if (GeneralMethods.isSolid(l.getBlock().getRelative(BlockFace.DOWN)) && isBreakable(l.getBlock()) && ElementalAbility.isAir(l.getBlock().getType()) && rand.nextInt(20) == 0 && EarthAbility.isEarthbendable(player, l.getBlock().getRelative(BlockFace.DOWN))) { - Material type = l.getBlock().getRelative(BlockFace.DOWN).getType(); - new RegenTempBlock(l.getBlock(), type, type.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000)); - } - } - - tempfallingblock.remove(); - } - - public static boolean isBreakable(Block block) { - return !Arrays.asList(unbreakables).contains(block.getType()); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return tfb != null ? tfb.getLocation() : null; - } - - @Override - public String getName() { - return "ElementSphereEarth"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public long getRevertDelay() { - return revertDelay; - } - - public void setRevertDelay(long revertDelay) { - this.revertDelay = revertDelay; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getImpactSize() { - return impactSize; - } - - public void setImpactSize(int impactSize) { - this.impactSize = impactSize; - } - - public TempFallingBlock getTempFallingBlock() { - return tfb; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } -} diff --git a/src/ability/avatar/elementsphere/ElementSphere.java b/src/ability/avatar/elementsphere/ElementSphere.java deleted file mode 100644 index ee6b1ca..0000000 --- a/src/ability/avatar/elementsphere/ElementSphere.java +++ /dev/null @@ -1,523 +0,0 @@ -package com.jedk1.jedcore.ability.avatar.elementsphere; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.MultiAbility; -import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; -import com.projectkorra.projectkorra.ability.util.MultiAbilityManager.MultiAbilityInfoSub; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.ChatColor; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ThreadLocalRandom; - -public class ElementSphere extends AvatarAbility implements AddonAbility, MultiAbility { - - protected static final ConcurrentMap> abilities = new ConcurrentHashMap<>(); - private static final ArrayList multiAbilityInfo = new ArrayList<>(); - - static { - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AIR)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.EARTH)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.FIRE)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.WATER)); - multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AVATAR)); - } - - private World world; - private int airUses; - private int fireUses; - private int waterUses; - private int earthUses; - private boolean setup; - private Location location; - private double yaw; - private int point; - private long endTime; - private long lastClickTime; - - @Attribute(Attribute.COOLDOWN) - public long cooldown; - @Attribute(Attribute.DURATION) - public long duration; - @Attribute(Attribute.HEIGHT) - private double height; - @Attribute(Attribute.SPEED) - private double speed; - - public ElementSphere(Player player) { - super(player); - - ElementSphere oldES = getAbility(player, ElementSphere.class); - - if (handleExistingSphere(player, oldES)) { - return; - } - - if (canStartNewSphere()) { - initializeNewSphere(player); - } - } - - private boolean handleExistingSphere(Player player, ElementSphere oldES) { - if (oldES != null) { - if (player.isSneaking()) { - oldES.prepareCancel(); - } else { - if (oldES.setup) { - handleElementSwitch(player); - } - } - return true; - } - return false; - } - - private void handleElementSwitch(Player player) { - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - return; - } - - switch (player.getInventory().getHeldItemSlot()) { - case 0: - if (checkPermission(player, "Air")) new ESAir(player); - break; - case 1: - if (checkPermission(player, "Earth")) new ESEarth(player); - break; - case 2: - if (checkPermission(player, "Fire")) new ESFire(player); - break; - case 3: - if (checkPermission(player, "Water")) new ESWater(player); - break; - case 4: - if (checkPermission(player, "Stream")) new ESStream(player); - break; - } - } - - private boolean checkPermission(Player player, String element) { - return player.hasPermission("bending.ability.ElementSphere." + element); - } - - private boolean canStartNewSphere() { - return bPlayer.canBend(this); - } - - private void initializeNewSphere(Player player) { - setFields(); - location = player.getLocation().clone().subtract(0, 1, 0); - world = player.getWorld(); - endTime = System.currentTimeMillis() + duration; - start(); - - if (!isRemoved()) { - bindAndCooldown(player); - enableFlight(player); - checkBoundAbilityName(); - } - } - - private void bindAndCooldown(Player player) { - MultiAbilityManager.bindMultiAbility(player, "ElementSphere"); - bPlayer.addCooldown(this); - } - - private void enableFlight(Player player) { - flightHandler.createInstance(player, this.getName()); - } - - private void checkBoundAbilityName() { - if (ChatColor.stripColor(bPlayer.getBoundAbilityName()) == null) { - remove(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - airUses = config.getInt("Abilities.Avatar.ElementSphere.Air.Uses"); - fireUses = config.getInt("Abilities.Avatar.ElementSphere.Fire.Uses"); - waterUses = config.getInt("Abilities.Avatar.ElementSphere.Water.Uses"); - earthUses = config.getInt("Abilities.Avatar.ElementSphere.Earth.Uses"); - cooldown = config.getLong("Abilities.Avatar.ElementSphere.Cooldown"); - duration = config.getLong("Abilities.Avatar.ElementSphere.Duration"); - height = config.getDouble("Abilities.Avatar.ElementSphere.MaxControlledHeight"); - speed = config.getDouble("Abilities.Avatar.ElementSphere.FlySpeed"); - } - - @Override - public void progress() { - if (!checkPlayerValidity()) { - return; - } - - if (!checkAbilityPrerequisites()) { - return; - } - - if (isDurationOver()) { - remove(); - return; - } - - if (!hasUsableElements()) { - remove(); - return; - } - - handlePlayerMovement(); - handleFlight(); - handleEntityPush(); - updateLocationAndPlayParticles(); - - setup = true; - } - - private boolean checkPlayerValidity() { - return !player.isDead() && player.isOnline() && world == player.getWorld() && !player.getGameMode().equals(GameMode.SPECTATOR); - } - - private boolean checkAbilityPrerequisites() { - return bPlayer.isToggled() && MultiAbilityManager.hasMultiAbilityBound(player, "ElementSphere"); - } - - private boolean isDurationOver() { - return duration > 0 && System.currentTimeMillis() > endTime; - } - - private boolean hasUsableElements() { - return airUses > 0 || fireUses > 0 || waterUses > 0 || earthUses > 0; - } - - private void handlePlayerMovement() { - player.setFallDistance(0); - if (player.isSneaking()) { - player.setVelocity(player.getLocation().getDirection().multiply(speed)); - } - } - - private void handleFlight() { - Block block = getGround(); - if (block != null) { - double dy = player.getLocation().getY() - block.getY(); - if (dy > height) { - removeFlight(); - } else { - allowFlight(); - } - } - } - - private void handleEntityPush() { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { - if (isPushableEntity(entity)) { - entity.setVelocity(entity.getLocation().toVector().subtract(player.getLocation().toVector()).multiply(1)); - } - } - } - - private boolean isPushableEntity(Entity entity) { - return entity instanceof LivingEntity && - entity.getEntityId() != player.getEntityId() && - !(entity instanceof ArmorStand) && - !RegionProtection.isRegionProtected(player, entity.getLocation(), this); - } - - private void updateLocationAndPlayParticles() { - location = player.getLocation().clone().subtract(0, 1, 0); - playParticles(); - } - - private void allowFlight() { - if (!player.getAllowFlight()) { - player.setAllowFlight(true); - } - if (!player.isFlying()) { - player.setFlying(true); - } - } - - private void removeFlight() { - if (player.getAllowFlight()) { - player.setAllowFlight(false); - } - if (player.isFlying()) { - player.setFlying(false); - } - } - - private Block getGround() { - Block standingblock = player.getLocation().getBlock(); - - for (int i = 0; i <= height + 5; i++) { - Block block = standingblock.getRelative(BlockFace.DOWN, i); - if (GeneralMethods.isSolid(block) || block.isLiquid()) { - return block; - } - } - - return null; - } - - private void playParticles() { - playAirParticles(); - playFireParticles(); - playWaterEarthParticles(); - updatePointCounter(); - } - - private void playAirParticles() { - if (airUses != 0) { - double currentYaw = yaw + 40; - yaw = currentYaw; - Location fakeLoc = createRotatedLocation(location.clone(), 0, currentYaw); - Vector direction = fakeLoc.getDirection(); - for (double j = -180; j <= 180; j += 45) { - Location tempLoc = calculateAirParticleLocation(fakeLoc, direction, j); - displayAirParticle(tempLoc); - } - } - } - - private Location createRotatedLocation(Location baseLoc, double pitchOffset, double yawOffset) { - Location newLoc = baseLoc.clone(); - newLoc.setPitch((float) pitchOffset); - newLoc.setYaw((float) yawOffset); - return newLoc; - } - - private Location calculateAirParticleLocation(Location center, Vector direction, double angleDegrees) { - Location tempLoc = center.clone(); - double angleRadians = Math.toRadians(angleDegrees); - Vector newDir = direction.clone().multiply(2 * Math.cos(angleRadians)); - tempLoc.add(newDir); - tempLoc.setY(tempLoc.getY() + 2 + (2 * Math.sin(angleRadians))); - return tempLoc; - } - - private void displayAirParticle(Location loc) { - String color = "#FFFFFF"; - int count = 1; - float offsetX = 0; - float offsetY = 0; - float offsetZ = 0; - float particleSpeed = 0.003f; - int viewDistance = 50; - - if (ThreadLocalRandom.current().nextInt(30) == 0) { - JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed); - } else { - JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed, viewDistance); - } - } - - private void playFireParticles() { - if (fireUses != 0) { - ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; - for (int i = -180; i < 180; i += 40) { - Location particleLoc = calculateCircularLocation(location, 2, i, 2); - flame.display(particleLoc, 0, 0, 0, 0, 1); - JCMethods.emitLight(particleLoc); - } - } - } - - private Location calculateCircularLocation(Location center, double radius, double angleOffsetDegrees, double yOffset) { - double angleRadians = Math.toRadians(angleOffsetDegrees); - double x = radius * Math.cos(angleRadians + point); - double z = radius * Math.sin(angleRadians + point); - return center.clone().add(x, yOffset, z); - } - - private void playWaterEarthParticles() { - Location centerLoc = location.clone().add(0, 2, 0); - double xRotation = Math.PI * 2.1 / 3; - double yawRadians = -(centerLoc.getYaw() * Math.PI / 180 - 1.575); - - for (int i = -180; i < 180; i += 30) { - double angle = Math.toRadians(i); - Vector v = new Vector(Math.cos(angle + point), Math.sin(angle + point), 0.0D).multiply(2); - Vector v1 = v.clone(); - - rotateAroundAxisX(v, xRotation); - rotateAroundAxisY(v, yawRadians); - rotateAroundAxisX(v1, -xRotation); - rotateAroundAxisY(v1, yawRadians); - - if (waterUses != 0) { - GeneralMethods.displayColoredParticle("06C1FF", centerLoc.clone().add(v)); - } - if (earthUses != 0) { - GeneralMethods.displayColoredParticle("754719", centerLoc.clone().add(v1)); - } - } - } - - private void updatePointCounter() { - point = (point + 1) % 360; - } - - private void rotateAroundAxisX(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double y = v.getY() * cos - v.getZ() * sin; - double z = v.getY() * sin + v.getZ() * cos; - v.setY(y).setZ(z); - } - - private void rotateAroundAxisY(Vector v, double angle) { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - double x = v.getX() * cos + v.getZ() * sin; - double z = v.getX() * -sin + v.getZ() * cos; - v.setX(x).setZ(z); - } - - @Override - public void remove() { - super.remove(); - MultiAbilityManager.unbindMultiAbility(player); - flightHandler.removeInstance(player, this.getName()); - } - - public void prepareCancel() { - if (System.currentTimeMillis() < lastClickTime + 500L) { - remove(); - } else { - lastClickTime = System.currentTimeMillis(); - } - } - - public int getAirUses() { - return airUses; - } - - public void setAirUses(int airuses) { - this.airUses = airuses; - } - - public int getEarthUses() { - return earthUses; - } - - public void setEarthUses(int earthuses) { - this.earthUses = earthuses; - } - - public int getFireUses() { - return fireUses; - } - - public void setFireUses(int fireuses) { - this.fireUses = fireuses; - } - - public int getWaterUses() { - return waterUses; - } - - public void setWaterUses(int wateruses) { - this.waterUses = wateruses; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public boolean requireAvatar() { - return false; - } - - @Override - public String getName() { - return "ElementSphere"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Avatar.ElementSphere.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); - } - - @Override - public ArrayList getMultiAbilities() { - FileConfiguration lang = getLanguageConfig(); - - String airName = lang.getString("Abilities.Avatar.ElementSphereAir.Name"); - String fireName = lang.getString("Abilities.Avatar.ElementSphereFire.Name"); - String waterName = lang.getString("Abilities.Avatar.ElementSphereWater.Name"); - String earthName = lang.getString("Abilities.Avatar.ElementSphereEarth.Name"); - String streamName = lang.getString("Abilities.Avatar.ElementSphereStream.Name"); - - multiAbilityInfo.get(0).setName(airName); - multiAbilityInfo.get(1).setName(earthName); - multiAbilityInfo.get(2).setName(fireName); - multiAbilityInfo.get(3).setName(waterName); - multiAbilityInfo.get(4).setName(streamName); - - return multiAbilityInfo; - } -} diff --git a/src/ability/chiblocking/DaggerThrow.java b/src/ability/chiblocking/DaggerThrow.java deleted file mode 100644 index 677e70a..0000000 --- a/src/ability/chiblocking/DaggerThrow.java +++ /dev/null @@ -1,348 +0,0 @@ -package com.jedk1.jedcore.ability.chiblocking; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.AbilitySelector; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -public class DaggerThrow extends ChiAbility implements AddonAbility { - private static final List INTERACTIONS = new ArrayList<>(); - private boolean particles; - - @Attribute(Attribute.DAMAGE) - private double damage; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private boolean limitEnabled; - @Attribute("MaxShots") - private int maxShots; - - private boolean requireArrows; - // require arrows (takes arrows from inv) - private boolean allowPickup; - // allow arrow pickup (disables pickup and removes the arrow entities) - - private long endTime; - private int shots = 1; - private int hits = 0; - private final List arrows = new ArrayList<>(); - - public DaggerThrow(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (bPlayer.isOnCooldown("DaggerThrowShot")) { - return; - } - - if (hasAbility(player, DaggerThrow.class)) { - DaggerThrow dt = getAbility(player, DaggerThrow.class); - dt.shootArrow(); - return; - } - - setFields(); - - start(); - if (!isRemoved()) { - shootArrow(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Chi.DaggerThrow.Cooldown"); - limitEnabled = config.getBoolean("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled"); - maxShots = config.getInt("Abilities.Chi.DaggerThrow.MaxDaggers.Amount"); - particles = config.getBoolean("Abilities.Chi.DaggerThrow.ParticleTrail"); - damage = config.getDouble("Abilities.Chi.DaggerThrow.Damage"); - requireArrows = config.getBoolean("Abilities.Chi.DaggerThrow.RequireArrows"); - allowPickup = config.getBoolean("Abilities.Chi.DaggerThrow.AllowPickup"); - - loadInteractions(); - } - - private void loadInteractions() { - INTERACTIONS.clear(); - - String path = "Abilities.Chi.DaggerThrow.Interactions"; - - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - ConfigurationSection section = config.getConfigurationSection(path); - for (String abilityName : section.getKeys(false)) { - INTERACTIONS.add(new AbilityInteraction(abilityName)); - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (System.currentTimeMillis() > endTime) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (shots > maxShots && limitEnabled) { - bPlayer.addCooldown(this); - remove(); - } - } - - private void shootArrow() { - shots++; - Location location = player.getEyeLocation(); - - Vector vector = location.toVector(). - add(location.getDirection().multiply(2.5)). - toLocation(location.getWorld()).toVector(). - subtract(player.getEyeLocation().toVector()); - - if (requireArrows) JCMethods.removeItemFromInventory(player, Material.ARROW, 1); - Arrow arrow = player.launchProjectile(Arrow.class); - arrow.setVelocity(vector); - arrow.getLocation().setDirection(vector); - arrow.setKnockbackStrength(0); - arrow.setBounce(false); - arrow.setMetadata("daggerthrow", new FixedMetadataValue(JedCore.plugin, "1")); - if (!allowPickup) arrow.setPickupStatus(Arrow.PickupStatus.DISALLOWED); - - if (particles) { - arrow.setCritical(true); - } - - arrows.add(arrow); - endTime = System.currentTimeMillis() + 500; - bPlayer.addCooldown("DaggerThrowShot", 100); - } - - public void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { - if (!(arrow.getShooter() instanceof Player shooter)) return; - - if (RegionProtection.isRegionProtected(shooter, arrow.getLocation(), "DaggerThrow")) return; - - arrow.setVelocity(new Vector(0, 0, 0)); - entity.setNoDamageTicks(0); - - double prevHealth = entity.getHealth(); - - DamageHandler.damageEntity(entity, damage, this); - - if (prevHealth > entity.getHealth()) { - arrow.remove(); - } - - if (!(entity instanceof Player target)) { - return; - } - - DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); - if (daggerThrow == null) { - return; - } - - daggerThrow.hits++; - BendingPlayer targetBPlayer = BendingPlayer.getBendingPlayer(target); - - for (AbilityInteraction interaction : INTERACTIONS) { - if (!interaction.enabled || daggerThrow.hits < interaction.hitRequirement) { - continue; - } - - CoreAbility abilityDefinition = AbilitySelector.getAbility(interaction.name); - if (abilityDefinition == null) { - continue; - } - - CoreAbility ability = CoreAbility.getAbility(target, abilityDefinition.getClass()); - if (ability == null) { - continue; - } - - ability.remove(); - targetBPlayer.addCooldown(ability, interaction.cooldown); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - return arrows.stream().map(Arrow::getLocation).collect(Collectors.toList()); - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Chi.DaggerThrow.AbilityCollisionRadius"); - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - Location location = collision.getLocationFirst(); - - Optional collidedObject = arrows.stream().filter(arrow -> arrow.getLocation().equals(location)).findAny(); - - if (collidedObject.isPresent()) { - arrows.remove(collidedObject.get()); - collidedObject.get().remove(); - } - } - } - - @Override - public String getName() { - return "DaggerThrow"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Chi.DaggerThrow.Description"); - } - - public boolean hasParticleTrail() { - return particles; - } - - public double getDamage() { - return damage; - } - - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; - } - - public int getShots() { - return shots; - } - - public void setShots(int shots) { - this.shots = shots; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public boolean isLimitEnabled() { - return limitEnabled; - } - - public void setLimitEnabled(boolean limitEnabled) { - this.limitEnabled = limitEnabled; - } - - public int getMaxShots() { - return maxShots; - } - - public void setMaxShots(int maxShots) { - this.maxShots = maxShots; - } - - public int getHits() { - return hits; - } - - public void setHits(int hits) { - this.hits = hits; - } - - public List getArrows() { - return arrows; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Chi.DaggerThrow.Enabled"); - } - - private class AbilityInteraction { - public boolean enabled; - public long cooldown; - public int hitRequirement; - public String name; - - public AbilityInteraction(String abilityName) { - this.name = abilityName; - loadConfig(); - } - - public void loadConfig() { - ConfigurationSection config = JedCoreConfig.getConfig(player); - this.enabled = config.getBoolean("Abilities.Chi.DaggerThrow.Interactions." + name + ".Enabled", true); - this.cooldown = config.getLong("Abilities.Chi.DaggerThrow.Interactions." + name + ".Cooldown", 1000); - this.hitRequirement = config.getInt("Abilities.Chi.DaggerThrow.Interactions." + name + ".HitsRequired", 1); - } - } -} diff --git a/src/ability/earthbending/EarthKick.java b/src/ability/earthbending/EarthKick.java deleted file mode 100644 index 83a0c64..0000000 --- a/src/ability/earthbending/EarthKick.java +++ /dev/null @@ -1,336 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.AABB; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.CollisionUtil; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.BlockUtil; -import com.jedk1.jedcore.util.TempFallingBlock; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.*; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.UUID; - -import static java.util.stream.Collectors.toList; - -public class EarthKick extends EarthAbility implements AddonAbility { - private final List temps = new ArrayList<>(); - - private BlockData materialData; - private Location location; - private final Random rand = new Random(); - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("MaxShots") - private int earthBlocks; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.DAMAGE) - private double metalDmg; - @Attribute("CollisionRadius") - private double entityCollisionRadius; - private Block block; - - private boolean multipleHits; - private int sourceRange; - private int spread; - private double velocity; - private boolean allowMetal; - - private Set hitEntities = new HashSet<>(); - - public EarthKick(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - location = player.getLocation(); - if ((player.getLocation().getPitch() > -5) && prepare()) { - if (RegionProtection.isRegionProtected(this, block.getLocation())) { - return; - } - launchBlocks(); - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.EarthKick.Cooldown"); - earthBlocks = config.getInt("Abilities.Earth.EarthKick.EarthBlocks"); - damage = config.getDouble("Abilities.Earth.EarthKick.Damage.Normal"); - metalDmg = config.getDouble("Abilities.Earth.EarthKick.Damage.Metal"); - entityCollisionRadius = config.getDouble("Abilities.Earth.EarthKick.EntityCollisionRadius"); - - multipleHits = config.getBoolean("Abilities.Earth.EarthKick.MultipleHits"); - sourceRange = config.getInt("Abilities.Earth.EarthKick.SourceRange"); - spread = config.getInt("Abilities.Earth.EarthKick.Spread"); - velocity = config.getDouble("Abilities.Earth.EarthKick.Velocity"); - allowMetal = config.getBoolean("Abilities.Earth.EarthKick.AllowMetal"); - - if (entityCollisionRadius < 1.0) { - entityCollisionRadius = 1.0; - } - } - - private boolean prepare() { - block = player.getTargetBlock(getTransparentMaterialSet(), sourceRange); - - if (!isEarthbendable(player, block)) { - return false; - } - - if (TempBlock.isTempBlock(block)) { - TempBlock.get(block).revertBlock(); - } - - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - - if (block != null && (allowMetal || !isMetal(block))) { - materialData = block.getBlockData().clone(); - location.setX(block.getX() + 0.5); - location.setY(block.getY()); - location.setZ(block.getZ() + 0.5); - - return true; - } - - return false; - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - remove(); - return; - } - - bPlayer.addCooldown(this); - track(); - - if (temps.isEmpty()) { - remove(); - } - } - - private void launchBlocks() { - if (getMovedEarth().containsKey(block)) { - block.setType(Material.AIR); - } - if (block.getType() != Material.AIR) { - TempBlock air = new TempBlock(block, Material.AIR); - air.setRevertTime(5000L); - } - - location.setPitch(0); - location.add(location.getDirection()); - - if (!isAir(location.getBlock().getType())) { - location.setY(location.getY() + 1.0); - } - - ParticleEffect.CRIT.display(location, 10, Math.random(), Math.random(), Math.random(), 0.1); - - int yaw = Math.round(location.getYaw()); - - playEarthbendingSound(location); - - for (int i = 0; i < earthBlocks; i++) { - location.setYaw(yaw + rand.nextInt((spread * 2) + 1) - spread); - location.setPitch(rand.nextInt(25) - 45); - - Vector v = location.clone().add(0, 0.8, 0).getDirection().normalize(); - Location location1 = location.clone().add(new Vector(v.getX() * 2, v.getY(), v.getZ() * 2)); - Vector dir = location1.setDirection(location.getDirection()).getDirection().multiply(velocity); - - temps.add(new TempFallingBlock(location, materialData, dir, this)); - } - } - - public void track() { - List destroy = new ArrayList<>(); - - for (TempFallingBlock tfb : temps) { - FallingBlock fb = tfb.getFallingBlock(); - - if (fb == null || fb.isDead()) { - destroy.add(tfb); - continue; - } - - for (int i = 0; i < 2; i++) { - ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.1, materialData); - ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.2, materialData); - } - - AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); - - CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { - UUID uuid = entity.getUniqueId(); - if (this.multipleHits || hitEntities.add(uuid)) { - DamageHandler.damageEntity(entity, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : damage, this); - } - return false; - }); - } - - temps.removeAll(destroy); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public List getLocations() { - return temps.stream().map(TempFallingBlock::getLocation).collect(toList()); - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Earth.EarthKick.AbilityCollisionRadius"); - } - - @Override - public void handleCollision(Collision collision) { - CollisionUtil.handleFallingBlockCollisions(collision, temps); - } - - @Override - public String getName() { - return "EarthKick"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthKick.Description"); - } - - public List getTemps() { - return temps; - } - - public BlockData getMaterialData() { - return materialData; - } - - public void setMaterialData(BlockData materialData) { - this.materialData = materialData; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getEarthBlocksQuantity() { - return earthBlocks; - } - - public void setEarthBlocksQuantity(int earthBlocks) { - this.earthBlocks = earthBlocks; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getMetalDmg() { - return metalDmg; - } - - public void setMetalDmg(double metalDmg) { - this.metalDmg = metalDmg; - } - - public double getEntityCollisionRadius() { - return entityCollisionRadius; - } - - public void setEntityCollisionRadius(double entityCollisionRadius) { - this.entityCollisionRadius = entityCollisionRadius; - } - - public Block getBlock() { - return block; - } - - public void setBlock(Block block) { - this.block = block; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthKick.Enabled"); - } -} diff --git a/src/ability/earthbending/EarthLine.java b/src/ability/earthbending/EarthLine.java deleted file mode 100644 index b0991dd..0000000 --- a/src/ability/earthbending/EarthLine.java +++ /dev/null @@ -1,492 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; -import com.jedk1.jedcore.util.RegenTempBlock; - -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.DamageHandler; - -import com.projectkorra.projectkorra.util.TempFallingBlock; - -import org.bukkit.Effect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -public class EarthLine extends EarthAbility implements AddonAbility { - - private Location location; - private Location endLocation; - private Block sourceBlock; - private TempBlock sourceTempBlock; - private Material sourceType; - private boolean progressing; - private boolean hitted; - private int goOnAfterHit; - private long removalTime = -1; - - private long useCooldown; - private long prepareCooldown; - @Attribute(Attribute.DURATION) - private long maxDuration; - @Attribute(Attribute.RANGE) - private double range; - @Attribute(Attribute.SELECT_RANGE) - private double prepareRange; - private double sourceKeepRange; - @Attribute(Attribute.RADIUS) - private int affectingRadius; - @Attribute(Attribute.DAMAGE) - private double damage; - private boolean allowChangeDirection; - private CompositeRemovalPolicy removalPolicy; - - public EarthLine(Player player) { - super(player); - - if (!isEnabled()) return; - - if (!bPlayer.canBend(this)) { - return; - } - goOnAfterHit = 1; - - setFields(); - if (prepare()) { - start(); - if (!isRemoved() && prepareCooldown != 0) { - bPlayer.addCooldown(this, prepareCooldown); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new SwappedSlotsRemovalPolicy<>(bPlayer, EarthLine.class) - ); - - this.removalPolicy.load(config); - - useCooldown = config.getLong("Abilities.Earth.EarthLine.Cooldown"); - prepareCooldown = config.getLong("Abilities.Earth.EarthLine.PrepareCooldown"); - range = config.getInt("Abilities.Earth.EarthLine.Range"); - prepareRange = config.getDouble("Abilities.Earth.EarthLine.PrepareRange"); - sourceKeepRange = config.getDouble("Abilities.Earth.EarthLine.SourceKeepRange"); - affectingRadius = config.getInt("Abilities.Earth.EarthLine.AffectingRadius"); - damage = config.getDouble("Abilities.Earth.EarthLine.Damage"); - allowChangeDirection = config.getBoolean("Abilities.Earth.EarthLine.AllowChangeDirection"); - maxDuration = config.getLong("Abilities.Earth.EarthLine.MaxDuration"); - } - - public boolean prepare() { - final Block block = getEarthSourceBlock(this.range); - if (block == null || !this.isEarthbendable(block)) { - return false; - } else if (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block)) { - return false; - } - - boolean selectedABlockInUse = false; - for (final EarthLine el : getAbilities(this.player, EarthLine.class)) { - if (!el.progressing) { - el.remove(); - } else if (block.equals(el.sourceBlock)) { - selectedABlockInUse = true; - } - } - - if (selectedABlockInUse) { - return false; - } - - if (block.getLocation().distanceSquared(this.player.getLocation()) > this.prepareRange * this.prepareRange) { - return false; - } - - this.sourceBlock = block; - this.focusBlock(); - return true; - } - - private void focusBlock() { - if (DensityShift.isPassiveSand(this.sourceBlock)) { - DensityShift.revertSand(this.sourceBlock); - } - - if (this.sourceBlock.getType() == Material.SAND) { - this.sourceType = Material.SAND; - sourceTempBlock = new TempBlock(sourceBlock, Material.SANDSTONE.createBlockData()); - //this.sourceBlock.setType(Material.SANDSTONE); - } else if (this.sourceBlock.getType() == Material.RED_SAND) { - this.sourceType = Material.RED_SAND; - sourceTempBlock = new TempBlock(sourceBlock, Material.RED_SANDSTONE.createBlockData()); - //this.sourceBlock.setType(Material.RED_SANDSTONE); - } else if (this.sourceBlock.getType() == Material.STONE) { - //this.sourceBlock.setType(Material.COBBLESTONE); - this.sourceType = Material.STONE; - sourceTempBlock = new TempBlock(sourceBlock, Material.COBBLESTONE.createBlockData()); - } else { - this.sourceType = this.sourceBlock.getType(); - //this.sourceBlock.setType(Material.STONE); - sourceTempBlock = new TempBlock(sourceBlock, Material.STONE.createBlockData()); - } - - this.location = this.sourceBlock.getLocation(); - } - - private void unfocusBlock() { - //sourceBlock.setType(sourceType); - sourceTempBlock.revertBlock(); - } - - @Override - public void remove() { -// if (sourceBlock != null && sourceBlock.getType() != Material.AIR) { -// sourceBlock.setType(sourceType); // Ensure no duplication of the source block -// } - sourceTempBlock.revertBlock(); - super.remove(); - } - - private static Location getTargetLocation(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - double range = config.getInt("Abilities.Earth.EarthLine.Range"); - Entity target = GeneralMethods.getTargetedEntity(player, range, player.getNearbyEntities(range, range, range)); - Location location; - if (target == null) { - location = GeneralMethods.getTargetedLocation(player, range); - } else { - location = ((LivingEntity) target).getEyeLocation(); - } - return location; - } - - public void shootLine(Location endLocation) { - if (useCooldown != 0 && bPlayer.getCooldown(this.getName()) < useCooldown) bPlayer.addCooldown(this, useCooldown); - if (maxDuration > 0) removalTime = System.currentTimeMillis() + maxDuration; - this.endLocation = endLocation; - progressing = true; - sourceBlock.getWorld().playEffect(sourceBlock.getLocation(), Effect.GHAST_SHOOT, 0, 10); - } - - public static void shootLine(Player player) { - if (hasAbility(player, EarthLine.class)) { - EarthLine el = getAbility(player, EarthLine.class); - if (!el.progressing) { - el.shootLine(getTargetLocation(player)); - } - } - } - - private boolean sourceOutOfRange() { - return sourceBlock == null || sourceBlock.getLocation().add(0.5, 0.5, 0.5).distanceSquared(player.getLocation()) > sourceKeepRange * sourceKeepRange || sourceBlock.getWorld() != player.getWorld(); - } - - public void progress() { - if (!progressing) { - if (sourceOutOfRange()) { - unfocusBlock(); - remove(); - } - return; - } - - if (removalPolicy.shouldRemove()) { - remove(); - return; - } - - if (sourceBlock == null || RegionProtection.isRegionProtected(this, location)) { - remove(); - return; - } - - if (removalTime > -1 && System.currentTimeMillis() > removalTime) { - remove(); - return; - } - - if (sourceOutOfRange()) { - remove(); - return; - } - - if (RegionProtection.isRegionProtected(player, location, this)) { - remove(); - return; - } - - if (allowChangeDirection && player.isSneaking() && bPlayer.getBoundAbilityName().equalsIgnoreCase("EarthLine")) { - endLocation = getTargetLocation(player); - } - - double x1 = endLocation.getX(); - double z1 = endLocation.getZ(); - double x0 = sourceBlock.getX(); - double z0 = sourceBlock.getZ(); - Vector looking = new Vector(x1 - x0, 0.0D, z1 - z0); - Vector push = new Vector(x1 - x0, 0.34999999999999998D, z1 - z0); - if (location.distance(sourceBlock.getLocation()) < range) { - Material cloneType = location.getBlock().getType(); - Location locationYUP = location.getBlock().getLocation().clone().add(0.5, 0.1, 0.5); - - playEarthbendingSound(location); - - if (isEarthbendable(location.getBlock())) { - //new RegenTempBlock(location.getBlock(), Material.AIR, Material.AIR.createBlockData(), 700L); - new TempBlock(location.getBlock(), Material.AIR.createBlockData(), 700L); - new TempFallingBlock(locationYUP, cloneType.createBlockData(), new Vector(0.0, 0.35, 0.0), this); - } - - location.add(looking.normalize()); - - if (!climb()) { - remove(); - return; - } - - if (hitted) { - if (goOnAfterHit != 0) { - goOnAfterHit--; - } else { - remove(); - return; - } - } else { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, affectingRadius)) { - if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))){ - return; - } - if ((entity instanceof LivingEntity) && entity.getEntityId() != player.getEntityId()) { - GeneralMethods.setVelocity(this, entity, push.normalize().multiply(2)); - DamageHandler.damageEntity(entity, damage, this); - hitted = true; - } - } - } - } else { - remove(); - return; - } - - if (!isEarthbendable(player, location.getBlock()) && !isTransparent(location.getBlock())) { - remove(); - } - } - - private boolean climb() { - Block above = location.getBlock().getRelative(BlockFace.UP); - - if (!isTransparent(above)) { - // Attempt to climb since the current location has a block above it. - location.add(0, 1, 0); - above = location.getBlock().getRelative(BlockFace.UP); - - // The new location must be earthbendable and have something transparent above it. - return isEarthbendable(location.getBlock()) && isTransparent(above); - } else if (isTransparent(location.getBlock()) ) { - // Attempt to fall since the current location is transparent and the above block was transparent. - location.add(0, -1, 0); - - // The new location must be earthbendable and we already know the block above it is transparent. - return isEarthbendable(location.getBlock()); - } - - return true; - } - - @Override - public long getCooldown() { - return useCooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "EarthLine"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthLine.Description"); - } - - public Location getEndLocation() { - return endLocation; - } - - public void setEndLocation(Location endLocation) { - this.endLocation = endLocation; - } - - public Block getSourceBlock() { - return sourceBlock; - } - - public void setSourceBlock(Block sourceBlock) { - this.sourceBlock = sourceBlock; - } - - public Material getSourceType() { - return sourceType; - } - - public void setSourceType(Material sourceType) { - this.sourceType = sourceType; - } - - public boolean isProgressing() { - return progressing; - } - - public void setProgressing(boolean progressing) { - this.progressing = progressing; - } - - public int getGoOnAfterHit() { - return goOnAfterHit; - } - - public void setGoOnAfterHit(int goOnAfterHit) { - this.goOnAfterHit = goOnAfterHit; - } - - public long getRemovalTime() { - return removalTime; - } - - public void setRemovalTime(long removalTime) { - this.removalTime = removalTime; - } - - public long getUseCooldown() { - return useCooldown; - } - - public void setUseCooldown(long useCooldown) { - this.useCooldown = useCooldown; - } - - public long getPrepareCooldown() { - return prepareCooldown; - } - - public void setPrepareCooldown(long prepareCooldown) { - this.prepareCooldown = prepareCooldown; - } - - public long getMaxDuration() { - return maxDuration; - } - - public void setMaxDuration(long maxDuration) { - this.maxDuration = maxDuration; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public double getPrepareRange() { - return prepareRange; - } - - public void setPrepareRange(double prepareRange) { - this.prepareRange = prepareRange; - } - - public double getSourceKeepRange() { - return sourceKeepRange; - } - - public void setSourceKeepRange(double sourceKeepRange) { - this.sourceKeepRange = sourceKeepRange; - } - - public int getAffectingRadius() { - return affectingRadius; - } - - public void setAffectingRadius(int affectingRadius) { - this.affectingRadius = affectingRadius; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean isAllowChangeDirection() { - return allowChangeDirection; - } - - public void setAllowChangeDirection(boolean allowChangeDirection) { - this.allowChangeDirection = allowChangeDirection; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthLine.Enabled"); - } -} \ No newline at end of file diff --git a/src/ability/earthbending/EarthPillar.java b/src/ability/earthbending/EarthPillar.java deleted file mode 100644 index 1935c15..0000000 --- a/src/ability/earthbending/EarthPillar.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.Collapse; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; - -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -public class EarthPillar extends EarthAbility implements AddonAbility { - - private static final ConcurrentHashMap AFFECTED_BLOCKS = new ConcurrentHashMap<>(); - private static final ConcurrentHashMap> AFFECTED = new ConcurrentHashMap<>(); - - private Block block; - private BlockFace face; - @Attribute(Attribute.HEIGHT) - private int height; - @Attribute(Attribute.RANGE) - private int range; - private int step; - - private final List blocks = new ArrayList<>(); - - public EarthPillar(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - Block target = BlockSource.getEarthSourceBlock(player, range, ClickType.SHIFT_DOWN); - if (target != null && !AFFECTED_BLOCKS.containsKey(target)) { - List blocks = player.getLastTwoTargetBlocks(null, range); - if (blocks.size() > 1) { - this.player = player; - face = blocks.get(1).getFace(blocks.get(0)); - block = blocks.get(1); - height = getEarthbendableBlocksLength(block, getDirection(face).clone().multiply(-1), height); - start(); - } - } else if (target != null && AFFECTED_BLOCKS.containsKey(target)) { - List blocks = AFFECTED.get(AFFECTED_BLOCKS.get(target)); - if (blocks != null && !blocks.isEmpty()) { - for (Block b : blocks) { - Collapse.revertBlock(b); - } - playEarthbendingSound(target.getLocation()); - AFFECTED.remove(AFFECTED_BLOCKS.get(target)); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - height = config.getInt("Abilities.Earth.EarthPillar.Height"); - range = config.getInt("Abilities.Earth.EarthPillar.Range"); - } - - @Override - public void progress() { - if (step < height) { - step++; - movePillar(); - } else { - AFFECTED.put(this, blocks); - remove(); - } - } - - private void movePillar() { - moveEarth(block, getDirection(face), height); - block = block.getRelative(face); - AFFECTED_BLOCKS.put(block, this); - blocks.add(block); - } - - private Vector getDirection(BlockFace face) { - switch (face) { - case UP: - return new Vector(0, 1, 0); - case DOWN: - return new Vector(0, -1, 0); - case NORTH: - return new Vector(0, 0, -1); - case SOUTH: - return new Vector(0, 0, 1); - case EAST: - return new Vector(1, 0, 0); - case WEST: - return new Vector(-1, 0, 0); - default: - return null; - } - } - - public static void progressAll() { - for (Block block : AFFECTED_BLOCKS.keySet()) { - if (!EarthAbility.isEarthbendable(AFFECTED_BLOCKS.get(block).getPlayer(), block)) { - AFFECTED_BLOCKS.remove(block); - } - } - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return block != null ? block.getLocation() : null; - } - - @Override - public String getName() { - return "EarthPillar"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthPillar.Description"); - } - - public Block getBlock() { - return block; - } - - public void setBlock(Block block) { - this.block = block; - } - - public BlockFace getFace() { - return face; - } - - public void setFace(BlockFace face) { - this.face = face; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public int getStep() { - return step; - } - - public void setStep(int step) { - this.step = step; - } - - public List getBlocks() { - return blocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthPillar.Enabled"); - } -} \ No newline at end of file diff --git a/src/ability/earthbending/EarthShard.java b/src/ability/earthbending/EarthShard.java deleted file mode 100644 index 793da8e..0000000 --- a/src/ability/earthbending/EarthShard.java +++ /dev/null @@ -1,274 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.AABB; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.CollisionUtil; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.BlockUtil; -import com.jedk1.jedcore.util.ThreadUtil; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.jedk1.jedcore.util.TempFallingBlock; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.*; -import org.bukkit.util.Vector; - -import java.util.*; -import java.util.stream.Collectors; - -public class EarthShard extends EarthAbility implements AddonAbility { - - @Attribute(Attribute.RANGE) - public static int range; - - public static int abilityRange; - - @Attribute(Attribute.DAMAGE) - public static double normalDmg, metalDmg; - - @Attribute("MaxShots") - public static int maxShards; - - @Attribute(Attribute.COOLDOWN) - public static long cooldown; - - private boolean isThrown = false; - private final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - private Location origin; - private double abilityCollisionRadius, entityCollisionRadius; - private boolean allowKnockup; - private double knockupVelocity; - - private final List tblockTracker = new ArrayList<>(); - private final List readyBlocksTracker = new ArrayList<>(); - private final List fallingBlocks = new ArrayList<>(); - - public EarthShard(Player player) { - super(player); - if (!bPlayer.canBend(this)) return; - - if (hasAbility(player, EarthShard.class)) { - for (EarthShard es : getAbilities(player, EarthShard.class)) { - if (es.isThrown && System.currentTimeMillis() - es.getStartTime() >= 20000) { - es.remove(); - } else { - es.select(); - return; - } - } - } - - setFields(); - origin = player.getLocation().clone(); - raiseEarthBlock(getEarthSourceBlock(range)); - start(); - } - - private void setFields() { - ConfigurationSection c = JedCoreConfig.getConfig(player); - range = c.getInt("Abilities.Earth.EarthShard.PrepareRange"); - abilityRange = c.getInt("Abilities.Earth.EarthShard.AbilityRange"); - normalDmg = c.getDouble("Abilities.Earth.EarthShard.Damage.Normal"); - metalDmg = c.getDouble("Abilities.Earth.EarthShard.Damage.Metal"); - maxShards = c.getInt("Abilities.Earth.EarthShard.MaxShards"); - cooldown = c.getLong("Abilities.Earth.EarthShard.Cooldown"); - abilityCollisionRadius = c.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); - entityCollisionRadius = c.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); - allowKnockup = c.getBoolean("Abilities.Earth.EarthShard.KnockUp.Allow"); - knockupVelocity = c.getDouble("Abilities.Earth.EarthShard.KnockUp.Velocity"); - } - - public void select() { - raiseEarthBlock(getEarthSourceBlock(range)); - } - - public void raiseEarthBlock(Block block) { - if (block == null || tblockTracker.size() >= maxShards) return; - - Vector blockVec = block.getLocation().toVector(); blockVec.setY(0); - for (TempBlock tb : tblockTracker) { - Vector tempVec = tb.getLocation().toVector(); tempVec.setY(0); - if (tempVec.equals(blockVec)) return; - } - - for (int i = 1; i <= 3; i++) { - if (!isTransparent(block.getRelative(BlockFace.UP, i))) return; - } - - if (!isEarthbendable(block)) return; - - if (isMetal(block)) { - playMetalbendingSound(block.getLocation()); - } else { - ParticleEffect.BLOCK_CRACK.display(block.getLocation().add(0, 1, 0), 20, 0, 0, 0, 0, block.getBlockData()); - playEarthbendingSound(block.getLocation()); - } - - Material mat = getCorrectType(block); - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - - Location loc = block.getLocation().add(0.5, 0, 0.5); - TempFallingBlock tfb = new TempFallingBlock(loc, mat.createBlockData(), new Vector(0, 0.8, 0), this); - fallingBlocks.add(tfb); - tblockTracker.add(new TempBlock(block, Material.AIR.createBlockData())); - - if (allowKnockup) { - for (Entity e : block.getWorld().getNearbyEntities(block.getLocation(), 1.5, 1.5, 1.5)) { - if (!(e instanceof FallingBlock) && e.getLocation().getY() >= block.getY()) { - ThreadUtil.ensureEntity(e, () -> e.setVelocity(e.getVelocity().add(new Vector(0, knockupVelocity, 0)))); - } - } - } - } - - private Material getCorrectType(Block b) { - switch (b.getType()) { - case SAND: return Material.SANDSTONE; - case RED_SAND: return Material.RED_SANDSTONE; - case GRAVEL: return Material.COBBLESTONE; - default: - if (b.getType().name().endsWith("CONCRETE_POWDER")) { - return Material.getMaterial(b.getType().name().replace("_POWDER", "")); - } - return b.getType(); - } - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - remove(); return; - } - - if (!isThrown) { - if (!bPlayer.canBendIgnoreCooldowns(this) || tblockTracker.isEmpty()) { - remove(); return; - } - - for (TempFallingBlock tfb : new ArrayList<>(TempFallingBlock.getFromAbility(this))) { - FallingBlock fb = tfb.getFallingBlock(); - if (fb == null || fb.isDead() || fb.getLocation().getBlockY() == origin.getBlockY() + 2) { - tfb.remove(); - readyBlocksTracker.add(new TempBlock(fb.getLocation().getBlock(), fb.getBlockData())); - } - } - } else { - for (TempFallingBlock tfb : new ArrayList<>(TempFallingBlock.getFromAbility(this))) { - FallingBlock fb = tfb.getFallingBlock(); - if (fb == null) continue; - AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); - CollisionDetector.checkEntityCollisions(player, collider, e -> { - DamageHandler.damageEntity(e, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : normalDmg, this); - if (e instanceof LivingEntity le) le.setNoDamageTicks(0); - ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 20, 0, 0, 0, 0, fb.getBlockData()); - tfb.remove(); - return false; - }); - } - - if (TempFallingBlock.getFromAbility(this).isEmpty()) { - remove(); - } - } - } - - public void throwShard() { - if (isThrown || readyBlocksTracker.isEmpty()) return; - - Location targetLoc = GeneralMethods.getTargetedLocation(player, abilityRange); - Entity ent = GeneralMethods.getTargetedEntity(player, abilityRange, new ArrayList<>()); - if (ent != null) targetLoc = ent.getLocation(); - - for (TempBlock tb : readyBlocksTracker) { - Vector vel = GeneralMethods.getDirection(tb.getLocation(), targetLoc) - .normalize().multiply(2).add(new Vector(0, 0.2, 0)); - TempFallingBlock tfb = new TempFallingBlock(tb.getLocation(), tb.getBlockData(), vel, this); - fallingBlocks.add(tfb); - } - - revertBlocks(); - isThrown = true; - BendingPlayer.getBendingPlayer(player).addCooldown(this); - } - - private void revertBlocks() { - tblockTracker.forEach(TempBlock::revertBlock); - readyBlocksTracker.forEach(TempBlock::revertBlock); - tblockTracker.clear(); - readyBlocksTracker.clear(); - } - - @Override - public void remove() { - TempFallingBlock.getFromAbility(this).forEach(TempFallingBlock::remove); - revertBlocks(); - super.remove(); - } - - @Override - public long getCooldown() { return cooldown; } - - @Override - public Location getLocation() { return null; } - - @Override - public List getLocations() { - return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); - } - - public void handleCollision(Collision collision) { - CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); - } - - @Override - public double getCollisionRadius() { return abilityCollisionRadius; } - - @Override - public String getName() { return "EarthShard"; } - - @Override - public boolean isHarmlessAbility() { return false; } - - @Override - public boolean isSneakAbility() { return true; } - - @Override - public String getAuthor() { return JedCore.dev; } - - @Override - public String getVersion() { return JedCore.version; } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthShard.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthShard.Enabled"); - } -} diff --git a/src/ability/earthbending/EarthSurf.java b/src/ability/earthbending/EarthSurf.java deleted file mode 100644 index 83df672..0000000 --- a/src/ability/earthbending/EarthSurf.java +++ /dev/null @@ -1,503 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.MaterialUtil; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.TempBlock; - -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.*; - -public class EarthSurf extends EarthAbility implements AddonAbility { - private static final double TARGET_HEIGHT = 1.5; - - private Location location; - private double prevHealth; - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private long minimumCooldown; - @Attribute(Attribute.DURATION) - private long duration; - private boolean cooldownEnabled; - private boolean durationEnabled; - private boolean removeOnAnyDamage; - @Attribute(Attribute.SPEED) - private double speed; - private double springStiffness; - private final Set ridingBlocks = new HashSet<>(); - private CollisionDetector collisionDetector = new DefaultCollisionDetector(); - private DoubleSmoother heightSmoother; - - public EarthSurf(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, EarthSurf.class)) { - getAbility(player, EarthSurf.class).remove(); - return; - } - - setFields(); - - location = player.getLocation(); - - if (canStart()) { - prevHealth = player.getHealth(); - - this.flightHandler.createInstance(player, this.getName()); - player.setAllowFlight(true); - player.setFlying(false); - start(); - } - } - - private boolean canStart() { - Block beneath = getBlockBeneath(player.getLocation().clone()); - double maxHeight = getMaxHeight(); - - return isEarthbendable(player, beneath) && !isMetal(beneath) && beneath.getLocation().distanceSquared(player.getLocation()) <= maxHeight * maxHeight; - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.Cooldown"); - minimumCooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown"); - duration = config.getLong("Abilities.Earth.EarthSurf.Duration.Duration"); - cooldownEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Enabled"); - durationEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Duration.Enabled"); - removeOnAnyDamage = config.getBoolean("Abilities.Earth.EarthSurf.RemoveOnAnyDamage"); - speed = config.getDouble("Abilities.Earth.EarthSurf.Speed"); - springStiffness = config.getDouble("Abilities.Earth.EarthSurf.SpringStiffness"); - - int smootherSize = config.getInt("Abilities.Earth.EarthSurf.HeightTolerance"); - this.heightSmoother = new DoubleSmoother(Math.max(smootherSize, 1)); - - if (config.getBoolean("Abilities.Earth.EarthSurf.RelaxedCollisions")) { - this.collisionDetector = new RelaxedCollisionDetector(); - } - - if (!config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Scaled")) { - minimumCooldown = cooldown; - } - } - - @Override - public void progress() { - if (shouldRemove()) { - remove(); - return; - } - - this.player.setFlying(false); - - if (!collisionDetector.isColliding(player) && player.getHealth() >= prevHealth) { - movePlayer(); - - if (removeOnAnyDamage) { - prevHealth = player.getHealth(); - } - } else { - remove(); - } - } - - private boolean shouldRemove() { - if (player == null || player.isDead() || !player.isOnline()) return true; - if (!bPlayer.canBendIgnoreCooldowns(this)) return true; - if (!isEarthbendable(player, getBlockBeneath(player.getLocation().clone()))) return true; - if (durationEnabled && System.currentTimeMillis() > getStartTime() + duration) return true; - - return player.isSneaking(); - } - - private void movePlayer() { - location = player.getEyeLocation().clone(); - location.setPitch(0); - Vector direction = location.getDirection().normalize(); - - // How far the player is above the ground. - double height = getPlayerDistance(); - double maxHeight = getMaxHeight(); - double smoothedHeight = heightSmoother.add(height); - - // Destroy ability if player gets too far from ground. - if (smoothedHeight > maxHeight) { - remove(); - return; - } - - // Calculate the spring force to push the player back to the target height. - double displacement = height - TARGET_HEIGHT; - double force = -springStiffness * displacement; - - double maxForce = 0.5; - if (Math.abs(force) > maxForce) { - // Cap the force to maxForce so the player isn't instantly pulled to the ground. - force = force / Math.abs(force) * maxForce; - } - - Vector velocity = direction.clone().multiply(speed).setY(force); - - rideWave(); - - player.setVelocity(velocity); - player.setFallDistance(0); - } - - private double getMaxHeight() { - return TARGET_HEIGHT + 2.0; - } - - private double getPlayerDistance() { - Location l = player.getLocation().clone(); - while (true) { - if (l.getBlockY() <= l.getWorld().getMinHeight()) break; - if (ElementalAbility.isAir(l.getBlock().getType()) && ridingBlocks.contains(l.getBlock())) break; - if (GeneralMethods.isSolid(l.getBlock())) break; - - l.add(0, -0.1, 0); - } - return player.getLocation().getY() - l.getY(); - } - - private Block getBlockBeneath(Location l) { - while (l.getBlockY() > l.getWorld().getMinHeight() && MaterialUtil.isTransparent(l.getBlock())) { - l.add(0, -0.5, 0); - } - return l.getBlock(); - } - - private void rideWave() { - for (int i = 0; i < 3; i++) { - Location loc = location.clone(); - if (i < 2) - loc.add(getSideDirection(i)); - - //Player Positioning - double distOffset = 2.5; - Location bL = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); - while (!ElementalAbility.isAir(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()).getBlock().getType())) { - loc.add(0, 0.1, 0); - } - - if (isEarthbendable(player, getBlockBeneath(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()))) && getBlockBeneath(bL) != null) { - Block block = loc.clone().add(0, -3.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset - 0.5)).toLocation(player.getWorld()).getBlock(); - Location temp = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); - - if (RegionProtection.isRegionProtected(this, block.getLocation())) { - continue; - } - // Don't render blocks above the player because it looks bad. - // TODO: Change this check to see if it's a reachable position instead. - if (block.getLocation().getY() > this.player.getLocation().getY()) { - continue; - } - - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - - if (!GeneralMethods.isSolid(block.getLocation().add(0, 1, 0).getBlock()) && !ElementalAbility.isAir(block.getLocation().add(0, 1, 0).getBlock().getType())) { - if (DensityShift.isPassiveSand(block.getRelative(BlockFace.UP))) { - DensityShift.revertSand(block.getRelative(BlockFace.UP)); - } - - new TempBlock(block.getRelative(BlockFace.UP), Material.AIR.createBlockData()); - } - - if (GeneralMethods.isSolid(block)) { - ridingBlocks.add(block); - new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L, true, ridingBlocks::remove); - } else { - new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L); - } - - new TempFallingBlock(temp, getBlockBeneath(bL).getBlockData(), new Vector(0, 0.25, 0), this, true); - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()), 1.5D)) { - if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { - e.setVelocity(new Vector(0, 0.3, 0)); - } - } - } - } - } - - private Vector getSideDirection(int side) { - Vector direction = location.clone().getDirection().normalize(); - switch (side) { - case 0: // RIGHT - return new Vector(-direction.getZ(), 0.0, direction.getX()).normalize(); - case 1: // LEFT - return new Vector(direction.getZ(), 0.0, -direction.getX()).normalize(); - default: - break; - } - - return null; - } - - @Override - public void remove() { - this.flightHandler.removeInstance(player, this.getName()); - - if (cooldownEnabled && player.isOnline()) { - long scaledCooldown = cooldown; - - if (durationEnabled && duration > 0) { - double t = Math.min((System.currentTimeMillis() - this.getStartTime()) / (double) duration, 1.0); - scaledCooldown = Math.max((long) (cooldown * t), minimumCooldown); - } - - bPlayer.addCooldown(this, scaledCooldown); - } - - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "EarthSurf"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthSurf.Description"); - } - - public static double getTargetHeight() { - return TARGET_HEIGHT; - } - - public void setLocation(Location location) { - this.location = location; - } - - public double getPrevHealth() { - return prevHealth; - } - - public void setPrevHealth(double prevHealth) { - this.prevHealth = prevHealth; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getMinimumCooldown() { - return minimumCooldown; - } - - public void setMinimumCooldown(long minimumCooldown) { - this.minimumCooldown = minimumCooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public boolean isCooldownEnabled() { - return cooldownEnabled; - } - - public void setCooldownEnabled(boolean cooldownEnabled) { - this.cooldownEnabled = cooldownEnabled; - } - - public boolean isDurationEnabled() { - return durationEnabled; - } - - public void setDurationEnabled(boolean durationEnabled) { - this.durationEnabled = durationEnabled; - } - - public boolean isRemoveOnAnyDamage() { - return removeOnAnyDamage; - } - - public void setRemoveOnAnyDamage(boolean removeOnAnyDamage) { - this.removeOnAnyDamage = removeOnAnyDamage; - } - - public double getSpeed() { - return speed; - } - - public void setSpeed(double speed) { - this.speed = speed; - } - - public double getSpringStiffness() { - return springStiffness; - } - - public void setSpringStiffness(double springStiffness) { - this.springStiffness = springStiffness; - } - - public Set getRidingBlocks() { - return ridingBlocks; - } - - public CollisionDetector getCollisionDetector() { - return collisionDetector; - } - - public void setCollisionDetector(CollisionDetector collisionDetector) { - this.collisionDetector = collisionDetector; - } - - public DoubleSmoother getHeightSmoother() { - return heightSmoother; - } - - public void setHeightSmoother(DoubleSmoother heightSmoother) { - this.heightSmoother = heightSmoother; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - return config.getBoolean("Abilities.Earth.EarthSurf.Enabled"); - } - - private interface CollisionDetector { - boolean isColliding(Player player); - } - - private abstract static class AbstractCollisionDetector implements CollisionDetector { - protected boolean isCollision(Location location) { - Block block = location.getBlock(); - return !MaterialUtil.isTransparent(block) || block.isLiquid() || block.getType().isSolid(); - } - } - - private class DefaultCollisionDetector extends AbstractCollisionDetector { - @Override - public boolean isColliding(Player player) { - // The location in front of the player, where the player will be in one second. - Location front = player.getEyeLocation().clone(); - front.setPitch(0); - - Vector direction = front.getDirection().clone().setY(0).normalize(); - double playerSpeed = player.getVelocity().clone().setY(0).length(); - - front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); - - for (int i = 0; i < 3; ++i) { - Location location = front.clone().add(0, -i, 0); - if (isCollision(location)) { - return true; - } - } - - return false; - } - } - - private class RelaxedCollisionDetector extends AbstractCollisionDetector { - @Override - public boolean isColliding(Player player) { - // The location in front of the player, where the player will be in one second. - Location front = player.getEyeLocation().clone().subtract(0.0, 0.5, 0.0); - front.setPitch(0); - - Vector direction = front.getDirection().clone().setY(0).normalize(); - double playerSpeed = player.getVelocity().clone().setY(0).length(); - - front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); - - return isCollision(front); - } - } - - private static class DoubleSmoother { - private final double[] values; - private final int size; - private int index; - - public DoubleSmoother(int size) { - this.size = size; - this.index = 0; - - values = new double[size]; - } - - public double add(double value) { - values[index] = value; - index = (index + 1) % size; - return get(); - } - - public double get() { - return Arrays.stream(this.values).sum() / this.size; - } - } -} diff --git a/src/ability/earthbending/Fissure.java b/src/ability/earthbending/Fissure.java deleted file mode 100644 index 7f947a5..0000000 --- a/src/ability/earthbending/Fissure.java +++ /dev/null @@ -1,441 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.Information; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.util.BlockIterator; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -public class Fissure extends LavaAbility implements AddonAbility { - - @Attribute(Attribute.RANGE) - private int slapRange; - @Attribute(Attribute.WIDTH) - private int maxWidth; - private long slapDelay; - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - private Location location; - private Vector direction; - private Vector blockDirection; - private long time; - private long step; - private int slap; - private int width; - private boolean progressed; - - static Random rand = new Random(); - - private final List centerSlap = new ArrayList<>(); - private final List blocks = new ArrayList<>(); - private final List tempblocks = new ArrayList<>(); - - public Fissure(Player player) { - super(player); - - if (!bPlayer.canBend(this) || hasAbility(player, Fissure.class) || !bPlayer.canLavabend()) { - return; - } - - setFields(); - time = System.currentTimeMillis(); - step = System.currentTimeMillis() + slapDelay; - location = player.getLocation().clone(); - location.setPitch(0); - direction = location.getDirection(); - blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); - blockDirection = blockDirection.setZ(Math.round(direction.getZ())); - if (prepareLine()) { - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - slapRange = config.getInt("Abilities.Earth.Fissure.SlapRange"); - maxWidth = config.getInt("Abilities.Earth.Fissure.MaxWidth"); - slapDelay = config.getInt("Abilities.Earth.Fissure.SlapDelay"); - duration = config.getInt("Abilities.Earth.Fissure.Duration"); - cooldown = config.getInt("Abilities.Earth.Fissure.Cooldown"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (System.currentTimeMillis() > step && slap <= centerSlap.size()) { - time = System.currentTimeMillis(); - step = System.currentTimeMillis() + slapDelay; - slapCenter(); - slap++; - } - if (System.currentTimeMillis() > time + duration) { - remove(); - } - } - - private boolean prepareLine() { - direction = player.getEyeLocation().getDirection().setY(0).normalize(); - blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); - blockDirection = blockDirection.setZ(Math.round(direction.getZ())); - Location origin = player.getLocation().add(0, -1, 0).add(blockDirection.multiply(2)); - if (isEarthbendable(player, origin.getBlock())) { - BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, slapRange); - - while (bi.hasNext()) { - Block b = bi.next(); - - if (b.getY() > 1 && b.getY() < 255 && !RegionProtection.isRegionProtected(this, b.getLocation())) { - if (EarthAbility.getMovedEarth().containsKey(b)){ - Information info = EarthAbility.getMovedEarth().get(b); - if(!info.getBlock().equals(b)) { - continue; - } - } - - while (!isEarthbendable(player, b)) { - b = b.getRelative(BlockFace.DOWN); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b)) { - break; - } - } - - while (!isTransparent(b.getRelative(BlockFace.UP))) { - b = b.getRelative(BlockFace.UP); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(player, b)) { - centerSlap.add(b.getLocation()); - } else { - break; - } - } - } - return true; - } - return false; - } - - private void slapCenter() { - for (Location location : centerSlap) { - if (centerSlap.indexOf(location) == slap) { - addTempBlock(location.getBlock(), Material.LAVA); - } - } - if (slap >= centerSlap.size()) { - progressed = true; - } - } - - public static void performAction(Player player) { - if (hasAbility(player, Fissure.class)) { - getAbility(player, Fissure.class).performAction(); - } - } - - private void performAction() { - if (width < maxWidth) { - expandFissure(); - } else if (blocks.contains(player.getTargetBlock(null, 10))) { - forceRevert(); - } - } - - private void expandFissure() { - if (progressed && width <= maxWidth) { - width++; - for (Location location : centerSlap) { - Block left = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)), width); - expand(left); - - Block right = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)).getOppositeFace(), width); - expand(right); - } - } - Collections.reverse(blocks); - } - - private void expand(Block block) { - if (block != null && block.getY() > 1 && block.getY() < 255 && !RegionProtection.isRegionProtected(this, block.getLocation())) { - if (EarthAbility.getMovedEarth().containsKey(block)){ - Information info = EarthAbility.getMovedEarth().get(block); - if(!info.getBlock().equals(block)) { - return; - } - } - - while (!isEarthbendable(player, block)) { - block = block.getRelative(BlockFace.DOWN); - if (block.getY() < 1 || block.getY() > 255) { - break; - } - if (isEarthbendable(player, block)) { - break; - } - } - - while (!isTransparent(player, block.getRelative(BlockFace.UP))) { - block = block.getRelative(BlockFace.UP); - if (block.getY() < 1 || block.getY() > 255) { - break; - } - if (isEarthbendable(player, block.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(player, block)) { - addTempBlock(block, Material.LAVA); - } - } - } - - private void addTempBlock(Block block, Material material) { - ParticleEffect.LAVA.display(block.getLocation(), 0, 0, 0, 0, 1); - playEarthbendingSound(block.getLocation()); - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } - tempblocks.add(new TempBlock(block, material.createBlockData(), this)); - blocks.add(block); - } - - public BlockFace getLeftBlockFace(BlockFace forward) { - switch (forward) { - case NORTH: - return BlockFace.WEST; - case SOUTH: - return BlockFace.EAST; - case WEST: - return BlockFace.SOUTH; - case EAST: - return BlockFace.NORTH; - case NORTH_WEST: - return BlockFace.SOUTH_WEST; - case NORTH_EAST: - return BlockFace.NORTH_WEST; - case SOUTH_WEST: - return BlockFace.SOUTH_EAST; - case SOUTH_EAST: - return BlockFace.NORTH_EAST; - default: - return BlockFace.NORTH; - } - } - - private void forceRevert() { - coolLava(); - } - - private void coolLava() { - tempblocks.forEach(TempBlock::revertBlock); - for (Block block : blocks) { - new TempBlock(block, Material.STONE.createBlockData(), 500 + (long) rand.nextInt((int) 1000)); - } - blocks.clear(); - tempblocks.clear(); - } - - @Override - public void remove() { - coolLava(); - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "Fissure"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.Fissure.Description"); - } - - public int getSlapRange() { - return slapRange; - } - - public void setSlapRange(int slapRange) { - this.slapRange = slapRange; - } - - public int getMaxWidth() { - return maxWidth; - } - - public void setMaxWidth(int maxWidth) { - this.maxWidth = maxWidth; - } - - public long getSlapDelay() { - return slapDelay; - } - - public void setSlapDelay(long slapDelay) { - this.slapDelay = slapDelay; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public void setLocation(Location location) { - this.location = location; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public Vector getBlockDirection() { - return blockDirection; - } - - public void setBlockDirection(Vector blockDirection) { - this.blockDirection = blockDirection; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public long getStep() { - return step; - } - - public void setStep(long step) { - this.step = step; - } - - public int getSlap() { - return slap; - } - - public void setSlap(int slap) { - this.slap = slap; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - - public boolean isProgressed() { - return progressed; - } - - public void setProgressed(boolean progressed) { - this.progressed = progressed; - } - - public List getCenterSlap() { - return centerSlap; - } - - public List getBlocks() { - return blocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.Fissure.Enabled"); - } -} \ No newline at end of file diff --git a/src/ability/earthbending/LavaDisc.java b/src/ability/earthbending/LavaDisc.java deleted file mode 100644 index 65cdf08..0000000 --- a/src/ability/earthbending/LavaDisc.java +++ /dev/null @@ -1,553 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.block.Block; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -public class LavaDisc extends LavaAbility implements AddonAbility { - - private Location location; - private int recallCount; - - private long time; - - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - private int recallLimit; - private boolean trailFlow; - - private CompositeRemovalPolicy removalPolicy; - private DiscRenderer discRenderer; - private State state; - private final Set trailBlocks = new HashSet<>(); - - public LavaDisc(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { - return; - } - - // Allow new LavaDisc if all existing instances for that player are in CleanupState. - for (LavaDisc disc : CoreAbility.getAbilities(player, LavaDisc.class)) { - if (!(disc.state instanceof CleanupState)) { - return; - } - } - - state = new HoldState(); - time = System.currentTimeMillis(); - discRenderer = new DiscRenderer(this.player); - - setFields(); - - if (prepare()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - damage = config.getDouble("Abilities.Earth.LavaDisc.Damage"); - cooldown = config.getLong("Abilities.Earth.LavaDisc.Cooldown"); - duration = config.getLong("Abilities.Earth.LavaDisc.Duration"); - recallLimit = config.getInt("Abilities.Earth.LavaDisc.RecallLimit") - 1; - trailFlow = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.TrailFlow"); - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new SwappedSlotsRemovalPolicy<>(bPlayer, LavaDisc.class) - ); - - this.removalPolicy.load(config); - } - - private boolean prepare() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - long sourceRegen = config.getLong("Abilities.Earth.LavaDisc.Source.RegenTime"); - boolean lavaOnly = config.getBoolean("Abilities.Earth.LavaDisc.Source.LavaOnly"); - double sourceRange = config.getDouble("Abilities.Earth.LavaDisc.Source.Range"); - - if (getLavaSourceBlock(player, sourceRange) != null) { - Block block = getLavaSourceBlock(player, sourceRange); - new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); - return true; - } else if (getEarthSourceBlock(sourceRange) != null) { - if (lavaOnly) - return false; - Block block = getEarthSourceBlock(sourceRange); - new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); - return true; - } - - return false; - } - - @Override - public void progress() { - if (this.removalPolicy.shouldRemove()) { - if (!player.isOnline()) { - // Revert all of the lava blocks if the player goes offline. - for (Block block : trailBlocks) { - RegenTempBlock.revert(block); - } - bPlayer.addCooldown(this); - remove(); - return; - } else if (!(state instanceof CleanupState)) { - state = new CleanupState(); - } - } - - if (!hasAbility(player, LavaDisc.class)) { - return; - } - - state.update(); - } - - public static boolean canFlowFrom(Block from) { - Material type = from.getType(); - if (type != Material.LAVA && !ElementalAbility.isAir(type)) { - return true; - } - - for (LavaDisc disc : CoreAbility.getAbilities(LavaDisc.class)) { - if (disc.trailFlow) continue; - - if (disc.trailBlocks.contains(from)) { - return false; - } - } - - return true; - } - - private boolean isLocationSafe() { - if (!isLocationSafe(location)) { - return false; - } - - Block block = location.getBlock(); - - return isTransparent(block); - } - - private boolean isLocationSafe(Location location) { - if (location == null || location.getWorld() == null) { - return false; - } - - return location.getY() >= location.getWorld().getMinHeight() && location.getY() <= (location.getWorld().getMaxHeight() - 1); - } - - private void doDamage(Entity entity) { - DamageHandler.damageEntity(entity, damage, this); - entity.setFireTicks(20); - new FireDamageTimer(entity, player, this); - ParticleEffect.LAVA.display(entity.getLocation(), 15, Math.random(), Math.random(), Math.random(), 0.1); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "LavaDisc"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaDisc.Description"); - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getRecallCount() { - return recallCount; - } - - public void setRecallCount(int recallCount) { - this.recallCount = recallCount; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public int getRecallLimit() { - return recallLimit; - } - - public void setRecallLimit(int recallLimit) { - this.recallLimit = recallLimit; - } - - public boolean isTrailFlow() { - return trailFlow; - } - - public void setTrailFlow(boolean trailFlow) { - this.trailFlow = trailFlow; - } - - public DiscRenderer getDiscRenderer() { - return discRenderer; - } - - public void setDiscRenderer(DiscRenderer discRenderer) { - this.discRenderer = discRenderer; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - public Set getTrailBlocks() { - return trailBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.LavaDisc.Enabled"); - } - - private interface State { - void update(); - } - - // Renders the particles showing that the player is holding lava. - // Transitions to ForwardTravelState when the player stops sneaking. - private class HoldState implements State { - @Override - public void update() { - location = player.getEyeLocation(); - Vector dV = location.getDirection().normalize(); - location.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); - - dV = dV.multiply(0.1); - - while (!isLocationSafe() && isLocationSafe(player.getLocation())) { - location.subtract(dV); - if (location.distanceSquared(player.getEyeLocation()) > (3 * 3)) { - break; - } - } - - discRenderer.render(location, false); - - location.setPitch(0); - - if (!player.isSneaking()) { - time = System.currentTimeMillis(); - state = new ForwardTravelState(location.getDirection().normalize()); - } - } - } - - private abstract class TravelState implements State { - private final boolean passHit; - - protected Vector direction; - protected boolean hasHit; - - public TravelState() { - this(player.getEyeLocation().getDirection()); - } - - public TravelState(Vector direction) { - this.direction = direction; - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - passHit = config.getBoolean("Abilities.Earth.LavaDisc.ContinueAfterEntityHit"); - } - - protected void move() { - for (int i = 0; i < 5; i++) { - location = location.add(direction.clone().multiply(0.15)); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.0D)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - doDamage(entity); - if (!passHit) { - hasHit = true; - return; - } - } - } - } - } - } - - // Moves the disc forward. Makes the disc destroy blocks if enabled. - // Transitions to ReverseTravelState if the player starts sneaking and can recall. - // Transitions to CleanupState if it times out or hits an entity. - private class ForwardTravelState extends TravelState { - public ForwardTravelState() { - this(player.getEyeLocation().getDirection()); - } - - public ForwardTravelState(Vector direction) { - super(direction); - } - - @Override - public void update() { - if (!isLocationSafe() || System.currentTimeMillis() > time + duration) { - state = new CleanupState(); - return; - } - - if (player.isSneaking() && recallCount <= recallLimit) { - state = new ReverseTravelState(); - return; - } - - alterPitch(); - move(); - discRenderer.render(location, true); - - if (hasHit) { - state = new CleanupState(); - } - } - - private void alterPitch() { - Location loc = player.getLocation().clone(); - - if (loc.getPitch() < -20) - loc.setPitch(-20); - if (loc.getPitch() > 20) - loc.setPitch(20); - - direction = loc.getDirection().normalize(); - } - } - - // Returns the disc to the player. - // Transitions to ForwardTravelState if the player stops sneaking. - // Transitions to HoldState if the disc gets close enough to the player. - private class ReverseTravelState extends TravelState { - @Override - public void update() { - if (!player.isSneaking()) { - state = new ForwardTravelState(); - return; - } - - Location loc = player.getEyeLocation(); - Vector dV = loc.getDirection().normalize(); - loc.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); - - Vector vector = loc.toVector().subtract(location.toVector()); - direction = loc.setDirection(vector).getDirection().normalize(); - - move(); - discRenderer.render(location, true); - - double distanceAway = location.distance(loc); - if (distanceAway < 0.5) { - recallCount++; - // Player is holding the disc when it gets close enough to them. - state = new HoldState(); - } - } - } - - // Waits for the RegenTempBlocks to revert. - // This exists so the instance stays alive and block flow events can stop the lava from flowing. - private class CleanupState implements State { - private final long startTime; - private final long regenTime; - - public CleanupState() { - this.startTime = System.currentTimeMillis(); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); - bPlayer.addCooldown(LavaDisc.this); - } - - @Override - public void update() { - if (System.currentTimeMillis() >= startTime + regenTime || trailBlocks.isEmpty()) { - remove(); - } - } - } - - private class DiscRenderer { - private final Player player; - private int angle; - - private final boolean damageBlocks; - private final List meltable; - private final long regenTime; - private final boolean lavaTrail; - - private final int particles; - - - public DiscRenderer(Player player) { - this.player = player; - this.angle = 0; - - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - damageBlocks = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.BlockDamage"); - meltable = config.getStringList("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks"); - regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); - lavaTrail = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.LavaTrail"); - particles = config.getInt("Abilities.Earth.LavaDisc.Particles"); - } - - void render(Location location, boolean largeLava) { - if (largeLava) - ParticleEffect.LAVA.display(location, particles * 2, Math.random(), Math.random(), Math.random(), 0.1); - else - ParticleEffect.LAVA.display(location, 1, Math.random(), Math.random(), Math.random(), 0.1); - - angle += 1; - if (angle > 360) - angle = 0; - - for (Location l : JCMethods.getCirclePoints(location, 20, 1, angle)) { - ParticleEffect.REDSTONE.display(l, 0, 196, 93, 0, 0.005F, new Particle.DustOptions(Color.fromRGB(196, 93, 0), 1)); - if (largeLava && damageBlocks) - damageBlocks(l); - } - - for (Location l : JCMethods.getCirclePoints(location, 10, 0.5, angle)) { - ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.01); - ParticleEffect.SMOKE_NORMAL.display(l, 1, 0, 0, 0, 0.05); - if (largeLava && damageBlocks) - damageBlocks(l); - } - } - - private void damageBlocks(Location l) { - if (!RegionProtection.isRegionProtected(player, l, LavaDisc.this)) { - if (!TempBlock.isTempBlock(l.getBlock()) && (isEarthbendable(player, l.getBlock()) || isMetal(l.getBlock()) || meltable.contains(l.getBlock().getType().name()))) { - if (DensityShift.isPassiveSand(l.getBlock())) { - DensityShift.revertSand(l.getBlock()); - } - - if (lavaTrail) { - new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled) bd).setLevel(4)), regenTime); - - trailBlocks.add(l.getBlock()); - } else { - new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), regenTime); - } - - ParticleEffect.LAVA.display(l, particles * 2, Math.random(), Math.random(), Math.random(), 0.2); - } - } - } - } -} diff --git a/src/ability/earthbending/LavaFlux.java b/src/ability/earthbending/LavaFlux.java deleted file mode 100644 index 6368fbf..0000000 --- a/src/ability/earthbending/LavaFlux.java +++ /dev/null @@ -1,451 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.Information; -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Bisected; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.BlockIterator; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; - -public class LavaFlux extends LavaAbility implements AddonAbility { - - @Attribute(Attribute.SPEED) - private int speed; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - private long cleanup; - @Attribute(Attribute.DAMAGE) - private double damage; - private boolean wave; - - private Location location; - private int step; - private int counter; - private long time; - private boolean complete; - - private double knockUp; - private double knockBack; - - Random rand = new Random(); - - private static final BlockData LAVA = Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(1)); - - private final List flux = new ArrayList<>(); - - private Map blocks = new HashMap<>(); - private Map above = new HashMap<>(); - - public LavaFlux(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { - return; - } - - setFields(); - time = System.currentTimeMillis(); - if (prepareLine()) { - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - speed = config.getInt("Abilities.Earth.LavaFlux.Speed"); - if (speed < 1) speed = 1; - range = config.getInt("Abilities.Earth.LavaFlux.Range"); - cooldown = config.getLong("Abilities.Earth.LavaFlux.Cooldown"); - duration = config.getLong("Abilities.Earth.LavaFlux.Duration"); - cleanup = config.getLong("Abilities.Earth.LavaFlux.Cleanup"); - damage = config.getDouble("Abilities.Earth.LavaFlux.Damage"); - wave = config.getBoolean("Abilities.Earth.LavaFlux.Wave"); - knockUp = config.getDouble("Abilities.Earth.LavaFlux.KnockUp"); - knockBack = config.getDouble("Abilities.Earth.LavaFlux.KnockBack"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - counter++; - if (!complete) { - if (speed <= 1 || counter % speed == 0) { - for (int i = 0; i <= 2; i++) { - step++; - progressFlux(); - } - } - } else if (duration > cleanup) { - if (System.currentTimeMillis() > time + duration) { - for (TempBlock tb : blocks.values()) { - if (!tb.isReverted()) tb.setType(Material.STONE); - } - remove(); - } - } - } - - private boolean prepareLine() { - Vector direction = player.getEyeLocation().getDirection().setY(0).normalize(); - Vector blockdirection = direction.clone().setX(Math.round(direction.getX())); - blockdirection = blockdirection.setZ(Math.round(direction.getZ())); - Location origin = player.getLocation().add(0, -1, 0).add(blockdirection.multiply(2)); - if (isEarthbendable(player, origin.getBlock())) { - BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, range); - - while (bi.hasNext()) { - Block b = bi.next(); - - if (b.getY() > b.getWorld().getMinHeight() && b.getY() < b.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, b.getLocation()) && !EarthAbility.getMovedEarth().containsKey(b)) { - if (isWater(b)) break; - while (!isEarthbendable(player, b)) { - b = b.getRelative(BlockFace.DOWN); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b)) { - break; - } - } - - while (!isTransparent(b.getRelative(BlockFace.UP))) { - b = b.getRelative(BlockFace.UP); - if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(player, b)) { - flux.add(b.getLocation()); - Block left = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)), 1); - expand(left); - Block right = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)).getOppositeFace(), 1); - expand(right); - } else { - break; - } - } - } - return true; - } - return false; - } - - private void progressFlux() { - for (Location location : flux) { - if (flux.indexOf(location) <= step) { - if (!blocks.containsKey(location.getBlock())) { //Make a new temp block if we haven't made one there before - blocks.put(location.getBlock(), new TempBlock(location.getBlock(), LAVA, duration + cleanup, this)); - } - - //new RegenTempBlock(location.getBlock(), Material.LAVA, LAVA, duration + cleanup); - this.location = location; - if (flux.indexOf(location) == step) { - Block above = location.getBlock().getRelative(BlockFace.UP); - ParticleEffect.LAVA.display(above.getLocation(), 2, Math.random(), Math.random(), Math.random(), 0); - applyDamageFromWave(above.getLocation()); - - if (isPlant(above) || isSnow(above)) { - final Block above2 = above.getRelative(BlockFace.UP); - if (isPlant(above) || isSnow(above)) { - TempBlock tb = new TempBlock(above, Material.AIR.createBlockData(), duration + cleanup, this); - this.above.put(above, tb); - if (isPlant(above2) && above2.getBlockData() instanceof Bisected) { - TempBlock tb2 = new TempBlock(above2, Material.AIR.createBlockData(), duration + cleanup + 30_000, this); - tb.addAttachedBlock(tb2); - } - } - } else if (wave && isTransparent(above)) { - new TempBlock(location.getBlock().getRelative(BlockFace.UP), LAVA, speed * 150L, this); - } - } - } - } - if (step >= flux.size()) { - wave = false; - complete = true; - time = System.currentTimeMillis(); - - for (TempBlock tb : blocks.values()) { //Make sure they all revert at the same time because it looks nice - long time = duration + cleanup + rand.nextInt(1000); - tb.setRevertTime(time); - - if (this.above.containsKey(tb.getBlock().getRelative(BlockFace.UP))) { - this.above.get(tb.getBlock().getRelative(BlockFace.UP)).setRevertTime(time); - } - } - } - } - - private void applyDamageFromWave(Location location) { - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 1.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - LivingEntity livingEntity = (LivingEntity) entity; - - DamageHandler.damageEntity(entity, damage, this); - new FireDamageTimer(entity, player, this); - - Vector direction = livingEntity.getLocation().toVector().subtract(player.getLocation().toVector()).normalize(); - Vector knockbackVelocity = direction.multiply(knockBack).setY(knockUp); - - livingEntity.setVelocity(knockbackVelocity); - } - } - } - - private void expand(Block block) { - if (block != null && block.getY() > block.getWorld().getMinHeight() && block.getY() < block.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, block.getLocation())) { - if (EarthAbility.getMovedEarth().containsKey(block)){ - Information info = EarthAbility.getMovedEarth().get(block); - if(!info.getBlock().equals(block)) { - return; - } - } - - if (isWater(block)) return; - while (!isEarthbendable(block)) { - block = block.getRelative(BlockFace.DOWN); - if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(block)) { - break; - } - } - - while (!isTransparent(block.getRelative(BlockFace.UP))) { - block = block.getRelative(BlockFace.UP); - if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { - break; - } - if (isEarthbendable(block.getRelative(BlockFace.UP))) { - break; - } - } - - if (isEarthbendable(block)) { - flux.add(block.getLocation()); - } - } - } - - public BlockFace getLeftBlockFace(BlockFace forward) { - switch (forward) { - case NORTH: - return BlockFace.WEST; - case SOUTH: - return BlockFace.EAST; - case WEST: - return BlockFace.SOUTH; - case NORTH_WEST: - return BlockFace.SOUTH_WEST; - case NORTH_EAST: - return BlockFace.NORTH_WEST; - case SOUTH_WEST: - return BlockFace.SOUTH_EAST; - case SOUTH_EAST: - return BlockFace.NORTH_EAST; - default: - return BlockFace.NORTH; - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "LavaFlux"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaFlux.Description"); - } - - public int getSpeed() { - return speed; - } - - public void setSpeed(int speed) { - this.speed = speed; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public long getCleanup() { - return cleanup; - } - - public void setCleanup(long cleanup) { - this.cleanup = cleanup; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean isWave() { - return wave; - } - - public void setWave(boolean wave) { - this.wave = wave; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getStep() { - return step; - } - - public void setStep(int step) { - this.step = step; - } - - public int getCounter() { - return counter; - } - - public void setCounter(int counter) { - this.counter = counter; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public boolean isComplete() { - return complete; - } - - public void setComplete(boolean complete) { - this.complete = complete; - } - - public List getFlux() { - return flux; - } - - @Override - public void load() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - if (config.get("Abilities.Earth.LavaFlux.Speed") instanceof String) { - config.set("Abilities.Earth.LavaFlux.Speed", 1); - JedCore.plugin.saveConfig(); - JedCore.plugin.reloadConfig(); - } - } - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.LavaFlux.Enabled"); - } -} \ No newline at end of file diff --git a/src/ability/earthbending/LavaThrow.java b/src/ability/earthbending/LavaThrow.java deleted file mode 100644 index 07bd010..0000000 --- a/src/ability/earthbending/LavaThrow.java +++ /dev/null @@ -1,344 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; - -import org.bukkit.FluidCollisionMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.RayTraceResult; -import org.bukkit.util.Vector; - -import java.util.concurrent.ConcurrentHashMap; - -public class LavaThrow extends LavaAbility implements AddonAbility { - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.SELECT_RANGE) - private int sourceRange; - private long sourceRegen; - @Attribute("MaxShots") - private int shotMax; - @Attribute(Attribute.FIRE_TICK) - private int fireTicks; - @Attribute("CurveFactor") - private double curveFactor; - - private Location location; - private int shots; - private Block selectedSource; - private boolean isInitialState = true; - - private final ConcurrentHashMap blasts = new ConcurrentHashMap<>(); - - public LavaThrow(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { - return; - } - - setFields(); - - location = player.getLocation(); - location.setPitch(0); - - if (prepare()) { - player.getWorld().playSound(selectedSource.getLocation(), Sound.ITEM_BUCKET_FILL_LAVA, 1.0f, 1.0f); - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.LavaThrow.Cooldown"); - range = config.getInt("Abilities.Earth.LavaThrow.Range"); - damage = config.getDouble("Abilities.Earth.LavaThrow.Damage"); - sourceRange = config.getInt("Abilities.Earth.LavaThrow.SourceGrabRange"); - sourceRegen = config.getLong("Abilities.Earth.LavaThrow.SourceRegenDelay"); - shotMax = config.getInt("Abilities.Earth.LavaThrow.MaxShots"); - fireTicks = config.getInt("Abilities.Earth.LavaThrow.FireTicks"); - curveFactor = config.getDouble("Abilities.Earth.LavaThrow.CurveFactor"); - } - - @Override - public void progress() { - if (player == null || player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.getBoundAbilityName().equalsIgnoreCase("LAVATHROW")) { - remove(); - if (shots > 0) bPlayer.addCooldown(this); - return; - } - - if (player.getLocation().distance(selectedSource.getLocation()) >= sourceRange) { - remove(); - if (shots > 0) bPlayer.addCooldown(this); - return; - } - - if (blasts.isEmpty() && shots >= shotMax && !isInitialState) { - remove(); - bPlayer.addCooldown(this); - return; - } - - selectedSource.getWorld().spawnParticle(Particle.FLAME, selectedSource.getLocation(), 2, 0.3, 1.0, 0.3, 0.05); - selectedSource.getWorld().spawnParticle(Particle.LAVA, selectedSource.getLocation(), 2, 0.2, 0.2, 0.2, 0); - - handleBlasts(); - } - - private boolean prepare() { - Block targetBlock = getTargetLavaBlock(sourceRange); - - if (targetBlock != null) { - selectedSource = targetBlock; - } - - return selectedSource != null; - } - - public Block getTargetLavaBlock(int maxDistance) { - Location eyeLocation = player.getEyeLocation(); - Vector direction = eyeLocation.getDirection(); - World world = player.getWorld(); - - RayTraceResult result = world.rayTraceBlocks( - eyeLocation, direction, maxDistance, - FluidCollisionMode.ALWAYS, true - ); - - if (result != null) { - Block hitBlock = result.getHitBlock(); - if (LavaAbility.isLava(hitBlock)) { - return hitBlock; - } - } - return null; - } - - public void createBlast() { - if (selectedSource != null && shots < shotMax) { - isInitialState = false; - shots++; - - if (shots >= shotMax) { - bPlayer.addCooldown(this); - } - - Location origin = selectedSource.getLocation().clone().add(0, 2, 0); - player.getWorld().playSound(origin, Sound.ITEM_BUCKET_EMPTY_LAVA, 1.0f, 1.0f); - double viewRange = range + origin.distance(player.getEyeLocation()); - Location viewTarget = GeneralMethods.getTargetedLocation(player, viewRange, Material.WATER, Material.LAVA); - Vector direction = viewTarget.clone().subtract(origin).toVector().normalize(); - Location head = origin.clone(); - - head.setDirection(direction); - blasts.put(head, origin); - - new RegenTempBlock(selectedSource.getRelative(BlockFace.UP), Material.LAVA, - Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); - new RegenTempBlock(selectedSource, Material.AIR, Material.AIR.createBlockData(), sourceRegen, false); - } - } - - public void handleBlasts() { - for (Location l : blasts.keySet()) { - Location head = l.clone(); - Location origin = blasts.get(l); - - if (l.distance(origin) > range) { - blasts.remove(l); - continue; - } - - if (GeneralMethods.isSolid(l.getBlock())) { - blasts.remove(l); - continue; - } - - Vector currentDirection = head.getDirection(); - Vector playerLookDirection = player.getEyeLocation().getDirection(); - - Vector curveVector = playerLookDirection.clone() - .subtract(currentDirection) - .multiply(curveFactor); - - Vector newDirection = currentDirection.clone() - .add(curveVector) - .normalize(); - - head.setDirection(newDirection); - head = head.add(newDirection.multiply(1)); - - new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); - ParticleEffect.LAVA.display(head, 1, Math.random(), Math.random(), Math.random(), 0); - - boolean hit = false; - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 2.0D)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { - DamageHandler.damageEntity(entity, damage, this); - blasts.remove(l); - - hit = true; - entity.setFireTicks(this.fireTicks); - } - } - - if (!hit) { - blasts.remove(l); - blasts.put(head, origin); - } - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "LavaThrow"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaThrow.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getSourceRange() { - return sourceRange; - } - - public void setSourceRange(int sourceRange) { - this.sourceRange = sourceRange; - } - - public long getSourceRegen() { - return sourceRegen; - } - - public void setSourceRegen(long sourceRegen) { - this.sourceRegen = sourceRegen; - } - - public int getShotMax() { - return shotMax; - } - - public void setShotMax(int shotMax) { - this.shotMax = shotMax; - } - - public int getFireTicks() { - return fireTicks; - } - - public void setFireTicks(int fireTicks) { - this.fireTicks = fireTicks; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getShots() { - return shots; - } - - public void setShots(int shots) { - this.shots = shots; - } - - public ConcurrentHashMap getBlasts() { - return blasts; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.LavaThrow.Enabled"); - } -} diff --git a/src/ability/earthbending/MagnetShield.java b/src/ability/earthbending/MagnetShield.java deleted file mode 100644 index 4373c5c..0000000 --- a/src/ability/earthbending/MagnetShield.java +++ /dev/null @@ -1,281 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; - -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; - - -public class MagnetShield extends MetalAbility implements AddonAbility { - - private static List METAL_LIST; - - private boolean isClickState = false; - private long startTime; - - @Attribute(Attribute.DURATION) - private long duration; - @Attribute(Attribute.RANGE) - private double range; - - private double velocity; - private boolean repelArrows; - private boolean repelLivingEntities; - private long shiftCooldown; - private long clickCooldown; - - public MagnetShield(Player player) { - super(player); - - if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { - return; - } - - if (!bPlayer.canBend(this)) { - return; - } - - player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); - - setFields(); - loadMaterialsFromConfig(); - start(); - } - - public MagnetShield(Player player, boolean isClickState) { - super(player); - - if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { - return; - } - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, MagnetShield.class)) { - getAbility(player, MagnetShield.class).remove(); - return; - } - - setFields(); - - if (isClickState) { - this.isClickState = true; - startTime = System.currentTimeMillis(); - bPlayer.addCooldown(this, duration + 1); - } - - player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); - - loadMaterialsFromConfig(); - start(); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { - remove(); - return; - } - - if (isClickState) { - if (System.currentTimeMillis() - startTime >= duration) { - bPlayer.addCooldown(this, clickCooldown); - remove(); - return; - } - } else { - if (!player.isSneaking()) { - bPlayer.addCooldown(this, shiftCooldown); - remove(); - return; - } - } - - renderMagneticFieldLines(); - repelMetal(); - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return player.getLocation(); - } - - @Override - public String getName() { - return "MagnetShield"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MagnetShield.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MagnetShield.Enabled"); - } - - private void renderMagneticFieldLines() { - Location playerLocation = player.getLocation(); - int numLoops = 5; - int pointsPerLoop = 30; - double verticalSpacing = 0.06; - - for (int loop = 0; loop < numLoops; loop++) { - double currentRadius = range * (1 - (double) loop / numLoops); - double currentHeight = ((loop - numLoops / 2.0) * verticalSpacing) + 0.3; - - for (int i = 0; i < pointsPerLoop; i++) { - double angle = 2 * Math.PI * i / pointsPerLoop; - double x = currentRadius * Math.cos(angle); - double z = currentRadius * Math.sin(angle); - Location particleLocation = playerLocation.clone().add(x, currentHeight, z); - JedCore.plugin.getParticleAdapter().displayMagneticParticles(particleLocation); - } - } - } - - private void loadMaterialsFromConfig() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - List materialNames = config.getStringList("Abilities.Earth.MagnetShield.Materials"); - METAL_LIST = new ArrayList<>(); - - for (String materialName : materialNames) { - Material material = Material.getMaterial(materialName.toUpperCase()); - if (material != null) { - METAL_LIST.add(material); - } else { - System.out.println("Invalid material in config: " + materialName); - } - } - } - - private void repelMetal() { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), range)) { - if (e instanceof Item) { - Item i = (Item) e; - if (isMetalMaterial(i.getItemStack().getType())) { - Vector direction = GeneralMethods.getDirection(player.getLocation(), i.getLocation()).multiply(velocity); - i.setVelocity(direction); - } - } else if (e instanceof FallingBlock) { - FallingBlock fb = (FallingBlock) e; - - if (isMetalMaterial(fb.getBlockData().getMaterial())) { - Vector direction = GeneralMethods.getDirection(player.getLocation(), fb.getLocation()).multiply(velocity); - fb.setVelocity(direction); - fb.setDropItem(false); - } - } else if (e instanceof Arrow && repelArrows) { - Arrow arrow = (Arrow) e; - Vector currentVelocity = arrow.getVelocity(); - Vector reversedVelocity = currentVelocity.multiply(-1); - arrow.setVelocity(reversedVelocity); - } else if (e instanceof LivingEntity && repelLivingEntities) { - LivingEntity livingEntity = (LivingEntity) e; - - if (livingEntity.getUniqueId().equals(player.getUniqueId())) continue; - - EntityEquipment equipment = livingEntity.getEquipment(); - if (equipment == null) continue; - - ItemStack mainHand = equipment.getItemInMainHand(); - ItemStack offHand = equipment.getItemInOffHand(); - ItemStack helmet = equipment.getHelmet(); - ItemStack chestplate = equipment.getChestplate(); - ItemStack leggings = equipment.getLeggings(); - ItemStack boots = equipment.getBoots(); - - boolean isMetal = isMetalItem(mainHand) || isMetalItem(offHand) || - isMetalItem(helmet) || isMetalItem(chestplate) || - isMetalItem(leggings) || isMetalItem(boots); - - if (isMetal) { - Vector direction = GeneralMethods.getDirection(player.getLocation(), e.getLocation()).multiply(velocity); - livingEntity.setVelocity(direction); - } - } - } - } - - private boolean isMetalItem(ItemStack itemStack) { - return itemStack != null && METAL_LIST.contains(itemStack.getType()); - } - - private boolean isMetalMaterial(Material material) { - return METAL_LIST.contains(material); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - duration = config.getLong("Abilities.Earth.MagnetShield.Duration"); - shiftCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Shift"); - clickCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Click"); - range = config.getDouble("Abilities.Earth.MagnetShield.Range"); - repelArrows = config.getBoolean("Abilities.Earth.MagnetShield.RepelArrows"); - repelLivingEntities = config.getBoolean("Abilities.Earth.MagnetShield.RepelLivingEntities"); - velocity = config.getDouble("Abilities.Earth.MagnetShield.Velocity"); - } -} \ No newline at end of file diff --git a/src/ability/earthbending/MetalArmor.java b/src/ability/earthbending/MetalArmor.java deleted file mode 100644 index ca1861e..0000000 --- a/src/ability/earthbending/MetalArmor.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.earthbending.EarthArmor; -import com.projectkorra.projectkorra.util.TempArmor; -import com.projectkorra.projectkorra.util.TempPotionEffect; - -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.LeatherArmorMeta; -import org.bukkit.potion.PotionEffect; - -import java.util.Arrays; -import java.util.List; - -public class MetalArmor extends EarthAbility implements AddonAbility { - - private static final int GOLD_BLOCK_COLOR = 0xF2F204; - private static final List METAL_COLORS = Arrays.asList( - 0xa39d91, 0xf4f4f4, 0xa2a38f, 0xF2F204, 0xb75656, 0xfff4f4 - ); - - private boolean useIronArmor; - private int resistStrength; - private int resistDuration; - - public MetalArmor(Player player) { - super(player); - - if (bPlayer == null || !bPlayer.canBendIgnoreCooldowns(CoreAbility.getAbility(EarthArmor.class)) || !bPlayer.canMetalbend()) { - return; - } - - if (!CoreAbility.hasAbility(player, EarthArmor.class)) { - return; - } - - setFields(); - start(); - } - - private void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - useIronArmor = config.getBoolean("Abilities.Earth.EarthArmor.UseIronArmor"); - resistStrength = config.getInt("Abilities.Earth.EarthArmor.Resistance.Strength"); - resistDuration = config.getInt("Abilities.Earth.EarthArmor.Resistance.Duration"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (!CoreAbility.hasAbility(player, EarthArmor.class)) { - remove(); - return; - } - - EarthArmor ea = CoreAbility.getAbility(player, EarthArmor.class); - if (!bPlayer.isToggled()) { - remove(); - ea.remove(); - return; - } - - if (ea.isFormed()) { - if (isMetalHelmet()) { - ItemStack[] armors = { new ItemStack(Material.CHAINMAIL_BOOTS, 1), - new ItemStack(Material.CHAINMAIL_LEGGINGS, 1), - new ItemStack(Material.CHAINMAIL_CHESTPLATE, 1), - new ItemStack(Material.CHAINMAIL_HELMET, 1) }; - - if(useIronArmor){ - armors = new ItemStack[]{ new ItemStack(Material.IRON_BOOTS, 1), - new ItemStack(Material.IRON_LEGGINGS, 1), - new ItemStack(Material.IRON_CHESTPLATE, 1), - new ItemStack(Material.IRON_HELMET, 1) }; - } - - if(useIronArmor && getHelmetColor().equals(Color.fromRGB(GOLD_BLOCK_COLOR))) { - armors = new ItemStack[]{ new ItemStack(Material.GOLDEN_BOOTS, 1), - new ItemStack(Material.GOLDEN_LEGGINGS, 1), - new ItemStack(Material.GOLDEN_CHESTPLATE, 1), - new ItemStack(Material.GOLDEN_HELMET, 1) }; - } - - player.getInventory().setArmorContents(armors); - - PotionEffect resistance = JedCore.plugin.getPotionEffectAdapter().getResistanceEffect(resistDuration, resistStrength); - new TempPotionEffect(player, resistance); - } - - remove(); - } - } - - private boolean isMetalHelmet() { - Color color = getHelmetColor(); - - return METAL_COLORS.contains(color.asRGB()); - } - - private Color getHelmetColor() { - if (!TempArmor.hasTempArmor(player)) { - return Color.BLACK; - } - - ItemStack helm = player.getInventory().getHelmet(); - if (helm.getType() != Material.LEATHER_HELMET) { - return Color.BLACK; - } - - LeatherArmorMeta meta = (LeatherArmorMeta)helm.getItemMeta(); - if (meta == null) { - return Color.BLACK; - } - - return meta.getColor(); - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalArmor"; - } - - @Override - public boolean isHiddenAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - return null; - } - - public boolean isUseIronArmor() { - return useIronArmor; - } - - public void setUseIronArmor(boolean useIronArmor) { - this.useIronArmor = useIronArmor; - } - - public int getResistStrength() { - return resistStrength; - } - - public void setResistStrength(int resistStrength) { - this.resistStrength = resistStrength; - } - - public int getResistDuration() { - return resistDuration; - } - - public void setResistDuration(int resistDuration) { - this.resistDuration = resistDuration; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthArmor.Enabled"); - } -} diff --git a/src/ability/earthbending/MetalFragments.java b/src/ability/earthbending/MetalFragments.java deleted file mode 100644 index 9a95cdd..0000000 --- a/src/ability/earthbending/MetalFragments.java +++ /dev/null @@ -1,430 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.util.TempFallingBlock; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.*; - -public class MetalFragments extends MetalAbility implements AddonAbility { - - @Attribute("MaxSources") - private int maxSources; - @Attribute(Attribute.SELECT_RANGE) - private int selectRange; - @Attribute("MaxShots") - private int maxFragments; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private double velocity; - - public List sources = new ArrayList<>(); - private final List thrownFragments = new ArrayList<>(); - private final List tblockTracker = new ArrayList<>(); - //private List fblockTracker = new ArrayList<>(); - private final HashMap counters = new HashMap<>(); - - public MetalFragments(Player player) { - super(player); - - if (hasAbility(player, MetalFragments.class)) { - MetalFragments.selectAnotherSource(player); - return; - } - - if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { - return; - } - - setFields(); - - if (tblockTracker.size() >= maxSources) { - return; - } - - if (prepare()) { - Block b = selectSource(); - if (RegionProtection.isRegionProtected(player, b.getLocation(), this)) { - return; - } - - start(); - if (!isRemoved()) { - translateUpward(b); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - maxSources = config.getInt("Abilities.Earth.MetalFragments.MaxSources"); - selectRange = config.getInt("Abilities.Earth.MetalFragments.SourceRange"); - maxFragments = config.getInt("Abilities.Earth.MetalFragments.MaxFragments"); - damage = config.getDouble("Abilities.Earth.MetalFragments.Damage"); - cooldown = config.getInt("Abilities.Earth.MetalFragments.Cooldown"); - velocity = config.getDouble("Abilities.Earth.MetalFragments.Velocity"); - } - - public static void shootFragment(Player player) { - if (hasAbility(player, MetalFragments.class)) { - getAbility(player, MetalFragments.class).shootFragment(); - } - } - - private void shootFragment() { - if (sources.size() <= 0) - return; - - Random randy = new Random(); - int i = randy.nextInt(sources.size()); - Block source = sources.get(i); - ItemStack is; - - switch (source.getType()) { - case GOLD_BLOCK: - case GOLD_ORE: - is = new ItemStack(Material.GOLD_INGOT, 1); - break; - case COAL_BLOCK: - is = new ItemStack(Material.COAL, 1); - break; - case COAL_ORE: - is = new ItemStack(Material.COAL_ORE, 1); - break; - default: - is = new ItemStack(Material.IRON_INGOT, 1); - break; - } - - Vector direction; - if (GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()) != null) { - direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()).getLocation()); - } else { - direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedLocation(player, 30)); - } - - Item ii = player.getWorld().dropItemNaturally(source.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(direction)).getLocation(), is); - ii.setPickupDelay(Integer.MAX_VALUE); - ii.setVelocity(direction.normalize().multiply(velocity)); - playMetalbendingSound(ii.getLocation()); - thrownFragments.add(ii); - - if (counters.containsKey(source)) { - int count = counters.get(source); - count++; - - if (count >= maxFragments) { - counters.remove(source); - source.getWorld().spawnFallingBlock(source.getLocation().add(0.5, 0, 0.5), source.getBlockData()); - TempBlock tempBlock = TempBlock.get(source); - if (tempBlock != null) { - tempBlock.revertBlock(); - } - sources.remove(source); - source.getWorld().playSound(source.getLocation(), Sound.ENTITY_ITEM_BREAK, 10, 5); - } else { - counters.put(source, count); - } - - if (sources.size() == 0) { - remove(); - } - } - } - - public static void selectAnotherSource(Player player) { - if (hasAbility(player, MetalFragments.class)) { - getAbility(player, MetalFragments.class).selectAnotherSource(); - } - } - - private void selectAnotherSource() { - if (tblockTracker.size() >= maxSources) - return; - - if (prepare()) { - Block b = selectSource(); - translateUpward(b); - } - } - - public boolean prepare() { - Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); - - if (block == null) - return false; - - return isMetal(block); - } - - public Block selectSource() { - Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); - if (isMetal(block)) - return block; - return null; - } - - public void translateUpward(Block block) { - if (block == null) - return; - - if (sources.contains(block)) - return; - - if (block.getRelative(BlockFace.UP).getType().isSolid()) - return; - - if (isEarthbendable(player, block)) { - new TempFallingBlock(block.getLocation().add(0.5, 0, 0.5), block.getBlockData(), new Vector(0, 0.8, 0), this); - block.setType(Material.AIR); - - playMetalbendingSound(block.getLocation()); - } - } - - public void progress() { - if (player == null || player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!hasAbility(player, MetalFragments.class)) { - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - - Iterator itr = tblockTracker.iterator(); - while (itr.hasNext()) { - TempBlock tb = itr.next(); - if (player.getLocation().distance(tb.getLocation()) >= 10) { - player.getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlockData()); - sources.remove(tb.getBlock()); - tb.revertBlock(); - itr.remove(); - } - } - - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fb = tfb.getFallingBlock(); - if (fb.getLocation().getY() >= player.getEyeLocation().getY() + 1) { - Block block = fb.getLocation().getBlock(); - TempBlock tb = new TempBlock(block, fb.getBlockData()); - - tblockTracker.add(tb); - sources.add(tb.getBlock()); - counters.put(tb.getBlock(), 0); - tfb.remove(); - } - - if (fb.isOnGround()) { - fb.getLocation().getBlock().setBlockData(fb.getBlockData()); - } - } - for (ListIterator iterator = thrownFragments.listIterator(); iterator.hasNext();) { - Item f = iterator.next(); - - boolean touchedLiving = false; - for (Entity e : GeneralMethods.getEntitiesAroundPoint(f.getLocation(), 1)) { - if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { - touchedLiving = true; - DamageHandler.damageEntity(e, damage, this); - } - } - if (touchedLiving || f.isOnGround() || f.isDead()) { - ParticleEffect.ITEM_CRACK.display(f.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, f.getItemStack()); - f.remove(); - iterator.remove(); - } - } - - //removeDeadFBlocks(); - } - - /* - public void removeDeadFBlocks() { - for (int i = 0; i < fblockTracker.size(); i++) - if (fblockTracker.get(i).isDead()) - fblockTracker.remove(i); - } - */ - - public void removeDeadItems() { - thrownFragments.removeIf(Item::isDead); - } - - - public void dropSources() { - for (TempBlock tb : tblockTracker) { - tb.getBlock().getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlock().getBlockData()); - tb.revertBlock(); - } - - tblockTracker.clear(); - } - - public void removeFragments() { - for (Item i : thrownFragments) { - ParticleEffect.ITEM_CRACK.display(i.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, i.getItemStack()); - i.remove(); - } - thrownFragments.clear(); - } - - public static void remove(Player player, Block block) { - if (hasAbility(player, MetalFragments.class)) { - MetalFragments mf = getAbility(player, MetalFragments.class); - if (mf.sources.contains(block)) { - mf.remove(); - } - } - } - - @Override - public void remove() { - dropSources(); - removeFragments(); - removeDeadItems(); - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalFragments"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalFragments.Description"); - } - - public int getMaxSources() { - return maxSources; - } - - public void setMaxSources(int maxSources) { - this.maxSources = maxSources; - } - - public int getSelectRange() { - return selectRange; - } - - public void setSelectRange(int selectRange) { - this.selectRange = selectRange; - } - - public int getMaxFragments() { - return maxFragments; - } - - public void setMaxFragments(int maxFragments) { - this.maxFragments = maxFragments; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public List getSources() { - return sources; - } - - public void setSources(List sources) { - this.sources = sources; - } - - public List getThrownFragments() { - return thrownFragments; - } - - public List getTblockTracker() { - return tblockTracker; - } - - public HashMap getCounters() { - return counters; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MetalFragments.Enabled"); - } -} diff --git a/src/ability/earthbending/MetalHook.java b/src/ability/earthbending/MetalHook.java deleted file mode 100644 index 3cbf551..0000000 --- a/src/ability/earthbending/MetalHook.java +++ /dev/null @@ -1,396 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; - -import com.projectkorra.projectkorra.attribute.Attribute; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class MetalHook extends MetalAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.RANGE) - private int range; - @Attribute("MaxHooks") - private int maxHooks; - private int totalHooks; - private int hooksUsed; - private boolean noSource; - private boolean barrierHooking; - - private boolean hasHook; - private boolean wasSprinting; - private long time; - - private Location destination; - - private final ConcurrentHashMap hooks = new ConcurrentHashMap<>(); - private final List hookIds = new ArrayList<>(); - - public MetalHook(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { - return; - } - - if (hasAbility(player, MetalHook.class)) { - MetalHook mh = getAbility(player, MetalHook.class); - mh.launchHook(); - return; - } - - setFields(); - - if (!hasRequiredInv()) { - return; - } - - wasSprinting = player.isSprinting(); - flightHandler.createInstance(player, this.getName()); - player.setAllowFlight(true); - - start(); - launchHook(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.MetalHook.Cooldown"); - range = config.getInt("Abilities.Earth.MetalHook.Range"); - maxHooks = config.getInt("Abilities.Earth.MetalHook.MaxHooks"); - totalHooks = config.getInt("Abilities.Earth.MetalHook.TotalHooks"); - noSource = config.getBoolean("Abilities.Earth.MetalHook.RequireItem"); - barrierHooking = config.getBoolean("Abilities.Earth.MetalHook.BarrierHooking"); - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - removeAllArrows(); - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBindsCooldowns(this) || hooks.isEmpty()) { - removeAllArrows(); - remove(); - return; - } - - if (!wasSprinting && player.isSprinting()) { - removeAllArrows(); - remove(); - return; - } - - wasSprinting = player.isSprinting(); - - if (player.isSneaking()) { - player.setVelocity(new Vector()); - - if (System.currentTimeMillis() > (time + 1000)) { - removeAllArrows(); - remove(); - return; - } - } else { - time = System.currentTimeMillis(); - } - - Vector target = new Vector(); - - for (Arrow a : hooks.keySet()) { - if (a != null) { - if (!isActiveArrow(a)) { - hooks.remove(a); - hookIds.remove(a.getUniqueId()); - a.remove(); - continue; - } - - if (a.getAttachedBlock() == null) { - hooks.replace(a, hooks.get(a), false); - } else { - hooks.replace(a, hooks.get(a), true); - hasHook = true; - } - - //Draws the particle lines. - for (Location location : JCMethods.getLinePoints(player.getLocation().add(0, 1, 0), a.getLocation(), ((int) player.getLocation().add(0,1,0).distance(a.getLocation()) * 2))) { - GeneralMethods.displayColoredParticle("#CCCCCC", location); - } - - if (hooks.get(a)) { - target.add(GeneralMethods.getDirection(player.getEyeLocation(), a.getLocation())); - } - } - } - - if (hasHook) { - destination = player.getLocation().clone().add(target); - - if (player.getLocation().distance(destination) > 2) { - player.setFlying(false); - double velocity = 0.8; - - GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); - } else if (player.getLocation().distance(destination) < 2 && player.getLocation().distance(destination) >= 1) { - player.setFlying(false); - double velocity = 0.35; - - GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); - } else { - GeneralMethods.setVelocity(this, player, new Vector(0, 0, 0)); - - if (player.getAllowFlight()) { - player.setFlying(true); - } - } - } - } - - private boolean isActiveArrow(Arrow arrow) { - if (arrow.isDead()) return false; - if (player.getWorld() != arrow.getWorld()) return false; - - Block attached = arrow.getAttachedBlock(); - - if (!barrierHooking && attached != null && attached.getType() == Material.BARRIER) return false; - - return player.getEyeLocation().distanceSquared(arrow.getLocation()) < range * range; - } - - @Override - public void remove() { - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - - flightHandler.removeInstance(player, this.getName()); - - super.remove(); - } - - public void launchHook() { - if (!hasRequiredInv()) return; - - Vector dir = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, range)); - - if (!hookIds.isEmpty() && hookIds.size() > (maxHooks - 1)) { - for (Arrow a : hooks.keySet()) { - if (a.getUniqueId().equals(hookIds.get(0))) { - hooks.remove(a); - hookIds.remove(0); - a.remove(); - break; - } - } - } - - if (totalHooks > 0 && hooksUsed++ > totalHooks) { - remove(); - return; - } - - Arrow a = player.getWorld().spawnArrow(player.getEyeLocation().add(player.getLocation().getDirection().multiply(2)), dir, 3, 0f); - a.setMetadata("metalhook", new FixedMetadataValue(JedCore.plugin, "1")); - - hooks.put(a, false); - hookIds.add(a.getUniqueId()); - } - - public void removeAllArrows() { - for (Arrow a : hooks.keySet()) { - a.remove(); - } - } - - public boolean hasRequiredInv() { - if (noSource) return true; - - if (player.getInventory().getChestplate() != null) { - Material[] chestplates = {Material.IRON_CHESTPLATE, Material.CHAINMAIL_CHESTPLATE}; - Material playerChest = player.getInventory().getChestplate().getType(); - - if (Arrays.asList(chestplates).contains(playerChest)) { - return true; - } - } - - Material[] metals = {Material.IRON_INGOT, Material.IRON_BLOCK}; - - for (ItemStack items : player.getInventory()) { - if (items != null && Arrays.asList(metals).contains(items.getType())) { - return true; - } - } - - return false; - } - - public int getMaxHooks() { - return this.maxHooks; - } - - public void setMaxHooks(int maxhooks) { - this.maxHooks = maxhooks; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalHook"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalHook.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public int getTotalHooks() { - return totalHooks; - } - - public void setTotalHooks(int totalHooks) { - this.totalHooks = totalHooks; - } - - public int getHooksUsed() { - return hooksUsed; - } - - public void setHooksUsed(int hooksUsed) { - this.hooksUsed = hooksUsed; - } - - public boolean isNoSource() { - return noSource; - } - - public void setNoSource(boolean noSource) { - this.noSource = noSource; - } - - public boolean isBarrierHooking() { - return barrierHooking; - } - - public void setBarrierHooking(boolean barrierHooking) { - this.barrierHooking = barrierHooking; - } - - public boolean isHasHook() { - return hasHook; - } - - public void setHasHook(boolean hasHook) { - this.hasHook = hasHook; - } - - public boolean isWasSprinting() { - return wasSprinting; - } - - public void setWasSprinting(boolean wasSprinting) { - this.wasSprinting = wasSprinting; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public Location getDestination() { - return destination; - } - - public void setDestination(Location destination) { - this.destination = destination; - } - - public ConcurrentHashMap getHooks() { - return hooks; - } - - public List getHookIds() { - return hookIds; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MetalHook.Enabled"); - } -} diff --git a/src/ability/earthbending/MetalShred.java b/src/ability/earthbending/MetalShred.java deleted file mode 100644 index ef79f8c..0000000 --- a/src/ability/earthbending/MetalShred.java +++ /dev/null @@ -1,483 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.MetalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.BlockSource; -import com.projectkorra.projectkorra.util.ClickType; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; - -public class MetalShred extends MetalAbility implements AddonAbility { - - @Attribute(Attribute.SELECT_RANGE) - private int selectRange; - private int extendTick; - @Attribute(Attribute.DAMAGE) - private double damage; - - private boolean horizontal = false; - private boolean started = false; - private boolean stop = false; - private boolean stopCoil = false; - private boolean extending = false; - private int length = 0; - private int fullLength = 0; - private long lastExtendTime; - private Block source; - private Block lastBlock; - private final List tblocks = new ArrayList<>(); - - public MetalShred(Player player) { - super(player); - - if (hasAbility(player, MetalShred.class)) { - getAbility(player, MetalShred.class).remove(); - } - - if (!bPlayer.canBend(this)) { - return; - } - - setFields(); - - if (selectSource()) { - if (horizontal) { - raiseBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); - } else { - shiftBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); - } - - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - selectRange = config.getInt("Abilities.Earth.MetalShred.SourceRange"); - extendTick = config.getInt("Abilities.Earth.MetalShred.ExtendTick"); - damage = config.getDouble("Abilities.Earth.MetalShred.Damage"); - } - - public boolean selectSource() { - Block b = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); - - if (!isMetal(b)) - return false; - - source = b; - - if (ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType()) && !isMetal(source.getRelative(BlockFace.DOWN))) { - horizontal = true; - } - - return true; - } - - public void raiseBlock(Block b, Vector d) { - Block up = b.getRelative(BlockFace.UP); - Block away = b.getRelative(GeneralMethods.getCardinalDirection(d)); - Block awayup = away.getRelative(BlockFace.UP); - Block deeperb = b.getRelative(BlockFace.DOWN); - Block deepera = away.getRelative(BlockFace.DOWN); - - for (TempBlock tb : tblocks) { - if (!ElementalAbility.isAir(tb.getBlock().getType())) - tb.setType(Material.AIR); - } - - if (!up.getType().isSolid()) { - TempBlock tbu = new TempBlock(up, b.getBlockData()); - tblocks.add(tbu); - } - - if (!awayup.getType().isSolid()) { - TempBlock tbau = new TempBlock(awayup, away.getBlockData()); - tblocks.add(tbau); - } - - if (isMetal(b)) { - TempBlock tbd = new TempBlock(b, Material.AIR.createBlockData()); - tblocks.add(tbd); - } - - if (isMetal(away)) { - TempBlock tba = new TempBlock(away, Material.AIR.createBlockData()); - tblocks.add(tba); - } - - if (isMetal(deeperb)) { - TempBlock tbdb = new TempBlock(deeperb, Material.AIR.createBlockData()); - tblocks.add(tbdb); - } - - if (isMetal(deepera)) { - TempBlock tbda = new TempBlock(deepera, Material.AIR.createBlockData()); - tblocks.add(tbda); - } - - playMetalbendingSound(b.getLocation()); - } - - public void shiftBlock(Block b, Vector d) { - Block under = b.getRelative(BlockFace.DOWN); - Block side = b.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); - Block underside = under.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); - - for (TempBlock tb : tblocks) { - if (!ElementalAbility.isAir(tb.getBlock().getType())) - tb.setType(Material.AIR); - } - - if (!side.getType().isSolid()) { - TempBlock tbs = new TempBlock(side, b.getBlockData()); - tblocks.add(tbs); - } - - if (!underside.getType().isSolid()) { - TempBlock tbus = new TempBlock(underside, under.getBlockData()); - tblocks.add(tbus); - } - - if (isMetal(b)) { - TempBlock tb1 = new TempBlock(b, Material.AIR.createBlockData()); - tblocks.add(tb1); - } - - if (isMetal(under)) { - TempBlock tb2 = new TempBlock(under, Material.AIR.createBlockData()); - tblocks.add(tb2); - } - - playMetalbendingSound(b.getLocation()); - } - - private void peelCoil(Block b) { - Block under = b.getRelative(BlockFace.DOWN); - - if (length <= 0) - return; - - if (!b.getType().isSolid()) { - TempBlock tbb = new TempBlock(b, Material.IRON_BLOCK.createBlockData()); - tblocks.add(tbb); - } - - else - stopCoil = true; - - if (!under.getType().isSolid()) { - TempBlock tbu = new TempBlock(under, Material.IRON_BLOCK.createBlockData()); - tblocks.add(tbu); - } - - else - stopCoil = true; - - playMetalbendingSound(b.getLocation()); - - length--; - } - - public static void startShred(Player player) { - if (hasAbility(player, MetalShred.class)) { - getAbility(player, MetalShred.class).startShred(); - } - } - - private void startShred() { - started = true; - } - - public static void extend(Player player) { - if (hasAbility(player, MetalShred.class)) { - getAbility(player, MetalShred.class).extend(); - } - } - - private void extend() { - if (extending) { - extending = false; - return; - } - - if (!stop) - return; - - lastExtendTime = System.currentTimeMillis(); - fullLength = length; - if (lastBlock != null) - lastBlock = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(player.getLocation(), lastBlock.getLocation())).getOppositeFace()); - else { - return; - } - extending = true; - } - - @Override - public void progress() { - if (!player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - - if (!player.isSprinting()) { - if (started) - stop = true; - } - - if (!horizontal && stop && !stopCoil && extending && System.currentTimeMillis() > lastExtendTime + extendTick) { - lastExtendTime = System.currentTimeMillis(); - if (length > 0) { - - Block b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(lastBlock.getLocation(), GeneralMethods.getTargetedLocation(player, fullLength)))); - - peelCoil(b); - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(b.getLocation(), 2)) { - if (!(e instanceof LivingEntity) || e.getEntityId() == player.getEntityId()) { - continue; - } - if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))) { - continue; - } - DamageHandler.damageEntity(e, damage, this); - GeneralMethods.setVelocity(this, e, e.getVelocity().add(player.getLocation().getDirection().add(new Vector(0, 0.1, 0)))); - } - - lastBlock = b; - } - - return; - } - - if (stop || !started) - return; - - Block b; - - if (lastBlock != null) { - b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); - } - - else { - b = source.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); - } - - if (!isMetal(b)) { - if (!ElementalAbility.isAir(b.getType())) { - remove(); - } - return; - } - - if (b.getLocation().getX() == player.getLocation().getBlockX() || b.getLocation().getZ() == player.getLocation().getBlockZ()) { - if (horizontal) - raiseBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); - else - shiftBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); - - length++; - lastBlock = b; - } - } - - private void revertAll() { - for (TempBlock tb : tblocks) { - tb.revertBlock(); - } - } - - @Override - public void remove() { - revertAll(); - super.remove(); - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MetalShred"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalShred.Description"); - } - - public int getSelectRange() { - return selectRange; - } - - public void setSelectRange(int selectRange) { - this.selectRange = selectRange; - } - - public int getExtendTick() { - return extendTick; - } - - public void setExtendTick(int extendTick) { - this.extendTick = extendTick; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public boolean isHorizontal() { - return horizontal; - } - - public void setHorizontal(boolean horizontal) { - this.horizontal = horizontal; - } - - @Override - public boolean isStarted() { - return started; - } - - public void setStarted(boolean started) { - this.started = started; - } - - public boolean isStop() { - return stop; - } - - public void setStop(boolean stop) { - this.stop = stop; - } - - public boolean isStopCoil() { - return stopCoil; - } - - public void setStopCoil(boolean stopCoil) { - this.stopCoil = stopCoil; - } - - public boolean isExtending() { - return extending; - } - - public void setExtending(boolean extending) { - this.extending = extending; - } - - public int getLength() { - return length; - } - - public void setLength(int length) { - this.length = length; - } - - public int getFullLength() { - return fullLength; - } - - public void setFullLength(int fullLength) { - this.fullLength = fullLength; - } - - public long getLastExtendTime() { - return lastExtendTime; - } - - public void setLastExtendTime(long lastExtendTime) { - this.lastExtendTime = lastExtendTime; - } - - public Block getSource() { - return source; - } - - public void setSource(Block source) { - this.source = source; - } - - public Block getLastBlock() { - return lastBlock; - } - - public void setLastBlock(Block lastBlock) { - this.lastBlock = lastBlock; - } - - public List getTblocks() { - return tblocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MetalShred.Enabled"); - } -} diff --git a/src/ability/earthbending/MudSurge.java b/src/ability/earthbending/MudSurge.java deleted file mode 100644 index c9b02e5..0000000 --- a/src/ability/earthbending/MudSurge.java +++ /dev/null @@ -1,654 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionUtil; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; - -import com.jedk1.jedcore.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; - -import java.util.*; -import java.util.stream.Collectors; - -public class MudSurge extends EarthAbility implements AddonAbility { - private int prepareRange; - private int blindChance; - private int blindTicks; - private boolean multipleHits; - @Attribute(Attribute.DAMAGE) - private double damage; - private int waves; - private int waterSearchRadius; - private boolean wetSource; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("CollisionRadius") - private double collisionRadius; - - public static int surgeInterval = 300; - public static int mudPoolRadius = 2; - public static Set mudTypes = new HashSet<>(); - - static { - mudTypes.addAll(Arrays.asList(Material.SAND, Material.RED_SAND, Material.CLAY, Material.TERRACOTTA, Material.BLACK_TERRACOTTA, Material.BLUE_TERRACOTTA, - Material.BROWN_TERRACOTTA, Material.CYAN_TERRACOTTA, Material.GRAY_TERRACOTTA, Material.GREEN_TERRACOTTA, - Material.LIGHT_BLUE_TERRACOTTA, Material.LIGHT_GRAY_TERRACOTTA, Material.LIME_TERRACOTTA, - Material.MAGENTA_TERRACOTTA, Material.ORANGE_TERRACOTTA, Material.PINK_TERRACOTTA, - Material.PURPLE_TERRACOTTA, Material.RED_TERRACOTTA, Material.WHITE_TERRACOTTA, Material.YELLOW_TERRACOTTA, - Material.GRASS_BLOCK, Material.DIRT, Material.MYCELIUM, Material.COARSE_DIRT, - Material.SOUL_SAND, Material.SOUL_SOIL, Material.RED_SANDSTONE, Material.SANDSTONE, Material.CHISELED_SANDSTONE, - Material.CHISELED_RED_SANDSTONE, Material.SMOOTH_SANDSTONE, Material.SMOOTH_RED_SANDSTONE, Material.CUT_SANDSTONE, - Material.CUT_RED_SANDSTONE)); - if (GeneralMethods.getMCVersion() >= 1170) { - mudTypes.add(Material.getMaterial("ROOTED_DIRT")); - } - if (GeneralMethods.getMCVersion() >= 1190) { - mudTypes.add(Material.getMaterial("MUD")); - mudTypes.add(Material.getMaterial("MUDDY_MANGROVE_ROOTS")); - mudTypes.add(Material.getMaterial("PACKED_MUD")); - } - } - - private CompositeRemovalPolicy removalPolicy; - - private Block source; - - private int wavesOnTheRun = 0; - private boolean mudFormed = false; - private boolean doNotSurge = false; - public boolean started = false; - - private final List mudArea = new ArrayList<>(); - private ListIterator mudAreaItr; - private final List mudBlocks = new ArrayList<>(); - private final List blind = new ArrayList<>(); - private final List affectedEntities = new ArrayList<>(); - - private final List fallingBlocks = new ArrayList<>(); - - private final Random rand = new Random(); - - public MudSurge(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, MudSurge.class)) { - MudSurge ms = getAbility(player, MudSurge.class); - if (!ms.hasStarted()) { - ms.remove(); - } else { - return; - } - } - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new OutOfRangeRemovalPolicy(this.player, 25.0, () -> this.source.getLocation()), - new SwappedSlotsRemovalPolicy<>(bPlayer, MudSurge.class) - ); - - setFields(); - - if (getSource()) { - start(); - if (!isRemoved()) { - loadMudPool(); - } - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - this.removalPolicy.load(config); - - prepareRange = config.getInt("Abilities.Earth.MudSurge.SourceRange"); - blindChance = config.getInt("Abilities.Earth.MudSurge.BlindChance"); - damage = config.getDouble("Abilities.Earth.MudSurge.Damage"); - waves = config.getInt("Abilities.Earth.MudSurge.Waves"); - waterSearchRadius = config.getInt("Abilities.Earth.MudSurge.WaterSearchRadius"); - wetSource = config.getBoolean("Abilities.Earth.MudSurge.WetSourceOnly"); - cooldown = config.getLong("Abilities.Earth.MudSurge.Cooldown"); - blindTicks = config.getInt("Abilities.Earth.MudSurge.BlindTicks"); - multipleHits = config.getBoolean("Abilities.Earth.MudSurge.MultipleHits"); - collisionRadius = config.getDouble("Abilities.Earth.MudSurge.CollisionRadius"); - } - - @Override - public void progress() { - if (removalPolicy.shouldRemove()) { - remove(); - return; - } - - long lastSurgeTime = 0; - if (mudFormed && started && System.currentTimeMillis() > lastSurgeTime + surgeInterval) { - surge(); - affect(); - if (TempFallingBlock.getFromAbility(this).isEmpty()) { - remove(); - return; - } - return; - } - - if (!mudFormed) { - createMudPool(); - } - } - - private boolean getSource() { - Block block = getMudSourceBlock(prepareRange); - - if (block != null) { - if (isMudBlock(block)) { - boolean water = true; - - if (wetSource) { - water = false; - List nearby = GeneralMethods.getBlocksAroundPoint(block.getLocation(), waterSearchRadius); - - for (Block b : nearby) { - if (b.getType() == Material.WATER) { - water = true; - break; - } - } - } - - if (water) { - this.source = block; - return true; - } - } - } - - return false; - } - - private void startSurge() { - started = true; - this.bPlayer.addCooldown(this); - - // Clear out the policies that only apply while sourcing. - this.removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); - this.removalPolicy.removePolicyType(OutOfRangeRemovalPolicy.class); - this.removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); - } - - private boolean hasStarted() { - return this.started; - } - - public static boolean isSurgeBlock(Block block) { - if (block.getType() != Material.BROWN_TERRACOTTA) { - return false; - } - - for (MudSurge surge : CoreAbility.getAbilities(MudSurge.class)) { - if (surge.mudArea.contains(block)) { - return true; - } - } - - return false; - } - - // Returns true if the event should be cancelled. - public static boolean onFallDamage(Player player) { - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null || !bPlayer.hasElement(Element.EARTH)) { - return false; - } - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - boolean fallDamage = config.getBoolean("Abilities.Earth.MudSurge.AllowFallDamage"); - if (fallDamage) { - return false; - } - - Block block = player.getLocation().clone().subtract(0, 0.1, 0).getBlock(); - return isSurgeBlock(block); - } - - public static void mudSurge(Player player) { - if (!hasAbility(player, MudSurge.class)) - return; - - getAbility(player, MudSurge.class).startSurge(); - } - - private Block getMudSourceBlock(int range) { - Block testBlock = GeneralMethods.getTargetedLocation(player, range, ElementalAbility.getTransparentMaterials()).getBlock(); - if (isMudBlock(testBlock)) - return testBlock; - - Location loc = player.getEyeLocation(); - Vector dir = player.getEyeLocation().getDirection().clone().normalize(); - - for (int i = 0; i <= range; i++) { - Block block = loc.clone().add(dir.clone().multiply(i == 0 ? 1 : i)).getBlock(); - if (RegionProtection.isRegionProtected(player, block.getLocation(), this)) - continue; - - if (isMudBlock(block)) - return block; - } - - return null; - } - - private boolean isMudBlock(Block block) { - for (Material mat : mudTypes) { - if (mat.name().equalsIgnoreCase(block.getType().name())) - return true; - } - - return false; - } - - private void createMud(Block block) { - mudBlocks.add(new TempBlock(block, Material.BROWN_TERRACOTTA.createBlockData())); - } - - private void loadMudPool() { - List area = GeneralMethods.getCircle(source.getLocation(), mudPoolRadius, 3, false, true, 0); - - for (Location l : area) { - Block b = l.getBlock(); - - if (isMudBlock(b)) { - if (isTransparent(b.getRelative(BlockFace.UP))) { - boolean water = true; - - if (wetSource) { - water = false; - List nearby = GeneralMethods.getBlocksAroundPoint(l, waterSearchRadius); - - for (Block block : nearby) { - if (block.getType() == Material.WATER) { - water = true; - break; - } - } - } - - if (water) { - mudArea.add(b); - playEarthbendingSound(b.getLocation()); - } - } - } - } - - Collections.shuffle(mudArea); - mudAreaItr = mudArea.listIterator(); - } - - private void createMudPool() { - if (!mudAreaItr.hasNext()) { - mudFormed = true; - return; - } - - Block b = mudAreaItr.next(); - - if (b != null) - createMud(b); - } - - private void revertMudPool() { - for (TempBlock tb : mudBlocks) - tb.revertBlock(); - - mudBlocks.clear(); - } - - private void surge() { - if (wavesOnTheRun >= waves) { - doNotSurge = true; - return; - } - - if (doNotSurge) - return; - - for (TempBlock tb : mudBlocks) { - Vector direction = GeneralMethods.getDirection(tb.getLocation().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, 30)).multiply(0.07); - - double x = rand.nextDouble() / 5; - double z = rand.nextDouble() / 5; - - x = (rand.nextBoolean()) ? -x : x; - z = (rand.nextBoolean()) ? -z : z; - - fallingBlocks.add(new TempFallingBlock(tb.getLocation().add(0.5, 1, 0.5), Material.BROWN_TERRACOTTA.createBlockData(), direction.clone().add(new Vector(x, 0.2, z)), this)); - - playEarthbendingSound(tb.getLocation()); - } - - wavesOnTheRun++; - } - - private void affect() { - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fb = tfb.getFallingBlock(); - if (fb.isDead()) { - tfb.remove(); - continue; - } - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(fb.getLocation(), 1.5)) { - if (fb.isDead()) { - tfb.remove(); - continue; - } - if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))){ - continue; - } - - if (e instanceof LivingEntity) { - if (this.multipleHits || !this.affectedEntities.contains(e)) { - DamageHandler.damageEntity(e, damage, this); - if (!this.multipleHits) { - this.affectedEntities.add(e); - } - } - - if (e instanceof Player) { - if (e.getEntityId() == player.getEntityId()) - continue; - - if (rand.nextInt(100) < blindChance && !blind.contains(e)) { - ((Player) e).addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, this.blindTicks, 2)); - } - - blind.add((Player) e); - } - - e.setVelocity(fb.getVelocity().multiply(0.8)); - tfb.remove(); - } - } - } - } - - @Override - public void remove() { - revertMudPool(); - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); - } - - @Override - public void handleCollision(Collision collision) { - CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); - } - - @Override - public double getCollisionRadius() { - return collisionRadius; - } - - @Override - public String getName() { - return "MudSurge"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MudSurge.Description"); - } - - public int getPrepareRange() { - return prepareRange; - } - - public void setPrepareRange(int prepareRange) { - this.prepareRange = prepareRange; - } - - public int getBlindChance() { - return blindChance; - } - - public void setBlindChance(int blindChance) { - this.blindChance = blindChance; - } - - public int getBlindTicks() { - return blindTicks; - } - - public void setBlindTicks(int blindTicks) { - this.blindTicks = blindTicks; - } - - public boolean isMultipleHits() { - return multipleHits; - } - - public void setMultipleHits(boolean multipleHits) { - this.multipleHits = multipleHits; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public int getWaves() { - return waves; - } - - public void setWaves(int waves) { - this.waves = waves; - } - - public int getWaterSearchRadius() { - return waterSearchRadius; - } - - public void setWaterSearchRadius(int waterSearchRadius) { - this.waterSearchRadius = waterSearchRadius; - } - - public boolean isWetSource() { - return wetSource; - } - - public void setWetSource(boolean wetSource) { - this.wetSource = wetSource; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public void setCollisionRadius(double collisionRadius) { - this.collisionRadius = collisionRadius; - } - - public static int getSurgeInterval() { - return surgeInterval; - } - - public static void setSurgeInterval(int surgeInterval) { - MudSurge.surgeInterval = surgeInterval; - } - - public static int getMudPoolRadius() { - return mudPoolRadius; - } - - public static void setMudPoolRadius(int mudPoolRadius) { - MudSurge.mudPoolRadius = mudPoolRadius; - } - - public static Material[] getMudTypes() { - return mudTypes.toArray(new Material[0]); - } - - public static Set getMudTypesSet() { - return mudTypes; - } - - public static void setMudTypes(Material[] mudTypes) { - MudSurge.mudTypes.clear(); - MudSurge.mudTypes.addAll(Arrays.asList(mudTypes)); - } - - public CompositeRemovalPolicy getRemovalPolicy() { - return removalPolicy; - } - - public void setRemovalPolicy(CompositeRemovalPolicy removalPolicy) { - this.removalPolicy = removalPolicy; - } - - public void setSource(Block source) { - this.source = source; - } - - public int getWavesOnTheRun() { - return wavesOnTheRun; - } - - public void setWavesOnTheRun(int wavesOnTheRun) { - this.wavesOnTheRun = wavesOnTheRun; - } - - public boolean isMudFormed() { - return mudFormed; - } - - public void setMudFormed(boolean mudFormed) { - this.mudFormed = mudFormed; - } - - public boolean isDoNotSurge() { - return doNotSurge; - } - - public void setDoNotSurge(boolean doNotSurge) { - this.doNotSurge = doNotSurge; - } - - @Override - public boolean isStarted() { - return started; - } - - public void setStarted(boolean started) { - this.started = started; - } - - public List getMudArea() { - return mudArea; - } - - public ListIterator getMudAreaItr() { - return mudAreaItr; - } - - public void setMudAreaItr(ListIterator mudAreaItr) { - this.mudAreaItr = mudAreaItr; - } - - public List getMudBlocks() { - return mudBlocks; - } - - public List getBlind() { - return blind; - } - - public List getAffectedEntities() { - return affectedEntities; - } - - public List getFallingBlocks() { - return fallingBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.MudSurge.Enabled"); - } -} diff --git a/src/ability/earthbending/SandBlast.java b/src/ability/earthbending/SandBlast.java deleted file mode 100644 index 75de3b1..0000000 --- a/src/ability/earthbending/SandBlast.java +++ /dev/null @@ -1,377 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.SandAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; - -import com.jedk1.jedcore.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import java.util.stream.Collectors; - -public class SandBlast extends SandAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.SELECT_RANGE) - private double sourceRange; - @Attribute(Attribute.RANGE) - private int range; - @Attribute("MaxShots") - private int maxBlasts; - @Attribute(Attribute.DAMAGE) - private static double damage; - - private Block source; - private BlockData sourceData; - private int blasts; - private boolean blasting; - private Vector direction; - private TempBlock tempBlock; - private final List affectedEntities = new ArrayList<>(); - private final List fallingBlocks = new ArrayList<>(); - - Random rand = new Random(); - - public SandBlast(Player player) { - super(player); - - if (!bPlayer.canBend(this)) { - return; - } - - if (hasAbility(player, SandBlast.class)) { - SandBlast sb = getAbility(player, SandBlast.class); - sb.remove(); - } - - setFields(); - if (prepare()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Earth.SandBlast.Cooldown"); - sourceRange = config.getDouble("Abilities.Earth.SandBlast.SourceRange"); - range = config.getInt("Abilities.Earth.SandBlast.Range"); - maxBlasts = config.getInt("Abilities.Earth.SandBlast.MaxSandBlocks"); - damage = config.getDouble("Abilities.Earth.SandBlast.Damage"); - } - - private boolean prepare() { - source = getEarthSourceBlock(sourceRange); - - if (source != null) { - if (isSand(source) && ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType())) { - this.sourceData = source.getBlockData().clone(); - if (DensityShift.isPassiveSand(source)) { - DensityShift.revertSand(source); - } - tempBlock = new TempBlock(source, Material.SANDSTONE.createBlockData()); - return true; - } - } - return false; - } - - @Override - public void progress() { - if (!hasAbility(player, SandBlast.class)) { - return; - } - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (player.getWorld() != source.getWorld()) { - remove(); - return; - } - if (blasting) { - if (blasts <= maxBlasts) { - blastSand(); - blasts++; - } else { - if (TempFallingBlock.getFromAbility(this).isEmpty()) { - remove(); - return; - } - } - affect(); - } - } - - @Override - public void remove() { - if (this.tempBlock != null) { - this.tempBlock.revertBlock(); - } - super.remove(); - } - - public static void blastSand(Player player) { - if (hasAbility(player, SandBlast.class)) { - SandBlast sb = getAbility(player, SandBlast.class); - if (sb.blasting) { - return; - } - sb.blastSand(); - } - } - - private void blastSand() { - if (!blasting) { - blasting = true; - direction = GeneralMethods.getDirection(source.getLocation().clone().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, range)).multiply(0.07); - this.bPlayer.addCooldown(this); - } - tempBlock.revertBlock(); - - //FallingBlock fblock = source.getWorld().spawnFallingBlock(source.getLocation().clone().add(0, 1, 0), source.getType(), source.getData()); - - if (rand.nextInt(2) == 0) { - DensityShift.playSandbendingSound(source.getLocation().add(0, 1, 0)); - } - - double x = rand.nextDouble() / 10; - double z = rand.nextDouble() / 10; - - x = (rand.nextBoolean()) ? -x : x; - z = (rand.nextBoolean()) ? -z : z; - - //fblock.setVelocity(direction.clone().add(new Vector(x, 0.2, z))); - //fblock.setDropItem(false); - //fblocks.put(fblock, player); - - fallingBlocks.add(new TempFallingBlock(source.getLocation().add(0, 1, 0), sourceData, direction.clone().add(new Vector(x, 0.2, z)), this)); - - } - - public void affect() { - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { - FallingBlock fblock = tfb.getFallingBlock(); - if (fblock.isDead()) { - tfb.remove(); - continue; - } - - if (RegionProtection.isRegionProtected(player, fblock.getLocation(), this)) { - tfb.remove(); - continue; - } - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(fblock.getLocation(), 1.5)) { - if (entity instanceof LivingEntity && !(entity instanceof ArmorStand)) { - if (entity == this.player) continue; - if (affectedEntities.contains(entity)) continue; - - if (!entity.isDead()) { - DamageHandler.damageEntity(entity, damage, this); - - affectedEntities.add(entity); - - LivingEntity le = (LivingEntity) entity; - if (le.hasPotionEffect(PotionEffectType.BLINDNESS)) { - le.removePotionEffect(PotionEffectType.BLINDNESS); - } - - le.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 60, 1)); - } - } - } - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - Location location = collision.getLocationFirst(); - - Optional collidedObject = fallingBlocks.stream().filter(temp -> temp.getLocation().equals(location)).findAny(); - - if (collidedObject.isPresent()) { - fallingBlocks.remove(collidedObject.get()); - collidedObject.get().remove(); - } - } - } - - @Override - public String getName() { - return "SandBlast"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.SandBlast.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public double getSourceRange() { - return sourceRange; - } - - public void setSourceRange(double sourceRange) { - this.sourceRange = sourceRange; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public int getMaxBlasts() { - return maxBlasts; - } - - public void setMaxBlasts(int maxBlasts) { - this.maxBlasts = maxBlasts; - } - - public static double getDamage() { - return damage; - } - - public static void setDamage(double damage) { - SandBlast.damage = damage; - } - - public Block getSource() { - return source; - } - - public void setSource(Block source) { - this.source = source; - } - - public BlockData getSourceData() { - return sourceData; - } - - public void setSourceData(BlockData sourceData) { - this.sourceData = sourceData; - } - - public int getBlasts() { - return blasts; - } - - public void setBlasts(int blasts) { - this.blasts = blasts; - } - - public boolean isBlasting() { - return blasting; - } - - public void setBlasting(boolean blasting) { - this.blasting = blasting; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public TempBlock getTempBlock() { - return tempBlock; - } - - public void setTempBlock(TempBlock tempBlock) { - this.tempBlock = tempBlock; - } - - public List getAffectedEntities() { - return affectedEntities; - } - - public List getFallingBlocks() { - return fallingBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.SandBlast.Enabled"); - } -} diff --git a/src/ability/earthbending/combo/Crevice.java b/src/ability/earthbending/combo/Crevice.java deleted file mode 100644 index f4e22c4..0000000 --- a/src/ability/earthbending/combo/Crevice.java +++ /dev/null @@ -1,370 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending.combo; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ClickType; - -import com.projectkorra.projectkorra.util.TempBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Random; - -public class Crevice extends EarthAbility implements AddonAbility, ComboAbility { - - @Attribute(Attribute.RANGE) - private double range; - private long regenDelay; - @Attribute("Depth") - private int randomDepth; - private int avatarDepth; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - private Location origin; - private Location location; - private Vector direction; - private double travelled; - private boolean skip; - - private final List> columns = new ArrayList<>(); - - private final Random rand = new Random(); - - public Crevice(Player player) { - super(player); - if (!bPlayer.canBendIgnoreBinds(this)) { - return; - } - - setFields(); - createInstance(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - range = config.getDouble("Abilities.Earth.EarthCombo.Crevice.Range"); - regenDelay = config.getLong("Abilities.Earth.EarthCombo.Crevice.RevertDelay"); - randomDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.Depth"); - avatarDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth"); - cooldown = config.getLong("Abilities.Earth.EarthCombo.Crevice.Cooldown"); - } - - private void createInstance() { - origin = player.getTargetBlock(null, 6).getLocation(); - if (isEarthbendable(origin.getBlock())) { - Location tempLoc = player.getLocation().clone(); - tempLoc.setPitch(0); - direction = tempLoc.getDirection().clone(); - origin.setDirection(tempLoc.getDirection()); - location = origin.clone(); - if (bPlayer.isAvatarState()) { - randomDepth = avatarDepth; - } - - start(); - if (!isRemoved()) { - bPlayer.addCooldown(this); - } - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - prepareRevert(); - remove(); - return; - } - if (travelled >= range || skip) { - if (System.currentTimeMillis() > getStartTime() + regenDelay) { - prepareRevert(); - remove(); - return; - } - return; - } - advanceCrevice(); - } - - @Override - public void remove() { - prepareRevert(); - super.remove(); - } - - public static void closeCrevice(Player player) { - Block target = player.getTargetBlock(null, 10); - for (Block near : GeneralMethods.getBlocksAroundPoint(target.getLocation(), 2)) { - for (Crevice c : getAbilities(Crevice.class)) { - for (List tbs : c.columns) { - for (TempBlock tb : tbs) { - if (near.getLocation().equals(tb.getLocation())) { - c.prepareRevert(); - c.remove(); - return; - } - } - } - } - } - } - - private void advanceCrevice() { - switch (rand.nextInt(2)) { - case 0: - if (location.getYaw() <= origin.getYaw()) { - location.setYaw(location.getYaw() + 40); - direction = location.getDirection().clone(); - } - break; - case 1: - if (location.getYaw() >= origin.getYaw()) { - location.setYaw(location.getYaw() - 40); - direction = location.getDirection().clone(); - } - break; - default: - direction = location.getDirection().clone(); - break; - } - - Location tempLoc = location.clone(); - location = location.add(direction.multiply(1)); - playEarthbendingSound(tempLoc); - location.getWorld().playSound(location, Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, (float) 0.5, (float) 0.5); - if (skip) { - return; - } - - travelled++; - if (travelled >= range) - return; - - if (RegionProtection.isRegionProtected(player, location, "RaiseEarth")) { - return; - } - - if (!isTransparent(location.getBlock().getRelative(BlockFace.UP))) { - location.add(0, 1, 0); - if (!isTransparent(location.getBlock().getRelative(BlockFace.UP)) || !isEarthbendable(location.getBlock())) { - skip = true; - return; - } - } else if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { - location.subtract(0, 1, 0); - if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { - skip = true; - return; - } - } - - removePillar(tempLoc, randInt(randomDepth + 1 - 2, randomDepth + 1 + 2)); - removePillar(GeneralMethods.getRightSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); - removePillar(GeneralMethods.getLeftSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); - } - - private int randInt(int min, int max) { - return rand.nextInt(max - min) + min; - } - - private void removePillar(Location location, int depth) { - List blocks = new ArrayList<>(); - Location tempLoc = location.clone().getBlock().getLocation(); - tempLoc.add(0, 1, 0); - for (int i = 0; i < depth + 1; i++) { - if (tempLoc.getY() < Objects.requireNonNull(tempLoc.getWorld()).getMinHeight() || tempLoc.getY() > tempLoc.getWorld().getMaxHeight()) { - break; - } - if (RegionProtection.isRegionProtected(player, tempLoc, this)) { - continue; - } - if (i == 0 && !isTransparent(tempLoc.getBlock())) { - continue; - } - if (i > 0 && !isEarthbendable(tempLoc.getBlock())) { - continue; - } - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tempLoc, 1)) { - entity.setVelocity(new Vector(0, -0.75, 0)); - } - - - blocks.add(new TempBlock(tempLoc.getBlock(), Material.AIR.createBlockData())); - tempLoc.subtract(0, 1, 0); - } - - Collections.reverse(blocks); - - columns.add(blocks); - } - - private void prepareRevert() { - for (int i = 0; i < columns.size(); ++i) { - List tbs = columns.get(i); - for (TempBlock tb : tbs) { - tb.revertBlock(); - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 1)) { - entity.setVelocity(new Vector(0, 0.7, 0)); - } - new RegenTempBlock(tb.getBlock(), Material.AIR, Material.AIR.createBlockData(), i * 50L); - } - } - columns.clear(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public String getName() { - return "Crevice"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public Object createNewComboInstance(Player player) { - return new Crevice(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.Crevice.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.Crevice.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.Crevice.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public long getRegenDelay() { - return regenDelay; - } - - public void setRegenDelay(long regenDelay) { - this.regenDelay = regenDelay; - } - - public int getDepth() { - return randomDepth; - } - - public void setDepth(int depth) { - this.randomDepth = depth; - } - - public int getAvatarDepth() { - return avatarDepth; - } - - public void setAvatarDepth(int avatarDepth) { - this.avatarDepth = avatarDepth; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - - public double getDistanceTravelled() { - return travelled; - } - - public void setDistanceTravelled(double travelled) { - this.travelled = travelled; - } - - public List> getColumns() { - return columns; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthCombo.Crevice.Enabled"); - } -} diff --git a/src/ability/earthbending/combo/MagmaBlast.java b/src/ability/earthbending/combo/MagmaBlast.java deleted file mode 100644 index 9b1f9d7..0000000 --- a/src/ability/earthbending/combo/MagmaBlast.java +++ /dev/null @@ -1,615 +0,0 @@ -package com.jedk1.jedcore.ability.earthbending.combo; - -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.MaterialUtil; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.util.ComboUtil; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ComboAbility; -import com.projectkorra.projectkorra.ability.LavaAbility; -import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -import com.projectkorra.projectkorra.util.TempFallingBlock; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.util.Vector; - -import java.util.*; -import java.util.stream.Collectors; - -public class MagmaBlast extends LavaAbility implements AddonAbility, ComboAbility { - private static final int PARTICLE_COUNT = 20; - private static final int RAISE_HEIGHT = 3; - private static final Random rand = new Random(); - - private final Set sources = new HashSet<>(); - private final List blocks = new ArrayList<>(); - private final List firedBlocks = new ArrayList<>(); - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long maxDuration; - private long shotCooldown; - @Attribute("MaxSources") - private int maxSources; - @Attribute(Attribute.SELECT_RANGE) - private int sourceRange; - @Attribute(Attribute.SELECT_RANGE) - private double selectRange; - @Attribute(Attribute.DAMAGE) - private double damage; - private double fireSpeed; - // How far away the player is allowed to be from the sources before the ability is destroyed. - private double maxDistanceFromSources; - private float explosionRadius = 2.0f; - // This will destroy the instance if LavaFlow is on cooldown. - private boolean requireLavaFlow; - private boolean playerCollisions; - private boolean entitySelection; - - private Location origin; - private int counter; - private long canLavaFlowTime; - private long lastShot; - private boolean stopFiring; - - public MagmaBlast(Player player) { - super(player); - setFields(); - - if (!bPlayer.canBendIgnoreBinds(this)) { - return; - } - - origin = player.getLocation().clone(); - - if (raiseSources()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - maxSources = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots"); - sourceRange = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange"); - damage = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage"); - cooldown = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown"); - requireLavaFlow = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow"); - playerCollisions = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions"); - entitySelection = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection"); - selectRange = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange"); - explosionRadius = (float) config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius"); - fireSpeed = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed"); - maxDuration = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration"); - maxDistanceFromSources = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources"); - shotCooldown = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown"); - } - - // Select random nearby earth blocks as sources and raise them in the air. - private boolean raiseSources() { - List potentialBlocks = GeneralMethods.getBlocksAroundPoint(origin, sourceRange).stream().filter(ElementalAbility::isEarth).collect(Collectors.toList()); - - Collections.shuffle(potentialBlocks); - - for (Block newSource : potentialBlocks) { - if (!isValidSource(newSource)) continue; - - newSource.getWorld().playSound(newSource.getLocation(), Sound.ENTITY_GHAST_SHOOT, 0.8f, 0.3f); - sources.add(new TempFallingBlock(newSource.getLocation().add(0, 1, 0), Material.MAGMA_BLOCK.createBlockData(), new Vector(0, 0.9, 0), this)); - - if (sources.size() >= maxSources) { - break; - } - } - - return !sources.isEmpty(); - } - - // Checks to make sure the source block has room to fly upwards. - private boolean isValidSource(Block block) { - for (int i = 0; i <= RAISE_HEIGHT; ++i) { - if (!MaterialUtil.isTransparent(block.getRelative(BlockFace.UP, i + 1)) || block.isLiquid()) { - return false; - } - } - - return true; - } - - public boolean shouldBlockLavaFlow() { - long time = System.currentTimeMillis(); - return time < canLavaFlowTime; - } - - @Override - public void progress() { - stopFiring = false; - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - - if (System.currentTimeMillis() > this.getStartTime() + maxDuration) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreBinds(this) || !(bPlayer.getBoundAbility() instanceof LavaFlow)) { - remove(); - return; - } - - if (requireLavaFlow && !bPlayer.canBend(getAbility("LavaFlow"))) { - remove(); - return; - } - - displayAnimation(); - handleSources(); - - if (playerCollisions) { - doPlayerCollisions(); - } - - if (sources.isEmpty() && firedBlocks.isEmpty() && blocks.isEmpty()) { - remove(); - return; - } - - if (hasBlocks() && this.player.getLocation().distanceSquared(origin) > maxDistanceFromSources * maxDistanceFromSources) { - remove(); - } - } - - @Override - public void remove() { - bPlayer.addCooldown(this); - super.remove(); - - for (TempFallingBlock ftb : sources) { - ftb.remove(); - } - - for (TempBlock tb : blocks) { - tb.revertBlock(); - } - - for (TempFallingBlock tfb : firedBlocks) { - tfb.remove(); - } - } - - private void handleSources() { - if (sources.isEmpty()) return; - - for (Iterator iter = sources.iterator(); iter.hasNext();) { - TempFallingBlock tfb = iter.next(); - - if (tfb.getLocation().getBlockY() >= (origin.getBlockY() + RAISE_HEIGHT)) { - blocks.add(new TempBlock(tfb.getLocation().getBlock(), Material.MAGMA_BLOCK.createBlockData())); - iter.remove(); - tfb.remove(); - } - } - } - - private void displayAnimation() { - if (++counter == 3) { - counter = 0; - } else { - return; - } - - for (Iterator iterator = firedBlocks.iterator(); iterator.hasNext();) { - TempFallingBlock tfb = iterator.next(); - - if (!tfb.getFallingBlock().isDead()) { - playParticles(tfb.getLocation()); - } else { - tfb.remove(); - iterator.remove(); - } - } - - for (TempBlock tb : blocks) { - playParticles(tb.getLocation()); - } - } - - private void doPlayerCollisions() { - List blocksCopy = new ArrayList<>(firedBlocks); - - for (TempFallingBlock tfb : blocksCopy) { - if (!firedBlocks.contains(tfb)) continue; - - boolean didExplode = false; - - for (Entity e : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), this.explosionRadius)) { - if (!(e instanceof LivingEntity)) continue; - if (e == this.player) continue; - - if (blast(tfb, true)) { - didExplode = true; - } - } - - if (didExplode) { - firedBlocks.remove(tfb); - } - } - } - - private void playParticles(Location location) { - location.add(.5,.5,.5); - ParticleEffect.LAVA.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); - ParticleEffect.SMOKE_NORMAL.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); - for (int i = 0; i < 10; i++) { - GeneralMethods.displayColoredParticle("FFA400", getOffsetLocation(location, 2)); - GeneralMethods.displayColoredParticle("FF8C00", getOffsetLocation(location, 2)); - } - } - - // Returns true if any source blocks still exist. Returns false is all of the source blocks have been fired. - public boolean hasBlocks() { - return !sources.isEmpty() || !blocks.isEmpty(); - } - - private Location getOffsetLocation(Location loc, double offset) { - return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); - } - - public static void performAction(Player player) { - MagmaBlast mb = getAbility(player, MagmaBlast.class); - - if (mb != null) { - mb.performAction(); - } - } - - private void performAction() { - long time = System.currentTimeMillis(); - - if (blocks.isEmpty() || stopFiring || time < lastShot + shotCooldown) return; - - Location target = null; - - if (entitySelection) { - Entity targetEntity = GeneralMethods.getTargetedEntity(player, selectRange); - - if (targetEntity instanceof LivingEntity) { - target = ((LivingEntity) targetEntity).getEyeLocation(); - } - } - - if (target == null) { - target = GeneralMethods.getTargetedLocation(player, selectRange, Material.MAGMA_BLOCK); - } - - TempBlock tb = getClosestSource(target); - - if (tb == null) return; - - stopFiring = true; - canLavaFlowTime = time + 1000; - blocks.remove(tb); - - Vector direction = GeneralMethods.getDirection(tb.getLocation().clone().add(0.5f, 0.5f, 0.5f), target).normalize(); - - tb.revertBlock(); - - FallingBlock fallingBlock = tb.getLocation().getWorld().spawnFallingBlock( - tb.getLocation().clone().add(0.5, 0.5, 0.5), - Material.MAGMA_BLOCK.createBlockData() - ); - - fallingBlock.setTicksLived(Integer.MAX_VALUE); - fallingBlock.setMetadata("magmablast", new FixedMetadataValue(JedCore.plugin, "1")); - fallingBlock.setDropItem(false); - fallingBlock.setCancelDrop(true); - - TempFallingBlock tfb = new TempFallingBlock(tb.getLocation(), Material.MAGMA_BLOCK.createBlockData(), direction.multiply(fireSpeed), this, true); - firedBlocks.add(tfb); - - lastShot = time; - } - - // Get the closest fireable source block to the target location. - private TempBlock getClosestSource(Location target) { - double distanceSq = Double.MAX_VALUE; - TempBlock closest = null; - - for (TempBlock tempBlock : blocks) { - double currentDistSq = tempBlock.getLocation().distanceSquared(target); - - if (currentDistSq < distanceSq) { - distanceSq = currentDistSq; - closest = tempBlock; - } - } - - return closest; - } - - public static void blast(TempFallingBlock tfb) { - blast(tfb, false); - } - - public static boolean blast(TempFallingBlock tfb, boolean entityCollision) { - MagmaBlast mb = (MagmaBlast) tfb.getAbility(); - Location location = tfb.getLocation().clone().add(0.5, 0.5, 0.5); - - Block hitBlock = location.getBlock(); - if (hitBlock.getType().isSolid()) { - blastEffects(location, mb); - tfb.remove(); - mb.firedBlocks.remove(tfb); - return true; - } - - float radius = mb.explosionRadius; - boolean didHit = false; - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, radius)) { - if (!(entity instanceof LivingEntity)) continue; - if (entity == mb.player) continue; - - DamageHandler.damageEntity(entity, mb.getDamage(), mb); - ((LivingEntity) entity).setNoDamageTicks(0); - didHit = true; - } - - if (didHit || entityCollision) { - blastEffects(location, mb); - tfb.remove(); - mb.firedBlocks.remove(tfb); - return true; - } - - return false; - } - - private static void blastEffects(Location location, MagmaBlast mb) { - float radius = mb.explosionRadius; - float speed = 0.1f; - - ParticleEffect.FLAME.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - ParticleEffect.SMOKE_LARGE.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - ParticleEffect.FIREWORKS_SPARK.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); - - location.getWorld().playSound(location, - (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, - 1f, 1f); - location.getWorld().playSound(location, - (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, - 1f, 1f); - } - - // Generates a random number between -max and max. - private static float randomBinomial(float max) { - return (rand.nextFloat() * max) - (rand.nextFloat() * max); - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "MagmaBlast"; - } - - @Override - public boolean isHiddenAbility() { - return false; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return false; - } - - @Override - public Object createNewComboInstance(Player player) { - return new MagmaBlast(player); - } - - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.MagmaBlast.Combination")); - } - - @Override - public String getInstructions() { - return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.MagmaBlast.Instructions"); - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.MagmaBlast.Description"); - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - public Set getSources() { - return sources; - } - - public List getBlocks() { - return blocks; - } - - public List getFiredBlocks() { - return firedBlocks; - } - - public long getMaxDuration() { - return maxDuration; - } - - public void setMaxDuration(long maxDuration) { - this.maxDuration = maxDuration; - } - - public long getShotCooldown() { - return shotCooldown; - } - - public void setShotCooldown(long shotCooldown) { - this.shotCooldown = shotCooldown; - } - - public int getMaxSources() { - return maxSources; - } - - public void setMaxSources(int maxSources) { - this.maxSources = maxSources; - } - - public int getSourceRange() { - return sourceRange; - } - - public void setSourceRange(int sourceRange) { - this.sourceRange = sourceRange; - } - - public double getSelectRange() { - return selectRange; - } - - public void setSelectRange(double selectRange) { - this.selectRange = selectRange; - } - - public double getFireSpeed() { - return fireSpeed; - } - - public void setFireSpeed(double fireSpeed) { - this.fireSpeed = fireSpeed; - } - - public double getMaxDistanceFromSources() { - return maxDistanceFromSources; - } - - public void setMaxDistanceFromSources(double maxDistanceFromSources) { - this.maxDistanceFromSources = maxDistanceFromSources; - } - - public float getExplosionRadius() { - return explosionRadius; - } - - public void setExplosionRadius(float explosionRadius) { - this.explosionRadius = explosionRadius; - } - - public boolean isRequireLavaFlow() { - return requireLavaFlow; - } - - public void setRequireLavaFlow(boolean requireLavaFlow) { - this.requireLavaFlow = requireLavaFlow; - } - - public boolean isPlayerCollisions() { - return playerCollisions; - } - - public void setPlayerCollisions(boolean playerCollisions) { - this.playerCollisions = playerCollisions; - } - - public boolean isEntitySelection() { - return entitySelection; - } - - public void setEntitySelection(boolean entitySelection) { - this.entitySelection = entitySelection; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public long getCanLavaFlowTime() { - return canLavaFlowTime; - } - - public void setCanLavaFlowTime(long canLavaFlowTime) { - this.canLavaFlowTime = canLavaFlowTime; - } - - public long getLastShotTime() { - return lastShot; - } - - public void setLastShotTime(long lastShot) { - this.lastShot = lastShot; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.Enabled"); - } -} \ No newline at end of file diff --git a/src/ability/firebending/Combustion.java b/src/ability/firebending/Combustion.java deleted file mode 100644 index 1e4edff..0000000 --- a/src/ability/firebending/Combustion.java +++ /dev/null @@ -1,629 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; -import com.jedk1.jedcore.util.FireTick; - -import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; -import org.bukkit.Tag; -import com.jedk1.jedcore.util.MaterialUtil; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.CombustionAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.stream.Collectors; - -public class Combustion extends CombustionAbility implements AddonAbility { - - private State state; - private Location location; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - private CompositeRemovalPolicy removalPolicy; - - private ArrayList skipMaterials; // use a configured list of blocks to skip through - - public Combustion(Player player) { - super(player); - - if (!isEnabled()) return; - - if (this.player == null || !bPlayer.canBend(this) || !bPlayer.canCombustionbend()) { - return; - } - - if (hasAbility(player, Combustion.class)) { - Combustion c = getAbility(player, Combustion.class); - if (c.state instanceof ChargeState) - return; - } - - setFields(); - - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.Combustion.Cooldown"); - - this.location = null; - this.state = new ChargeState(); - - this.removalPolicy = new CompositeRemovalPolicy(this, - new CannotBendRemovalPolicy(this.bPlayer, this, true, true), - new IsOfflineRemovalPolicy(this.player), - new IsDeadRemovalPolicy(this.player), - new SwappedSlotsRemovalPolicy<>(bPlayer, Combustion.class) - ); - - this.removalPolicy.load(config, "Abilities.Fire.Combustion"); - - this.skipMaterials = loadSkipMaterials(); - } - - @Override - public void progress() { - if (this.removalPolicy.shouldRemove()) { - remove(); - return; - } - - state.update(); - } - - public static void combust(Player player) { - if(hasAbility(player, Combustion.class)) { - Combustion c = getAbility(player, Combustion.class); - - c.selfCombust(); - } - } - - public void selfCombust() { - if (this.state instanceof TravelState) { - this.state = new CombustState(location); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - // Only enable the collision while traveling. - if (state instanceof TravelState) { - return location; - } - - return null; - } - - @Override - public double getCollisionRadius() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getDouble("Abilities.Fire.Combustion.AbilityCollisionRadius"); - } - - @Override - public String getName() { - return "Combustion"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.Combustion.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.Combustion.Enabled"); - } - - private ArrayList loadSkipMaterials() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - ArrayList skipList = new ArrayList<>(); - - if (config.contains("Abilities.Fire.Combustion.SkipMaterials")) { - List configuredSkipList = config.getStringList("Abilities.Fire.Combustion.SkipMaterials"); - - for (String entry : configuredSkipList) { - if (entry.startsWith("#")) { - String tagName = entry.substring(1).toLowerCase(); - - NamespacedKey tagKey = NamespacedKey.minecraft(tagName); - Tag materialTag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, tagKey, Material.class); - - if (materialTag != null) { - skipList.addAll(materialTag.getValues().stream() - .map(material -> material.name().toLowerCase()) - .collect(Collectors.toList())); - } - } else { - skipList.add(entry.toLowerCase()); - } - } - } - - return skipList; - } - - private interface State { - void update(); - } - - // This is the initial state of Combustion. - // It's used to render the particle ring that happens during charging. - // This state transitions to TravelState if the player stops sneaking after charging is done. - // This state transitions to CombustState if the player takes damage while charging. - private class ChargeState implements State { - private final long startTime; - private int currPoint = (int) player.getLocation().getYaw() + 90; - private final long warmup; - private final double playerStartHealth; - private final boolean instantExplodeIfHit; - - public ChargeState() { - this.startTime = System.currentTimeMillis(); - this.playerStartHealth = player.getHealth(); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - this.instantExplodeIfHit = config.getBoolean("Abilities.Fire.Combustion.InstantExplodeIfHit"); - this.warmup = config.getLong("Abilities.Fire.Combustion.Warmup"); - } - - @Override - public void update() { - long time = System.currentTimeMillis(); - - boolean charged = time >= this.startTime + warmup; - - if (player.isSneaking()) { - if (!bPlayer.canBendIgnoreBinds(Combustion.this)) { - remove(); - return; - } - - playParticleRing(60, 1.75F, 2); - - if (instantExplodeIfHit && player.getHealth() < playerStartHealth) { - // Remove and combust at player's location - state = new CombustState(player.getLocation(), true); - bPlayer.addCooldown(Combustion.this); - return; - } - - if (charged) { - ParticleEffect.SMOKE_LARGE.display(player.getLocation(), 1, Math.random(), Math.random(), Math.random(), 0.1); - } - } else { - if (charged) { - state = new TravelState(); - bPlayer.addCooldown(Combustion.this); - } else { - remove(); - } - } - } - - private void playParticleRing(int points, float size, int speed) { - for (int i = 0; i < speed; ++i) { - currPoint += 360 / points; - - if (currPoint > 360) { - currPoint = 0; - } - - double angle = currPoint * 3.141592653589793D / 180.0D; - double x = size * Math.cos(angle); - double z = size * Math.sin(angle); - - Location loc = player.getLocation().add(x, 1.0D, z); - playFirebendingParticles(loc, 3, 0.0, 0.0, 0.0); - ParticleEffect.SMOKE_NORMAL.display(loc, 4, 0.0, 0.0, 0.0, 0.01); - JCMethods.emitLight(loc); - } - } - } - - // This state is used after the player releases a charged Combustion. - // It's used for moving and rendering the projectile. - // This state transitions to CombustState when it collides with terrain or an entity. - private class TravelState implements State { - private Vector direction; - private final int range; - private final double speed; - private final boolean explodeOnDeath; - private final double entityCollisionRadius; - private double distanceTraveled; - - public TravelState() { - removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); - - Location origin = player.getEyeLocation().clone(); - origin.setY(origin.getY() - 0.8D); - location = origin.clone(); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - range = config.getInt("Abilities.Fire.Combustion.Range"); - speed = config.getDouble("Abilities.Fire.Combustion.Speed"); - explodeOnDeath = config.getBoolean("Abilities.Fire.Combustion.ExplodeOnDeath"); - entityCollisionRadius = config.getDouble("Abilities.Fire.Combustion.EntityCollisionRadius"); - - if (explodeOnDeath) { - removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); - removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); - } - - direction = player.getEyeLocation().getDirection().normalize(); - distanceTraveled = 0; - } - - @Override - public void update() { - if (explodeOnDeath && player.isDead()) { - state = new CombustState(location); - return; - } - - // Manually handle the region protection check because the CannotBendRemovalPolicy no longer checks it - // when explodeOnDeath is true. This stops players from firing Combustion and then walking into a - // protected area. - if (explodeOnDeath) { - if (RegionProtection.isRegionProtected(Combustion.this, player.getLocation())) { - remove(); - return; - } - } - - if (distanceTraveled >= range) { - remove(); - return; - } - - travel(); - } - - private void travel() { - double stepDistance = speed; - - for (int i = 0; i < (int) (speed * 5); ++i) { - render(); - - Sphere collider = new Sphere(location.toVector(), entityCollisionRadius); - - boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { - location = entity.getLocation(); - state = new CombustState(location); - return true; - }); - - if (hit) { - return; - } - - if (!MaterialUtil.isTransparent(location.getBlock()) || isWater(location.getBlock())) { - Material blockMaterial = location.getBlock().getType(); - String blockMaterialName = blockMaterial.name().toLowerCase(); - - boolean shouldSkip = skipMaterials.contains(blockMaterialName); - - if (!shouldSkip) { - state = new CombustState(location); - return; - } - } - - direction = player.getEyeLocation().getDirection().normalize(); - location = location.add(direction.clone().multiply(stepDistance)); - - distanceTraveled += stepDistance; - - if (distanceTraveled >= range) { - remove(); - return; - } - } - } - - private void render() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - ParticleEffect.SOUL_FIRE_FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); - } else { - ParticleEffect.FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); - } - ParticleEffect.SMOKE_LARGE.display(location, 1, 0.0, 0.0, 0.0F, 0.06); - ParticleEffect.FIREWORKS_SPARK.display(location, 1, 0.0, 0.0, 0.0F, 0.06); - - location.getWorld().playSound(location, Sound.ENTITY_FIREWORK_ROCKET_BLAST, 1.0F, 0.01F); - - JCMethods.emitLight(location); - } - } - - @Override - public void handleCollision(final Collision collision) { - super.handleCollision(collision); - - if (collision.isRemovingFirst()) { - state = new CombustState(collision.getLocationFirst()); - } - } - - // This state is used for doing the explosion. - // ChargeState can transition to this state if the player takes damage while charging. - // TravelState can transition to this state if the projectile collides with terrain, entity, or collidable ability. - private class CombustState implements State { - private final long startTime; - private final long regenTime; - private boolean waitForRegen; - - public CombustState(Location location) { - this(location, false); - } - - public CombustState(Location location, boolean misfire) { - removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); - // This stops players from moving into a protected area to bypass the regen wait time. - removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); - - ConfigurationSection config = JedCoreConfig.getConfig(player); - - this.startTime = System.currentTimeMillis(); - this.regenTime = config.getLong("Abilities.Fire.Combustion.RegenTime"); - this.waitForRegen = config.getBoolean("Abilities.Fire.Combustion.WaitForRegen"); - - double damage = config.getDouble("Abilities.Fire.Combustion.Damage"); - int fireTick = config.getInt("Abilities.Fire.Combustion.FireTick"); - int power = config.getInt("Abilities.Fire.Combustion.Power"); - boolean damageBlocks = config.getBoolean("Abilities.Fire.Combustion.DamageBlocks"); - boolean regenBlocks = config.getBoolean("Abilities.Fire.Combustion.RegenBlocks"); - - ExplosionMethod explosionMethod; - if (regenBlocks) { - explosionMethod = new RegenExplosionMethod(damageBlocks, regenTime); - } else { - explosionMethod = new PermanentExplosionMethod(damageBlocks); - } - - // Don't wait for regen if the blocks aren't even being destroyed. - if (!damageBlocks) { - waitForRegen = false; - } - - double modifier = 0; - if (misfire) { - modifier = config.getInt("Abilities.Fire.Combustion.MisfireModifier"); - } - - int destroyedCount = explosionMethod.explode(location, power + modifier, damage + modifier, fireTick); - - // Don't wait for regen if nothing was actually destroyed. - if (destroyedCount <= 0) { - waitForRegen = false; - } - - AirAbility.removeAirSpouts(location, power, player); - WaterAbility.removeWaterSpouts(location, power, player); - } - - @Override - public void update() { - if (!waitForRegen || System.currentTimeMillis() >= (this.startTime + this.regenTime)) { - remove(); - } - } - } - - private interface ExplosionMethod { - // Returns how many blocks were destroyed. - int explode(Location location, double size, double damage, int fireTick); - } - - private abstract class AbstractExplosionMethod implements ExplosionMethod { - protected List blocks = Arrays.asList( - Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.BEDROCK, Material.CHEST, Material.TRAPPED_CHEST, Material.OBSIDIAN, - Material.NETHER_PORTAL, Material.END_PORTAL, Material.END_PORTAL_FRAME, Material.FIRE, - Material.WATER, Material.LAVA, Material.DROPPER, Material.FURNACE, - Material.DISPENSER, Material.HOPPER, Material.BEACON, Material.BARRIER, Material.SPAWNER - ); - - private final boolean destroy; - private final Random rand = new Random(); - - public AbstractExplosionMethod(boolean destroy) { - this.destroy = destroy; - } - - public int explode(Location location, double size, double damage, int fireTick) { - render(location); - - if (!destroy) { - return 0; - } - - location.getWorld().createExplosion(location, 0.0F); - int destroyCount = destroyBlocks(location, (int)size); - damageEntities(location, size, damage, fireTick); - - return destroyCount; - } - - private void render(Location location) { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - ParticleEffect.SOUL_FIRE_FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - } else { - ParticleEffect.FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - } - ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.FIREWORKS_SPARK.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random()); - ParticleEffect.EXPLOSION_HUGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); - - location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 1f, 1f); - } - - private int destroyBlocks(Location location, int size) { - int count = 0; - - for (Location l : GeneralMethods.getCircle(location, size, size, false, true, 0)) { - if (!RegionProtection.isRegionProtected(Combustion.this, l)) { - if (destroyBlock(l)) { - ++count; - } - } - } - - return count; - } - - private void damageEntities(Location location, double size, double damage, int fireTick) { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, size)) { - if (e instanceof LivingEntity) { - if (!RegionProtection.isRegionProtected(Combustion.this, e.getLocation())) { - DamageHandler.damageEntity(e, damage, Combustion.this); - FireTick.set(e, fireTick); - } - } - } - } - - protected void placeRandomFire(Location location) { - int chance = rand.nextInt(3); - - if ((!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) || (chance != 0)) - return; - - location.getBlock().setType(Material.FIRE); - } - - protected void placeRandomBlock(Location location) { - int chance = rand.nextInt(3); - - if (!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) - return; - - Material block = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType(); - - if (chance == 0) - location.getBlock().setType(block); - } - - // Returns how many blocks were destroyed. - public abstract boolean destroyBlock(Location location); - } - - private class RegenExplosionMethod extends AbstractExplosionMethod { - private final long regenTime; - - public RegenExplosionMethod(boolean destroy, long regenTime) { - super(destroy); - this.regenTime = regenTime; - } - - @Override - public boolean destroyBlock(Location l) { - Block block = l.getBlock(); - - if (TempBlock.isTempBlock(block)) - TempBlock.revertBlock(block, Material.AIR); - if (TempBlock.isTempBlock(block)) - TempBlock.removeBlock(block); - - if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { - new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), regenTime, false); - placeRandomBlock(l); - placeRandomFire(l); - - return true; - } - - return false; - } - } - - private class PermanentExplosionMethod extends AbstractExplosionMethod { - public PermanentExplosionMethod(boolean destroy) { - super(destroy); - } - - @Override - public boolean destroyBlock(Location l) { - Block block = l.getBlock(); - - if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { - Block newBlock = l.getWorld().getBlockAt(l); - newBlock.setType(Material.AIR); - placeRandomBlock(l); - placeRandomFire(l); - - return true; - } - - return false; - } - } -} diff --git a/src/ability/firebending/FireBreath.java b/src/ability/firebending/FireBreath.java deleted file mode 100644 index 6a063c8..0000000 --- a/src/ability/firebending/FireBreath.java +++ /dev/null @@ -1,427 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.UUID; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.listener.CommandListener; -import com.jedk1.jedcore.util.FireTick; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ChatUtil; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; - -public class FireBreath extends FireAbility implements AddonAbility { - - public static List rainbowPlayer = new ArrayList<>(); - - private int ticks; - Random rand = new Random(); - private final List locations = new ArrayList<>(); - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.DURATION) - private long duration; - private int particles; - @Attribute(Attribute.DAMAGE) - private double playerDamage; - @Attribute(Attribute.DAMAGE) - private double mobDamage; - @Attribute(Attribute.DURATION) - private int fireDuration; - @Attribute(Attribute.RANGE) - private int range; - private boolean spawnFire; - private boolean meltEnabled; - private int meltChance; - - - public FireBreath(Player player) { - super(player); - if (!bPlayer.canBend(this) || hasAbility(player, FireBreath.class)) { - return; - } - - setFields(); - - if (bPlayer.isAvatarState()) { - range = range * 2; - playerDamage = playerDamage * 1.5; - mobDamage = mobDamage * 2; - duration = duration * 3; - } else if (JCMethods.isSozinsComet(player.getWorld())) { - range = range * 2; - playerDamage = playerDamage * 1.5; - mobDamage = mobDamage * 2; - } - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.FireBreath.Cooldown"); - duration = config.getLong("Abilities.Fire.FireBreath.Duration"); - particles = config.getInt("Abilities.Fire.FireBreath.Particles"); - playerDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Player"); - mobDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Mob"); - fireDuration = config.getInt("Abilities.Fire.FireBreath.FireDuration"); - range = config.getInt("Abilities.Fire.FireBreath.Range"); - spawnFire = config.getBoolean("Abilities.Fire.FireBreath.Avatar.FireEnabled"); - meltEnabled = config.getBoolean("Abilities.Fire.FireBreath.Melt.Enabled"); - meltChance = config.getInt("Abilities.Fire.FireBreath.Melt.Chance"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); - range *= BlueFireAbility.getRangeFactor(); - playerDamage *= BlueFireAbility.getDamageFactor(); - mobDamage *= BlueFireAbility.getDamageFactor(); - } - - if (isDay(player.getWorld())) { - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - range = (int) getDayFactor(range); - playerDamage = getDayFactor(playerDamage); - mobDamage = getDayFactor(mobDamage); - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (!player.isSneaking()) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (System.currentTimeMillis() < getStartTime() + duration) { - createBeam(); - } else { - bPlayer.addCooldown(this); - remove(); - } - } - - private boolean isLocationSafe(Location loc) { - Block block = loc.getBlock(); - if (RegionProtection.isRegionProtected(player, loc, this)) { - return false; - } - if (!isTransparent(block)) { - return false; - } - return !isWater(block); - } - - private void createBeam() { - Location loc = player.getEyeLocation(); - Vector dir = player.getLocation().getDirection(); - double step = 1; - double size = 0; - double offset = 0; - double damageRegion = 1.5; - - locations.clear(); - - for (double k = 0; k < range; k += step) { - loc = loc.add(dir.clone().multiply(step)); - size += 0.005; - offset += 0.3; - damageRegion += 0.01; - if (meltEnabled) { - for (Block b : GeneralMethods.getBlocksAroundPoint(loc, damageRegion)) { - if (isIce(b) && rand.nextInt(meltChance) == 0) { - if (TempBlock.isTempBlock(b)) { - TempBlock temp = TempBlock.get(b); - if (PhaseChange.getFrozenBlocksMap().containsKey(temp)) { - temp.revertBlock(); - PhaseChange.getFrozenBlocksMap().remove(temp); - } - } - } - } - } - if (!isLocationSafe(loc)) - return; - - locations.add(loc); - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - if (entity instanceof Player) { - FireTick.set(entity, fireDuration / 50); - DamageHandler.damageEntity(entity, playerDamage, this); - } else { - FireTick.set(entity, fireDuration / 50); - DamageHandler.damageEntity(entity, mobDamage, this); - } - } - } - - playFirebendingSound(loc); - if (bPlayer.isAvatarState() && spawnFire) { - new BlazeArc(player, loc, dir, 2); - } - - if (rainbowPlayer.contains(player.getUniqueId())) { - ticks++; - if (ticks >= 301) - ticks = 0; - if (isInRange(ticks, 0, 50)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 140, 32, 32); - } else if (isInRange(ticks, 51, 100)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 196, 93, 0); - } else if (isInRange(ticks, 101, 150)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 186, 166, 37); - } else if (isInRange(ticks, 151, 200)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 36, 171, 47); - } else if (isInRange(ticks, 201, 250)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 36, 142, 171); - } else if (isInRange(ticks, 251, 300)) { - for (int i = 0; i < 6; i++) - displayParticle(getOffsetLocation(loc, offset), 1, 128, 36, 171); - } - } else { - playFirebendingParticles(loc, particles, Math.random(), Math.random(), Math.random()); - ParticleEffect.SMOKE_NORMAL.display(loc, particles, Math.random(), Math.random(), Math.random(), size); - JCMethods.emitLight(loc); - } - } - } - - private void displayParticle(Location location, int amount, int r, int g, int b) { - ParticleEffect.REDSTONE.display(location, amount, 0, 0, 0, 0.005, new Particle.DustOptions(Color.fromRGB(r, g, b), 1)); - JCMethods.emitLight(location); - } - - private boolean isInRange(int x, int min, int max) { - return min <= x && x <= max; - } - - /** - * Generates an offset location around a given location with variable offset - * amount. - */ - private Location getOffsetLocation(Location loc, double offset) { - return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); - } - - public static void toggleRainbowBreath(Player player, boolean activate) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - - boolean easterEgg = config.getBoolean("Abilities.Fire.FireBreath.RainbowBreath.Enabled"); - String bindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "")); - String unbindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "")); - String deniedMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "")); - - if (easterEgg && (player.hasPermission("bending.ability.FireBreath.RainbowBreath") - || Arrays.asList(CommandListener.DEVELOPERS).contains(player.getUniqueId().toString()))) { - if (activate) { - if (!rainbowPlayer.contains(player.getUniqueId())) { - rainbowPlayer.add(player.getUniqueId()); - if (!bindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + bindMsg); - } - } else { - if (rainbowPlayer.contains(player.getUniqueId())) { - rainbowPlayer.remove(player.getUniqueId()); - if (!unbindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + unbindMsg); - } - } - } else if (!deniedMsg.equals("")) { - player.sendMessage(Element.FIRE.getColor() + deniedMsg); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return player.getLocation(); - } - - @Override - public List getLocations() { - return locations; - } - - @Override - public String getName() { - return "FireBreath"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireBreath.Description"); - } - - public static List getRainbowPlayer() { - return rainbowPlayer; - } - - public static void setRainbowPlayer(List rainbowPlayer) { - FireBreath.rainbowPlayer = rainbowPlayer; - } - - public int getTicks() { - return ticks; - } - - public void setTicks(int ticks) { - this.ticks = ticks; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public int getParticles() { - return particles; - } - - public void setParticles(int particles) { - this.particles = particles; - } - - public double getPlayerDamage() { - return playerDamage; - } - - public void setPlayerDamage(double playerDamage) { - this.playerDamage = playerDamage; - } - - public double getMobDamage() { - return mobDamage; - } - - public void setMobDamage(double mobDamage) { - this.mobDamage = mobDamage; - } - - public int getFireDuration() { - return fireDuration; - } - - public void setFireDuration(int fireDuration) { - this.fireDuration = fireDuration; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public boolean isSpawnFire() { - return spawnFire; - } - - public void setSpawnFire(boolean spawnFire) { - this.spawnFire = spawnFire; - } - - public boolean isMeltEnabled() { - return meltEnabled; - } - - public void setMeltEnabled(boolean meltEnabled) { - this.meltEnabled = meltEnabled; - } - - public int getMeltChance() { - return meltChance; - } - - public void setMeltChance(int meltChance) { - this.meltChance = meltChance; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FireBreath.Enabled"); - } -} diff --git a/src/ability/firebending/FireShots.java b/src/ability/firebending/FireShots.java deleted file mode 100644 index a03efeb..0000000 --- a/src/ability/firebending/FireShots.java +++ /dev/null @@ -1,416 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.collision.CollisionDetector; -import com.jedk1.jedcore.collision.Sphere; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.AirShieldReflector; -import com.jedk1.jedcore.util.FireTick; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.util.Collision; -import com.projectkorra.projectkorra.airbending.AirShield; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.Ability; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import org.bukkit.inventory.MainHand; -import org.bukkit.util.Vector; - -public class FireShots extends FireAbility implements AddonAbility { - - private final List shots = new ArrayList<>(); - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute("MaxShots") - private int startAmount; - @Attribute(Attribute.FIRE_TICK) - private int fireticks; - @Attribute(Attribute.RANGE) - private int range; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute("CollisionRadius") - private double collisionRadius; - private Boolean flameInMainHand = null; - - public int amount; - - public FireShots(Player player){ - super(player); - - if (!bPlayer.canBend(this) || hasAbility(player, FireShots.class)) { - return; - } - - if (!player.hasGravity()) - player.setGravity(true); - - setFields(); - - amount = startAmount; - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.FireShots.Cooldown"); - startAmount = config.getInt("Abilities.Fire.FireShots.FireBalls"); - fireticks = config.getInt("Abilities.Fire.FireShots.FireDuration"); - range = config.getInt("Abilities.Fire.FireShots.Range"); - damage = config.getDouble("Abilities.Fire.FireShots.Damage"); - collisionRadius = config.getDouble("Abilities.Fire.FireShots.CollisionRadius"); - - applyModifiers(); - } - - private void applyModifiers() { - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - cooldown *= BlueFireAbility.getCooldownFactor(); - range *= BlueFireAbility.getRangeFactor(); - damage *= BlueFireAbility.getDamageFactor(); - } - - if (isDay(player.getWorld())) { - cooldown -= ((long) getDayFactor(cooldown) - cooldown); - range = (int) getDayFactor(range); - damage = getDayFactor(damage); - } - } - - public class FireShot { - - private final Ability ability; - private final Player player; - private Location location; - private final int range; - private final int fireTicks; - private double distanceTravelled; - private final double damage; - private Vector direction = null; - - public FireShot(Ability ability, Player player, Location location, int range, int fireTicks, double damage) { - this.ability = ability; - this.player = player; - this.location = location; - this.range = range; - this.fireTicks = fireTicks; - this.damage = damage; - } - - public boolean progress() { - if (player.isDead() || !player.isOnline()) { - return false; - } - if (distanceTravelled >= range) { - return false; - } - for (int i = 0; i < 2; i++) { - distanceTravelled ++; - if (distanceTravelled >= range) - return false; - - Vector dir = direction; - if (dir == null) { - dir = this.player.getLocation().getDirection().clone(); - } - - location = location.add(dir); - - if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())){ - return false; - } - - if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { - ParticleEffect.SOUL_FIRE_FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); - } else { - ParticleEffect.FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); - } - ParticleEffect.SMOKE_NORMAL.display(location, 2, 0.0, 0.0, 0.0, 0.01); - - JCMethods.emitLight(location); - - Sphere collider = new Sphere(location.toVector(), collisionRadius); - - boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { - DamageHandler.damageEntity(entity, damage, ability); - FireTick.set(entity, Math.round(fireTicks / 50F)); - new FireDamageTimer(entity, player, FireShots.this); - return true; - }); - - if (hit) { - return false; - } - } - return true; - } - - public Ability getAbility() { - return ability; - } - - public Player getPlayer() { - return player; - } - - public Location getLocation() { - return location; - } - - public void setLocation(Location location) { - this.location = location; - } - - public int getRange() { - return range; - } - - public int getFireTicks() { - return fireTicks; - } - - public double getDistanceTravelled() { - return distanceTravelled; - } - - public void setDistanceTravelled(double distanceTravelled) { - this.distanceTravelled = distanceTravelled; - } - - public double getDamage() { - return damage; - } - - public Vector getDirection() { - return direction; - } - - public void setDirection(Vector direction) { - this.direction = direction; - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - - if (!bPlayer.canBendIgnoreCooldowns(this)) { - amount = 0; - if (!bPlayer.isOnCooldown(this)) { - bPlayer.addCooldown(this); - } - } - - shots.removeIf(shot -> !shot.progress()); - - if (amount <= 0 && shots.isEmpty()) { - remove(); - return; - } - - if (amount > 0) { - displayFireBalls(); - } - } - - public static void fireShot(Player player) { - FireShots fs = getAbility(player, FireShots.class); - if (fs != null) { - fs.fireShot(); - } - } - - public static void swapHands(Player player) { - FireShots fs = getAbility(player, FireShots.class); - if (fs == null) - return; - if (fs.flameInMainHand == null) - fs.flameInMainHand = true; - else fs.flameInMainHand = !fs.flameInMainHand; - } - - public void fireShot() { - if (amount >= 1) { - if (--amount <= 0) { - bPlayer.addCooldown(this); - } - shots.add(new FireShot(this, player, getRightHandPos(), range, fireticks, damage)); - } - } - - public Location getRightHandPos() { - return (player.getMainHand()==MainHand.RIGHT == ((flameInMainHand == null) || flameInMainHand) ? - GeneralMethods.getRightSide(player.getLocation(), .55) : - GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); - } - - private void displayFireBalls() { - playFirebendingParticles(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0); - ParticleEffect.SMOKE_NORMAL.display(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0, 0.01); - JCMethods.emitLight(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld())); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public List getLocations() { - List list = shots.stream().map(shot -> shot.location).collect(Collectors.toList()); - list.add(getRightHandPos()); - return list; - } - - @Override - public void handleCollision(Collision collision) { - if (collision.isRemovingFirst()) { - Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); - - collidedShot.ifPresent(shots::remove); - } else { - CoreAbility second = collision.getAbilitySecond(); - if (second instanceof AirShield) { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - boolean reflect = config.getBoolean("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); - - if (reflect) { - Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); - - if (collidedShot.isPresent()) { - FireShot fireShot = collidedShot.get(); - AirShield shield = (AirShield) second; - - fireShot.direction = player.getLocation().getDirection().clone(); - AirShieldReflector.reflect(shield, fireShot.location, fireShot.direction); - } - } - } - } - } - - @Override - public String getName() { - return "FireShots"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireShots.Description"); - } - - public List getShots() { - return shots; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public int getStartAmount() { - return startAmount; - } - - public void setStartAmount(int startAmount) { - this.startAmount = startAmount; - } - - public int getFireticks() { - return fireticks; - } - - public void setFireticks(int fireticks) { - this.fireticks = fireticks; - } - - public int getRange() { - return range; - } - - public void setRange(int range) { - this.range = range; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - @Override - public double getCollisionRadius() { - return collisionRadius; - } - - public void setCollisionRadius(double collisionRadius) { - this.collisionRadius = collisionRadius; - } - - public int getAmount() { - return amount; - } - - public void setAmount(int amount) { - this.amount = amount; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.FireShots.Enabled"); - } -} diff --git a/src/ability/firebending/LightningBurst.java b/src/ability/firebending/LightningBurst.java deleted file mode 100644 index 2227761..0000000 --- a/src/ability/firebending/LightningBurst.java +++ /dev/null @@ -1,370 +0,0 @@ -package com.jedk1.jedcore.ability.firebending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.LightningAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; - -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; - -public class LightningBurst extends LightningAbility implements AddonAbility { - - private static final ConcurrentHashMap BOLTS = new ConcurrentHashMap<>(); - - Random rand = new Random(); - @Attribute(Attribute.COOLDOWN) - private long cooldown, avatarCooldown; - @Attribute(Attribute.CHARGE_DURATION) - private long chargeUp, avatarChargeup; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.RADIUS) - private double radius; - - private boolean charged; - private static int ID = Integer.MIN_VALUE; - - private float soundVolume; - private int soundInterval; - - public LightningBurst(Player player) { - super(player); - if (!bPlayer.canBend(this) || hasAbility(player, LightningBurst.class)) { - return; - } - - setFields(); - if (bPlayer.isAvatarState() || JCMethods.isSozinsComet(player.getWorld())) { - chargeUp = avatarChargeup; - cooldown = avatarCooldown; - } - - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Fire.LightningBurst.Cooldown"); - chargeUp = config.getLong("Abilities.Fire.LightningBurst.ChargeUp"); - avatarCooldown = config.getLong("Abilities.Fire.LightningBurst.AvatarCooldown"); - avatarChargeup = config.getLong("Abilities.Fire.LightningBurst.AvatarChargeUp"); - damage = config.getDouble("Abilities.Fire.LightningBurst.Damage"); - radius = config.getDouble("Abilities.Fire.LightningBurst.Radius"); - - soundVolume = (float) config.getDouble("Abilities.Fire.LightningBurst.Sound.Volume"); - soundInterval = config.getInt("Abilities.Fire.LightningBurst.Sound.Interval"); - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - if (RegionProtection.isRegionProtected(player, player.getLocation(), this)) { - remove(); - return; - } - if (!player.isSneaking()) { - if (!isCharging()) { - Location fake = player.getLocation().add(0, -2, 0); - fake.setPitch(0); - for (int i = -180; i < 180; i += 55) { - fake.setYaw(i); - for (double j = -180; j <= 180; j += 55) { - Location temp = fake.clone(); - Vector dir = fake.getDirection().clone().multiply(2 * Math.cos(Math.toRadians(j))); - temp.add(dir); - temp.setY(temp.getY() + 2 + (2 * Math.sin(Math.toRadians(j)))); - dir = GeneralMethods.getDirection(player.getLocation().add(0, 0, 0), temp); - spawnBolt(player.getLocation().clone().add(0, 1, 0).setDirection(dir), radius, 1, 20, true); - } - } - bPlayer.addCooldown(this); - } - remove(); - } else if (System.currentTimeMillis() > getStartTime() + chargeUp){ - setCharging(false); - displayCharging(); - } - } - - private void spawnBolt(Location location, double max, double gap, int arc, boolean doDamage) { - int id = ID; - BOLTS.put(id, new Bolt(this, location, id, max, gap, arc, doDamage)); - if (ID == Integer.MAX_VALUE) - ID = Integer.MIN_VALUE; - ID++; - } - - private void displayCharging() { - Location fake = player.getLocation().add(0, 0, 0); - fake.setPitch(0); - for (int i = -180; i < 180; i += 55) { - fake.setYaw(i); - for (double j = -180; j <= 180; j += 55) { - if (rand.nextInt(100) == 0) { - Location temp = fake.clone(); - Vector dir = fake.getDirection().clone().multiply(1.2 * Math.cos(Math.toRadians(j))); - temp.add(dir); - temp.setY(temp.getY() + 1.2 + (1.2 * Math.sin(Math.toRadians(j)))); - dir = GeneralMethods.getDirection(temp, player.getLocation().add(0, 1, 0)); - spawnBolt(temp.setDirection(dir), 1, 0.2, 20, false); - } - } - } - } - - public static void progressAll() { - BOLTS.values().forEach(Bolt::progress); - } - - public boolean isCharging() { - return !charged; - } - - public void setCharging(boolean charging) { - this.charged = !charging; - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "LightningBurst"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Fire.LightningBurst.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getAvatarCooldown() { - return avatarCooldown; - } - - public void setAvatarCooldown(long avatarCooldown) { - this.avatarCooldown = avatarCooldown; - } - - public long getChargeUp() { - return chargeUp; - } - - public void setChargeUp(long chargeUp) { - this.chargeUp = chargeUp; - } - - public long getAvatarChargeup() { - return avatarChargeup; - } - - public void setAvatarChargeup(long avatarChargeup) { - this.avatarChargeup = avatarChargeup; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getRadius() { - return radius; - } - - public void setRadius(double radius) { - this.radius = radius; - } - - public boolean isCharged() { - return charged; - } - - public void setCharged(boolean charged) { - this.charged = charged; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Fire.LightningBurst.Enabled"); - } - - public class Bolt { - - private final LightningBurst ability; - private Location location; - private final float initYaw; - private final float initPitch; - private double step; - private final double max; - private final double gap; - private final int id; - private final int arc; - private final boolean doDamage; - - public Bolt(LightningBurst ability, Location location, int id, double max, double gap, int arc, boolean doDamage) { - this.ability = ability; - this.location = location; - this.id = id; - this.max = max; - this.arc = arc; - this.gap = gap; - this.doDamage = doDamage; - initYaw = location.getYaw(); - initPitch = location.getPitch(); - } - - private void progress() { - if (this.step >= max) { - BOLTS.remove(id); - return; - } - if (RegionProtection.isRegionProtected(player, location, LightningBurst.this) || !isTransparent(location.getBlock())) { - BOLTS.remove(id); - return; - } - double step = 0.2; - for (double i = 0; i < gap; i+= step) { - this.step += step; - location = location.add(location.getDirection().clone().multiply(step)); - - playLightningbendingParticle(location, 0f, 0f, 0f); - JCMethods.emitLight(location); - } - switch (rand.nextInt(3)) { - case 0: - location.setYaw(initYaw - arc); - break; - case 1: - location.setYaw(initYaw + arc); - break; - default: - location.setYaw(initYaw); - break; - } - switch (rand.nextInt(3)) { - case 0: - location.setPitch(initPitch - arc); - break; - case 1: - location.setPitch(initPitch + arc); - break; - default: - location.setPitch(initPitch); - break; - } - - if (rand.nextInt(soundInterval) == 0) { - location.getWorld().playSound(location, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); - } - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && doDamage) { - DamageHandler.damageEntity(entity, damage, ability); - } - } - } - - public LightningBurst getAbility() { - return ability; - } - - public Location getLocation() { - return location; - } - - public float getInitYaw() { - return initYaw; - } - - public float getInitPitch() { - return initPitch; - } - - public double getStep() { - return step; - } - - public double getMax() { - return max; - } - - public double getGap() { - return gap; - } - - public int getId() { - return id; - } - - public int getArc() { - return arc; - } - - public boolean isDoDamage() { - return doDamage; - } - } -} \ No newline at end of file diff --git a/src/ability/waterbending/BloodPuppet.java b/src/ability/waterbending/BloodPuppet.java deleted file mode 100644 index 6e3bf14..0000000 --- a/src/ability/waterbending/BloodPuppet.java +++ /dev/null @@ -1,511 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import java.util.*; - -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.region.RegionProtection; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.*; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.BloodAbility; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.util.DamageHandler; - -public class BloodPuppet extends BloodAbility implements AddonAbility { - - private boolean nightOnly; - private boolean fullMoonOnly; - private boolean undeadMobs; - private boolean bloodPuppetThroughBlocks; - private boolean requireBound; - private int distance; - @Attribute(Attribute.DURATION) - private long holdTime; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - private long endTime; - - public LivingEntity puppet; - private long lastDamageTime = 0; - - Random rand = new Random(); - - public BloodPuppet(Player player) { - super(player); - if (!isEligible(player, true)) { - return; - } - - setFields(); - endTime = System.currentTimeMillis() + holdTime; - - if (grab()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - nightOnly = config.getBoolean("Abilities.Water.BloodPuppet.NightOnly"); - fullMoonOnly = config.getBoolean("Abilities.Water.BloodPuppet.FullMoonOnly"); - undeadMobs = config.getBoolean("Abilities.Water.BloodPuppet.UndeadMobs"); - bloodPuppetThroughBlocks = config.getBoolean("Abilities.Water.BloodPuppet.IgnoreWalls"); - requireBound = config.getBoolean("Abilities.Water.BloodPuppet.RequireBound"); - distance = config.getInt("Abilities.Water.BloodPuppet.Distance"); - holdTime = config.getLong("Abilities.Water.BloodPuppet.HoldTime"); - cooldown = config.getLong("Abilities.Water.BloodPuppet.Cooldown"); - } - - public boolean isEligible(Player player, boolean hasAbility) { - if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, BloodPuppet.class))) { - return false; - } - if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { - return false; - } - return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); - } - - private boolean canAttack() { - switch (puppet.getType()) { - case SKELETON: - case SPIDER: - case GIANT: - case ZOMBIE: - case SLIME: - case GHAST: - case PIGLIN: - case ZOMBIFIED_PIGLIN: - case ENDERMAN: - case CAVE_SPIDER: - case SILVERFISH: - case BLAZE: - case MAGMA_CUBE: - case WITCH: - case ENDERMITE: - case DROWNED: - case PLAYER: - return true; - default: - return false; - } - } - - private boolean grab() { - List entities = new ArrayList<>(); - for (int i = 1; i < distance; i++) { - Location location; - if (bloodPuppetThroughBlocks) { - location = player.getTargetBlock(null, i).getLocation(); - } else { - location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); - } - entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); - entities.remove(player); - if (!entities.isEmpty() && !entities.contains(player)) { - break; - } - } - if (entities.isEmpty()) { - return false; - } - Entity e = entities.get(0); - - if (e == null) - return false; - - if (!(e instanceof LivingEntity)) - return false; - - if (!undeadMobs && GeneralMethods.isUndead(e)) - return false; - - if ((e instanceof Player) && !canBeBloodbent((Player) e)) { - return false; - } - if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { - return false; - } - - for (BloodPuppet bb : getAbilities(BloodPuppet.class)) { - if (bb.puppet.getEntityId() == e.getEntityId()) { - return false; - } - } - - puppet = (LivingEntity) e; - DamageHandler.damageEntity(puppet, 0, this); - if (puppet instanceof Creature) - ((Creature) puppet).setTarget(null); - - if (e instanceof Player && BendingPlayer.getBendingPlayer((Player) e) != null) { - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer((Player) e); - bPlayer.blockChi(); - } - - return true; - } - - private boolean canBeBloodbent(Player player) { - if (Commands.invincible.contains(player.getName())) { - return false; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (requireBound) { - if (bPlayer.getAbilities().containsValue("Bloodbending")) { - return false; - } - return !bPlayer.getAbilities().containsValue("BloodPuppet"); - } else { - if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { - return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); - } - } - return true; - } - - public static void attack(Player player) { - if (hasAbility(player, BloodPuppet.class)) { - getAbility(player, BloodPuppet.class).attack(); - } - } - - private void attack() { - if (!canAttack()) - return; - - long damageCd = 0; - if (System.currentTimeMillis() > lastDamageTime + damageCd) { - lastDamageTime = System.currentTimeMillis(); - - if (puppet instanceof Skeleton) { - Skeleton skelly = (Skeleton) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(skelly.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); - Arrow a = puppet.getWorld().spawnArrow(loc, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()), 0.6f, 12); - a.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else if (puppet instanceof Creeper) { - Creeper creep = (Creeper) puppet; - creep.setPowered(true); - } - - else if (puppet instanceof Ghast) { - Ghast gaga = (Ghast) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(gaga.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); - Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); - fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.25)); - fb.setIsIncendiary(true); - fb.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else if (puppet instanceof Blaze) { - Blaze balawalaze = (Blaze) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(balawalaze.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); - Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); - fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.5)); - fb.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else if (puppet instanceof Witch) { - Witch missmagus = (Witch) puppet; - List nearby = GeneralMethods.getEntitiesAroundPoint(missmagus.getLocation(), 5); - nearby.remove(puppet); - if (nearby.size() < 1) - return; - int randy = rand.nextInt(nearby.size()); - Entity target = nearby.get(randy); - if (target instanceof LivingEntity) { - LivingEntity e = (LivingEntity) target; - ThrownPotion tp = missmagus.launchProjectile(ThrownPotion.class, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation())); - ItemStack potionItem = new ItemStack(Material.SPLASH_POTION, 1); - PotionMeta potion = (PotionMeta) potionItem.getItemMeta(); - potion.setBasePotionType(JedCore.plugin.getPotionEffectAdapter().getHarmingPotionType()); - potionItem.setItemMeta(potion); - tp.setItem(potionItem); - tp.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.125)); - tp.setShooter(puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - - else { - for (Entity e : GeneralMethods.getEntitiesAroundPoint(puppet.getLocation(), 2)) { - if (e.getEntityId() == puppet.getEntityId()) - continue; - - if (e instanceof LivingEntity) { - int damage = 2; - if (puppet instanceof Player) { - Player p = (Player) puppet; - - switch (p.getInventory().getItemInMainHand().getType()) { - case WOODEN_SWORD: - case GOLDEN_SWORD: - damage = 5; - break; - case STONE_SWORD: - damage = 6; - break; - case IRON_SWORD: - damage = 7; - break; - case DIAMOND_SWORD: - damage = 8; - break; - default: - break; - } - } - ((LivingEntity) e).damage(damage, puppet); - if (e instanceof Creature) - ((Creature) e).setTarget(puppet); - } - } - } - } - } - - @Override - public void progress() { - if (player == null || !player.isOnline() || player.isDead()) { - remove(); - return; - } - if (!isEligible(player, false)) { - remove(); - return; - } - - if (!player.isSneaking()) { - remove(); - return; - } - - if (System.currentTimeMillis() > endTime) { - remove(); - return; - } - - if ((puppet instanceof Player && !((Player) puppet).isOnline()) || puppet.isDead()) { - remove(); - return; - } - - Location newLocation = puppet.getLocation(); - - Location location = GeneralMethods.getTargetedLocation(player, distance + 1); - double distance = location.distance(newLocation); - double dx, dy, dz; - dx = location.getX() - newLocation.getX(); - dy = location.getY() - newLocation.getY(); - dz = location.getZ() - newLocation.getZ(); - Vector vector = new Vector(dx, dy, dz); - if (distance > .5) { - puppet.setVelocity(vector.normalize().multiply(.5)); - } else { - puppet.setVelocity(new Vector(0, 0, 0)); - } - puppet.setFallDistance(0); - if (puppet instanceof Creature) { - ((Creature) puppet).setTarget(null); - } - AirAbility.breakBreathbendingHold(puppet); - } - - @Override - public void remove() { - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - if (puppet instanceof Player && ((Player) puppet).isOnline()) { - BendingPlayer.getBendingPlayer((Player) puppet).unblockChi(); - } - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "BloodPuppet"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.BloodPuppet.Description"); - } - - public boolean isNightOnly() { - return nightOnly; - } - - public void setNightOnly(boolean nightOnly) { - this.nightOnly = nightOnly; - } - - public boolean isFullMoonOnly() { - return fullMoonOnly; - } - - public void setFullMoonOnly(boolean fullMoonOnly) { - this.fullMoonOnly = fullMoonOnly; - } - - public boolean isUndeadMobs() { - return undeadMobs; - } - - public void setUndeadMobs(boolean undeadMobs) { - this.undeadMobs = undeadMobs; - } - - public boolean canBloodPuppetThroughBlocks() { - return bloodPuppetThroughBlocks; - } - - public void setCanBloodPuppetThroughBlocks(boolean bloodPuppetThroughBlocks) { - this.bloodPuppetThroughBlocks = bloodPuppetThroughBlocks; - } - - public boolean requiresBound() { - return requireBound; - } - - public void setRequireBound(boolean requireBound) { - this.requireBound = requireBound; - } - - public int getDistance() { - return distance; - } - - public void setDistance(int distance) { - this.distance = distance; - } - - public long getHoldTime() { - return holdTime; - } - - public void setHoldTime(long holdTime) { - this.holdTime = holdTime; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; - } - - public LivingEntity getPuppet() { - return puppet; - } - - public void setPuppet(LivingEntity puppet) { - this.puppet = puppet; - } - - public long getLastDamageTime() { - return lastDamageTime; - } - - public void setLastDamageTime(long lastDamageTime) { - this.lastDamageTime = lastDamageTime; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.BloodPuppet.Enabled"); - } -} diff --git a/src/ability/waterbending/BloodShot.java b/src/ability/waterbending/BloodShot.java deleted file mode 100644 index ea1ef6a..0000000 --- a/src/ability/waterbending/BloodShot.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BloodAbility; -import com.projectkorra.projectkorra.util.DamageHandler; -import org.bukkit.*; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; -import org.bukkit.Particle.DustTransition; - -import java.util.List; - -import static java.lang.Thread.sleep; - -public class BloodShot extends BloodAbility implements AddonAbility { - - private static final String path = "ExtraAbilities.Hihelloy.BloodShot."; - - private long cooldown; - private double damage; - private int range; - private double hitRadius; - private double selfDamage; - private double speed; - - private Location origin; - private Vector direction; - - public BloodShot(Player player) { - super(player); - - if (!bPlayer.canBend(this) || bPlayer.isOnCooldown(this)) return; - - setFieldsFromConfig(); - DamageHandler.damageEntity(player, selfDamage, this); - this.origin = player.getEyeLocation().clone(); - this.direction = origin.getDirection().normalize(); - - bPlayer.addCooldown(this); - start(); - - launchWave(); - } - - private void setFieldsFromConfig() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - cooldown = config.getLong(path + "Cooldown"); - damage = config.getDouble(path + "Damage"); - range = config.getInt(path + "Range"); - hitRadius = config.getDouble(path + "Hitradius"); - selfDamage = config.getDouble(path + "SelfDamage"); - speed = config.getDouble(path + "Speed"); - } - - public void launchWave() { - // Schedule task using Folia-safe method - Bukkit.getGlobalRegionScheduler().run(JedCore.plugin, scheduledTask -> { - Location current = origin.clone(); - DustTransition dust = new DustTransition(Color.RED, Color.RED, 1.2F); - - for (int i = 0; i < range; i++) { - current.add(direction.clone().multiply(speed)); - - // Check if ability is still active - if (!this.bPlayer.canBend(this) || !player.isOnline() || player.isDead()) { - remove(); - return; - } - - Location particleLoc = current.clone(); - - // Execute particle and hit detection on main thread - Bukkit.getScheduler().runTask(JedCore.plugin, () -> { - World world = particleLoc.getWorld(); - if (world == null) return; - - world.spawnParticle(Particle.DUST_COLOR_TRANSITION, particleLoc, 10, 0.2, 0.2, 0.2, 0, dust); - world.playSound(particleLoc, Sound.ENTITY_PLAYER_ATTACK_STRONG, 1.0f, 2f); - - List entities = GeneralMethods.getEntitiesAroundPoint(particleLoc, hitRadius); - for (Entity entity : entities) { - if (entity instanceof LivingEntity && !entity.equals(player)) { - DamageHandler.damageEntity(entity, damage, this); - entity.setFireTicks(0); - remove(); - } - } - }); - - // Delay between iterations (speed can be adjusted here) - try { - sleep(10); // ~1 tick - } catch (InterruptedException ignored) {} - } - - // Clean up after loop ends - Bukkit.getScheduler().runTask(JedCore.plugin, this::remove); - }); - } - - // Required AddonAbility metadata - @Override public String getName() { return "BloodShot"; } - @Override public String getInstructions() { return "Left-click to fire a blood energy wave."; } - @Override public String getDescription() { - return "An ability that fires a wave of blood energy to damage opponents, but hurts you as well."; - } - @Override public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean(path + "Enabled"); - } - @Override public long getCooldown() { return cooldown; } - @Override public boolean isSneakAbility() { return false; } - @Override public boolean isHarmlessAbility() { return false; } - @Override public void progress() {} // Not used in instant abilities - @Override public void load() {} - @Override public void stop() {} - @Override public String getAuthor() { return "Hihelloy"; } - @Override public String getVersion() { return "1.0"; } - @Override public Location getLocation() { return origin; } - - @Override - public void remove() { - super.remove(); - } -} diff --git a/src/ability/waterbending/Bloodbending.java b/src/ability/waterbending/Bloodbending.java deleted file mode 100644 index 5c2e122..0000000 --- a/src/ability/waterbending/Bloodbending.java +++ /dev/null @@ -1,377 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.ThrownEntityTracker; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.BloodAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.DamageHandler; - -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.*; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class Bloodbending extends BloodAbility implements AddonAbility { - - private boolean nightOnly; - private boolean fullMoonOnly; - private boolean undeadMobs; - private boolean bloodbendingThroughBlocks; - private boolean requireBound; - private int distance; - @Attribute(Attribute.DURATION) - private long holdTime; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - - private long time; - public LivingEntity victim; - private BendingPlayer victimBPlayer; - private boolean grabbed; - - public Bloodbending(Player player) { - super(player); - if (this.player == null || !isEligible(player, true)) { - return; - } - setFields(); - time = System.currentTimeMillis() + holdTime; - if (grab()) { - start(); - } - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - nightOnly = config.getBoolean("Abilities.Water.Bloodbending.NightOnly"); - fullMoonOnly = config.getBoolean("Abilities.Water.Bloodbending.FullMoonOnly"); - undeadMobs = config.getBoolean("Abilities.Water.Bloodbending.UndeadMobs"); - bloodbendingThroughBlocks = config.getBoolean("Abilities.Water.Bloodbending.IgnoreWalls"); - requireBound = config.getBoolean("Abilities.Water.Bloodbending.RequireBound"); - distance = config.getInt("Abilities.Water.Bloodbending.Distance"); - holdTime = config.getLong("Abilities.Water.Bloodbending.HoldTime"); - cooldown = config.getLong("Abilities.Water.Bloodbending.Cooldown"); - } - - public boolean isEligible(Player player, boolean hasAbility) { - if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, Bloodbending.class))) { - return false; - } - if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { - return false; - } - return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); - } - - public static void launch(Player player) { - if (hasAbility(player, Bloodbending.class)) { - getAbility(player, Bloodbending.class).launch(); - } - } - - private void launch() { - if (Arrays.asList(ElementalAbility.getTransparentMaterials()).contains(player.getEyeLocation().getBlock().getType())) { - Vector direction = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, 20, ElementalAbility.getTransparentMaterials())).normalize().multiply(3); - if (!victim.isDead()) { - victim.setVelocity(direction); - - new HorizontalVelocityTracker(victim, player, 200L, this); - new ThrownEntityTracker(this, victim, player, 200L); - } - remove(); - } - } - - private boolean grab() { - List entities = new ArrayList<>(); - for (int i = 1; i < distance; i++) { - Location location; - if (bloodbendingThroughBlocks) { - location = player.getTargetBlock(null, i).getLocation(); - } else { - location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); - } - entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); - entities.remove(player); - - if (!entities.isEmpty() && !entities.contains(player)) { - break; - } - } - if (entities.isEmpty()) { - return false; - } - Entity e = entities.get(0); - if (e == null) { - return false; - } - if (!(e instanceof LivingEntity)) { - return false; - } - if (e instanceof ArmorStand) { - return false; - } - if (!undeadMobs && GeneralMethods.isUndead(e)) { - return false; - } - if ((e instanceof Player) && !canBeBloodbent((Player) e)) { - return false; - } - if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { - return false; - } - for (Bloodbending bb : getAbilities(Bloodbending.class)) { - if (bb.victim.getEntityId() == e.getEntityId()) { - return false; - } - } - - victim = (LivingEntity) e; - DamageHandler.damageEntity(victim, 0, this); - HorizontalVelocityTracker.remove(victim); - if (victim instanceof Creature) { - ((Creature) victim).setTarget(null); - } - if ((e instanceof Player) && BendingPlayer.getBendingPlayer((Player) e) != null) { - victimBPlayer = BendingPlayer.getBendingPlayer((Player) e); - } - return true; - } - - private boolean canBeBloodbent(Player player) { - if (Commands.invincible.contains(player.getName())) { - return false; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (requireBound) { - if (bPlayer.getAbilities().containsValue("Bloodbending")) { - return false; - } - return !bPlayer.getAbilities().containsValue("BloodPuppet"); - } else { - if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { - return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); - } - } - return true; - } - - @Override - public void progress() { - if (!isEligible(player, false)) { - remove(); - return; - } - if (!grabbed) { - if (victim instanceof Player && victimBPlayer != null) { - victimBPlayer.blockChi(); - grabbed = true; - } - } - - if (!player.isSneaking()) { - remove(); - return; - } - if (!player.isOnline() || player.isDead()) { - remove(); - return; - } - if (System.currentTimeMillis() > time) { - remove(); - return; - } - if (victim.isDead()) { - remove(); - return; - } - if ((victim instanceof Player) && !((Player) victim).isOnline()) { - remove(); - return; - } - Location oldLocation = victim.getLocation(); - Location loc = GeneralMethods.getTargetedLocation(player, (int) player.getLocation().distance(oldLocation)); - double distance = loc.distance(oldLocation); - Vector v = GeneralMethods.getDirection(oldLocation, GeneralMethods.getTargetedLocation(player, 10)); - if (distance > 1.2D) { - victim.setVelocity(v.normalize().multiply(0.8D)); - } else { - victim.setVelocity(new Vector(0, 0, 0)); - } - victim.setFallDistance(0.0F); - if (victim instanceof Creature) { - ((Creature) victim).setTarget(null); - } - AirAbility.breakBreathbendingHold(victim); - } - - @Override - public void remove() { - if (player.isOnline()) { - bPlayer.addCooldown(this); - } - if (victim instanceof Player && victimBPlayer != null) { - victimBPlayer.unblockChi(); - } - super.remove(); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "Bloodbending"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.Bloodbending.Description"); - } - - public boolean isNightOnly() { - return nightOnly; - } - - public void setNightOnly(boolean nightOnly) { - this.nightOnly = nightOnly; - } - - public boolean isFullMoonOnly() { - return fullMoonOnly; - } - - public void setFullMoonOnly(boolean fullMoonOnly) { - this.fullMoonOnly = fullMoonOnly; - } - - public boolean isUndeadMobs() { - return undeadMobs; - } - - public void setUndeadMobs(boolean undeadMobs) { - this.undeadMobs = undeadMobs; - } - - public boolean isBloodbendingThroughBlocks() { - return bloodbendingThroughBlocks; - } - - public void setBloodbendingThroughBlocks(boolean bloodbendingThroughBlocks) { - this.bloodbendingThroughBlocks = bloodbendingThroughBlocks; - } - - public boolean isRequireBound() { - return requireBound; - } - - public void setRequireBound(boolean requireBound) { - this.requireBound = requireBound; - } - - public int getDistance() { - return distance; - } - - public void setDistance(int distance) { - this.distance = distance; - } - - public long getHoldTime() { - return holdTime; - } - - public void setHoldTime(long holdTime) { - this.holdTime = holdTime; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public LivingEntity getVictim() { - return victim; - } - - public void setVictim(LivingEntity victim) { - this.victim = victim; - } - - public BendingPlayer getVictimBPlayer() { - return victimBPlayer; - } - - public void setVictimBPlayer(BendingPlayer victimBPlayer) { - this.victimBPlayer = victimBPlayer; - } - - public boolean isGrabbed() { - return grabbed; - } - - public void setGrabbed(boolean grabbed) { - this.grabbed = grabbed; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.Bloodbending.Enabled"); - } -} diff --git a/src/ability/waterbending/Drain.java b/src/ability/waterbending/Drain.java deleted file mode 100644 index ea33485..0000000 --- a/src/ability/waterbending/Drain.java +++ /dev/null @@ -1,605 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ElementalAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.util.WaterReturn; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.Levelled; -import org.bukkit.block.data.Waterlogged; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; - -public class Drain extends WaterAbility implements AddonAbility { - - private final List locations = new ArrayList<>(); - static final Set WATER_TEMPS = new HashSet<>(); - - //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. - private static float MAX_TEMP = 1.0F; - private static float MIN_HUMIDITY = 0.01F; - - private long regenDelay; - @Attribute(Attribute.DURATION) - private long duration; // 2000 - @Attribute(Attribute.COOLDOWN) - private long cooldown; // 2000 - private double absorbSpeed; // 0.1 - @Attribute(Attribute.RADIUS) - private int radius; // 6 - @Attribute("Chance") - private int chance; // 20 - private int absorbRate; // 6 - private int holdRange; // 2 - private boolean blastsEnabled; // true - private int maxBlasts; - private boolean keepSrc; // false - private boolean useRain; - private boolean usePlants; - - private double blastRange; // 20 - private double blastDamage; // 1.5 - private double blastSpeed; // 2 - - private boolean drainTemps; - - private long endTime; - private int absorbed = 0; - private int charge = 7; - private boolean noFill; - private int blasts; - private boolean hasCharge; - private final Material[] fillables = { Material.GLASS_BOTTLE, Material.BUCKET }; - - Random rand = new Random(); - - public Drain(Player player) { - super(player); - if (!bPlayer.canBend(this) || hasAbility(player, Drain.class)) { - return; - } - setFields(); - this.usePlants = bPlayer.canPlantbend(); - endTime = System.currentTimeMillis() + duration; - if (!canFill()) { - if (!blastsEnabled) - return; - noFill = true; - } - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - regenDelay = config.getLong("Abilities.Water.Drain.RegenDelay"); - duration = config.getLong("Abilities.Water.Drain.Duration"); - cooldown = config.getLong("Abilities.Water.Drain.Cooldown"); - absorbSpeed = config.getDouble("Abilities.Water.Drain.AbsorbSpeed"); - radius = config.getInt("Abilities.Water.Drain.Radius"); - chance = config.getInt("Abilities.Water.Drain.AbsorbChance"); - absorbRate = config.getInt("Abilities.Water.Drain.AbsorbRate"); - holdRange = config.getInt("Abilities.Water.Drain.HoldRange"); - blastsEnabled = config.getBoolean("Abilities.Water.Drain.BlastsEnabled"); - maxBlasts = config.getInt("Abilities.Water.Drain.MaxBlasts"); - keepSrc = config.getBoolean("Abilities.Water.Drain.KeepSource"); - blastRange = config.getDouble("Abilities.Water.Drain.BlastRange"); - blastDamage = config.getDouble("Abilities.Water.Drain.BlastDamage"); - blastSpeed = config.getDouble("Abilities.Water.Drain.BlastSpeed"); - useRain = config.getBoolean("Abilities.Water.Drain.AllowRainSource"); - drainTemps = config.getBoolean("Abilities.Water.Drain.DrainTempBlocks"); - - applyModifiers(); - } - - private void applyModifiers() { - if (isNight(player.getWorld())) { - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - blastRange = getNightFactor(blastRange); - blastDamage = getNightFactor(blastDamage); - } - } - - @Override - public void progress() { - if (player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (!noFill) { - if (!player.isSneaking()) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (!canFill()) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (System.currentTimeMillis() > endTime) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (absorbed >= absorbRate) { - fill(); - absorbed = 0; - } - checkForValidSource(); - } else { - if (blasts >= maxBlasts) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (player.isSneaking()) { - if (charge >= 2) { - checkForValidSource(); - } - if (absorbed >= absorbRate) { - hasCharge = true; - absorbed = 0; - if (charge >= 3) { - charge -= 2; - } - } - } else if (!hasCharge || !keepSrc) { - bPlayer.addCooldown(this); - remove(); - return; - } - if (hasCharge) { - displayWaterSource(); - } - } - dragWater(); - } - - public static void fireBlast(Player player) { - if (hasAbility(player, Drain.class)) { - getAbility(player, Drain.class).fireBlast(); - } - } - - private void fireBlast() { - if (charge <= 1) { - hasCharge = false; - charge = 7; - blasts++; - new DrainBlast(player, blastRange, blastDamage, blastSpeed, holdRange); - } - } - - private void displayWaterSource() { - Location location = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)); - Block block = location.getBlock(); - if (!GeneralMethods.isSolid(block) || isTransparent(block)) { - TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(charge)), 100L); - WATER_TEMPS.add(tb); - tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); - } - } - - private boolean canFill() { - for (ItemStack items : player.getInventory()) { - if (items != null && Arrays.asList(fillables).contains(items.getType())) { - return true; - } - } - return false; - } - - private void fill() { - for (int x = 0; x < absorbed; x++) { - for (Material fillable : fillables) { - int slot = player.getInventory().first(fillable); - if (slot == -1){ - continue; - } - if (player.getInventory().getItem(slot).getAmount() > 1) { - player.getInventory().getItem(slot).setAmount(player.getInventory().getItem(slot).getAmount() - 1); - - ItemStack filled = getFilled(fillable); - HashMap cantfit = player.getInventory().addItem(filled); - for (int id : cantfit.keySet()) { - player.getWorld().dropItem(player.getEyeLocation(), cantfit.get(id)); - } - } else { - player.getInventory().setItem(slot, getFilled(fillable)); - } - break; - } - } - } - - private ItemStack getFilled(Material type) { - ItemStack filled = null; - if (type == Material.GLASS_BOTTLE) { - filled = WaterReturn.waterBottleItem(); - } else if (type == Material.BUCKET) { - filled = new ItemStack(Material.WATER_BUCKET, 1); - } - - return filled; - } - - private void checkForValidSource() { - List locs = GeneralMethods.getCircle(player.getLocation(), radius, radius, false, true, 0); - for (int i = 0; i < locs.size(); i++) { - Block block = locs.get(rand.nextInt(locs.size()-1)).getBlock(); - if (rand.nextInt(chance) == 0) { - Location pLoc = player.getLocation(); - World world = pLoc.getWorld(); - double temp = world.getTemperature(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); - double humidity = world.getHumidity(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); - if (block.getY() > world.getMinHeight() && block.getY() < world.getMaxHeight()) { - Location bLoc = block.getLocation(); - if (useRain && world.hasStorm() && !(temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { - if (pLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { - if (bLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { - locations.add(bLoc.clone().add(.5, .5, .5)); - return; - } - } - } - if (usePlants && JCMethods.isSmallPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { - drainPlant(block); - } else if (usePlants && ElementalAbility.isPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { - locations.add(bLoc.clone().add(.5, .5, .5)); - new TempBlock(block, Material.AIR.createBlockData(), regenDelay); - } else if (isWater(block)) { - TempBlock tb = TempBlock.get(block); - if ((tb == null || (drainTemps && !WATER_TEMPS.contains(tb)))) { - drainWater(block); - } - } - } - } - } - } - - private boolean isObstructed(Location location1, Location location2) { - Vector loc1 = location1.toVector(); - Vector loc2 = location2.toVector(); - - Vector direction = loc2.subtract(loc1); - direction.normalize(); - - Location loc; - - double max = location1.distance(location2); - - for (double i = 1; i <= max; i++) { - loc = location1.clone().add(direction.clone().multiply(i)); - if (!isTransparent(loc.getBlock())) - return true; - } - - return false; - } - - private void drainPlant(Block block) { - if (JCMethods.isSmallPlant(block)) { - if (JCMethods.isSmallPlant(block.getRelative(BlockFace.DOWN))) { - if (JCMethods.isDoublePlant(block.getType())) { - block = block.getRelative(BlockFace.DOWN); - locations.add(block.getLocation().clone().add(.5, .5, .5)); - new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); - return; - } - block = block.getRelative(BlockFace.DOWN); - } - locations.add(block.getLocation().clone().add(.5, .5, .5)); - new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); - } - } - - private void drainWater(Block block) { - if (isTransparent(block.getRelative(BlockFace.UP)) && !isWater(block.getRelative(BlockFace.UP))) { - locations.add(block.getLocation().clone().add(.5, .5, .5)); - if (block.getBlockData() instanceof Waterlogged) { - new TempBlock(block, block.getType().createBlockData(bd -> ((Waterlogged) bd).setWaterlogged(false)), regenDelay); - } else { - TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(1)), regenDelay); - WATER_TEMPS.add(tb); - tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); - } - } - } - - private void dragWater() { - List toRemove = new ArrayList<>(); - if (!locations.isEmpty()) { - for (Location l : locations) { - Location playerLoc = player.getLocation().add(0, 1, 0); - if (noFill) - playerLoc = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)).subtract(0, .8, 0); - Vector dir = GeneralMethods.getDirection(l, playerLoc); - l = l.add(dir.multiply(absorbSpeed)); - ParticleEffect.WATER_SPLASH.display(l, 1, 0, 0, 0, 0); - GeneralMethods.displayColoredParticle("0099FF", l); - if (l.distance(playerLoc) < 1) { - toRemove.add(locations.indexOf(l)); - absorbed++; - } - } - } - if (!toRemove.isEmpty()) { - for (int i : toRemove) { - if (i < locations.size()) - locations.remove(i); - } - toRemove.clear(); - } - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "Drain"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.Drain.Description"); - } - - @Override - public List getLocations() { - return locations; - } - - public long getRegenDelay() { - return regenDelay; - } - - public void setRegenDelay(long regenDelay) { - this.regenDelay = regenDelay; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public double getAbsorbSpeed() { - return absorbSpeed; - } - - public void setAbsorbSpeed(double absorbSpeed) { - this.absorbSpeed = absorbSpeed; - } - - public int getRadius() { - return radius; - } - - public void setRadius(int radius) { - this.radius = radius; - } - - public int getChance() { - return chance; - } - - public void setChance(int chance) { - this.chance = chance; - } - - public int getAbsorbRate() { - return absorbRate; - } - - public void setAbsorbRate(int absorbRate) { - this.absorbRate = absorbRate; - } - - public int getHoldRange() { - return holdRange; - } - - public void setHoldRange(int holdRange) { - this.holdRange = holdRange; - } - - public boolean isBlastsEnabled() { - return blastsEnabled; - } - - public void setBlastsEnabled(boolean blastsEnabled) { - this.blastsEnabled = blastsEnabled; - } - - public int getMaxBlasts() { - return maxBlasts; - } - - public void setMaxBlasts(int maxBlasts) { - this.maxBlasts = maxBlasts; - } - - public boolean isKeepSrc() { - return keepSrc; - } - - public void setKeepSrc(boolean keepSrc) { - this.keepSrc = keepSrc; - } - - public boolean isUseRain() { - return useRain; - } - - public void setUseRain(boolean useRain) { - this.useRain = useRain; - } - - public boolean isUsePlants() { - return usePlants; - } - - public void setUsePlants(boolean usePlants) { - this.usePlants = usePlants; - } - - public double getBlastRange() { - return blastRange; - } - - public void setBlastRange(double blastRange) { - this.blastRange = blastRange; - } - - public double getBlastDamage() { - return blastDamage; - } - - public void setBlastDamage(double blastDamage) { - this.blastDamage = blastDamage; - } - - public double getBlastSpeed() { - return blastSpeed; - } - - public void setBlastSpeed(double blastSpeed) { - this.blastSpeed = blastSpeed; - } - - public boolean isDrainTemps() { - return drainTemps; - } - - public void setDrainTemps(boolean drainTemps) { - this.drainTemps = drainTemps; - } - - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; - } - - public int getAbsorbed() { - return absorbed; - } - - public void setAbsorbed(int absorbed) { - this.absorbed = absorbed; - } - - public int getCharge() { - return charge; - } - - public void setCharge(int charge) { - this.charge = charge; - } - - public boolean isNoFill() { - return noFill; - } - - public void setNoFill(boolean noFill) { - this.noFill = noFill; - } - - public int getBlasts() { - return blasts; - } - - public void setBlasts(int blasts) { - this.blasts = blasts; - } - - public boolean isHasCharge() { - return hasCharge; - } - - public void setHasCharge(boolean hasCharge) { - this.hasCharge = hasCharge; - } - - public Material[] getFillables() { - return fillables; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.Drain.Enabled"); - } -} diff --git a/src/ability/waterbending/FrostBreath.java b/src/ability/waterbending/FrostBreath.java deleted file mode 100644 index 9a2ab0f..0000000 --- a/src/ability/waterbending/FrostBreath.java +++ /dev/null @@ -1,440 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.command.Commands; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.IceAbility; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -public class FrostBreath extends IceAbility implements AddonAbility { - - private static final List INVALID_MATERIALS = new ArrayList(){{ - addAll(Arrays.asList( - Material.ICE, - Material.LAVA, - Material.AIR, - Material.VOID_AIR, - Material.CAVE_AIR)); - if (GeneralMethods.getMCVersion() >= 1170) { - add(Material.getMaterial("LIGHT")); - } - }}; - - //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. - private static float MAX_TEMP = 1.0F; - private static float MIN_HUMIDITY = 0.01F; - - public Config config; - - private State state; - private final List frozenBlocks = new ArrayList<>(); - - public FrostBreath(Player player) { - super(player); - - if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { - return; - } - - this.config = new Config(player); - this.state = new BeamState(); - - double temp = player.getLocation().getWorld().getTemperature(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); - double humidity = player.getLocation().getWorld().getHumidity(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); - - if (config.restrictBiomes && (temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { - return; - } - - start(); - } - - @Override - public void progress() { - if (!state.update()) { - remove(); - } - - long time = System.currentTimeMillis(); - - frozenBlocks.removeIf(frozen -> { - if (time >= frozen.endTime) { - removeFrozenBlock(frozen.tempBlock); - frozen.tempBlock.revertBlock(); - return true; - } - - return false; - }); - } - - @Override - public void remove() { - super.remove(); - - frozenBlocks.forEach(fb -> { - removeFrozenBlock(fb.tempBlock); - fb.tempBlock.revertBlock(); - }); - frozenBlocks.clear(); - } - - @Override - public long getCooldown() { - return config.cooldown; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "FrostBreath"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.FrostBreath.Description"); - } - - public static List getInvalidMaterials() { - return INVALID_MATERIALS; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - public List getFrozenBlocks() { - return frozenBlocks; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.FrostBreath.Enabled"); - } - - private void addFrozenBlock(TempBlock tempBlock) { - PhaseChange.getFrozenBlocksMap().put(tempBlock, player); - } - - private void removeFrozenBlock(TempBlock tempBlock) { - PhaseChange.getFrozenBlocksMap().remove(tempBlock); - } - - private interface State { - boolean update(); - } - - private class BeamState implements State { - @Override - public boolean update() { - if (player == null || !player.isOnline()) { - return transition(); - } - - if (!bPlayer.canBendIgnoreCooldowns(FrostBreath.this)) { - return transition(); - } - - if (!player.isSneaking() || player.isDead()) { - return transition(); - } - - if (System.currentTimeMillis() >= getStartTime() + config.duration) { - return transition(); - } - - createBeam(); - - return true; - } - - private boolean transition() { - state = new SnowMeltingState(); - - return true; - } - - private boolean isLocationSafe(Location loc) { - Block block = loc.getBlock(); - - if (RegionProtection.isRegionProtected(player, loc, FrostBreath.this)) { - return false; - } - - return isTransparent(block); - } - - private boolean isFreezable(Location location, Entity entity) { - if (RegionProtection.isRegionProtected(FrostBreath.this, location)) { - return false; - } - - if (entity instanceof Player && Commands.invincible.contains(entity.getName())) { - return false; - } - - return !location.getBlock().getType().isSolid(); - } - - private void createBeam() { - Location loc = player.getEyeLocation(); - Vector dir = player.getLocation().getDirection(); - double step = 1; - double size = 0; - double offset = 0; - double damageRegion = 1.5; - - for (double i = 0; i < config.range; i += step) { - loc = loc.add(dir.clone().multiply(step)); - size += 0.005; - offset += 0.3; - damageRegion += 0.01; - - if (!isLocationSafe(loc)) - return; - - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { - for (Location cageLocation : createCage(entity.getLocation())) { - if (isFreezable(cageLocation, entity)) { - Block block = cageLocation.getBlock(); - - updateFrozenBlock(block, Material.ICE, config.freezeDuration); - } - } - - if (config.slowEnabled) { - ((LivingEntity) entity).addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect((int) config.slowDuration, 5)); - } - - if (config.damageEnabled) { - if (entity instanceof Player) { - DamageHandler.damageEntity(entity, config.playerDamage, FrostBreath.this); - } else { - DamageHandler.damageEntity(entity, config.mobDamage, FrostBreath.this); - } - } - } - } - - if (config.snowEnabled) { - freezeGround(loc); - } - - ParticleEffect.SNOW_SHOVEL.display(loc, config.particles, Math.random(), Math.random(), Math.random(), size); - - JCMethods.displayColoredParticles("#DCDCDC", loc, 1, Math.random(), Math.random(), Math.random(), 0.003f); - JCMethods.displayColoredParticles("#9696FF", loc, 1, Math.random(), Math.random(), Math.random(), 0.0035f); - } - } - - private Location getOffsetLocation(Location loc, double offset) { - return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); - } - - private void freezeGround(Location loc) { - for (Location l : GeneralMethods.getCircle(loc, 2, 2, false, true, 0)) { - if (!RegionProtection.isRegionProtected(player, l, FrostBreath.this)) { - Block block = l.getBlock(); - - if (isWater(l.getBlock())) { - updateFrozenBlock(block, Material.ICE, config.frozenWaterDuration); - } else if (isTransparent(l.getBlock()) && l.clone().add(0, -1, 0).getBlock().getType().isSolid() && !INVALID_MATERIALS.contains(l.clone().add(0, -1, 0).getBlock().getType())) { - if (config.bendSnow) { - updateFrozenBlock(block, Material.SNOW, config.snowDuration); - } else { - TempBlock current = TempBlock.get(block); - - // Refresh any existing TempBlock so the timer resets. - if (current != null) { - current.revertBlock(); - } - - TempBlock tempBlock = new TempBlock(block, Material.SNOW.createBlockData()); - tempBlock.setRevertTime(config.snowDuration); - } - } - } - } - } - - private void updateFrozenBlock(Block block, Material type, long duration) { - // Store the TempBlock as a FrozenBlock block so it can be reverted later. - for (FrozenBlock fb : frozenBlocks) { - if (fb.tempBlock.getBlock().equals(block)) { - if (fb.tempBlock.getBlockData().getMaterial() != type) { - // Completely overwrite this FrozenBlock if the new type doesn't match the old one. - removeFrozenBlock(fb.tempBlock); - fb.tempBlock.revertBlock(); - frozenBlocks.remove(fb); - break; - } - - fb.endTime = System.currentTimeMillis() + duration; - return; - } - } - - TempBlock tempBlock = new TempBlock(block, type.createBlockData()); - - frozenBlocks.add(new FrozenBlock(tempBlock, System.currentTimeMillis() + duration)); - - // Add the TempBlock to a ProjectKorra block list so it can be used as a water source. - // I don't believe there exists a way to make a TempBlock water bendable right now, so this - // is a hack to make it work. - addFrozenBlock(tempBlock); - } - - private List createCage(Location centerBlock) { - List selectedBlocks = new ArrayList<>(); - - int bX = centerBlock.getBlockX(); - int bY = centerBlock.getBlockY(); - int bZ = centerBlock.getBlockZ(); - - for (int x = bX - 1; x <= bX + 1; x++) { - for (int y = bY - 1; y <= bY + 1; y++) { - Location l = new Location(centerBlock.getWorld(), x, y, bZ); - selectedBlocks.add(l); - } - } - - for (int y = bY - 1; y <= bY + 2; y++) { - Location l = new Location(centerBlock.getWorld(), bX, y, bZ); - selectedBlocks.add(l); - } - - for (int z = bZ - 1; z <= bZ + 1; z++) { - for (int y = bY - 1; y <= bY + 1; y++) { - Location l = new Location(centerBlock.getWorld(), bX, y, z); - selectedBlocks.add(l); - } - } - - for (int x = bX - 1; x <= bX + 1; x++) { - for (int z = bZ - 1; z <= bZ + 1; z++) { - Location l = new Location(centerBlock.getWorld(), x, bY, z); - selectedBlocks.add(l); - } - } - - return selectedBlocks; - } - } - - // Wait for the frozen blocks to melt and remove it from bendable water list. - private class SnowMeltingState implements State { - SnowMeltingState() { - bPlayer.addCooldown(FrostBreath.this); - } - - @Override - public boolean update() { - return !frozenBlocks.isEmpty(); - } - } - - private static class FrozenBlock { - TempBlock tempBlock; - long endTime; - - FrozenBlock(TempBlock tempBlock, long endTime) { - this.tempBlock = tempBlock; - this.endTime = endTime; - } - } - - public static class Config { - long cooldown; - long duration; - int particles; - int freezeDuration; - int snowDuration; - int frozenWaterDuration; - int range; - boolean snowEnabled; - boolean bendSnow; - boolean damageEnabled; - double playerDamage; - double mobDamage; - boolean slowEnabled; - long slowDuration; - boolean restrictBiomes; - - Config(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - - cooldown = config.getLong("Abilities.Water.FrostBreath.Cooldown"); - duration = config.getLong("Abilities.Water.FrostBreath.Duration"); - particles = config.getInt("Abilities.Water.FrostBreath.Particles"); - freezeDuration = config.getInt("Abilities.Water.FrostBreath.FrostDuration"); - snowDuration = config.getInt("Abilities.Water.FrostBreath.SnowDuration"); - frozenWaterDuration = config.getInt("Abilities.Water.FrostBreath.FrozenWaterDuration"); - range = config.getInt("Abilities.Water.FrostBreath.Range"); - snowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Snow"); - bendSnow = config.getBoolean("Abilities.Water.FrostBreath.BendableSnow"); - damageEnabled = config.getBoolean("Abilities.Water.FrostBreath.Damage.Enabled"); - playerDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Player"); - mobDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Mob"); - slowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Slow.Enabled"); - slowDuration = config.getLong("Abilities.Water.FrostBreath.Slow.Duration"); - restrictBiomes = config.getBoolean("Abilities.Water.FrostBreath.RestrictBiomes"); - } - } -} diff --git a/src/ability/waterbending/HealingWaters.java b/src/ability/waterbending/HealingWaters.java deleted file mode 100644 index c5aa09f..0000000 --- a/src/ability/waterbending/HealingWaters.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.util.LightManager; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.HealingAbility; -import com.projectkorra.projectkorra.chiblocking.Smokescreen; -import com.projectkorra.projectkorra.region.RegionProtection; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -import com.projectkorra.projectkorra.waterbending.util.WaterReturn; -import org.bukkit.*; -import org.bukkit.block.Block; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Damageable; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Random; - -public class HealingWaters extends HealingAbility implements AddonAbility { - - private static long time = 0; - private static boolean enabled = true; - - public HealingWaters(Player player) { - super(player); - } - - public static void heal(Server server) { - if (enabled) { - if (System.currentTimeMillis() - time >= 1000) { - time = System.currentTimeMillis(); - for (Player player : server.getOnlinePlayers()) { - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer != null && bPlayer.canBend(getAbility("HealingWaters"))) { - heal(player); - } - } - } - } - } - - @SuppressWarnings("deprecation") - private static void heal(Player player) { - if (inWater(player)) { - if (player.isSneaking()) { - Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); - if (entity instanceof LivingEntity && inWater(entity)) { - Location playerLoc = entity.getLocation(); - playerLoc.add(0, 1, 0); - JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHPToEntity((LivingEntity) entity); - emitLight(playerLoc); - emitLight(entity.getLocation()); - } - } else { - Location playerLoc = player.getLocation(); - playerLoc.add(0, 1, 0); - JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHP(player); - emitLight(playerLoc); - } - - } else if(hasWaterSupply(player) && player.isSneaking()) { - Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); - if (entity != null) { - if (entity instanceof LivingEntity) { - Damageable dLe = (Damageable) entity; - if (dLe.getHealth() < dLe.getMaxHealth()) { - Location playerLoc = entity.getLocation(); - playerLoc.add(0, 1, 0); - JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHPToEntity((LivingEntity) entity); - entity.setFireTicks(0); - Random rand = new Random(); - if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); - emitLight(playerLoc); - emitLight(entity.getLocation()); - } - } - } else { - Location playerLoc = player.getLocation(); - playerLoc.add(0, 1, 0); - - JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); - JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f); - - ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); - giveHP(player); - player.setFireTicks(0); - Random rand = new Random(); - if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); - emitLight(playerLoc); - } - } - } - - @SuppressWarnings("deprecation") - private static void giveHPToEntity(LivingEntity le) { - if (!le.isDead() && le.getHealth() < le.getMaxHealth()) { - applyHealingToEntity(le); - } - for (PotionEffect effect : le.getActivePotionEffects()) { - if (isNegativeEffect(effect.getType())) { - le.removePotionEffect(effect.getType()); - } - } - } - - private static void giveHP(Player player){ - if (!player.isDead() && player.getHealth() < 20) { - applyHealing(player); - } - for(PotionEffect effect : player.getActivePotionEffects()) { - if(isNegativeEffect(effect.getType())) { - if((effect.getType() == PotionEffectType.BLINDNESS) && Smokescreen.getBlindedTimes().containsKey(player.getName())) { - return; - } - player.removePotionEffect(effect.getType()); - } - } - } - - - - private static boolean inWater(Entity entity) { - Block block = entity.getLocation().getBlock(); - return isWater(block) && !TempBlock.isTempBlock(block); - } - - private static boolean hasWaterSupply(Player player){ - ItemStack heldItem = player.getInventory().getItemInMainHand(); - return (heldItem.isSimilar(WaterReturn.waterBottleItem()) || heldItem.getType() == Material.WATER_BUCKET); - - } - - private static void drainWaterSupply(Player player){ - ItemStack heldItem = player.getInventory().getItemInMainHand(); - ItemStack emptyBottle = new ItemStack(Material.GLASS_BOTTLE, 1); - if (heldItem.isSimilar(WaterReturn.waterBottleItem())) { - if (heldItem.getAmount() > 1) { - heldItem.setAmount(heldItem.getAmount() - 1); - HashMap cantFit = player.getInventory().addItem(emptyBottle); - for (int id : cantFit.keySet()) { - player.getWorld().dropItem(player.getEyeLocation(), cantFit.get(id)); - } - } else { - player.getInventory().setItemInMainHand(emptyBottle); - } - } - } - - @SuppressWarnings("deprecation") - private static void applyHealing(Player player) { - if (!RegionProtection.isRegionProtected(player, player.getLocation(), "HealingWaters")) - if(player.getHealth() < player.getMaxHealth()) { - player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, getPower(player))); - AirAbility.breakBreathbendingHold(player); - } - } - - @SuppressWarnings("deprecation") - private static void applyHealingToEntity(LivingEntity le) { - if (le.getHealth() < le.getMaxHealth()) { - le.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, 1)); - AirAbility.breakBreathbendingHold(le); - } - } - - public static int getPower(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - return config.getInt("Abilities.Water.HealingWaters.Power"); - } - - public static double getRange(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - return config.getDouble("Abilities.Water.HealingWaters.Range"); - } - - public static int getDrainChance(Player player) { - ConfigurationSection config = JedCoreConfig.getConfig(player); - return config.getInt("Abilities.Water.HealingWaters.DrainChance"); - } - - public static void emitLight(Location loc) { - ConfigurationSection config = JedCoreConfig.getConfig((Player)null); - if (config.getBoolean("Abilities.Water.HealingWaters.DynamicLight.Enabled")) { - int brightness = config.getInt("Abilities.Water.HealingWaters.DynamicLight.Brightness"); - long keepAlive = config.getLong("Abilities.Water.HealingWaters.DynamicLight.KeepAlive"); - - LightManager.createLight(loc).brightness(brightness).timeUntilFadeout(keepAlive).emit(); - } - } - - @Override - public long getCooldown() { - return 0; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public String getName() { - return "HealingWaters"; - } - - @Override - public boolean isHarmlessAbility() { - return true; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.HealingWaters.Description"); - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - enabled = config.getBoolean("Abilities.Water.HealingWaters.Enabled"); - return enabled; - } - - @Override - public void progress() {} -} \ No newline at end of file diff --git a/src/ability/waterbending/IceClaws.java b/src/ability/waterbending/IceClaws.java deleted file mode 100644 index e211317..0000000 --- a/src/ability/waterbending/IceClaws.java +++ /dev/null @@ -1,299 +0,0 @@ -package com.jedk1.jedcore.ability.waterbending; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.ability.firebending.FirePunch; -import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.IceAbility; -import com.projectkorra.projectkorra.attribute.Attribute; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; - -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.MainHand; -import org.bukkit.potion.PotionEffectType; - -public class IceClaws extends IceAbility implements AddonAbility { - - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.CHARGE_DURATION) - private long chargeUp; - private int slowDur; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.RANGE) - private double range; - private boolean throwable; - - private Location head; - private Location origin; - private boolean launched; - - private Boolean iceInMainHand = null; - - public IceClaws(Player player) { - super(player); - if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { - return; - } - - if (hasAbility(player, IceClaws.class)) { - IceClaws ic = getAbility(player, IceClaws.class); - if (!ic.throwable) { - ic.remove(); - } - return; - } - - setFields(); - start(); - } - - public void setFields() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - - cooldown = config.getLong("Abilities.Water.IceClaws.Cooldown"); - chargeUp = config.getLong("Abilities.Water.IceClaws.ChargeTime"); - slowDur = config.getInt("Abilities.Water.IceClaws.SlowDuration")/50; - damage = config.getDouble("Abilities.Water.IceClaws.Damage"); - range = config.getDouble("Abilities.Water.IceClaws.Range"); - throwable = config.getBoolean("Abilities.Water.IceClaws.Throwable"); - - applyModifiers(); - } - - private void applyModifiers() { - cooldown -= ((long) getNightFactor(cooldown) - cooldown); - damage = getNightFactor(damage); - range = getNightFactor(range); - } - - @Override - public void progress() { - if (player == null || player.isDead() || !player.isOnline()) { - remove(); - return; - } - if (!bPlayer.canBendIgnoreCooldowns(this)) { - remove(); - return; - } - if (System.currentTimeMillis() > getStartTime() + chargeUp) { - if (!launched && throwable) { - displayClaws(); - } else { - if (!shoot()) { - remove(); - } - } - } else if (player.isSneaking()) { - displayChargeUp(); - } else { - remove(); - } - } - - - public static void swapHands(Player player) { - IceClaws ic = getAbility(player, IceClaws.class); - if (ic == null) - return; - if (ic.iceInMainHand == null) - ic.iceInMainHand = true; - else ic.iceInMainHand = !ic.iceInMainHand; - } - - public Location getRightHandPos() { - return (player.getMainHand() == MainHand.RIGHT == ((iceInMainHand == null) || iceInMainHand) ? - GeneralMethods.getRightSide(player.getLocation(), .55) : - GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); - } - - public boolean shoot() { - for (double i = 0; i < 1; i+=.5) { - head.add(origin.clone().getDirection().multiply(.5)); - if (origin.distance(head) >= range) return false; - if (!isTransparent(head.getBlock())) return false; - GeneralMethods.displayColoredParticle("66FFFF", head); - GeneralMethods.displayColoredParticle("CCFFFF", head); - ParticleEffect.SNOW_SHOVEL.display(head, 1, 0, 0, 0, 0); - for (Entity entity : GeneralMethods.getEntitiesAroundPoint(head, 1.5)) { - if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { - freezeEntity((LivingEntity) entity); - return false; - } - } - } - return true; - - } - - public static void throwClaws(Player player) { - if (hasAbility(player, IceClaws.class)) { - IceClaws ic = getAbility(player, IceClaws.class); - if (!ic.launched && player.isSneaking()) { - ic.launched = true; - ic.origin = ic.player.getEyeLocation(); - ic.head = ic.origin.clone(); - } - } - } - - private void displayClaws() { - Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); - GeneralMethods.displayColoredParticle("66FFFF", location); - GeneralMethods.displayColoredParticle("CCFFFF", location); - } - - private void displayChargeUp() { - Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); - ParticleEffect.WATER_SPLASH.display(location, 1, Math.random()/3, Math.random()/3, Math.random()/3, 0.0); - } - - public static boolean freezeEntity(Player player, LivingEntity entity) { - if (hasAbility(player, IceClaws.class)) { - getAbility(player, IceClaws.class).freezeEntity(entity); - return true; - } - return false; - } - - private void freezeEntity(LivingEntity entity) { - if (entity.hasPotionEffect(PotionEffectType.SPEED)) { - entity.removePotionEffect(PotionEffectType.SPEED); - } - // todo: doesnt seem to be affecting mobs? frostbreath does. - entity.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect(slowDur, 3)); - bPlayer.addCooldown(this); - remove(); - DamageHandler.damageEntity(entity, damage, this); - } - - @Override - public long getCooldown() { - return cooldown; - } - - @Override - public Location getLocation() { - return head; - } - - @Override - public String getName() { - return "IceClaws"; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public String getAuthor() { - return JedCore.dev; - } - - @Override - public String getVersion() { - return JedCore.version; - } - - @Override - public String getDescription() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return "* JedCore Addon *\n" + config.getString("Abilities.Water.IceClaws.Description"); - } - - public void setCooldown(long cooldown) { - this.cooldown = cooldown; - } - - public long getChargeUp() { - return chargeUp; - } - - public void setChargeUp(long chargeUp) { - this.chargeUp = chargeUp; - } - - public int getSlowDuration() { - return slowDur; - } - - public void setSlowDuration(int slowDuration) { - this.slowDur = slowDuration; - } - - public double getDamage() { - return damage; - } - - public void setDamage(double damage) { - this.damage = damage; - } - - public double getRange() { - return range; - } - - public void setRange(double range) { - this.range = range; - } - - public boolean isThrowable() { - return throwable; - } - - public void setThrowable(boolean throwable) { - this.throwable = throwable; - } - - public Location getHead() { - return head; - } - - public void setHead(Location head) { - this.head = head; - } - - public Location getOrigin() { - return origin; - } - - public void setOrigin(Location origin) { - this.origin = origin; - } - - public boolean isLaunched() { - return launched; - } - - public void setLaunched(boolean launched) { - this.launched = launched; - } - - @Override - public void load() {} - - @Override - public void stop() {} - - @Override - public boolean isEnabled() { - ConfigurationSection config = JedCoreConfig.getConfig(this.player); - return config.getBoolean("Abilities.Water.IceClaws.Enabled"); - } -} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/JCManager.java b/src/com/jedk1/jedcore/JCManager.java new file mode 100644 index 0000000..be8b8bc --- /dev/null +++ b/src/com/jedk1/jedcore/JCManager.java @@ -0,0 +1,29 @@ +package com.jedk1.jedcore; + +import com.jedk1.jedcore.ability.earthbending.EarthPillar; +import com.jedk1.jedcore.ability.firebending.LightningBurst; +import com.jedk1.jedcore.ability.waterbending.HealingWaters; +import com.jedk1.jedcore.ability.waterbending.IcePassive; +import com.jedk1.jedcore.ability.waterbending.IceWall; +import com.jedk1.jedcore.util.RegenTempBlock; +import org.bukkit.Bukkit; + +public class JCManager implements Runnable { + + public JedCore plugin; + + public JCManager(JedCore plugin) { + this.plugin = plugin; + } + + public void run() { + LightningBurst.progressAll(); + + HealingWaters.heal(Bukkit.getServer()); + IcePassive.handleSkating(); + IceWall.progressAll(); + EarthPillar.progressAll(); + + RegenTempBlock.manage(); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/JCMethods.java b/src/com/jedk1/jedcore/JCMethods.java new file mode 100644 index 0000000..590d3cf --- /dev/null +++ b/src/com/jedk1/jedcore/JCMethods.java @@ -0,0 +1,356 @@ +package com.jedk1.jedcore; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.FireTick; +import com.jedk1.jedcore.util.LightManagerUtil; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ProjectKorra; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class JCMethods { + + // todo: either use PKs isPlant or the registry/tags (with config) + private static final ArrayList SMALL_PLANTS = new ArrayList(){{ + addAll(Arrays.asList(Material.GRASS, Material.FERN, Material.POPPY, Material.DANDELION, Material.OAK_SAPLING, + Material.SPRUCE_SAPLING, Material.BIRCH_SAPLING, Material.JUNGLE_SAPLING, Material.ACACIA_SAPLING, + Material.DARK_OAK_SAPLING, Material.ALLIUM, Material.ORANGE_TULIP, Material.PINK_TULIP, Material.RED_TULIP, + Material.WHITE_TULIP, Material.ROSE_BUSH, Material.BLUE_ORCHID, Material.LILAC, Material.OXEYE_DAISY, + Material.AZURE_BLUET, Material.PEONY, Material.SUNFLOWER, Material.LARGE_FERN, Material.RED_MUSHROOM, + Material.BROWN_MUSHROOM, Material.PUMPKIN_STEM, Material.MELON_STEM, Material.WHEAT, Material.TALL_GRASS, + Material.BEETROOTS, Material.CARROTS, Material.POTATOES, Material.CRIMSON_FUNGUS, Material.WARPED_FUNGUS, + Material.BAMBOO, Material.BAMBOO_SAPLING)); + + int serverVersion = GeneralMethods.getMCVersion(); + if (serverVersion >= 1170) { + add(Material.getMaterial("AZALEA")); + add(Material.getMaterial("FLOWERING_AZALEA")); + add(Material.getMaterial("FLOWERING_AZALEA_LEAVES")); + add(Material.getMaterial("AZALEA_LEAVES")); + add(Material.getMaterial("BIG_DRIPLEAF")); + add(Material.getMaterial("BIG_DRIPLEAF_STEM")); + add(Material.getMaterial("SMALL_DRIPLEAF")); + add(Material.getMaterial("HANGING_ROOTS")); + add(Material.getMaterial("GLOW_LICHEN")); + add(Material.getMaterial("CAVE_VINES")); + add(Material.getMaterial("CAVE_VINES_PLANT")); + } + }}; + + private static List worlds = new ArrayList<>(); + private static List combos = new ArrayList<>(); + + public static List getDisabledWorlds() { + return JCMethods.worlds; + } + + public static void registerDisabledWorlds() { + worlds.clear(); + List registeredworlds = ProjectKorra.plugin.getConfig().getStringList("Properties.DisabledWorlds"); + if (!registeredworlds.isEmpty()) { + worlds.addAll(registeredworlds); + } + } + + public static boolean isDisabledWorld(World world) { + return getDisabledWorlds().contains(world.getName()); + } + + public static List getCombos() { + return JCMethods.combos; + } + + public static void registerCombos() { + combos.clear(); + combos.addAll(ComboManager.getComboAbilities().keySet()); + } + + /** + * Gets the points of a line between two points. + * @param startLoc + * @param endLoc + * @param points + * @return locations + */ + public static List getLinePoints(Location startLoc, Location endLoc, int points){ + List locations = new ArrayList(); + Location diff = endLoc.subtract(startLoc); + double diffX = diff.getX() / points; + double diffY = diff.getY() / points; + double diffZ = diff.getZ() / points; + Location loc = startLoc; + for(int i = 0; i < points; i++){ + loc.add(new Location(startLoc.getWorld(), diffX, diffY, diffZ)); + locations.add(loc.clone()); + } + return locations; + } + + public static List getCirclePoints(Location location, int points, double size) { + return getCirclePoints(location, points, size, 0); + } + + /** + * Gets points in a circle. + * @param location + * @param points + * @param size + * @return + */ + public static List getCirclePoints(Location location, int points, double size, double startangle){ + List locations = new ArrayList(); + for(int i = 0; i < 360; i += 360/points){ + double angle = (i * Math.PI / 180); + double x = size * Math.cos(angle + startangle); + double z = size * Math.sin(angle + startangle); + Location loc = location.clone(); + loc.add(x, 0, z); + locations.add(loc); + } + return locations; + } + + /** + * Gets points in a vertical circle. + * @param location + * @param points + * @param size + * @param yawOffset + * @return + */ + public static List getVerticalCirclePoints(Location location, int points, double size, float yawOffset) { + List locations = new ArrayList<>(); + Location fakeLoc = location.clone(); + fakeLoc.setPitch(0); + fakeLoc.setYaw(yawOffset); + Vector direction = fakeLoc.getDirection(); + + for(double j = -180; j <= 180; j += points){ + Location tempLoc = fakeLoc.clone(); + Vector newDir = direction.clone().multiply(size * Math.cos(Math.toRadians(j))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + size + (size * Math.sin(Math.toRadians(j)))); + locations.add(tempLoc.clone()); + } + return locations; + } + + /** + * Remove an item from a players inventory. + * @param player + * @param material + * @param amount + * @return + */ + public static boolean removeItemFromInventory(Player player, Material material, int amount) { + for (ItemStack item : player.getInventory().getContents()) { + if (item != null && item.getType() == material) { + if (item.getAmount() == amount) { + Map remaining = player.getInventory().removeItem(item); + + if (!remaining.isEmpty()) { + ItemStack offhand = player.getInventory().getItemInOffHand(); + + // Spigot seems to not handle offhand correctly with removeItem, so try to manually remove it. + if (offhand != null && offhand.getType() == material && offhand.getAmount() == amount) { + player.getInventory().setItemInOffHand(null); + } + } + } else if (item.getAmount() > amount) { + item.setAmount(item.getAmount() - amount); + } + + return true; + } + } + + return false; + } + + /** + * Gets points in a spiral shape. + * @param location + * @param points + * @param spiralCount + * @param startAngle + * @param startSize + * @param finalSize + * @param noClip + * @return + */ + public static List getSpiralPoints(Location location, int points, int spiralCount, int startAngle, double startSize, double finalSize, boolean noClip){ + return getSpiralPoints(location, points, spiralCount, 0.0D, startAngle, startSize, finalSize, noClip); + } + + /** + * Gets points in a vertical spiral shape, could be used for a tornado. + * @param location + * @param points + * @param spiralCount + * @param height + * @param startAngle + * @param startSize + * @param finalSize + * @param noClip + * @return + */ + public static List getSpiralPoints(Location location, int points, int spiralCount, double height, int startAngle, double startSize, double finalSize, boolean noClip){ + List locations = new ArrayList(); + + points = points/spiralCount; + double sizeIncr = ((finalSize - startSize) / points)/spiralCount; + double hightIncr = (height/points)/spiralCount; + double size = startSize; + for(int i = 0; i < spiralCount; i++){ + for(int j = 0; j < 360; j += 360/points){ + hightIncr = hightIncr + ((height/points)/spiralCount); + size = size + sizeIncr; + double angle = (j * Math.PI / 180); + double x = size * Math.cos(angle + startAngle); + double z = size * Math.sin(angle + startAngle); + Location loc = location.clone(); + loc.add(x, hightIncr, z); + if(!noClip && ElementalAbility.isAir(loc.getBlock().getType())) + locations.add(loc); + else if(noClip) + locations.add(loc); + } + } + + return locations; + } + + public static void extinguishBlocks(Player player, String ability, int range, int radius, boolean fire, boolean lava){ + for (Block block : GeneralMethods.getBlocksAroundPoint(player.getTargetBlock(null, range).getLocation(), radius)) { + Material mat = block.getType(); + if(mat != Material.FIRE && mat != Material.LAVA && mat != Material.SOUL_FIRE) + continue; + if (RegionProtection.isRegionProtected(player, block.getLocation(), ability)) + continue; + if (((mat == Material.FIRE || mat == Material.SOUL_FIRE) && fire)||(mat == Material.LAVA && lava)) { + block.setType(mat != Material.LAVA ? Material.AIR : isLiquidSource(block) ? Material.OBSIDIAN : Material.COBBLESTONE); + block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0); + } + } + } + + /** + * Checks if 3 blocks around the block are of the required type. + * @param block + * @param type + * @return + */ + public static boolean isAdjacentToThreeOrMoreSources(Block block, Material type) { + if (TempBlock.isTempBlock(block)) { + return false; + } + int sources = 0; + BlockFace[] faces = { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN }; + for (BlockFace face : faces) { + Block blocki = block.getRelative(face); + if ((blocki.getType() == type)) { + sources++; + } + } + if (sources >= 2) + return true; + return false; + } + + static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, + Material.NETHER_PORTAL, Material.END_PORTAL, + Material.END_PORTAL_FRAME, Material.OBSIDIAN}; + + public static boolean isUnbreakable(Block block) { + if (block.getState() instanceof InventoryHolder) { + return true; + } + if (Arrays.asList(unbreakables).contains(block.getType())) + return true; + return false; + } + + public static boolean isLiquidSource(Block block) { + if (!block.isLiquid()) { + return false; + } + + if (!(block.getBlockData() instanceof Levelled)) { + return false; + } + + Levelled levelData = (Levelled) block.getBlockData(); + + return levelData.getLevel() == 0; + } + + // TODO: Should this be reimplemented or has the rpg plugin been abandoned? + public static boolean isSozinsComet(World world) { + return false; + } + + // TODO: Should this be reimplemented or has the rpg plugin been abandoned? + public static boolean isLunarEclipse(World world) { + return false; + } + + // todo: see SMALL_PLANTS + public static boolean isDoublePlant(Material material) { + return material == Material.SUNFLOWER || material == Material.LILAC || material == Material.TALL_GRASS || + material == Material.LARGE_FERN || material == Material.ROSE_BUSH || material == Material.PEONY; + } + + public static boolean isSmallPlant(Block block) { + return isSmallPlant(block.getType()); + } + + public static boolean isSmallPlant(Material material) { + return WaterAbility.isPlant(material); + //return SMALL_PLANTS.contains(material); + } + + public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra) { + displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, 255); + } + + public static void displayColoredParticles(String hex, Location location, int amount, double offsetX, double offsetY, double offsetZ, double extra, int alpha) { + JedCore.plugin.getParticleAdapter().displayColoredParticles(hex, location, amount, offsetX, offsetY, offsetZ, extra, alpha); + } + + public static void emitLight(Location loc) { + LightManagerUtil.emitFirebendingLight(loc); + } + + public static void reload() { + JedCore.log.info("JedCore Reloaded."); + JedCore.plugin.reloadConfig(); + JedCore.logDebug = JedCoreConfig.getConfig((World)null).getBoolean("Properties.LogDebug"); + CoreAbility.registerPluginAbilities(JedCore.plugin, "com.jedk1.jedcore.ability"); + registerDisabledWorlds(); + registerCombos(); + RegenTempBlock.revertAll(); + JedCore.plugin.initializeCollisions(); + FireTick.loadMethod(); + } +} \ No newline at end of file diff --git a/src/JedCore.java b/src/com/jedk1/jedcore/JedCore.java similarity index 82% rename from src/JedCore.java rename to src/com/jedk1/jedcore/JedCore.java index dfebb83..bb065c2 100644 --- a/src/JedCore.java +++ b/src/com/jedk1/jedcore/JedCore.java @@ -1,26 +1,28 @@ package com.jedk1.jedcore; -import java.io.IOException; -import java.util.logging.*; +import com.cjcrafter.foliascheduler.FoliaCompatibility; +import com.cjcrafter.foliascheduler.ServerImplementation; import com.google.common.reflect.ClassPath; -import com.jedk1.jedcore.ability.waterbending.BloodShot; +import com.jedk1.jedcore.util.*; import com.jedk1.jedcore.command.Commands; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.listener.AbilityListener; import com.jedk1.jedcore.listener.CommandListener; import com.jedk1.jedcore.listener.JCListener; -import com.jedk1.jedcore.util.*; +import com.jedk1.jedcore.util.ChiRestrictor; import com.jedk1.jedcore.util.versionadapter.ParticleAdapter; import com.jedk1.jedcore.util.versionadapter.ParticleAdapterFactory; import com.jedk1.jedcore.util.versionadapter.PotionEffectAdapter; import com.jedk1.jedcore.util.versionadapter.PotionEffectAdapterFactory; import com.projectkorra.projectkorra.ability.CoreAbility; - import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.plugin.java.JavaPlugin; +import java.io.IOException; +import java.util.logging.Logger; + public class JedCore extends JavaPlugin { public static JedCore plugin; @@ -31,12 +33,15 @@ public class JedCore extends JavaPlugin { public static boolean isFolia; public static boolean luminol; public static boolean paper; + public static boolean spigot; + public static ServerImplementation scheduler; private ParticleAdapter particleAdapter; private PotionEffectAdapter potionEffectAdapter; @Override public void onEnable() { + scheduler = new FoliaCompatibility(this).getServerImplementation(); plugin = this; log = this.getLogger(); new JedCoreConfig(this); @@ -62,23 +67,22 @@ public void onEnable() { } catch (ClassNotFoundException ignored) {} if (isFolia) { - if (Bukkit.getVersion().contains("Folia")) { getLogger().info("Server is running on Folia"); - } } if (paper) { - if (Bukkit.getVersion().contains("Paper")) { getLogger().info("Server is running on Paper"); - } } if (luminol) { - if (Bukkit.getVersion().contains("Luminol")) { getLogger().info("Server is running on Luminol"); - } } + if (!luminol && !isFolia && !paper) { + spigot = true; + getLogger().info("Server is running on Spigot"); + } + JCMethods.registerDisabledWorlds(); CoreAbility.registerPluginAbilities(this, "com.jedk1.jedcore.ability"); @@ -88,7 +92,7 @@ public void onEnable() { getServer().getPluginManager().registerEvents(new ChiRestrictor(), this); // Repeating logic task - uses ThreadUtil - ThreadUtil.runSyncTimer(new JCManager(this), 0L, 1L); + ThreadUtil.runGlobalTimer(new JCManager(this), 0L, 1L); new Commands(); FireTick.loadMethod(); @@ -97,24 +101,19 @@ public void onEnable() { potionEffectAdapter = new PotionEffectAdapterFactory().getAdapter(); // Delayed combo/collision init - ThreadUtil.runSyncLater(() -> { + ThreadUtil.runGlobalLater(() -> { JCMethods.registerCombos(); initializeCollisions(); }, 1L); - // Optional Metrics - disabled on Folia-like servers - if (!isFolia) { - try { - MetricsLite metrics = new MetricsLite(this); - metrics.start(); - log.info("Initialized Metrics."); - } catch (IOException e) { - log.info("Failed to submit statistics for MetricsLite."); - } - } else { - log.info("Skipping MetricsLite: incompatible with Folia/Luminol."); - } + try { + MetricsLite metrics = new MetricsLite(this); + metrics.start(); + log.info("Initialized Metrics."); + } catch (IOException e) { + log.info("Failed to submit statistics for MetricsLite."); + } } public void initializeCollisions() { @@ -172,4 +171,8 @@ public static boolean isPaper() { public static boolean isLuminol() { return luminol; } + + public static boolean isSpigot() { + return spigot; + } } diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java new file mode 100644 index 0000000..feb1787 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java @@ -0,0 +1,331 @@ +package com.jedk1.jedcore.ability.airbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.*; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class AirBlade extends AirAbility implements AddonAbility { + + private Set cuttableBlocks; + + private Location location; + private Vector direction; + private double travelled; + private boolean blockCuttingEnabled; + private boolean revertCutBlocks; + private long revertTime; + + @Attribute("Growth") + private double growth = 1; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute("CollisionRadius") + private double entityCollisionRadius; + @Attribute(Attribute.SPEED) + private double speed; + @Attribute(Attribute.KNOCKBACK) + private double knockback; + + public AirBlade(Player player) { + super(player); + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + this.location = player.getEyeLocation().clone(); + this.direction = player.getEyeLocation().getDirection().clone(); + + start(); + if (!isRemoved()) + bPlayer.addCooldown(this); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Air.AirBlade.Cooldown"); + range = config.getDouble("Abilities.Air.AirBlade.Range"); + damage = config.getDouble("Abilities.Air.AirBlade.Damage"); + entityCollisionRadius = config.getDouble("Abilities.Air.AirBlade.EntityCollisionRadius"); + speed = config.getDouble("Abilities.Air.AirBlade.Speed"); + knockback = config.getDouble("Abilities.Air.AirBlade.Knockback"); + + ConfigurationSection cuttingConfig = config.getConfigurationSection("Abilities.Air.AirBlade.BlockCutting"); + + blockCuttingEnabled = cuttingConfig.getBoolean("Enabled"); + revertCutBlocks = cuttingConfig.getBoolean("Revert"); + revertTime = cuttingConfig.getLong("RevertTime"); + cuttableBlocks = loadCuttableBlocks(cuttingConfig.getStringList("Materials")); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (travelled >= range) { + remove(); + return; + } + + progressBlade(); + } + + private void progressBlade() { + for (int j = 0; j < 2; j++) { + if (!moveAndCheckCollision()) { + return; + } + + double pitch = -location.getPitch(); + Location lastLoc = location.clone(); + + for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { + Location tempLoc = calculateParticleLocation(i); + playAirbendingParticles(tempLoc, 1, (float) Math.random() / 2, (float) Math.random() / 2, (float) Math.random() / 2); + + if (j == 0 && blockCuttingEnabled && cuttableBlocks.contains(tempLoc.getBlock().getType()) && !RegionProtection.isRegionProtected(this.player, tempLoc)) { + if (revertCutBlocks) { + new TempBlock(tempLoc.getBlock(), Material.AIR.createBlockData(), revertTime); + } else { + tempLoc.getBlock().breakNaturally(); + } + } + + if (j == 0 && !lastLoc.getBlock().getLocation().equals(tempLoc.getBlock().getLocation())) { + if (handleEntityCollision(tempLoc)) { + return; + } + lastLoc = tempLoc; + } + } + } + } + + private boolean moveAndCheckCollision() { + location = location.add(direction.multiply(speed)); + playAirbendingSound(location); + travelled += speed; + growth += 0.125; + + if (travelled >= range || + !isTransparent(location.getBlock()) || + RegionProtection.isRegionProtected(player, player.getLocation(), this)) { + remove(); + return false; + } + return true; + } + + private Location calculateParticleLocation(double angle) { + Location tempLoc = location.clone(); + tempLoc.setPitch(0); + Vector tempDir = tempLoc.getDirection().clone(); + tempDir.setY(0); + Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(angle))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(angle)))); + return tempLoc; + } + + private boolean handleEntityCollision(Location tempLoc) { + return CollisionDetector.checkEntityCollisions(player, new Sphere(tempLoc.toVector(), entityCollisionRadius), entity -> { + DamageHandler.damageEntity(entity, damage, this); + + if (knockback > 0) { + Vector knockDir = entity.getLocation().toVector().subtract(location.toVector()).normalize(); + entity.setVelocity(entity.getVelocity().add(knockDir.multiply(knockback))); + } + + remove(); + return true; + }); + } + + private Set loadCuttableBlocks(List entries) { + Set result = new HashSet<>(); + for (String entry : entries) { + if (entry.startsWith("#")) { + String tagKey = entry.substring(1).toLowerCase(); + NamespacedKey ns = NamespacedKey.minecraft(tagKey); + Tag tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, ns, Material.class); + if (tag != null) tag.getValues().forEach(result::add); + } else { + try { + result.add(Material.valueOf(entry.toUpperCase())); + } catch (IllegalArgumentException ignored) {} + } + } + return result; + } + + @Override + public Player getPlayer() { + return player; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public List getLocations() { + List locations = new ArrayList<>(); + + double pitch = -location.getPitch(); + + for (double i = -90 + pitch; i <= 90 + pitch; i += 8) { + Location tempLoc = location.clone(); + tempLoc.setPitch(0); + + Vector tempDir = tempLoc.getDirection().clone(); + tempDir.setY(0); + + Vector newDir = tempDir.clone().multiply(growth * Math.cos(Math.toRadians(i))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + (growth * Math.sin(Math.toRadians(i)))); + + locations.add(tempLoc); + } + + return locations; + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Air.AirBlade.AbilityCollisionRadius"); + } + + public long getCooldown() { + return cooldown; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + @Override + public String getName() { + return "AirBlade"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Air.AirBlade.Description"); + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getTravelled() { + return travelled; + } + + public void setTravelled(double travelled) { + this.travelled = travelled; + } + + public double getGrowth() { + return growth; + } + + public void setGrowth(double growth) { + this.growth = growth; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Air.AirBlade.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/airbending/AirBreath.java b/src/com/jedk1/jedcore/ability/airbending/AirBreath.java similarity index 100% rename from src/ability/airbending/AirBreath.java rename to src/com/jedk1/jedcore/ability/airbending/AirBreath.java diff --git a/src/ability/airbending/AirGlide.java b/src/com/jedk1/jedcore/ability/airbending/AirGlide.java similarity index 100% rename from src/ability/airbending/AirGlide.java rename to src/com/jedk1/jedcore/ability/airbending/AirGlide.java diff --git a/src/ability/airbending/AirPunch.java b/src/com/jedk1/jedcore/ability/airbending/AirPunch.java similarity index 100% rename from src/ability/airbending/AirPunch.java rename to src/com/jedk1/jedcore/ability/airbending/AirPunch.java diff --git a/src/ability/airbending/Meditate.java b/src/com/jedk1/jedcore/ability/airbending/Meditate.java similarity index 100% rename from src/ability/airbending/Meditate.java rename to src/com/jedk1/jedcore/ability/airbending/Meditate.java diff --git a/src/ability/airbending/SonicBlast.java b/src/com/jedk1/jedcore/ability/airbending/SonicBlast.java similarity index 100% rename from src/ability/airbending/SonicBlast.java rename to src/com/jedk1/jedcore/ability/airbending/SonicBlast.java diff --git a/src/ability/airbending/combo/AirSlam.java b/src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java similarity index 100% rename from src/ability/airbending/combo/AirSlam.java rename to src/com/jedk1/jedcore/ability/airbending/combo/AirSlam.java diff --git a/src/ability/airbending/combo/SwiftStream.java b/src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java similarity index 100% rename from src/ability/airbending/combo/SwiftStream.java rename to src/com/jedk1/jedcore/ability/airbending/combo/SwiftStream.java diff --git a/src/ability/avatar/SpiritBeam.java b/src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java similarity index 100% rename from src/ability/avatar/SpiritBeam.java rename to src/com/jedk1/jedcore/ability/avatar/SpiritBeam.java diff --git a/src/ability/avatar/elementsphere/ESAir.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java similarity index 100% rename from src/ability/avatar/elementsphere/ESAir.java rename to src/com/jedk1/jedcore/ability/avatar/elementsphere/ESAir.java diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java new file mode 100644 index 0000000..05832ec --- /dev/null +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESEarth.java @@ -0,0 +1,215 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; + +import java.util.Arrays; +import java.util.concurrent.ThreadLocalRandom; + +public class ESEarth extends AvatarAbility implements AddonAbility { + + static Material[] unbreakables = { Material.BEDROCK, Material.BARRIER, Material.NETHER_PORTAL, Material.END_PORTAL, + Material.END_PORTAL_FRAME, Material.ENDER_CHEST, Material.CHEST, Material.TRAPPED_CHEST }; + + private TempFallingBlock tfb; + private long revertDelay; + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute("Size") + private int impactSize; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + public ESEarth(Player player) { + super(player); + if (!hasAbility(player, ElementSphere.class)) { + return; + } + ElementSphere currES = getAbility(player, ElementSphere.class); + if (currES.getEarthUses() == 0) { + return; + } + if (bPlayer.isOnCooldown("ESEarth")) { + return; + } + if (RegionProtection.isRegionProtected(this, player.getTargetBlock(getTransparentMaterialSet(), 40).getLocation())) { + return; + } + setFields(); + start(); + if (!isRemoved()) { + bPlayer.addCooldown("ESEarth", getCooldown()); + currES.setEarthUses(currES.getEarthUses() - 1); + Location location = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().multiply(1)); + tfb = new TempFallingBlock(location, Material.DIRT.createBlockData(), location.getDirection().multiply(3), this); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + revertDelay = config.getLong("Abilities.Avatar.ElementSphere.Earth.ImpactRevert"); + damage = config.getDouble("Abilities.Avatar.ElementSphere.Earth.Damage"); + impactSize = config.getInt("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize"); + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Earth.Cooldown"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline()) { + tfb.remove(); + remove(); + return; + } + if (tfb.getFallingBlock().isDead()) { + remove(); + return; + } + if (RegionProtection.isRegionProtected(this, tfb.getLocation())){ + remove(); + return; + } + + EarthAbility.playEarthbendingSound(tfb.getLocation()); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), 2.5)) { + if (entity instanceof LivingEntity && !(entity instanceof ArmorStand) && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player targetPlayer) && Commands.invincible.contains(targetPlayer.getName()))) { + DamageHandler.damageEntity(entity, damage, this); + } + } + } + + // Unused + public static void explodeEarth(TempFallingBlock tempfallingblock) { + FallingBlock fb = tempfallingblock.getFallingBlock(); + ESEarth es = (ESEarth) tempfallingblock.getAbility(); + Player player = es.getPlayer(); + + ParticleEffect.SMOKE_LARGE.display(fb.getLocation(), 0, 0, 0, 0.3F, 25); + fb.getWorld().playSound(fb.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 2f, 0.5f); + + ThreadLocalRandom rand = ThreadLocalRandom.current(); + + for (Location l : GeneralMethods.getCircle(fb.getLocation(), es.impactSize, 1, false, true, 0)) { + if (isBreakable(l.getBlock()) && !RegionProtection.isRegionProtected(player, l, "ElementSphere") && EarthAbility.isEarthbendable(player, l.getBlock())) { + ParticleEffect.SMOKE_LARGE.display(l, 0, 0, 0, 0.1F, 2); + new RegenTempBlock(l.getBlock(), Material.AIR, Material.AIR.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000), false); + } + + if (GeneralMethods.isSolid(l.getBlock().getRelative(BlockFace.DOWN)) && isBreakable(l.getBlock()) && ElementalAbility.isAir(l.getBlock().getType()) && rand.nextInt(20) == 0 && EarthAbility.isEarthbendable(player, l.getBlock().getRelative(BlockFace.DOWN))) { + Material type = l.getBlock().getRelative(BlockFace.DOWN).getType(); + new RegenTempBlock(l.getBlock(), type, type.createBlockData(), rand.nextInt((int) es.revertDelay - (int) (es.revertDelay - 1000)) + (es.revertDelay - 1000)); + } + } + + tempfallingblock.remove(); + } + + public static boolean isBreakable(Block block) { + return !Arrays.asList(unbreakables).contains(block.getType()); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return tfb != null ? tfb.getLocation() : null; + } + + @Override + public String getName() { + return "ElementSphereEarth"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public long getRevertDelay() { + return revertDelay; + } + + public void setRevertDelay(long revertDelay) { + this.revertDelay = revertDelay; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getImpactSize() { + return impactSize; + } + + public void setImpactSize(int impactSize) { + this.impactSize = impactSize; + } + + public TempFallingBlock getTempFallingBlock() { + return tfb; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/avatar/elementsphere/ESFire.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java similarity index 100% rename from src/ability/avatar/elementsphere/ESFire.java rename to src/com/jedk1/jedcore/ability/avatar/elementsphere/ESFire.java diff --git a/src/ability/avatar/elementsphere/ESStream.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java similarity index 100% rename from src/ability/avatar/elementsphere/ESStream.java rename to src/com/jedk1/jedcore/ability/avatar/elementsphere/ESStream.java diff --git a/src/ability/avatar/elementsphere/ESWater.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java similarity index 100% rename from src/ability/avatar/elementsphere/ESWater.java rename to src/com/jedk1/jedcore/ability/avatar/elementsphere/ESWater.java diff --git a/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java new file mode 100644 index 0000000..22e9122 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/avatar/elementsphere/ElementSphere.java @@ -0,0 +1,520 @@ +package com.jedk1.jedcore.ability.avatar.elementsphere; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AvatarAbility; +import com.projectkorra.projectkorra.ability.MultiAbility; +import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; +import com.projectkorra.projectkorra.ability.util.MultiAbilityManager.MultiAbilityInfoSub; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ThreadLocalRandom; + +public class ElementSphere extends AvatarAbility implements AddonAbility, MultiAbility { + + protected static final ConcurrentMap> abilities = new ConcurrentHashMap<>(); + private static final ArrayList multiAbilityInfo = new ArrayList<>(); + + static { + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AIR)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.EARTH)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.FIRE)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.WATER)); + multiAbilityInfo.add(new MultiAbilityInfoSub("", Element.AVATAR)); + } + + private World world; + private int airUses; + private int fireUses; + private int waterUses; + private int earthUses; + private boolean setup; + private Location location; + private double yaw; + private int point; + private long endTime; + private long lastClickTime; + + @Attribute(Attribute.COOLDOWN) + public long cooldown; + @Attribute(Attribute.DURATION) + public long duration; + @Attribute(Attribute.HEIGHT) + private double height; + @Attribute(Attribute.SPEED) + private double speed; + + public ElementSphere(Player player) { + super(player); + + ElementSphere oldES = getAbility(player, ElementSphere.class); + + if (handleExistingSphere(player, oldES)) { + return; + } + + if (canStartNewSphere()) { + initializeNewSphere(player); + } + } + + private boolean handleExistingSphere(Player player, ElementSphere oldES) { + if (oldES != null) { + if (player.isSneaking()) { + oldES.prepareCancel(); + } else { + if (oldES.setup) { + handleElementSwitch(player); + } + } + return true; + } + return false; + } + + private void handleElementSwitch(Player player) { + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + return; + } + + switch (player.getInventory().getHeldItemSlot()) { + case 0: + if (checkPermission(player, "Air")) new ESAir(player); + break; + case 1: + if (checkPermission(player, "Earth")) new ESEarth(player); + break; + case 2: + if (checkPermission(player, "Fire")) new ESFire(player); + break; + case 3: + if (checkPermission(player, "Water")) new ESWater(player); + break; + case 4: + if (checkPermission(player, "Stream")) new ESStream(player); + break; + } + } + + private boolean checkPermission(Player player, String element) { + return player.hasPermission("bending.ability.ElementSphere." + element); + } + + private boolean canStartNewSphere() { + return bPlayer.canBend(this); + } + + private void initializeNewSphere(Player player) { + setFields(); + location = player.getLocation().clone().subtract(0, 1, 0); + world = player.getWorld(); + endTime = System.currentTimeMillis() + duration; + start(); + + if (!isRemoved()) { + bindAndCooldown(player); + enableFlight(player); + checkBoundAbilityName(); + } + } + + private void bindAndCooldown(Player player) { + MultiAbilityManager.bindMultiAbility(player, "ElementSphere"); + bPlayer.addCooldown(this); + } + + private void enableFlight(Player player) { + flightHandler.createInstance(player, this.getName()); + } + + private void checkBoundAbilityName() { + if (ChatColor.stripColor(bPlayer.getBoundAbilityName()) == null) { + remove(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + airUses = config.getInt("Abilities.Avatar.ElementSphere.Air.Uses"); + fireUses = config.getInt("Abilities.Avatar.ElementSphere.Fire.Uses"); + waterUses = config.getInt("Abilities.Avatar.ElementSphere.Water.Uses"); + earthUses = config.getInt("Abilities.Avatar.ElementSphere.Earth.Uses"); + cooldown = config.getLong("Abilities.Avatar.ElementSphere.Cooldown"); + duration = config.getLong("Abilities.Avatar.ElementSphere.Duration"); + height = config.getDouble("Abilities.Avatar.ElementSphere.MaxControlledHeight"); + speed = config.getDouble("Abilities.Avatar.ElementSphere.FlySpeed"); + } + + @Override + public void progress() { + if (!checkPlayerValidity()) { + return; + } + + if (!checkAbilityPrerequisites()) { + return; + } + + if (isDurationOver()) { + remove(); + return; + } + + if (!hasUsableElements()) { + remove(); + return; + } + + handlePlayerMovement(); + handleFlight(); + handleEntityPush(); + updateLocationAndPlayParticles(); + + setup = true; + } + + private boolean checkPlayerValidity() { + return !player.isDead() && player.isOnline() && world == player.getWorld() && !player.getGameMode().equals(GameMode.SPECTATOR); + } + + private boolean checkAbilityPrerequisites() { + return bPlayer.isToggled() && MultiAbilityManager.hasMultiAbilityBound(player, "ElementSphere"); + } + + private boolean isDurationOver() { + return duration > 0 && System.currentTimeMillis() > endTime; + } + + private boolean hasUsableElements() { + return airUses > 0 || fireUses > 0 || waterUses > 0 || earthUses > 0; + } + + private void handlePlayerMovement() { + player.setFallDistance(0); + if (player.isSneaking()) { + player.setVelocity(player.getLocation().getDirection().multiply(speed)); + } + } + + private void handleFlight() { + Block block = getGround(); + if (block != null) { + double dy = player.getLocation().getY() - block.getY(); + if (dy > height) { + removeFlight(); + } else { + allowFlight(); + } + } + } + + private void handleEntityPush() { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.5)) { + if (isPushableEntity(entity)) { + entity.setVelocity(entity.getLocation().toVector().subtract(player.getLocation().toVector()).multiply(1)); + } + } + } + + private boolean isPushableEntity(Entity entity) { + return entity instanceof LivingEntity && + entity.getEntityId() != player.getEntityId() && + !(entity instanceof ArmorStand) && + !RegionProtection.isRegionProtected(player, entity.getLocation(), this); + } + + private void updateLocationAndPlayParticles() { + location = player.getLocation().clone().subtract(0, 1, 0); + playParticles(); + } + + private void allowFlight() { + if (!player.getAllowFlight()) { + player.setAllowFlight(true); + } + if (!player.isFlying()) { + player.setFlying(true); + } + } + + private void removeFlight() { + if (player.getAllowFlight()) { + player.setAllowFlight(false); + } + if (player.isFlying()) { + player.setFlying(false); + } + } + + private Block getGround() { + Block standingblock = player.getLocation().getBlock(); + + for (int i = 0; i <= height + 5; i++) { + Block block = standingblock.getRelative(BlockFace.DOWN, i); + if (GeneralMethods.isSolid(block) || block.isLiquid()) { + return block; + } + } + + return null; + } + + private void playParticles() { + playAirParticles(); + playFireParticles(); + playWaterEarthParticles(); + updatePointCounter(); + } + + private void playAirParticles() { + if (airUses != 0) { + double currentYaw = yaw + 40; + yaw = currentYaw; + Location fakeLoc = createRotatedLocation(location.clone(), 0, currentYaw); + Vector direction = fakeLoc.getDirection(); + for (double j = -180; j <= 180; j += 45) { + Location tempLoc = calculateAirParticleLocation(fakeLoc, direction, j); + displayAirParticle(tempLoc); + } + } + } + + private Location createRotatedLocation(Location baseLoc, double pitchOffset, double yawOffset) { + Location newLoc = baseLoc.clone(); + newLoc.setPitch((float) pitchOffset); + newLoc.setYaw((float) yawOffset); + return newLoc; + } + + private Location calculateAirParticleLocation(Location center, Vector direction, double angleDegrees) { + Location tempLoc = center.clone(); + double angleRadians = Math.toRadians(angleDegrees); + Vector newDir = direction.clone().multiply(2 * Math.cos(angleRadians)); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + 2 + (2 * Math.sin(angleRadians))); + return tempLoc; + } + + private void displayAirParticle(Location loc) { + String color = "#FFFFFF"; + int count = 1; + float offsetX = 0; + float offsetY = 0; + float offsetZ = 0; + float particleSpeed = 0.003f; + int viewDistance = 50; + + if (ThreadLocalRandom.current().nextInt(30) == 0) { + JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed); + } else { + JCMethods.displayColoredParticles(color, loc, count, offsetX, offsetY, offsetZ, particleSpeed, viewDistance); + } + } + + private void playFireParticles() { + if (fireUses != 0) { + ParticleEffect flame = bPlayer.hasSubElement(Element.BLUE_FIRE) ? ParticleEffect.SOUL_FIRE_FLAME : ParticleEffect.FLAME; + for (int i = -180; i < 180; i += 40) { + Location particleLoc = calculateCircularLocation(location, 2, i, 2); + flame.display(particleLoc, 0, 0, 0, 0, 1); + JCMethods.emitLight(particleLoc); + } + } + } + + private Location calculateCircularLocation(Location center, double radius, double angleOffsetDegrees, double yOffset) { + double angleRadians = Math.toRadians(angleOffsetDegrees); + double x = radius * Math.cos(angleRadians + point); + double z = radius * Math.sin(angleRadians + point); + return center.clone().add(x, yOffset, z); + } + + private void playWaterEarthParticles() { + Location centerLoc = location.clone().add(0, 2, 0); + double xRotation = Math.PI * 2.1 / 3; + double yawRadians = -(centerLoc.getYaw() * Math.PI / 180 - 1.575); + + for (int i = -180; i < 180; i += 30) { + double angle = Math.toRadians(i); + Vector v = new Vector(Math.cos(angle + point), Math.sin(angle + point), 0.0D).multiply(2); + Vector v1 = v.clone(); + + rotateAroundAxisX(v, xRotation); + rotateAroundAxisY(v, yawRadians); + rotateAroundAxisX(v1, -xRotation); + rotateAroundAxisY(v1, yawRadians); + if (waterUses != 0) { + centerLoc.getWorld().spawnParticle(Particle.WATER_WAKE, centerLoc.clone().add(v), 3, 0.0, 0.0, 0.0, 0.005F); + GeneralMethods.displayColoredParticle("06C1FF", centerLoc.clone().add(v)); + } + if (earthUses != 0) { + GeneralMethods.displayColoredParticle("754719", centerLoc.clone().add(v1)); + } + } + } + + private void updatePointCounter() { + point = (point + 1) % 360; + } + + private void rotateAroundAxisX(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double y = v.getY() * cos - v.getZ() * sin; + double z = v.getY() * sin + v.getZ() * cos; + v.setY(y).setZ(z); + } + + private void rotateAroundAxisY(Vector v, double angle) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + double x = v.getX() * cos + v.getZ() * sin; + double z = v.getX() * -sin + v.getZ() * cos; + v.setX(x).setZ(z); + } + + @Override + public void remove() { + super.remove(); + MultiAbilityManager.unbindMultiAbility(player); + flightHandler.removeInstance(player, this.getName()); + } + + public void prepareCancel() { + if (System.currentTimeMillis() < lastClickTime + 500L) { + remove(); + } else { + lastClickTime = System.currentTimeMillis(); + } + } + + public int getAirUses() { + return airUses; + } + + public void setAirUses(int airuses) { + this.airUses = airuses; + } + + public int getEarthUses() { + return earthUses; + } + + public void setEarthUses(int earthuses) { + this.earthUses = earthuses; + } + + public int getFireUses() { + return fireUses; + } + + public void setFireUses(int fireuses) { + this.fireUses = fireuses; + } + + public int getWaterUses() { + return waterUses; + } + + public void setWaterUses(int wateruses) { + this.waterUses = wateruses; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public boolean requireAvatar() { + return false; + } + + @Override + public String getName() { + return "ElementSphere"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Avatar.ElementSphere.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Avatar.ElementSphere.Enabled"); + } + + @Override + public ArrayList getMultiAbilities() { + FileConfiguration lang = getLanguageConfig(); + + String airName = lang.getString("Abilities.Avatar.ElementSphereAir.Name"); + String fireName = lang.getString("Abilities.Avatar.ElementSphereFire.Name"); + String waterName = lang.getString("Abilities.Avatar.ElementSphereWater.Name"); + String earthName = lang.getString("Abilities.Avatar.ElementSphereEarth.Name"); + String streamName = lang.getString("Abilities.Avatar.ElementSphereStream.Name"); + + multiAbilityInfo.get(0).setName(airName); + multiAbilityInfo.get(1).setName(earthName); + multiAbilityInfo.get(2).setName(fireName); + multiAbilityInfo.get(3).setName(waterName); + multiAbilityInfo.get(4).setName(streamName); + + return multiAbilityInfo; + } +} \ No newline at end of file diff --git a/src/ability/chiblocking/Backstab.java b/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java similarity index 99% rename from src/ability/chiblocking/Backstab.java rename to src/com/jedk1/jedcore/ability/chiblocking/Backstab.java index f6c87ec..701121a 100644 --- a/src/ability/chiblocking/Backstab.java +++ b/src/com/jedk1/jedcore/ability/chiblocking/Backstab.java @@ -1,18 +1,17 @@ package com.jedk1.jedcore.ability.chiblocking; +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.chiblocking.passive.ChiPassive; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; - -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.chiblocking.passive.ChiPassive; import org.bukkit.util.Vector; public class Backstab extends ChiAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java new file mode 100644 index 0000000..1b57acf --- /dev/null +++ b/src/com/jedk1/jedcore/ability/chiblocking/DaggerThrow.java @@ -0,0 +1,351 @@ +package com.jedk1.jedcore.ability.chiblocking; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.AbilitySelector; +import com.jedk1.jedcore.util.ThreadUtil; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ChiAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class DaggerThrow extends ChiAbility implements AddonAbility { + private static final List INTERACTIONS = new ArrayList<>(); + + private final List arrows = new ArrayList<>(); + + private boolean limitEnabled; + private boolean requireArrows; + private boolean allowPickup; + private boolean particles; + private long endTime; + private int shots = 1; + private int hits = 0; + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("MaxShots") + private int maxShots; + + public DaggerThrow(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (bPlayer.isOnCooldown("DaggerThrowShot")) { + return; + } + + if (hasAbility(player, DaggerThrow.class)) { + DaggerThrow dt = getAbility(player, DaggerThrow.class); + dt.shootArrow(); + return; + } + + setFields(); + + start(); + + if (!isRemoved()) { + shootArrow(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Chi.DaggerThrow.Cooldown"); + limitEnabled = config.getBoolean("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled"); + maxShots = config.getInt("Abilities.Chi.DaggerThrow.MaxDaggers.Amount"); + particles = config.getBoolean("Abilities.Chi.DaggerThrow.ParticleTrail"); + damage = config.getDouble("Abilities.Chi.DaggerThrow.Damage"); + requireArrows = config.getBoolean("Abilities.Chi.DaggerThrow.RequireArrows"); + allowPickup = config.getBoolean("Abilities.Chi.DaggerThrow.AllowPickup"); + + loadInteractions(); + } + + private void loadInteractions() { + INTERACTIONS.clear(); + + String path = "Abilities.Chi.DaggerThrow.Interactions"; + + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + ConfigurationSection section = config.getConfigurationSection(path); + + for (String abilityName : section.getKeys(false)) { + INTERACTIONS.add(new AbilityInteraction(abilityName)); + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (System.currentTimeMillis() > endTime) { + bPlayer.addCooldown(this); + remove(); + return; + } + + if (shots > maxShots && limitEnabled) { + bPlayer.addCooldown(this); + remove(); + } + } + + private void shootArrow() { + shots++; + Location location = player.getEyeLocation(); + + Vector vector = location.toVector(). + add(location.getDirection().multiply(2.5)). + toLocation(location.getWorld()).toVector(). + subtract(player.getEyeLocation().toVector()); + + if (requireArrows) JCMethods.removeItemFromInventory(player, Material.ARROW, 1); + + Arrow arrow = player.launchProjectile(Arrow.class); + arrow.setVelocity(vector); + arrow.getLocation().setDirection(vector); + arrow.setKnockbackStrength(0); + arrow.setBounce(false); + arrow.setMetadata("daggerthrow", new FixedMetadataValue(JedCore.plugin, "1")); + + if (!allowPickup) arrow.setPickupStatus(Arrow.PickupStatus.DISALLOWED); + + if (particles) { + arrow.setCritical(true); + } + + arrows.add(arrow); + endTime = System.currentTimeMillis() + 500; + bPlayer.addCooldown("DaggerThrowShot", 100); + } + + public void damageEntityFromArrow(LivingEntity entity, Arrow arrow) { + if (!(arrow.getShooter() instanceof Player shooter)) return; + + if (RegionProtection.isRegionProtected(shooter, arrow.getLocation(), "DaggerThrow")) return; + + ThreadUtil.ensureEntity(arrow, () -> arrow.setVelocity(new Vector(0, 0, 0))); + ThreadUtil.ensureEntity(entity, () -> entity.setNoDamageTicks(0)); + + double prevHealth = entity.getHealth(); + + ThreadUtil.ensureEntity(entity, () -> DamageHandler.damageEntity(entity, damage, this)); + + if (prevHealth > entity.getHealth()) { + ThreadUtil.ensureEntity(arrow, arrow::remove); + } + + if (!(entity instanceof Player target)) { + return; + } + + DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); + if (daggerThrow == null) { + return; + } + + daggerThrow.hits++; + BendingPlayer targetBPlayer = BendingPlayer.getBendingPlayer(target); + + for (AbilityInteraction interaction : INTERACTIONS) { + if (!interaction.enabled || daggerThrow.hits < interaction.hitRequirement) { + continue; + } + + CoreAbility abilityDefinition = AbilitySelector.getAbility(interaction.name); + if (abilityDefinition == null) { + continue; + } + + CoreAbility ability = CoreAbility.getAbility(target, abilityDefinition.getClass()); + if (ability == null) { + continue; + } + + ability.remove(); + targetBPlayer.addCooldown(ability, interaction.cooldown); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + return arrows.stream().map(Arrow::getLocation).collect(Collectors.toList()); + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Chi.DaggerThrow.AbilityCollisionRadius"); + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + Location location = collision.getLocationFirst(); + + Optional collidedObject = arrows.stream().filter(arrow -> arrow.getLocation().equals(location)).findAny(); + + if (collidedObject.isPresent()) { + arrows.remove(collidedObject.get()); + collidedObject.get().remove(); + } + } + } + + @Override + public String getName() { + return "DaggerThrow"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Chi.DaggerThrow.Description"); + } + + public boolean hasParticleTrail() { + return particles; + } + + public double getDamage() { + return damage; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public int getShots() { + return shots; + } + + public void setShots(int shots) { + this.shots = shots; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public boolean isLimitEnabled() { + return limitEnabled; + } + + public void setLimitEnabled(boolean limitEnabled) { + this.limitEnabled = limitEnabled; + } + + public int getMaxShots() { + return maxShots; + } + + public void setMaxShots(int maxShots) { + this.maxShots = maxShots; + } + + public int getHits() { + return hits; + } + + public void setHits(int hits) { + this.hits = hits; + } + + public List getArrows() { + return arrows; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Chi.DaggerThrow.Enabled"); + } + + private class AbilityInteraction { + public boolean enabled; + public long cooldown; + public int hitRequirement; + public String name; + + public AbilityInteraction(String abilityName) { + this.name = abilityName; + loadConfig(); + } + + public void loadConfig() { + ConfigurationSection config = JedCoreConfig.getConfig(player); + this.enabled = config.getBoolean("Abilities.Chi.DaggerThrow.Interactions." + name + ".Enabled", true); + this.cooldown = config.getLong("Abilities.Chi.DaggerThrow.Interactions." + name + ".Cooldown", 1000); + this.hitRequirement = config.getInt("Abilities.Chi.DaggerThrow.Interactions." + name + ".HitsRequired", 1); + } + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java new file mode 100644 index 0000000..31b9e9a --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthKick.java @@ -0,0 +1,343 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.AABB; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.CollisionUtil; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.BlockUtil; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +import static java.util.stream.Collectors.toList; + +public class EarthKick extends EarthAbility implements AddonAbility { + private final List temps = new ArrayList<>(); + private final Set hitEntities = new HashSet<>(); + + private BlockData materialData; + private Location location; + private Block block; + private boolean multipleHits; + private int sourceRange; + private int spread; + private double velocity; + private boolean allowMetal; + private boolean replaceSource; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("MaxShots") + private int earthBlocks; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.DAMAGE) + private double metalDmg; + @Attribute("CollisionRadius") + private double entityCollisionRadius; + + public EarthKick(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + location = player.getLocation(); + + if ((player.getLocation().getPitch() > -5) && prepare()) { + if (RegionProtection.isRegionProtected(this, block.getLocation())) { + return; + } + launchBlocks(); + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.EarthKick.Cooldown"); + earthBlocks = config.getInt("Abilities.Earth.EarthKick.EarthBlocks"); + damage = config.getDouble("Abilities.Earth.EarthKick.Damage.Normal"); + metalDmg = config.getDouble("Abilities.Earth.EarthKick.Damage.Metal"); + entityCollisionRadius = config.getDouble("Abilities.Earth.EarthKick.EntityCollisionRadius"); + multipleHits = config.getBoolean("Abilities.Earth.EarthKick.MultipleHits"); + sourceRange = config.getInt("Abilities.Earth.EarthKick.SourceRange"); + spread = config.getInt("Abilities.Earth.EarthKick.Spread"); + velocity = config.getDouble("Abilities.Earth.EarthKick.Velocity"); + allowMetal = config.getBoolean("Abilities.Earth.EarthKick.AllowMetal"); + replaceSource = config.getBoolean("Abilities.Earth.EarthKick.ReplaceSource"); + + if (entityCollisionRadius < 1.0) { + entityCollisionRadius = 1.0; + } + } + + private boolean prepare() { + block = player.getTargetBlock(getTransparentMaterialSet(), sourceRange); + + if (EarthAbility.getMovedEarth().containsKey(block)) { + return false; + } + + if (!isEarthbendable(player, block)) { + return false; + } + + if (TempBlock.isTempBlock(block)) { + TempBlock.get(block).revertBlock(); + } + + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + if (block != null && (allowMetal || !isMetal(block))) { + materialData = block.getBlockData().clone(); + location.setX(block.getX() + 0.5); + location.setY(block.getY()); + location.setZ(block.getZ() + 0.5); + + return true; + } + + return false; + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + remove(); + return; + } + + bPlayer.addCooldown(this); + + track(); + + if (temps.isEmpty()) { + remove(); + } + } + + private void launchBlocks() { + if (replaceSource) { + if (getMovedEarth().containsKey(block)) { + block.setType(Material.AIR); + } + + if (block.getType() != Material.AIR) { + TempBlock air = new TempBlock(block, Material.AIR); + air.setRevertTime(5000L); + } + } + + location.setPitch(0); + location.add(location.getDirection()); + + if (!isAir(location.getBlock().getType())) { + location.setY(location.getY() + 1.0); + } + + ParticleEffect.CRIT.display(location, 10, Math.random(), Math.random(), Math.random(), 0.1); + + int yaw = Math.round(location.getYaw()); + + playEarthbendingSound(location); + + ThreadLocalRandom rand = ThreadLocalRandom.current(); + + for (int i = 0; i < earthBlocks; i++) { + location.setYaw(yaw + rand.nextInt((spread * 2) + 1) - spread); + location.setPitch(rand.nextInt(25) - 45); + + Vector v = location.clone().add(0, 0.8, 0).getDirection().normalize(); + Location location1 = location.clone().add(new Vector(v.getX() * 2, v.getY(), v.getZ() * 2)); + Vector dir = location1.setDirection(location.getDirection()).getDirection().multiply(velocity); + + temps.add(new TempFallingBlock(location, materialData, dir, this)); + } + } + + public void track() { + List destroy = new ArrayList<>(); + + for (TempFallingBlock tfb : temps) { + FallingBlock fb = tfb.getFallingBlock(); + + if (fb == null || fb.isDead()) { + destroy.add(tfb); + continue; + } + + for (int i = 0; i < 2; i++) { + ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.1, materialData); + ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 1, 0.0, 0.0, 0.0, 0.2, materialData); + } + + AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); + + CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { + UUID uuid = entity.getUniqueId(); + if (this.multipleHits || hitEntities.add(uuid)) { + DamageHandler.damageEntity(entity, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : damage, this); + } + return false; + }); + } + + temps.removeAll(destroy); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public List getLocations() { + return temps.stream().map(TempFallingBlock::getLocation).collect(toList()); + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Earth.EarthKick.AbilityCollisionRadius"); + } + + @Override + public void handleCollision(Collision collision) { + CollisionUtil.handleFallingBlockCollisions(collision, temps); + } + + @Override + public String getName() { + return "EarthKick"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthKick.Description"); + } + + public List getTemps() { + return temps; + } + + public BlockData getMaterialData() { + return materialData; + } + + public void setMaterialData(BlockData materialData) { + this.materialData = materialData; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getEarthBlocksQuantity() { + return earthBlocks; + } + + public void setEarthBlocksQuantity(int earthBlocks) { + this.earthBlocks = earthBlocks; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getMetalDmg() { + return metalDmg; + } + + public void setMetalDmg(double metalDmg) { + this.metalDmg = metalDmg; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + public Block getBlock() { + return block; + } + + public void setBlock(Block block) { + this.block = block; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthKick.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java new file mode 100644 index 0000000..e047ed3 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthLine.java @@ -0,0 +1,490 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class EarthLine extends EarthAbility implements AddonAbility { + + private Location location; + private Location endLocation; + private Block sourceBlock; + private TempBlock sourceTempBlock; + private Material sourceType; + private boolean progressing; + private boolean hitted; + private int goOnAfterHit; + private long removalTime = -1; + private boolean allowChangeDirection; + private CompositeRemovalPolicy removalPolicy; + private long useCooldown; + private long prepareCooldown; + private double sourceKeepRange; + + @Attribute(Attribute.DURATION) + private long maxDuration; + @Attribute(Attribute.RANGE) + private double range; + @Attribute(Attribute.SELECT_RANGE) + private double prepareRange; + @Attribute(Attribute.RADIUS) + private int affectingRadius; + @Attribute(Attribute.DAMAGE) + private double damage; + + public EarthLine(Player player) { + super(player); + + if (!isEnabled()) return; + + if (!bPlayer.canBend(this)) { + return; + } + goOnAfterHit = 1; + + setFields(); + + if (prepare()) { + start(); + if (!isRemoved() && prepareCooldown != 0) { + bPlayer.addCooldown(this, prepareCooldown); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new SwappedSlotsRemovalPolicy<>(bPlayer, EarthLine.class) + ); + + this.removalPolicy.load(config); + + useCooldown = config.getLong("Abilities.Earth.EarthLine.Cooldown"); + prepareCooldown = config.getLong("Abilities.Earth.EarthLine.PrepareCooldown"); + range = config.getInt("Abilities.Earth.EarthLine.Range"); + prepareRange = config.getDouble("Abilities.Earth.EarthLine.PrepareRange"); + sourceKeepRange = config.getDouble("Abilities.Earth.EarthLine.SourceKeepRange"); + affectingRadius = config.getInt("Abilities.Earth.EarthLine.AffectingRadius"); + damage = config.getDouble("Abilities.Earth.EarthLine.Damage"); + allowChangeDirection = config.getBoolean("Abilities.Earth.EarthLine.AllowChangeDirection"); + maxDuration = config.getLong("Abilities.Earth.EarthLine.MaxDuration"); + } + + public boolean prepare() { + final Block block = getEarthSourceBlock(this.range); + + if (block == null || !this.isEarthbendable(block)) { + return false; + } else if (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block)) { + return false; + } else if (EarthAbility.getMovedEarth().containsKey(block)) { + return false; + } + + boolean selectedABlockInUse = false; + for (final EarthLine el : getAbilities(this.player, EarthLine.class)) { + if (!el.progressing) { + el.remove(); + } else if (block.equals(el.sourceBlock)) { + selectedABlockInUse = true; + } + } + + if (selectedABlockInUse) { + return false; + } + + if (block.getLocation().distanceSquared(this.player.getLocation()) > this.prepareRange * this.prepareRange) { + return false; + } + + this.sourceBlock = block; + this.focusBlock(); + + return true; + } + + private void focusBlock() { + if (DensityShift.isPassiveSand(this.sourceBlock)) { + DensityShift.revertSand(this.sourceBlock); + } + + if (this.sourceBlock.getType() == Material.SAND) { + this.sourceType = Material.SAND; + sourceTempBlock = new TempBlock(sourceBlock, Material.SANDSTONE.createBlockData()); + } else if (this.sourceBlock.getType() == Material.RED_SAND) { + this.sourceType = Material.RED_SAND; + sourceTempBlock = new TempBlock(sourceBlock, Material.RED_SANDSTONE.createBlockData()); + } else if (this.sourceBlock.getType() == Material.STONE) { + this.sourceType = Material.STONE; + sourceTempBlock = new TempBlock(sourceBlock, Material.COBBLESTONE.createBlockData()); + } else { + this.sourceType = this.sourceBlock.getType(); + sourceTempBlock = new TempBlock(sourceBlock, Material.STONE.createBlockData()); + } + + this.location = this.sourceBlock.getLocation(); + } + + private void unfocusBlock() { + sourceTempBlock.revertBlock(); + } + + @Override + public void remove() { + sourceTempBlock.revertBlock(); + super.remove(); + } + + // todo: static + private static Location getTargetLocation(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + + double range = config.getInt("Abilities.Earth.EarthLine.Range"); + + Entity target = GeneralMethods.getTargetedEntity(player, range, player.getNearbyEntities(range, range, range)); + Location location; + + if (target == null) { + location = GeneralMethods.getTargetedLocation(player, range); + } else { + location = ((LivingEntity) target).getEyeLocation(); + } + + return location; + } + + public void shootLine(Location endLocation) { + if (useCooldown != 0 && bPlayer.getCooldown(this.getName()) < useCooldown) bPlayer.addCooldown(this, useCooldown); + if (maxDuration > 0) removalTime = System.currentTimeMillis() + maxDuration; + this.endLocation = endLocation; + progressing = true; + sourceBlock.getWorld().playEffect(sourceBlock.getLocation(), Effect.GHAST_SHOOT, 0, 10); + } + + public static void shootLine(Player player) { + if (hasAbility(player, EarthLine.class)) { + EarthLine el = getAbility(player, EarthLine.class); + if (!el.progressing) { + el.shootLine(getTargetLocation(player)); + } + } + } + + private boolean sourceOutOfRange() { + return sourceBlock == null || sourceBlock.getLocation().add(0.5, 0.5, 0.5).distanceSquared(player.getLocation()) > sourceKeepRange * sourceKeepRange || sourceBlock.getWorld() != player.getWorld(); + } + + public void progress() { + if (!progressing) { + if (sourceOutOfRange()) { + unfocusBlock(); + remove(); + } + return; + } + + if (removalPolicy.shouldRemove()) { + remove(); + return; + } + + if (sourceBlock == null || RegionProtection.isRegionProtected(this, location)) { + remove(); + return; + } + + if (removalTime > -1 && System.currentTimeMillis() > removalTime) { + remove(); + return; + } + + if (sourceOutOfRange()) { + remove(); + return; + } + + if (RegionProtection.isRegionProtected(player, location, this)) { + remove(); + return; + } + + if (allowChangeDirection && player.isSneaking() && bPlayer.getBoundAbilityName().equalsIgnoreCase("EarthLine")) { + endLocation = getTargetLocation(player); + } + + double x1 = endLocation.getX(); + double z1 = endLocation.getZ(); + double x0 = sourceBlock.getX(); + double z0 = sourceBlock.getZ(); + + Vector looking = new Vector(x1 - x0, 0.0D, z1 - z0); + Vector push = new Vector(x1 - x0, 0.34999999999999998D, z1 - z0); + + if (location.distance(sourceBlock.getLocation()) < range) { + Material cloneType = location.getBlock().getType(); + Location locationYUP = location.getBlock().getLocation().clone().add(0.5, 0.1, 0.5); + + playEarthbendingSound(location); + + if (isEarthbendable(location.getBlock())) { + new TempBlock(location.getBlock(), Material.AIR.createBlockData(), 700L); + new TempFallingBlock(locationYUP, cloneType.createBlockData(), new Vector(0.0, 0.35, 0.0), this); + } + + location.add(looking.normalize()); + + if (!climb()) { + remove(); + return; + } + + if (hitted) { + if (goOnAfterHit != 0) { + goOnAfterHit--; + } else { + remove(); + return; + } + } else { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, affectingRadius)) { + if (RegionProtection.isRegionProtected(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(entity.getName()))) { + return; + } + + if ((entity instanceof LivingEntity) && entity.getEntityId() != player.getEntityId()) { + GeneralMethods.setVelocity(this, entity, push.normalize().multiply(2)); + DamageHandler.damageEntity(entity, damage, this); + hitted = true; + } + } + } + } else { + remove(); + return; + } + + if (!isEarthbendable(player, location.getBlock()) && !isTransparent(location.getBlock())) { + remove(); + } + } + + private boolean climb() { + Block above = location.getBlock().getRelative(BlockFace.UP); + + if (!isTransparent(above)) { + // Attempt to climb since the current location has a block above it. + location.add(0, 1, 0); + above = location.getBlock().getRelative(BlockFace.UP); + + // The new location must be earthbendable and have something transparent above it. + return isEarthbendable(location.getBlock()) && isTransparent(above); + } else if (isTransparent(location.getBlock()) ) { + // Attempt to fall since the current location is transparent and the above block was transparent. + location.add(0, -1, 0); + + // The new location must be earthbendable and we already know the block above it is transparent. + return isEarthbendable(location.getBlock()); + } + + return true; + } + + @Override + public long getCooldown() { + return useCooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "EarthLine"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthLine.Description"); + } + + public Location getEndLocation() { + return endLocation; + } + + public void setEndLocation(Location endLocation) { + this.endLocation = endLocation; + } + + public Block getSourceBlock() { + return sourceBlock; + } + + public void setSourceBlock(Block sourceBlock) { + this.sourceBlock = sourceBlock; + } + + public Material getSourceType() { + return sourceType; + } + + public void setSourceType(Material sourceType) { + this.sourceType = sourceType; + } + + public boolean isProgressing() { + return progressing; + } + + public void setProgressing(boolean progressing) { + this.progressing = progressing; + } + + public int getGoOnAfterHit() { + return goOnAfterHit; + } + + public void setGoOnAfterHit(int goOnAfterHit) { + this.goOnAfterHit = goOnAfterHit; + } + + public long getRemovalTime() { + return removalTime; + } + + public void setRemovalTime(long removalTime) { + this.removalTime = removalTime; + } + + public long getUseCooldown() { + return useCooldown; + } + + public void setUseCooldown(long useCooldown) { + this.useCooldown = useCooldown; + } + + public long getPrepareCooldown() { + return prepareCooldown; + } + + public void setPrepareCooldown(long prepareCooldown) { + this.prepareCooldown = prepareCooldown; + } + + public long getMaxDuration() { + return maxDuration; + } + + public void setMaxDuration(long maxDuration) { + this.maxDuration = maxDuration; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public double getPrepareRange() { + return prepareRange; + } + + public void setPrepareRange(double prepareRange) { + this.prepareRange = prepareRange; + } + + public double getSourceKeepRange() { + return sourceKeepRange; + } + + public void setSourceKeepRange(double sourceKeepRange) { + this.sourceKeepRange = sourceKeepRange; + } + + public int getAffectingRadius() { + return affectingRadius; + } + + public void setAffectingRadius(int affectingRadius) { + this.affectingRadius = affectingRadius; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean isAllowChangeDirection() { + return allowChangeDirection; + } + + public void setAllowChangeDirection(boolean allowChangeDirection) { + this.allowChangeDirection = allowChangeDirection; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthLine.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java b/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java new file mode 100644 index 0000000..2067b0c --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthPillar.java @@ -0,0 +1,215 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.Collapse; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class EarthPillar extends EarthAbility implements AddonAbility { + + private static final ConcurrentHashMap AFFECTED_BLOCKS = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap> AFFECTED = new ConcurrentHashMap<>(); + + private Block block; + private BlockFace face; + @Attribute(Attribute.HEIGHT) + private int height; + @Attribute(Attribute.RANGE) + private int range; + private int step; + + private final List blocks = new ArrayList<>(); + + public EarthPillar(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + Block target = BlockSource.getEarthSourceBlock(player, range, ClickType.SHIFT_DOWN); + if (target != null && !AFFECTED_BLOCKS.containsKey(target)) { + List blocks = player.getLastTwoTargetBlocks(null, range); + if (blocks.size() > 1) { + this.player = player; + face = blocks.get(1).getFace(blocks.get(0)); + block = blocks.get(1); + height = getEarthbendableBlocksLength(block, getDirection(face).clone().multiply(-1), height); + start(); + } + } else if (target != null && AFFECTED_BLOCKS.containsKey(target)) { + List blocks = AFFECTED.get(AFFECTED_BLOCKS.get(target)); + if (blocks != null && !blocks.isEmpty()) { + for (Block b : blocks) { + Collapse.revertBlock(b); + } + playEarthbendingSound(target.getLocation()); + AFFECTED.remove(AFFECTED_BLOCKS.get(target)); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + height = config.getInt("Abilities.Earth.EarthPillar.Height"); + range = config.getInt("Abilities.Earth.EarthPillar.Range"); + } + + @Override + public void progress() { + if (step < height) { + step++; + movePillar(); + } else { + AFFECTED.put(this, blocks); + remove(); + } + } + + private void movePillar() { + moveEarth(block, getDirection(face), height); + block = block.getRelative(face); + AFFECTED_BLOCKS.put(block, this); + blocks.add(block); + } + + private Vector getDirection(BlockFace face) { + switch (face) { + case UP: + return new Vector(0, 1, 0); + case DOWN: + return new Vector(0, -1, 0); + case NORTH: + return new Vector(0, 0, -1); + case SOUTH: + return new Vector(0, 0, 1); + case EAST: + return new Vector(1, 0, 0); + case WEST: + return new Vector(-1, 0, 0); + default: + return null; + } + } + + public static void progressAll() { + for (Block block : AFFECTED_BLOCKS.keySet()) { + if (!EarthAbility.isEarthbendable(AFFECTED_BLOCKS.get(block).getPlayer(), block)) { + AFFECTED_BLOCKS.remove(block); + } + } + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return block != null ? block.getLocation() : null; + } + + @Override + public String getName() { + return "EarthPillar"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthPillar.Description"); + } + + public Block getBlock() { + return block; + } + + public void setBlock(Block block) { + this.block = block; + } + + public BlockFace getFace() { + return face; + } + + public void setFace(BlockFace face) { + this.face = face; + } + + public int getHeight() { + return height; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public List getBlocks() { + return blocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthPillar.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java new file mode 100644 index 0000000..6ee028d --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java @@ -0,0 +1,528 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.AABB; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.CollisionUtil; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.BlockUtil; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class EarthShard extends EarthAbility implements AddonAbility { + @Attribute(Attribute.RANGE) + public static int range; + public static int abilityRange; + + @Attribute(Attribute.DAMAGE) + public static double normalDmg; + @Attribute(Attribute.DAMAGE) + public static double metalDmg; + + @Attribute("MaxShots") + public static int maxShards; + @Attribute(Attribute.COOLDOWN) + public static long cooldown; + + private boolean isThrown = false; + private Location origin; + private double abilityCollisionRadius; + private double entityCollisionRadius; + + private final List tblockTracker = new ArrayList<>(); + private final List readyBlocksTracker = new ArrayList<>(); + private final List fallingBlocks = new ArrayList<>(); + + private boolean allowKnockup; + private double knockupVelocity; + private double knockupRange; + + private boolean allowKnockupSelf; + private double knockupSelfVelocity; + private double knockupSelfRange; + + public EarthShard(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, EarthShard.class)) { + for (EarthShard es : EarthShard.getAbilities(player, EarthShard.class)) { + if (es.isThrown && System.currentTimeMillis() - es.getStartTime() >= 20000) { + // Remove the old instance because it got into a broken state. + // This shouldn't affect normal gameplay because the cooldown is long enough that the + // shards should have already hit their target. + es.remove(); + } else { + es.select(); + return; + } + } + } + + setFields(); + origin = player.getLocation().clone(); + raiseEarthBlock(getEarthSourceBlock(range)); + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + range = config.getInt("Abilities.Earth.EarthShard.PrepareRange"); + abilityRange = config.getInt("Abilities.Earth.EarthShard.AbilityRange"); + normalDmg = config.getDouble("Abilities.Earth.EarthShard.Damage.Normal"); + metalDmg = config.getDouble("Abilities.Earth.EarthShard.Damage.Metal"); + maxShards = config.getInt("Abilities.Earth.EarthShard.MaxShards"); + cooldown = config.getLong("Abilities.Earth.EarthShard.Cooldown"); + abilityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); + entityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); + allowKnockup = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Others.Allow"); + knockupVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Velocity"); + knockupRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Range"); + allowKnockupSelf = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Self.Allow"); + knockupSelfVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Velocity"); + knockupSelfRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Range"); + } + + public void select() { + raiseEarthBlock(getEarthSourceBlock(range)); + } + + public void raiseEarthBlock(Block block) { + if (block == null) return; + if (EarthAbility.getMovedEarth().containsKey(block)) return; + if (tblockTracker.size() >= maxShards) return; + + Vector blockVector = block.getLocation().toVector().toBlockVector().setY(0); + + for (TempBlock tempBlock : tblockTracker) { + if (tempBlock.getLocation().getWorld() != block.getWorld()) continue; + + Vector tempBlockVector = tempBlock.getLocation().toVector().toBlockVector().setY(0); + if (tempBlockVector.equals(blockVector)) return; + } + + for (int i = 1; i < 4; i++) { + if (!isTransparent(block.getRelative(BlockFace.UP, i))) return; + } + + if (!isEarthbendable(block)) return; + + if (isMetal(block)) { + playMetalbendingSound(block.getLocation()); + } else { + ParticleEffect.BLOCK_CRACK.display( + block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData() + ); + playEarthbendingSound(block.getLocation()); + } + + Material material = getCorrectType(block); + + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + Location loc = block.getLocation().add(0.5, 0, 0.5); + new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); + TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); + tblockTracker.add(tb); + + handleKnockup(block); + } + + private void handleKnockup(Block origin) { + if (!allowKnockup && !allowKnockupSelf) return; + + Location originLoc = origin.getLocation(); + World world = origin.getWorld(); + + for (Entity entity : world.getNearbyEntities(originLoc, Math.max(knockupRange, knockupSelfRange), knockupRange, knockupRange)) { + if (entity instanceof FallingBlock) continue; + + if (entity.equals(player)) { + if (!allowKnockupSelf) continue; + if (entity.getLocation().distance(originLoc) <= knockupSelfRange) { + entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupSelfVelocity, 0))); + } + } else { + if (!allowKnockup) continue; + if (entity.getLocation().distance(originLoc) <= knockupRange) { + entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupVelocity, 0))); + } + } + } + } + + public Material getCorrectType(Block block) { + if (block.getType() == Material.SAND) { + return Material.SANDSTONE; + } + if (block.getType() == Material.RED_SAND) { + return Material.RED_SANDSTONE; + } + if (block.getType() == Material.GRAVEL) { + return Material.COBBLESTONE; + } + if (block.getType().name().endsWith("CONCRETE_POWDER")) { + return Material.getMaterial(block.getType().name().replace("_POWDER", "")); + } + + return block.getType(); + } + + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (!isThrown) { + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + + if (tblockTracker.isEmpty()) { + remove(); + return; + } + + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fb = tfb.getFallingBlock(); + + if (fb.isDead() || fb.getLocation().getBlockY() == origin.getBlockY() + 2) { + TempBlock tb = new TempBlock(fb.getLocation().getBlock(), fb.getBlockData()); + readyBlocksTracker.add(tb); + tfb.remove(); + } + } + } else { + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fb = tfb.getFallingBlock(); + + AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); + + CollisionDetector.checkEntityCollisions(player, collider, (e) -> { + DamageHandler.damageEntity(e, isMetal(fb.getBlockData().getMaterial()) ? metalDmg : normalDmg, this); + ((LivingEntity) e).setNoDamageTicks(0); + ParticleEffect.BLOCK_CRACK.display(fb.getLocation(), 20, 0, 0, 0, 0, fb.getBlockData()); + tfb.remove(); + return false; + }); + + if (fb.isDead()) { + tfb.remove(); + } + } + + if (TempFallingBlock.getFromAbility(this).isEmpty()) { + remove(); + } + } + } + + public static void throwShard(Player player) { + if (hasAbility(player, EarthShard.class)) { + for (EarthShard es : EarthShard.getAbilities(player, EarthShard.class)) { + if (!es.isThrown) { + es.throwShard(); + break; + } + } + } + } + + public void throwShard() { + if (isThrown || tblockTracker.size() > readyBlocksTracker.size()) { + return; + } + + Location targetLocation = GeneralMethods.getTargetedLocation(player, abilityRange); + + if (GeneralMethods.getTargetedEntity(player, abilityRange, new ArrayList<>()) != null) { + targetLocation = GeneralMethods.getTargetedEntity(player, abilityRange, new ArrayList<>()).getLocation(); + } + + Vector vel = null; + + for (TempBlock tb : readyBlocksTracker) { + Location target = player.getTargetBlock(null, 30).getLocation(); + + if (target.getBlockX() == tb.getBlock().getX() && target.getBlockY() == tb.getBlock().getY() && target.getBlockZ() == tb.getBlock().getZ()) { + vel = player.getEyeLocation().getDirection().multiply(2).add(new Vector(0, 0.2, 0)); + break; + } + + vel = GeneralMethods.getDirection(tb.getLocation(), targetLocation).normalize().multiply(2).add(new Vector(0, 0.2, 0)); + } + + for (TempBlock tb : readyBlocksTracker) { + fallingBlocks.add(new TempFallingBlock(tb.getLocation(), tb.getBlock().getBlockData(), vel, this)); + tb.revertBlock(); + } + + revertBlocks(); + + isThrown = true; + + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + } + + public void revertBlocks() { + for (TempBlock tb : tblockTracker) { + tb.revertBlock(); + } + + for (TempBlock tb : readyBlocksTracker) { + tb.revertBlock(); + } + + tblockTracker.clear(); + readyBlocksTracker.clear(); + } + + @Override + public void remove() { + // Destroy any remaining falling blocks. + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + tfb.remove(); + } + + revertBlocks(); + + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); + } + + @Override + public void handleCollision(Collision collision) { + CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); + } + + @Override + public double getCollisionRadius() { + return abilityCollisionRadius; + } + + @Override + public String getName() { + return "EarthShard"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthShard.Description"); + } + + public static int getRange() { + return range; + } + + public static void setRange(int range) { + EarthShard.range = range; + } + + public static int getAbilityRange() { + return abilityRange; + } + + public static void setAbilityRange(int abilityRange) { + EarthShard.abilityRange = abilityRange; + } + + public static double getNormalDmg() { + return normalDmg; + } + + public static void setNormalDmg(double normalDmg) { + EarthShard.normalDmg = normalDmg; + } + + public static double getMetalDmg() { + return metalDmg; + } + + public static void setMetalDmg(double metalDmg) { + EarthShard.metalDmg = metalDmg; + } + + public static int getMaxShards() { + return maxShards; + } + + public static void setMaxShards(int maxShards) { + EarthShard.maxShards = maxShards; + } + + public static void setCooldown(long cooldown) { + EarthShard.cooldown = cooldown; + } + + public boolean isThrown() { + return isThrown; + } + + public void setThrown(boolean thrown) { + isThrown = thrown; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public double getAbilityCollisionRadius() { + return abilityCollisionRadius; + } + + public void setAbilityCollisionRadius(double abilityCollisionRadius) { + this.abilityCollisionRadius = abilityCollisionRadius; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public void setEntityCollisionRadius(double entityCollisionRadius) { + this.entityCollisionRadius = entityCollisionRadius; + } + + public List getTblockTracker() { + return tblockTracker; + } + + public List getReadyBlocksTracker() { + return readyBlocksTracker; + } + + public List getFallingBlocks() { + return fallingBlocks; + } + + public boolean isAllowKnockup() { + return allowKnockup; + } + + public void setAllowKnockup(boolean allowKnockup) { + this.allowKnockup = allowKnockup; + } + + public double getKnockupVelocity() { + return knockupVelocity; + } + + public void setKnockupVelocity(double knockupVelocity) { + this.knockupVelocity = knockupVelocity; + } + + public double getKnockupRange() { + return knockupRange; + } + + public void setKnockupRange(double knockupRange) { + this.knockupRange = knockupRange; + } + + public boolean isAllowKnockupSelf() { + return allowKnockupSelf; + } + + public void setAllowKnockupSelf(boolean allowKnockupSelf) { + this.allowKnockupSelf = allowKnockupSelf; + } + + public double getKnockupSelfVelocity() { + return knockupSelfVelocity; + } + + public void setKnockupSelfVelocity(double knockupSelfVelocity) { + this.knockupSelfVelocity = knockupSelfVelocity; + } + + public double getKnockupSelfRange() { + return knockupSelfRange; + } + + public void setKnockupSelfRange(double knockupSelfRange) { + this.knockupSelfRange = knockupSelfRange; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthShard.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java b/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java new file mode 100644 index 0000000..425962b --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthSurf.java @@ -0,0 +1,505 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.MaterialUtil; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class EarthSurf extends EarthAbility implements AddonAbility { + private static final double TARGET_HEIGHT = 1.5; + + private Location location; + private double prevHealth; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private long minimumCooldown; + @Attribute(Attribute.DURATION) + private long duration; + private boolean cooldownEnabled; + private boolean durationEnabled; + private boolean removeOnAnyDamage; + @Attribute(Attribute.SPEED) + private double speed; + private double springStiffness; + private final Set ridingBlocks = new HashSet<>(); + private CollisionDetector collisionDetector = new DefaultCollisionDetector(); + private DoubleSmoother heightSmoother; + + public EarthSurf(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, EarthSurf.class)) { + getAbility(player, EarthSurf.class).remove(); + return; + } + + setFields(); + + location = player.getLocation(); + + if (canStart()) { + prevHealth = player.getHealth(); + + this.flightHandler.createInstance(player, this.getName()); + player.setAllowFlight(true); + player.setFlying(false); + start(); + } + } + + private boolean canStart() { + Block beneath = getBlockBeneath(player.getLocation().clone()); + double maxHeight = getMaxHeight(); + + return isEarthbendable(player, beneath) && !isMetal(beneath) && beneath.getLocation().distanceSquared(player.getLocation()) <= maxHeight * maxHeight && !EarthAbility.getMovedEarth().containsKey(beneath); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.Cooldown"); + minimumCooldown = config.getLong("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown"); + duration = config.getLong("Abilities.Earth.EarthSurf.Duration.Duration"); + cooldownEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Enabled"); + durationEnabled = config.getBoolean("Abilities.Earth.EarthSurf.Duration.Enabled"); + removeOnAnyDamage = config.getBoolean("Abilities.Earth.EarthSurf.RemoveOnAnyDamage"); + speed = config.getDouble("Abilities.Earth.EarthSurf.Speed"); + springStiffness = config.getDouble("Abilities.Earth.EarthSurf.SpringStiffness"); + + int smootherSize = config.getInt("Abilities.Earth.EarthSurf.HeightTolerance"); + this.heightSmoother = new DoubleSmoother(Math.max(smootherSize, 1)); + + if (config.getBoolean("Abilities.Earth.EarthSurf.RelaxedCollisions")) { + this.collisionDetector = new RelaxedCollisionDetector(); + } + + if (!config.getBoolean("Abilities.Earth.EarthSurf.Cooldown.Scaled")) { + minimumCooldown = cooldown; + } + } + + @Override + public void progress() { + if (shouldRemove()) { + remove(); + return; + } + + this.player.setFlying(false); + + if (!collisionDetector.isColliding(player) && player.getHealth() >= prevHealth) { + movePlayer(); + + if (removeOnAnyDamage) { + prevHealth = player.getHealth(); + } + } else { + remove(); + } + } + + private boolean shouldRemove() { + if (player == null || player.isDead() || !player.isOnline()) return true; + if (!bPlayer.canBendIgnoreCooldowns(this)) return true; + if (!isEarthbendable(player, getBlockBeneath(player.getLocation().clone()))) return true; + if (durationEnabled && System.currentTimeMillis() > getStartTime() + duration) return true; + + return player.isSneaking(); + } + + private void movePlayer() { + location = player.getEyeLocation().clone(); + location.setPitch(0); + Vector direction = location.getDirection().normalize(); + + // How far the player is above the ground. + double height = getPlayerDistance(); + double maxHeight = getMaxHeight(); + double smoothedHeight = heightSmoother.add(height); + + // Destroy ability if player gets too far from ground. + if (smoothedHeight > maxHeight) { + remove(); + return; + } + + // Calculate the spring force to push the player back to the target height. + double displacement = height - TARGET_HEIGHT; + double force = -springStiffness * displacement; + + double maxForce = 0.5; + if (Math.abs(force) > maxForce) { + // Cap the force to maxForce so the player isn't instantly pulled to the ground. + force = force / Math.abs(force) * maxForce; + } + + Vector velocity = direction.clone().multiply(speed).setY(force); + + rideWave(); + + player.setVelocity(velocity); + player.setFallDistance(0); + } + + private double getMaxHeight() { + return TARGET_HEIGHT + 2.0; + } + + private double getPlayerDistance() { + Location l = player.getLocation().clone(); + while (true) { + if (l.getBlockY() <= l.getWorld().getMinHeight()) break; + if (ElementalAbility.isAir(l.getBlock().getType()) && ridingBlocks.contains(l.getBlock())) break; + if (GeneralMethods.isSolid(l.getBlock())) break; + + l.add(0, -0.1, 0); + } + return player.getLocation().getY() - l.getY(); + } + + private Block getBlockBeneath(Location l) { + while (l.getBlockY() > l.getWorld().getMinHeight() && MaterialUtil.isTransparent(l.getBlock())) { + l.add(0, -0.5, 0); + } + return l.getBlock(); + } + + private void rideWave() { + for (int i = 0; i < 3; i++) { + Location loc = location.clone(); + if (i < 2) + loc.add(getSideDirection(i)); + + //Player Positioning + double distOffset = 2.5; + Location bL = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); + while (!ElementalAbility.isAir(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()).getBlock().getType())) { + loc.add(0, 0.1, 0); + } + + Block beneath = getBlockBeneath(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld())); + if (isEarthbendable(player, beneath) && beneath != null && !EarthAbility.getMovedEarth().containsKey(beneath)) { + Block block = loc.clone().add(0, -3.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset - 0.5)).toLocation(player.getWorld()).getBlock(); + Location temp = loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()); + + if (RegionProtection.isRegionProtected(this, block.getLocation())) { + continue; + } + // Don't render blocks above the player because it looks bad. + // TODO: Change this check to see if it's a reachable position instead. + if (block.getLocation().getY() > this.player.getLocation().getY()) { + continue; + } + + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + if (!GeneralMethods.isSolid(block.getLocation().add(0, 1, 0).getBlock()) && !ElementalAbility.isAir(block.getLocation().add(0, 1, 0).getBlock().getType())) { + if (DensityShift.isPassiveSand(block.getRelative(BlockFace.UP))) { + DensityShift.revertSand(block.getRelative(BlockFace.UP)); + } + + new TempBlock(block.getRelative(BlockFace.UP), Material.AIR.createBlockData()); + } + + if (GeneralMethods.isSolid(block)) { + ridingBlocks.add(block); + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L, true, ridingBlocks::remove); + } else { + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), 1000L); + } + + new TempFallingBlock(temp, getBlockBeneath(bL).getBlockData(), new Vector(0, 0.25, 0), this, true); + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(loc.clone().add(0, -2.9, 0).toVector().add(location.clone().getDirection().multiply(distOffset)).toLocation(player.getWorld()), 1.5D)) { + if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { + e.setVelocity(new Vector(0, 0.3, 0)); + } + } + } + } + } + + private Vector getSideDirection(int side) { + Vector direction = location.clone().getDirection().normalize(); + switch (side) { + case 0: // RIGHT + return new Vector(-direction.getZ(), 0.0, direction.getX()).normalize(); + case 1: // LEFT + return new Vector(direction.getZ(), 0.0, -direction.getX()).normalize(); + default: + break; + } + + return null; + } + + @Override + public void remove() { + this.flightHandler.removeInstance(player, this.getName()); + + if (cooldownEnabled && player.isOnline()) { + long scaledCooldown = cooldown; + + if (durationEnabled && duration > 0) { + double t = Math.min((System.currentTimeMillis() - this.getStartTime()) / (double) duration, 1.0); + scaledCooldown = Math.max((long) (cooldown * t), minimumCooldown); + } + + bPlayer.addCooldown(this, scaledCooldown); + } + + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "EarthSurf"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthSurf.Description"); + } + + public static double getTargetHeight() { + return TARGET_HEIGHT; + } + + public void setLocation(Location location) { + this.location = location; + } + + public double getPrevHealth() { + return prevHealth; + } + + public void setPrevHealth(double prevHealth) { + this.prevHealth = prevHealth; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getMinimumCooldown() { + return minimumCooldown; + } + + public void setMinimumCooldown(long minimumCooldown) { + this.minimumCooldown = minimumCooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public boolean isCooldownEnabled() { + return cooldownEnabled; + } + + public void setCooldownEnabled(boolean cooldownEnabled) { + this.cooldownEnabled = cooldownEnabled; + } + + public boolean isDurationEnabled() { + return durationEnabled; + } + + public void setDurationEnabled(boolean durationEnabled) { + this.durationEnabled = durationEnabled; + } + + public boolean isRemoveOnAnyDamage() { + return removeOnAnyDamage; + } + + public void setRemoveOnAnyDamage(boolean removeOnAnyDamage) { + this.removeOnAnyDamage = removeOnAnyDamage; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public double getSpringStiffness() { + return springStiffness; + } + + public void setSpringStiffness(double springStiffness) { + this.springStiffness = springStiffness; + } + + public Set getRidingBlocks() { + return ridingBlocks; + } + + public CollisionDetector getCollisionDetector() { + return collisionDetector; + } + + public void setCollisionDetector(CollisionDetector collisionDetector) { + this.collisionDetector = collisionDetector; + } + + public DoubleSmoother getHeightSmoother() { + return heightSmoother; + } + + public void setHeightSmoother(DoubleSmoother heightSmoother) { + this.heightSmoother = heightSmoother; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + return config.getBoolean("Abilities.Earth.EarthSurf.Enabled"); + } + + private interface CollisionDetector { + boolean isColliding(Player player); + } + + private abstract static class AbstractCollisionDetector implements CollisionDetector { + protected boolean isCollision(Location location) { + Block block = location.getBlock(); + return !MaterialUtil.isTransparent(block) || block.isLiquid() || block.getType().isSolid(); + } + } + + private class DefaultCollisionDetector extends AbstractCollisionDetector { + @Override + public boolean isColliding(Player player) { + // The location in front of the player, where the player will be in one second. + Location front = player.getEyeLocation().clone(); + front.setPitch(0); + + Vector direction = front.getDirection().clone().setY(0).normalize(); + double playerSpeed = player.getVelocity().clone().setY(0).length(); + + front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); + + for (int i = 0; i < 3; ++i) { + Location location = front.clone().add(0, -i, 0); + if (isCollision(location)) { + return true; + } + } + + return false; + } + } + + private class RelaxedCollisionDetector extends AbstractCollisionDetector { + @Override + public boolean isColliding(Player player) { + // The location in front of the player, where the player will be in one second. + Location front = player.getEyeLocation().clone().subtract(0.0, 0.5, 0.0); + front.setPitch(0); + + Vector direction = front.getDirection().clone().setY(0).normalize(); + double playerSpeed = player.getVelocity().clone().setY(0).length(); + + front.add(direction.clone().multiply(Math.max(speed, playerSpeed))); + + return isCollision(front); + } + } + + private static class DoubleSmoother { + private final double[] values; + private final int size; + private int index; + + public DoubleSmoother(int size) { + this.size = size; + this.index = 0; + + values = new double[size]; + } + + public double add(double value) { + values[index] = value; + index = (index + 1) % size; + return get(); + } + + public double get() { + return Arrays.stream(this.values).sum() / this.size; + } + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/Fissure.java b/src/com/jedk1/jedcore/ability/earthbending/Fissure.java new file mode 100644 index 0000000..c3bbc98 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/Fissure.java @@ -0,0 +1,439 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.Information; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +public class Fissure extends LavaAbility implements AddonAbility { + + @Attribute(Attribute.RANGE) + private int slapRange; + @Attribute(Attribute.WIDTH) + private int maxWidth; + private long slapDelay; + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + private Location location; + private Vector direction; + private Vector blockDirection; + private long time; + private long step; + private int slap; + private int width; + private boolean progressed; + + static Random rand = new Random(); + + private final List centerSlap = new ArrayList<>(); + private final List blocks = new ArrayList<>(); + private final List tempblocks = new ArrayList<>(); + + public Fissure(Player player) { + super(player); + + if (!bPlayer.canBend(this) || hasAbility(player, Fissure.class) || !bPlayer.canLavabend()) { + return; + } + + setFields(); + time = System.currentTimeMillis(); + step = System.currentTimeMillis() + slapDelay; + location = player.getLocation().clone(); + location.setPitch(0); + direction = location.getDirection(); + blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); + blockDirection = blockDirection.setZ(Math.round(direction.getZ())); + if (prepareLine()) { + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + slapRange = config.getInt("Abilities.Earth.Fissure.SlapRange"); + maxWidth = config.getInt("Abilities.Earth.Fissure.MaxWidth"); + slapDelay = config.getInt("Abilities.Earth.Fissure.SlapDelay"); + duration = config.getInt("Abilities.Earth.Fissure.Duration"); + cooldown = config.getInt("Abilities.Earth.Fissure.Cooldown"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (System.currentTimeMillis() > step && slap <= centerSlap.size()) { + time = System.currentTimeMillis(); + step = System.currentTimeMillis() + slapDelay; + slapCenter(); + slap++; + } + if (System.currentTimeMillis() > time + duration) { + remove(); + } + } + + private boolean prepareLine() { + direction = player.getEyeLocation().getDirection().setY(0).normalize(); + blockDirection = this.direction.clone().setX(Math.round(this.direction.getX())); + blockDirection = blockDirection.setZ(Math.round(direction.getZ())); + Location origin = player.getLocation().add(0, -1, 0).add(blockDirection.multiply(2)); + if (isEarthbendable(player, origin.getBlock())) { + BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, slapRange); + + while (bi.hasNext()) { + Block b = bi.next(); + + if (b.getY() > b.getWorld().getMinHeight() && b.getY() < b.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, b.getLocation())) { + if (EarthAbility.getMovedEarth().containsKey(b)){ + Information info = EarthAbility.getMovedEarth().get(b); + if(!info.getBlock().equals(b)) { + continue; + } + } + + while (!isEarthbendable(player, b)) { + b = b.getRelative(BlockFace.DOWN); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b)) { + break; + } + } + + while (!isTransparent(b.getRelative(BlockFace.UP))) { + b = b.getRelative(BlockFace.UP); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(player, b)) { + centerSlap.add(b.getLocation()); + } else { + break; + } + } + } + return true; + } + return false; + } + + private void slapCenter() { + for (Location location : centerSlap) { + if (centerSlap.indexOf(location) == slap) { + addTempBlock(location.getBlock(), Material.LAVA); + } + } + if (slap >= centerSlap.size()) { + progressed = true; + } + } + + public static void performAction(Player player) { + if (hasAbility(player, Fissure.class)) { + getAbility(player, Fissure.class).performAction(); + } + } + + private void performAction() { + if (width < maxWidth) { + expandFissure(); + } else if (blocks.contains(player.getTargetBlock(null, 10))) { + forceRevert(); + } + } + + private void expandFissure() { + if (progressed && width <= maxWidth) { + width++; + for (Location location : centerSlap) { + Block left = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)), width); + expand(left); + + Block right = location.getBlock().getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockDirection)).getOppositeFace(), width); + expand(right); + } + } + Collections.reverse(blocks); + } + + private void expand(Block block) { + if (block != null && block.getY() > block.getWorld().getMinHeight() && block.getY() < block.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, block.getLocation())) { + if (EarthAbility.getMovedEarth().containsKey(block)){ + Information info = EarthAbility.getMovedEarth().get(block); + if(!info.getBlock().equals(block)) { + return; + } + } + + while (!isEarthbendable(player, block)) { + block = block.getRelative(BlockFace.DOWN); + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, block)) { + break; + } + } + + while (!isTransparent(player, block.getRelative(BlockFace.UP))) { + block = block.getRelative(BlockFace.UP); + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, block.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(player, block)) { + addTempBlock(block, Material.LAVA); + } + } + } + + private void addTempBlock(Block block, Material material) { + ParticleEffect.LAVA.display(block.getLocation(), 0, 0, 0, 0, 1); + playEarthbendingSound(block.getLocation()); + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + tempblocks.add(new TempBlock(block, material.createBlockData(), this)); + blocks.add(block); + } + + public BlockFace getLeftBlockFace(BlockFace forward) { + switch (forward) { + case NORTH: + return BlockFace.WEST; + case SOUTH: + return BlockFace.EAST; + case WEST: + return BlockFace.SOUTH; + case EAST: + return BlockFace.NORTH; + case NORTH_WEST: + return BlockFace.SOUTH_WEST; + case NORTH_EAST: + return BlockFace.NORTH_WEST; + case SOUTH_WEST: + return BlockFace.SOUTH_EAST; + case SOUTH_EAST: + return BlockFace.NORTH_EAST; + default: + return BlockFace.NORTH; + } + } + + private void forceRevert() { + coolLava(); + } + + private void coolLava() { + tempblocks.forEach(TempBlock::revertBlock); + for (Block block : blocks) { + new TempBlock(block, Material.STONE.createBlockData(), 500 + (long) rand.nextInt((int) 1000)); + } + blocks.clear(); + tempblocks.clear(); + } + + @Override + public void remove() { + coolLava(); + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "Fissure"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.Fissure.Description"); + } + + public int getSlapRange() { + return slapRange; + } + + public void setSlapRange(int slapRange) { + this.slapRange = slapRange; + } + + public int getMaxWidth() { + return maxWidth; + } + + public void setMaxWidth(int maxWidth) { + this.maxWidth = maxWidth; + } + + public long getSlapDelay() { + return slapDelay; + } + + public void setSlapDelay(long slapDelay) { + this.slapDelay = slapDelay; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public void setLocation(Location location) { + this.location = location; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public Vector getBlockDirection() { + return blockDirection; + } + + public void setBlockDirection(Vector blockDirection) { + this.blockDirection = blockDirection; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public long getStep() { + return step; + } + + public void setStep(long step) { + this.step = step; + } + + public int getSlap() { + return slap; + } + + public void setSlap(int slap) { + this.slap = slap; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public boolean isProgressed() { + return progressed; + } + + public void setProgressed(boolean progressed) { + this.progressed = progressed; + } + + public List getCenterSlap() { + return centerSlap; + } + + public List getBlocks() { + return blocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.Fissure.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java b/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java new file mode 100644 index 0000000..5d64f5f --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaDisc.java @@ -0,0 +1,555 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class LavaDisc extends LavaAbility implements AddonAbility { + + private Location location; + private int recallCount; + + private long time; + + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + private int recallLimit; + private boolean trailFlow; + + private CompositeRemovalPolicy removalPolicy; + private DiscRenderer discRenderer; + private State state; + private final Set trailBlocks = new HashSet<>(); + + public LavaDisc(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { + return; + } + + // Allow new LavaDisc if all existing instances for that player are in CleanupState. + for (LavaDisc disc : CoreAbility.getAbilities(player, LavaDisc.class)) { + if (!(disc.state instanceof CleanupState)) { + return; + } + } + + state = new HoldState(); + time = System.currentTimeMillis(); + discRenderer = new DiscRenderer(this.player); + + setFields(); + + if (prepare()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + damage = config.getDouble("Abilities.Earth.LavaDisc.Damage"); + cooldown = config.getLong("Abilities.Earth.LavaDisc.Cooldown"); + duration = config.getLong("Abilities.Earth.LavaDisc.Duration"); + recallLimit = config.getInt("Abilities.Earth.LavaDisc.RecallLimit") - 1; + trailFlow = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.TrailFlow"); + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new SwappedSlotsRemovalPolicy<>(bPlayer, LavaDisc.class) + ); + + this.removalPolicy.load(config); + } + + private boolean prepare() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + long sourceRegen = config.getLong("Abilities.Earth.LavaDisc.Source.RegenTime"); + boolean lavaOnly = config.getBoolean("Abilities.Earth.LavaDisc.Source.LavaOnly"); + double sourceRange = config.getDouble("Abilities.Earth.LavaDisc.Source.Range"); + + Block lavaSource = getLavaSourceBlock(player, sourceRange); + if (lavaSource != null && !EarthAbility.getMovedEarth().containsKey(lavaSource)) { + new RegenTempBlock(lavaSource, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); + return true; + } else { + Block earthSource = getEarthSourceBlock(sourceRange); + if (earthSource != null && !lavaOnly && !EarthAbility.getMovedEarth().containsKey(earthSource)) { + new RegenTempBlock(earthSource, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(4)), sourceRegen); + return true; + } + } + + return false; + } + + @Override + public void progress() { + if (this.removalPolicy.shouldRemove()) { + if (!player.isOnline()) { + // Revert all of the lava blocks if the player goes offline. + for (Block block : trailBlocks) { + RegenTempBlock.revert(block); + } + bPlayer.addCooldown(this); + remove(); + return; + } else if (!(state instanceof CleanupState)) { + state = new CleanupState(); + } + } + + if (!hasAbility(player, LavaDisc.class)) { + return; + } + + state.update(); + } + + public static boolean canFlowFrom(Block from) { + Material type = from.getType(); + if (type != Material.LAVA && !ElementalAbility.isAir(type)) { + return true; + } + + for (LavaDisc disc : CoreAbility.getAbilities(LavaDisc.class)) { + if (disc.trailFlow) continue; + + if (disc.trailBlocks.contains(from)) { + return false; + } + } + + return true; + } + + private boolean isLocationSafe() { + if (!isLocationSafe(location)) { + return false; + } + + Block block = location.getBlock(); + + return isTransparent(block); + } + + private boolean isLocationSafe(Location location) { + if (location == null || location.getWorld() == null) { + return false; + } + + return location.getY() >= location.getWorld().getMinHeight() && location.getY() <= (location.getWorld().getMaxHeight() - 1); + } + + private void doDamage(Entity entity) { + DamageHandler.damageEntity(entity, damage, this); + entity.setFireTicks(20); + new FireDamageTimer(entity, player, this); + ParticleEffect.LAVA.display(entity.getLocation(), 15, Math.random(), Math.random(), Math.random(), 0.1); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "LavaDisc"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaDisc.Description"); + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getRecallCount() { + return recallCount; + } + + public void setRecallCount(int recallCount) { + this.recallCount = recallCount; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public int getRecallLimit() { + return recallLimit; + } + + public void setRecallLimit(int recallLimit) { + this.recallLimit = recallLimit; + } + + public boolean isTrailFlow() { + return trailFlow; + } + + public void setTrailFlow(boolean trailFlow) { + this.trailFlow = trailFlow; + } + + public DiscRenderer getDiscRenderer() { + return discRenderer; + } + + public void setDiscRenderer(DiscRenderer discRenderer) { + this.discRenderer = discRenderer; + } + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + public Set getTrailBlocks() { + return trailBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.LavaDisc.Enabled"); + } + + private interface State { + void update(); + } + + // Renders the particles showing that the player is holding lava. + // Transitions to ForwardTravelState when the player stops sneaking. + private class HoldState implements State { + @Override + public void update() { + location = player.getEyeLocation(); + Vector dV = location.getDirection().normalize(); + location.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); + + dV = dV.multiply(0.1); + + while (!isLocationSafe() && isLocationSafe(player.getLocation())) { + location.subtract(dV); + if (location.distanceSquared(player.getEyeLocation()) > (3 * 3)) { + break; + } + } + + discRenderer.render(location, false); + + location.setPitch(0); + + if (!player.isSneaking()) { + time = System.currentTimeMillis(); + state = new ForwardTravelState(location.getDirection().normalize()); + } + } + } + + private abstract class TravelState implements State { + private final boolean passHit; + + protected Vector direction; + protected boolean hasHit; + + public TravelState() { + this(player.getEyeLocation().getDirection()); + } + + public TravelState(Vector direction) { + this.direction = direction; + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + passHit = config.getBoolean("Abilities.Earth.LavaDisc.ContinueAfterEntityHit"); + } + + protected void move() { + for (int i = 0; i < 5; i++) { + location = location.add(direction.clone().multiply(0.15)); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2.0D)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + doDamage(entity); + if (!passHit) { + hasHit = true; + return; + } + } + } + } + } + } + + // Moves the disc forward. Makes the disc destroy blocks if enabled. + // Transitions to ReverseTravelState if the player starts sneaking and can recall. + // Transitions to CleanupState if it times out or hits an entity. + private class ForwardTravelState extends TravelState { + public ForwardTravelState() { + this(player.getEyeLocation().getDirection()); + } + + public ForwardTravelState(Vector direction) { + super(direction); + } + + @Override + public void update() { + if (!isLocationSafe() || System.currentTimeMillis() > time + duration) { + state = new CleanupState(); + return; + } + + if (player.isSneaking() && recallCount <= recallLimit) { + state = new ReverseTravelState(); + return; + } + + alterPitch(); + move(); + discRenderer.render(location, true); + + if (hasHit) { + state = new CleanupState(); + } + } + + private void alterPitch() { + Location loc = player.getLocation().clone(); + + if (loc.getPitch() < -20) + loc.setPitch(-20); + if (loc.getPitch() > 20) + loc.setPitch(20); + + direction = loc.getDirection().normalize(); + } + } + + // Returns the disc to the player. + // Transitions to ForwardTravelState if the player stops sneaking. + // Transitions to HoldState if the disc gets close enough to the player. + private class ReverseTravelState extends TravelState { + @Override + public void update() { + if (!player.isSneaking()) { + state = new ForwardTravelState(); + return; + } + + Location loc = player.getEyeLocation(); + Vector dV = loc.getDirection().normalize(); + loc.add(new Vector(dV.getX() * 3, dV.getY() * 3, dV.getZ() * 3)); + + Vector vector = loc.toVector().subtract(location.toVector()); + direction = loc.setDirection(vector).getDirection().normalize(); + + move(); + discRenderer.render(location, true); + + double distanceAway = location.distance(loc); + if (distanceAway < 0.5) { + recallCount++; + // Player is holding the disc when it gets close enough to them. + state = new HoldState(); + } + } + } + + // Waits for the RegenTempBlocks to revert. + // This exists so the instance stays alive and block flow events can stop the lava from flowing. + private class CleanupState implements State { + private final long startTime; + private final long regenTime; + + public CleanupState() { + this.startTime = System.currentTimeMillis(); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); + bPlayer.addCooldown(LavaDisc.this); + } + + @Override + public void update() { + if (System.currentTimeMillis() >= startTime + regenTime || trailBlocks.isEmpty()) { + remove(); + } + } + } + + private class DiscRenderer { + private final Player player; + private int angle; + + private final boolean damageBlocks; + private final List meltable; + private final long regenTime; + private final boolean lavaTrail; + + private final int particles; + + + public DiscRenderer(Player player) { + this.player = player; + this.angle = 0; + + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + damageBlocks = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.BlockDamage"); + meltable = config.getStringList("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks"); + regenTime = config.getLong("Abilities.Earth.LavaDisc.Destroy.RegenTime"); + lavaTrail = config.getBoolean("Abilities.Earth.LavaDisc.Destroy.LavaTrail"); + particles = config.getInt("Abilities.Earth.LavaDisc.Particles"); + } + + void render(Location location, boolean largeLava) { + if (largeLava) + ParticleEffect.LAVA.display(location, particles * 2, Math.random(), Math.random(), Math.random(), 0.1); + else + ParticleEffect.LAVA.display(location, 1, Math.random(), Math.random(), Math.random(), 0.1); + + angle += 1; + if (angle > 360) + angle = 0; + + for (Location l : JCMethods.getCirclePoints(location, 20, 1, angle)) { + ParticleEffect.REDSTONE.display(l, 0, 196, 93, 0, 0.005F, new Particle.DustOptions(Color.fromRGB(196, 93, 0), 1)); + if (largeLava && damageBlocks) + damageBlocks(l); + } + + for (Location l : JCMethods.getCirclePoints(location, 10, 0.5, angle)) { + ParticleEffect.FLAME.display(l, 1, 0, 0, 0, 0.01); + ParticleEffect.SMOKE_NORMAL.display(l, 1, 0, 0, 0, 0.05); + if (largeLava && damageBlocks) + damageBlocks(l); + } + } + + private void damageBlocks(Location l) { + Block block = l.getBlock(); + if (EarthAbility.getMovedEarth().containsKey(block)) { + ParticleEffect.LAVA.display(l, 20, 0.5, 0.5, 0.5, 0.2); + ParticleEffect.BLOCK_CRACK.display(l, 15, 0.3, 0.3, 0.3, 0.15, Material.LAVA.createBlockData()); + return; + } + if (!RegionProtection.isRegionProtected(player, l, LavaDisc.this)) { + if (!TempBlock.isTempBlock(block) && (isEarthbendable(player, block) || isMetal(block) || meltable.contains(block.getType().name()))) { + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + if (lavaTrail) { + new RegenTempBlock(block, Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled) bd).setLevel(4)), regenTime); + + trailBlocks.add(block); + } else { + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), regenTime); + } + + ParticleEffect.LAVA.display(l, particles * 2, Math.random(), Math.random(), Math.random(), 0.2); + } + } + } + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java b/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java new file mode 100644 index 0000000..4b836e2 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaFlux.java @@ -0,0 +1,445 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.Information; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.BlockIterator; +import org.bukkit.util.Vector; + +import java.util.*; + +public class LavaFlux extends LavaAbility implements AddonAbility { + + @Attribute(Attribute.SPEED) + private int speed; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + private long cleanup; + @Attribute(Attribute.DAMAGE) + private double damage; + private boolean wave; + + private Location location; + private int step; + private int counter; + private long time; + private boolean complete; + + private double knockUp; + private double knockBack; + + Random rand = new Random(); + + private static final BlockData LAVA = Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(1)); + + private final List flux = new ArrayList<>(); + + private Map blocks = new HashMap<>(); + private Map above = new HashMap<>(); + + public LavaFlux(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { + return; + } + + setFields(); + time = System.currentTimeMillis(); + if (prepareLine()) { + start(); + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + speed = config.getInt("Abilities.Earth.LavaFlux.Speed"); + if (speed < 1) speed = 1; + range = config.getInt("Abilities.Earth.LavaFlux.Range"); + cooldown = config.getLong("Abilities.Earth.LavaFlux.Cooldown"); + duration = config.getLong("Abilities.Earth.LavaFlux.Duration"); + cleanup = config.getLong("Abilities.Earth.LavaFlux.Cleanup"); + damage = config.getDouble("Abilities.Earth.LavaFlux.Damage"); + wave = config.getBoolean("Abilities.Earth.LavaFlux.Wave"); + knockUp = config.getDouble("Abilities.Earth.LavaFlux.KnockUp"); + knockBack = config.getDouble("Abilities.Earth.LavaFlux.KnockBack"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + counter++; + if (!complete) { + if (speed <= 1 || counter % speed == 0) { + for (int i = 0; i <= 2; i++) { + step++; + progressFlux(); + } + } + } else if (duration > cleanup) { + if (System.currentTimeMillis() > time + duration) { + for (TempBlock tb : blocks.values()) { + if (!tb.isReverted()) tb.setType(Material.STONE); + } + remove(); + } + } + } + + private boolean prepareLine() { + Vector direction = player.getEyeLocation().getDirection().setY(0).normalize(); + Vector blockdirection = direction.clone().setX(Math.round(direction.getX())); + blockdirection = blockdirection.setZ(Math.round(direction.getZ())); + Location origin = player.getLocation().add(0, -1, 0).add(blockdirection.multiply(2)); + if (isEarthbendable(player, origin.getBlock())) { + BlockIterator bi = new BlockIterator(player.getWorld(), origin.toVector(), direction, 0, range); + + while (bi.hasNext()) { + Block b = bi.next(); + + if (b.getY() > b.getWorld().getMinHeight() && b.getY() < b.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, b.getLocation()) && !EarthAbility.getMovedEarth().containsKey(b)) { + if (isWater(b)) break; + while (!isEarthbendable(player, b)) { + b = b.getRelative(BlockFace.DOWN); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b)) { + break; + } + } + + while (!isTransparent(b.getRelative(BlockFace.UP))) { + b = b.getRelative(BlockFace.UP); + if (b.getY() < b.getWorld().getMinHeight() || b.getY() > b.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(player, b.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(player, b)) { + flux.add(b.getLocation()); + Block left = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)), 1); + expand(left); + Block right = b.getRelative(getLeftBlockFace(GeneralMethods.getCardinalDirection(blockdirection)).getOppositeFace(), 1); + expand(right); + } else { + break; + } + } + } + return true; + } + return false; + } + + private void progressFlux() { + for (Location location : flux) { + if (flux.indexOf(location) <= step) { + if (!blocks.containsKey(location.getBlock())) { //Make a new temp block if we haven't made one there before + blocks.put(location.getBlock(), new TempBlock(location.getBlock(), LAVA, duration + cleanup, this)); + } + + //new RegenTempBlock(location.getBlock(), Material.LAVA, LAVA, duration + cleanup); + this.location = location; + if (flux.indexOf(location) == step) { + Block above = location.getBlock().getRelative(BlockFace.UP); + ParticleEffect.LAVA.display(above.getLocation(), 2, Math.random(), Math.random(), Math.random(), 0); + applyDamageFromWave(above.getLocation()); + + if (isPlant(above) || isSnow(above)) { + final Block above2 = above.getRelative(BlockFace.UP); + if (isPlant(above) || isSnow(above)) { + TempBlock tb = new TempBlock(above, Material.AIR.createBlockData(), duration + cleanup, this); + this.above.put(above, tb); + if (isPlant(above2) && above2.getBlockData() instanceof Bisected) { + TempBlock tb2 = new TempBlock(above2, Material.AIR.createBlockData(), duration + cleanup + 30_000, this); + tb.addAttachedBlock(tb2); + } + } + } else if (wave && isTransparent(above)) { + new TempBlock(location.getBlock().getRelative(BlockFace.UP), LAVA, speed * 150L, this); + } + } + } + } + if (step >= flux.size()) { + wave = false; + complete = true; + time = System.currentTimeMillis(); + + for (TempBlock tb : blocks.values()) { //Make sure they all revert at the same time because it looks nice + long time = duration + cleanup + rand.nextInt(1000); + tb.setRevertTime(time); + + if (this.above.containsKey(tb.getBlock().getRelative(BlockFace.UP))) { + this.above.get(tb.getBlock().getRelative(BlockFace.UP)).setRevertTime(time); + } + } + } + } + + private void applyDamageFromWave(Location location) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 1.5)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + LivingEntity livingEntity = (LivingEntity) entity; + + DamageHandler.damageEntity(entity, damage, this); + new FireDamageTimer(entity, player, this); + + Vector direction = livingEntity.getLocation().toVector().subtract(player.getLocation().toVector()).normalize(); + Vector knockbackVelocity = direction.multiply(knockBack).setY(knockUp); + + livingEntity.setVelocity(knockbackVelocity); + } + } + } + + private void expand(Block block) { + if (block != null && block.getY() > block.getWorld().getMinHeight() && block.getY() < block.getWorld().getMaxHeight() && !RegionProtection.isRegionProtected(this, block.getLocation())) { + if (EarthAbility.getMovedEarth().containsKey(block)){ + Information info = EarthAbility.getMovedEarth().get(block); + if(!info.getBlock().equals(block)) { + return; + } + } + + if (isWater(block)) return; + while (!isEarthbendable(block)) { + block = block.getRelative(BlockFace.DOWN); + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(block)) { + break; + } + } + + while (!isTransparent(block.getRelative(BlockFace.UP))) { + block = block.getRelative(BlockFace.UP); + if (block.getY() < block.getWorld().getMinHeight() || block.getY() > block.getWorld().getMaxHeight()) { + break; + } + if (isEarthbendable(block.getRelative(BlockFace.UP))) { + break; + } + } + + if (isEarthbendable(block)) { + flux.add(block.getLocation()); + } + } + } + + public BlockFace getLeftBlockFace(BlockFace forward) { + switch (forward) { + case NORTH: + return BlockFace.WEST; + case SOUTH: + return BlockFace.EAST; + case WEST: + return BlockFace.SOUTH; + case NORTH_WEST: + return BlockFace.SOUTH_WEST; + case NORTH_EAST: + return BlockFace.NORTH_WEST; + case SOUTH_WEST: + return BlockFace.SOUTH_EAST; + case SOUTH_EAST: + return BlockFace.NORTH_EAST; + default: + return BlockFace.NORTH; + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "LavaFlux"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaFlux.Description"); + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public long getCleanup() { + return cleanup; + } + + public void setCleanup(long cleanup) { + this.cleanup = cleanup; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean isWave() { + return wave; + } + + public void setWave(boolean wave) { + this.wave = wave; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public int getCounter() { + return counter; + } + + public void setCounter(int counter) { + this.counter = counter; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public boolean isComplete() { + return complete; + } + + public void setComplete(boolean complete) { + this.complete = complete; + } + + public List getFlux() { + return flux; + } + + @Override + public void load() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + if (config.get("Abilities.Earth.LavaFlux.Speed") instanceof String) { + config.set("Abilities.Earth.LavaFlux.Speed", 1); + JedCore.plugin.saveConfig(); + JedCore.plugin.reloadConfig(); + } + } + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.LavaFlux.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java new file mode 100644 index 0000000..2f3aab8 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/LavaThrow.java @@ -0,0 +1,340 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.LavaAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.RayTraceResult; +import org.bukkit.util.Vector; + +import java.util.concurrent.ConcurrentHashMap; + +public class LavaThrow extends LavaAbility implements AddonAbility { + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.SELECT_RANGE) + private int sourceRange; + private long sourceRegen; + @Attribute("MaxShots") + private int shotMax; + @Attribute(Attribute.FIRE_TICK) + private int fireTicks; + @Attribute("CurveFactor") + private double curveFactor; + + private Location location; + private int shots; + private Block selectedSource; + private boolean isInitialState = true; + + private final ConcurrentHashMap blasts = new ConcurrentHashMap<>(); + + public LavaThrow(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canLavabend()) { + return; + } + + setFields(); + + location = player.getLocation(); + location.setPitch(0); + + if (prepare()) { + player.getWorld().playSound(selectedSource.getLocation(), Sound.ITEM_BUCKET_FILL_LAVA, 1.0f, 1.0f); + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.LavaThrow.Cooldown"); + range = config.getInt("Abilities.Earth.LavaThrow.Range"); + damage = config.getDouble("Abilities.Earth.LavaThrow.Damage"); + sourceRange = config.getInt("Abilities.Earth.LavaThrow.SourceGrabRange"); + sourceRegen = config.getLong("Abilities.Earth.LavaThrow.SourceRegenDelay"); + shotMax = config.getInt("Abilities.Earth.LavaThrow.MaxShots"); + fireTicks = config.getInt("Abilities.Earth.LavaThrow.FireTicks"); + curveFactor = config.getDouble("Abilities.Earth.LavaThrow.CurveFactor"); + } + + @Override + public void progress() { + if (player == null || player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.getBoundAbilityName().equalsIgnoreCase("LAVATHROW")) { + remove(); + if (shots > 0) bPlayer.addCooldown(this); + return; + } + + if (player.getLocation().distance(selectedSource.getLocation()) >= sourceRange) { + remove(); + if (shots > 0) bPlayer.addCooldown(this); + return; + } + + if (blasts.isEmpty() && shots >= shotMax && !isInitialState) { + remove(); + bPlayer.addCooldown(this); + return; + } + + selectedSource.getWorld().spawnParticle(Particle.FLAME, selectedSource.getLocation(), 2, 0.3, 1.0, 0.3, 0.05); + selectedSource.getWorld().spawnParticle(Particle.LAVA, selectedSource.getLocation(), 2, 0.2, 0.2, 0.2, 0); + + handleBlasts(); + } + + private boolean prepare() { + Block targetBlock = getTargetLavaBlock(sourceRange); + + if (targetBlock != null && !TempBlock.isTempBlock(targetBlock) && !EarthAbility.getMovedEarth().containsKey(targetBlock)) { + selectedSource = targetBlock; + return true; + } + + return false; + } + + public Block getTargetLavaBlock(int maxDistance) { + Location eyeLocation = player.getEyeLocation(); + Vector direction = eyeLocation.getDirection(); + World world = player.getWorld(); + + RayTraceResult result = world.rayTraceBlocks( + eyeLocation, direction, maxDistance, + FluidCollisionMode.ALWAYS, true + ); + + if (result != null) { + Block hitBlock = result.getHitBlock(); + if (LavaAbility.isLava(hitBlock)) { + return hitBlock; + } + } + return null; + } + + public void createBlast() { + if (selectedSource != null && shots < shotMax) { + isInitialState = false; + shots++; + + if (shots >= shotMax) { + bPlayer.addCooldown(this); + } + + Location origin = selectedSource.getLocation().clone().add(0, 2, 0); + player.getWorld().playSound(origin, Sound.ITEM_BUCKET_EMPTY_LAVA, 1.0f, 1.0f); + double viewRange = range + origin.distance(player.getEyeLocation()); + Location viewTarget = GeneralMethods.getTargetedLocation(player, viewRange, Material.WATER, Material.LAVA); + Vector direction = viewTarget.clone().subtract(origin).toVector().normalize(); + Location head = origin.clone(); + + head.setDirection(direction); + blasts.put(head, origin); + + new RegenTempBlock(selectedSource.getRelative(BlockFace.UP), Material.LAVA, + Material.LAVA.createBlockData(), 200); + } + } + + public void handleBlasts() { + for (Location l : blasts.keySet()) { + Location head = l.clone(); + Location origin = blasts.get(l); + + if (l.distance(origin) > range) { + blasts.remove(l); + continue; + } + + if (GeneralMethods.isSolid(l.getBlock())) { + blasts.remove(l); + continue; + } + + Vector currentDirection = head.getDirection(); + Vector playerLookDirection = player.getEyeLocation().getDirection(); + + Vector curveVector = playerLookDirection.clone() + .subtract(currentDirection) + .multiply(curveFactor); + + Vector newDirection = currentDirection.clone() + .add(curveVector) + .normalize(); + + head.setDirection(newDirection); + head = head.add(newDirection.multiply(1)); + + new RegenTempBlock(l.getBlock(), Material.LAVA, Material.LAVA.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 200); + ParticleEffect.LAVA.display(head, 1, Math.random(), Math.random(), Math.random(), 0); + + boolean hit = false; + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(l, 2.0D)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !RegionProtection.isRegionProtected(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { + DamageHandler.damageEntity(entity, damage, this); + blasts.remove(l); + + hit = true; + entity.setFireTicks(this.fireTicks); + } + } + + if (!hit) { + blasts.remove(l); + blasts.put(head, origin); + } + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "LavaThrow"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.LavaThrow.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getSourceRange() { + return sourceRange; + } + + public void setSourceRange(int sourceRange) { + this.sourceRange = sourceRange; + } + + public long getSourceRegen() { + return sourceRegen; + } + + public void setSourceRegen(long sourceRegen) { + this.sourceRegen = sourceRegen; + } + + public int getShotMax() { + return shotMax; + } + + public void setShotMax(int shotMax) { + this.shotMax = shotMax; + } + + public int getFireTicks() { + return fireTicks; + } + + public void setFireTicks(int fireTicks) { + this.fireTicks = fireTicks; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getShots() { + return shots; + } + + public void setShots(int shots) { + this.shots = shots; + } + + public ConcurrentHashMap getBlasts() { + return blasts; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.LavaThrow.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java b/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java new file mode 100644 index 0000000..8eb0e43 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/MagnetShield.java @@ -0,0 +1,274 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + + +public class MagnetShield extends MetalAbility implements AddonAbility { + + private static List METAL_LIST; + + private boolean isClickState = false; + private long startTime; + + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.RANGE) + private double range; + + private double velocity; + private boolean repelArrows; + private boolean repelLivingEntities; + private long shiftCooldown; + private long clickCooldown; + + public MagnetShield(Player player) { + super(player); + + if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { + return; + } + + if (!bPlayer.canBend(this)) { + return; + } + + player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); + + setFields(); + loadMaterialsFromConfig(); + start(); + } + + public MagnetShield(Player player, boolean isClickState) { + super(player); + + if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canMetalbend()) { + return; + } + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, MagnetShield.class)) { + getAbility(player, MagnetShield.class).remove(); + return; + } + + setFields(); + + if (isClickState) { + this.isClickState = true; + startTime = System.currentTimeMillis(); + bPlayer.addCooldown(this, duration + 1); + } + + player.getWorld().playSound(player.getLocation(), Sound.BLOCK_CONDUIT_ACTIVATE, 1.0f, 1.5f); + + loadMaterialsFromConfig(); + start(); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this)) { + remove(); + return; + } + + if (isClickState) { + if (System.currentTimeMillis() - startTime >= duration) { + bPlayer.addCooldown(this, clickCooldown); + remove(); + return; + } + } else { + if (!player.isSneaking()) { + bPlayer.addCooldown(this, shiftCooldown); + remove(); + return; + } + } + + renderMagneticFieldLines(); + repelMetal(); + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return player.getLocation(); + } + + @Override + public String getName() { + return "MagnetShield"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MagnetShield.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MagnetShield.Enabled"); + } + + private void renderMagneticFieldLines() { + Location playerLocation = player.getLocation(); + int numLoops = 5; + int pointsPerLoop = 30; + double verticalSpacing = 0.06; + + for (int loop = 0; loop < numLoops; loop++) { + double currentRadius = range * (1 - (double) loop / numLoops); + double currentHeight = ((loop - numLoops / 2.0) * verticalSpacing) + 0.3; + + for (int i = 0; i < pointsPerLoop; i++) { + double angle = 2 * Math.PI * i / pointsPerLoop; + double x = currentRadius * Math.cos(angle); + double z = currentRadius * Math.sin(angle); + Location particleLocation = playerLocation.clone().add(x, currentHeight, z); + JedCore.plugin.getParticleAdapter().displayMagneticParticles(particleLocation); + } + } + } + + private void loadMaterialsFromConfig() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + List materialNames = config.getStringList("Abilities.Earth.MagnetShield.Materials"); + METAL_LIST = new ArrayList<>(); + + for (String materialName : materialNames) { + Material material = Material.getMaterial(materialName.toUpperCase()); + if (material != null) { + METAL_LIST.add(material); + } else { + System.out.println("Invalid material in config: " + materialName); + } + } + } + + private void repelMetal() { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), range)) { + if (e instanceof Item) { + Item i = (Item) e; + if (isMetalMaterial(i.getItemStack().getType())) { + Vector direction = GeneralMethods.getDirection(player.getLocation(), i.getLocation()).multiply(velocity); + i.setVelocity(direction); + } + } else if (e instanceof FallingBlock) { + FallingBlock fb = (FallingBlock) e; + + if (isMetalMaterial(fb.getBlockData().getMaterial())) { + Vector direction = GeneralMethods.getDirection(player.getLocation(), fb.getLocation()).multiply(velocity); + fb.setVelocity(direction); + fb.setDropItem(false); + } + } else if (e instanceof Arrow && repelArrows) { + Arrow arrow = (Arrow) e; + Vector currentVelocity = arrow.getVelocity(); + Vector reversedVelocity = currentVelocity.multiply(-1); + arrow.setVelocity(reversedVelocity); + } else if (e instanceof LivingEntity && repelLivingEntities) { + LivingEntity livingEntity = (LivingEntity) e; + + if (livingEntity.getUniqueId().equals(player.getUniqueId())) continue; + + EntityEquipment equipment = livingEntity.getEquipment(); + if (equipment == null) continue; + + ItemStack mainHand = equipment.getItemInMainHand(); + ItemStack offHand = equipment.getItemInOffHand(); + ItemStack helmet = equipment.getHelmet(); + ItemStack chestplate = equipment.getChestplate(); + ItemStack leggings = equipment.getLeggings(); + ItemStack boots = equipment.getBoots(); + + boolean isMetal = isMetalItem(mainHand) || isMetalItem(offHand) || + isMetalItem(helmet) || isMetalItem(chestplate) || + isMetalItem(leggings) || isMetalItem(boots); + + if (isMetal) { + Vector direction = GeneralMethods.getDirection(player.getLocation(), e.getLocation()).multiply(velocity); + livingEntity.setVelocity(direction); + } + } + } + } + + private boolean isMetalItem(ItemStack itemStack) { + return itemStack != null && METAL_LIST.contains(itemStack.getType()); + } + + private boolean isMetalMaterial(Material material) { + return METAL_LIST.contains(material); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + duration = config.getLong("Abilities.Earth.MagnetShield.Duration"); + shiftCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Shift"); + clickCooldown = config.getLong("Abilities.Earth.MagnetShield.Cooldowns.Click"); + range = config.getDouble("Abilities.Earth.MagnetShield.Range"); + repelArrows = config.getBoolean("Abilities.Earth.MagnetShield.RepelArrows"); + repelLivingEntities = config.getBoolean("Abilities.Earth.MagnetShield.RepelLivingEntities"); + velocity = config.getDouble("Abilities.Earth.MagnetShield.Velocity"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java b/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java new file mode 100644 index 0000000..8bca0c5 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalArmor.java @@ -0,0 +1,211 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.earthbending.EarthArmor; +import com.projectkorra.projectkorra.util.TempArmor; +import com.projectkorra.projectkorra.util.TempPotionEffect; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.potion.PotionEffect; + +import java.util.Arrays; +import java.util.List; + +public class MetalArmor extends EarthAbility implements AddonAbility { + + private static final int GOLD_BLOCK_COLOR = 0xF2F204; + private static final List METAL_COLORS = Arrays.asList( + 0xa39d91, 0xf4f4f4, 0xa2a38f, 0xF2F204, 0xb75656, 0xfff4f4 + ); + + private boolean useIronArmor; + private int resistStrength; + private int resistDuration; + + public MetalArmor(Player player) { + super(player); + + if (bPlayer == null || !bPlayer.canBendIgnoreCooldowns(CoreAbility.getAbility(EarthArmor.class)) || !bPlayer.canMetalbend()) { + return; + } + + if (!CoreAbility.hasAbility(player, EarthArmor.class)) { + return; + } + + setFields(); + start(); + } + + private void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + useIronArmor = config.getBoolean("Abilities.Earth.EarthArmor.UseIronArmor"); + resistStrength = config.getInt("Abilities.Earth.EarthArmor.Resistance.Strength"); + resistDuration = config.getInt("Abilities.Earth.EarthArmor.Resistance.Duration"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (!CoreAbility.hasAbility(player, EarthArmor.class)) { + remove(); + return; + } + + EarthArmor ea = CoreAbility.getAbility(player, EarthArmor.class); + if (!bPlayer.isToggled()) { + remove(); + ea.remove(); + return; + } + + if (ea.isFormed()) { + if (isMetalHelmet()) { + ItemStack[] armors = { new ItemStack(Material.CHAINMAIL_BOOTS, 1), + new ItemStack(Material.CHAINMAIL_LEGGINGS, 1), + new ItemStack(Material.CHAINMAIL_CHESTPLATE, 1), + new ItemStack(Material.CHAINMAIL_HELMET, 1) }; + + if(useIronArmor){ + armors = new ItemStack[]{ new ItemStack(Material.IRON_BOOTS, 1), + new ItemStack(Material.IRON_LEGGINGS, 1), + new ItemStack(Material.IRON_CHESTPLATE, 1), + new ItemStack(Material.IRON_HELMET, 1) }; + } + + if(useIronArmor && getHelmetColor().equals(Color.fromRGB(GOLD_BLOCK_COLOR))) { + armors = new ItemStack[]{ new ItemStack(Material.GOLDEN_BOOTS, 1), + new ItemStack(Material.GOLDEN_LEGGINGS, 1), + new ItemStack(Material.GOLDEN_CHESTPLATE, 1), + new ItemStack(Material.GOLDEN_HELMET, 1) }; + } + + player.getInventory().setArmorContents(armors); + + PotionEffect resistance = JedCore.plugin.getPotionEffectAdapter().getResistanceEffect(resistDuration, resistStrength); + new TempPotionEffect(player, resistance); + } + + remove(); + } + } + + private boolean isMetalHelmet() { + Color color = getHelmetColor(); + + return METAL_COLORS.contains(color.asRGB()); + } + + private Color getHelmetColor() { + if (!TempArmor.hasTempArmor(player)) { + return Color.BLACK; + } + + ItemStack helm = player.getInventory().getHelmet(); + if (helm.getType() != Material.LEATHER_HELMET) { + return Color.BLACK; + } + + LeatherArmorMeta meta = (LeatherArmorMeta)helm.getItemMeta(); + if (meta == null) { + return Color.BLACK; + } + + return meta.getColor(); + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalArmor"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public boolean isUseIronArmor() { + return useIronArmor; + } + + public void setUseIronArmor(boolean useIronArmor) { + this.useIronArmor = useIronArmor; + } + + public int getResistStrength() { + return resistStrength; + } + + public void setResistStrength(int resistStrength) { + this.resistStrength = resistStrength; + } + + public int getResistDuration() { + return resistDuration; + } + + public void setResistDuration(int resistDuration) { + this.resistDuration = resistDuration; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthArmor.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java b/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java new file mode 100644 index 0000000..134e1ee --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalFragments.java @@ -0,0 +1,426 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.*; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.*; + +public class MetalFragments extends MetalAbility implements AddonAbility { + + @Attribute("MaxSources") + private int maxSources; + @Attribute(Attribute.SELECT_RANGE) + private int selectRange; + @Attribute("MaxShots") + private int maxFragments; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private double velocity; + + public List sources = new ArrayList<>(); + private final List thrownFragments = new ArrayList<>(); + private final List tblockTracker = new ArrayList<>(); + //private List fblockTracker = new ArrayList<>(); + private final HashMap counters = new HashMap<>(); + + public MetalFragments(Player player) { + super(player); + + if (hasAbility(player, MetalFragments.class)) { + MetalFragments.selectAnotherSource(player); + return; + } + + if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { + return; + } + + setFields(); + + if (tblockTracker.size() >= maxSources) { + return; + } + + if (prepare()) { + Block b = selectSource(); + if (RegionProtection.isRegionProtected(player, b.getLocation(), this)) { + return; + } + + start(); + if (!isRemoved()) { + translateUpward(b); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + maxSources = config.getInt("Abilities.Earth.MetalFragments.MaxSources"); + selectRange = config.getInt("Abilities.Earth.MetalFragments.SourceRange"); + maxFragments = config.getInt("Abilities.Earth.MetalFragments.MaxFragments"); + damage = config.getDouble("Abilities.Earth.MetalFragments.Damage"); + cooldown = config.getInt("Abilities.Earth.MetalFragments.Cooldown"); + velocity = config.getDouble("Abilities.Earth.MetalFragments.Velocity"); + } + + public static void shootFragment(Player player) { + if (hasAbility(player, MetalFragments.class)) { + getAbility(player, MetalFragments.class).shootFragment(); + } + } + + private void shootFragment() { + if (sources.size() <= 0) + return; + + Random randy = new Random(); + int i = randy.nextInt(sources.size()); + Block source = sources.get(i); + ItemStack is; + + switch (source.getType()) { + case GOLD_BLOCK: + case GOLD_ORE: + is = new ItemStack(Material.GOLD_INGOT, 1); + break; + case COAL_BLOCK: + is = new ItemStack(Material.COAL, 1); + break; + case COAL_ORE: + is = new ItemStack(Material.COAL_ORE, 1); + break; + default: + is = new ItemStack(Material.IRON_INGOT, 1); + break; + } + + Vector direction; + if (GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()) != null) { + direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedEntity(player, 30, new ArrayList<>()).getLocation()); + } else { + direction = GeneralMethods.getDirection(source.getLocation(), GeneralMethods.getTargetedLocation(player, 30)); + } + + Item ii = player.getWorld().dropItemNaturally(source.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(direction)).getLocation(), is); + ii.setPickupDelay(Integer.MAX_VALUE); + ii.setVelocity(direction.normalize().multiply(velocity)); + playMetalbendingSound(ii.getLocation()); + thrownFragments.add(ii); + + if (counters.containsKey(source)) { + int count = counters.get(source); + count++; + + if (count >= maxFragments) { + counters.remove(source); + source.getWorld().spawnFallingBlock(source.getLocation().add(0.5, 0, 0.5), source.getBlockData()); + TempBlock tempBlock = TempBlock.get(source); + if (tempBlock != null) { + tempBlock.revertBlock(); + } + sources.remove(source); + source.getWorld().playSound(source.getLocation(), Sound.ENTITY_ITEM_BREAK, 10, 5); + } else { + counters.put(source, count); + } + + if (sources.size() == 0) { + remove(); + } + } + } + + public static void selectAnotherSource(Player player) { + if (hasAbility(player, MetalFragments.class)) { + getAbility(player, MetalFragments.class).selectAnotherSource(); + } + } + + private void selectAnotherSource() { + if (tblockTracker.size() >= maxSources) + return; + + if (prepare()) { + Block b = selectSource(); + translateUpward(b); + } + } + + public boolean prepare() { + Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); + + if (block == null) + return false; + + if (EarthAbility.getMovedEarth().containsKey(block)) + return false; + + return isMetal(block); + } + + public Block selectSource() { + Block block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); + if (EarthAbility.getMovedEarth().containsKey(block)) + return null; + if (isMetal(block)) + return block; + return null; + } + + public void translateUpward(Block block) { + if (block == null) + return; + + if (sources.contains(block)) + return; + + if (block.getRelative(BlockFace.UP).getType().isSolid()) + return; + + if (isEarthbendable(player, block)) { + new TempFallingBlock(block.getLocation().add(0.5, 0, 0.5), block.getBlockData(), new Vector(0, 0.8, 0), this); + block.setType(Material.AIR); + + playMetalbendingSound(block.getLocation()); + } + } + + public void progress() { + if (player == null || player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!hasAbility(player, MetalFragments.class)) { + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + + Iterator itr = tblockTracker.iterator(); + while (itr.hasNext()) { + TempBlock tb = itr.next(); + if (player.getLocation().distance(tb.getLocation()) >= 10) { + player.getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlockData()); + sources.remove(tb.getBlock()); + tb.revertBlock(); + itr.remove(); + } + } + + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fb = tfb.getFallingBlock(); + if (fb.getLocation().getY() >= player.getEyeLocation().getY() + 1) { + Block block = fb.getLocation().getBlock(); + TempBlock tb = new TempBlock(block, fb.getBlockData()); + + tblockTracker.add(tb); + sources.add(tb.getBlock()); + counters.put(tb.getBlock(), 0); + tfb.remove(); + } + + if (fb.isOnGround()) { + fb.getLocation().getBlock().setBlockData(fb.getBlockData()); + } + } + for (ListIterator iterator = thrownFragments.listIterator(); iterator.hasNext();) { + Item f = iterator.next(); + + boolean touchedLiving = false; + for (Entity e : GeneralMethods.getEntitiesAroundPoint(f.getLocation(), 1)) { + if (e instanceof LivingEntity && e.getEntityId() != player.getEntityId()) { + touchedLiving = true; + DamageHandler.damageEntity(e, damage, this); + } + } + if (touchedLiving || f.isOnGround() || f.isDead()) { + ParticleEffect.ITEM_CRACK.display(f.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, f.getItemStack()); + f.remove(); + iterator.remove(); + } + } + + //removeDeadFBlocks(); + } + + /* + public void removeDeadFBlocks() { + for (int i = 0; i < fblockTracker.size(); i++) + if (fblockTracker.get(i).isDead()) + fblockTracker.remove(i); + } + */ + + public void removeDeadItems() { + thrownFragments.removeIf(Item::isDead); + } + + + public void dropSources() { + for (TempBlock tb : tblockTracker) { + tb.getBlock().getWorld().spawnFallingBlock(tb.getLocation().add(0.5,0.0,0.5), tb.getBlock().getBlockData()); + tb.revertBlock(); + } + + tblockTracker.clear(); + } + + public void removeFragments() { + for (Item i : thrownFragments) { + ParticleEffect.ITEM_CRACK.display(i.getLocation(), 3, 0.3, 0.3, 0.3, 0.2, i.getItemStack()); + i.remove(); + } + thrownFragments.clear(); + } + + public static void remove(Player player, Block block) { + if (hasAbility(player, MetalFragments.class)) { + MetalFragments mf = getAbility(player, MetalFragments.class); + if (mf.sources.contains(block)) { + mf.remove(); + } + } + } + + @Override + public void remove() { + dropSources(); + removeFragments(); + removeDeadItems(); + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalFragments"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalFragments.Description"); + } + + public int getMaxSources() { + return maxSources; + } + + public void setMaxSources(int maxSources) { + this.maxSources = maxSources; + } + + public int getSelectRange() { + return selectRange; + } + + public void setSelectRange(int selectRange) { + this.selectRange = selectRange; + } + + public int getMaxFragments() { + return maxFragments; + } + + public void setMaxFragments(int maxFragments) { + this.maxFragments = maxFragments; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public List getSources() { + return sources; + } + + public void setSources(List sources) { + this.sources = sources; + } + + public List getThrownFragments() { + return thrownFragments; + } + + public List getTblockTracker() { + return tblockTracker; + } + + public HashMap getCounters() { + return counters; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MetalFragments.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java b/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java new file mode 100644 index 0000000..218a17b --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalHook.java @@ -0,0 +1,395 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class MetalHook extends MetalAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.RANGE) + private int range; + @Attribute("MaxHooks") + private int maxHooks; + private int totalHooks; + private int hooksUsed; + private boolean noSource; + private boolean barrierHooking; + + private boolean hasHook; + private boolean wasSprinting; + private long time; + + private Location destination; + + private final ConcurrentHashMap hooks = new ConcurrentHashMap<>(); + private final List hookIds = new ArrayList<>(); + + public MetalHook(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canMetalbend()) { + return; + } + + if (hasAbility(player, MetalHook.class)) { + MetalHook mh = getAbility(player, MetalHook.class); + mh.launchHook(); + return; + } + + setFields(); + + if (!hasRequiredInv()) { + return; + } + + wasSprinting = player.isSprinting(); + flightHandler.createInstance(player, this.getName()); + player.setAllowFlight(true); + + start(); + launchHook(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.MetalHook.Cooldown"); + range = config.getInt("Abilities.Earth.MetalHook.Range"); + maxHooks = config.getInt("Abilities.Earth.MetalHook.MaxHooks"); + totalHooks = config.getInt("Abilities.Earth.MetalHook.TotalHooks"); + noSource = config.getBoolean("Abilities.Earth.MetalHook.RequireItem"); + barrierHooking = config.getBoolean("Abilities.Earth.MetalHook.BarrierHooking"); + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + removeAllArrows(); + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBindsCooldowns(this) || hooks.isEmpty()) { + removeAllArrows(); + remove(); + return; + } + + if (!wasSprinting && player.isSprinting()) { + removeAllArrows(); + remove(); + return; + } + + wasSprinting = player.isSprinting(); + + if (player.isSneaking()) { + player.setVelocity(new Vector()); + + if (System.currentTimeMillis() > (time + 1000)) { + removeAllArrows(); + remove(); + return; + } + } else { + time = System.currentTimeMillis(); + } + + Vector target = new Vector(); + + for (Arrow a : hooks.keySet()) { + if (a != null) { + if (!isActiveArrow(a)) { + hooks.remove(a); + hookIds.remove(a.getUniqueId()); + a.remove(); + continue; + } + + if (a.getAttachedBlock() == null) { + hooks.replace(a, hooks.get(a), false); + } else { + hooks.replace(a, hooks.get(a), true); + hasHook = true; + } + + //Draws the particle lines. + for (Location location : JCMethods.getLinePoints(player.getLocation().add(0, 1, 0), a.getLocation(), ((int) player.getLocation().add(0,1,0).distance(a.getLocation()) * 2))) { + GeneralMethods.displayColoredParticle("#CCCCCC", location); + } + + if (hooks.get(a)) { + target.add(GeneralMethods.getDirection(player.getEyeLocation(), a.getLocation())); + } + } + } + + if (hasHook) { + destination = player.getLocation().clone().add(target); + + if (player.getLocation().distance(destination) > 2) { + player.setFlying(false); + double velocity = 0.8; + + GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); + } else if (player.getLocation().distance(destination) < 2 && player.getLocation().distance(destination) >= 1) { + player.setFlying(false); + double velocity = 0.35; + + GeneralMethods.setVelocity(this, player, target.clone().normalize().multiply(velocity)); + } else { + GeneralMethods.setVelocity(this, player, new Vector(0, 0, 0)); + + if (player.getAllowFlight()) { + player.setFlying(true); + } + } + } + } + + private boolean isActiveArrow(Arrow arrow) { + if (arrow.isDead()) return false; + if (player.getWorld() != arrow.getWorld()) return false; + + Block attached = arrow.getAttachedBlock(); + + if (!barrierHooking && attached != null && attached.getType() == Material.BARRIER) return false; + + return player.getEyeLocation().distanceSquared(arrow.getLocation()) < range * range; + } + + @Override + public void remove() { + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + + flightHandler.removeInstance(player, this.getName()); + + super.remove(); + } + + public void launchHook() { + if (!hasRequiredInv()) return; + + Vector dir = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, range)); + + if (!hookIds.isEmpty() && hookIds.size() > (maxHooks - 1)) { + for (Arrow a : hooks.keySet()) { + if (a.getUniqueId().equals(hookIds.get(0))) { + hooks.remove(a); + hookIds.remove(0); + a.remove(); + break; + } + } + } + + if (totalHooks > 0 && hooksUsed++ > totalHooks) { + remove(); + return; + } + + Arrow a = player.getWorld().spawnArrow(player.getEyeLocation().add(player.getLocation().getDirection().multiply(2)), dir, 3, 0f); + a.setMetadata("metalhook", new FixedMetadataValue(JedCore.plugin, "1")); + + hooks.put(a, false); + hookIds.add(a.getUniqueId()); + } + + public void removeAllArrows() { + for (Arrow a : hooks.keySet()) { + a.remove(); + } + } + + public boolean hasRequiredInv() { + if (noSource) return true; + + if (player.getInventory().getChestplate() != null) { + Material[] chestplates = {Material.IRON_CHESTPLATE, Material.CHAINMAIL_CHESTPLATE}; + Material playerChest = player.getInventory().getChestplate().getType(); + + if (Arrays.asList(chestplates).contains(playerChest)) { + return true; + } + } + + Material[] metals = {Material.IRON_INGOT, Material.IRON_BLOCK}; + + for (ItemStack items : player.getInventory()) { + if (items != null && Arrays.asList(metals).contains(items.getType())) { + return true; + } + } + + return false; + } + + public int getMaxHooks() { + return this.maxHooks; + } + + public void setMaxHooks(int maxhooks) { + this.maxHooks = maxhooks; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalHook"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalHook.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public int getTotalHooks() { + return totalHooks; + } + + public void setTotalHooks(int totalHooks) { + this.totalHooks = totalHooks; + } + + public int getHooksUsed() { + return hooksUsed; + } + + public void setHooksUsed(int hooksUsed) { + this.hooksUsed = hooksUsed; + } + + public boolean isNoSource() { + return noSource; + } + + public void setNoSource(boolean noSource) { + this.noSource = noSource; + } + + public boolean isBarrierHooking() { + return barrierHooking; + } + + public void setBarrierHooking(boolean barrierHooking) { + this.barrierHooking = barrierHooking; + } + + public boolean isHasHook() { + return hasHook; + } + + public void setHasHook(boolean hasHook) { + this.hasHook = hasHook; + } + + public boolean isWasSprinting() { + return wasSprinting; + } + + public void setWasSprinting(boolean wasSprinting) { + this.wasSprinting = wasSprinting; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public Location getDestination() { + return destination; + } + + public void setDestination(Location destination) { + this.destination = destination; + } + + public ConcurrentHashMap getHooks() { + return hooks; + } + + public List getHookIds() { + return hookIds; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MetalHook.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java b/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java new file mode 100644 index 0000000..dac3122 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/MetalShred.java @@ -0,0 +1,486 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.MetalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; + +public class MetalShred extends MetalAbility implements AddonAbility { + + @Attribute(Attribute.SELECT_RANGE) + private int selectRange; + private int extendTick; + @Attribute(Attribute.DAMAGE) + private double damage; + + private boolean horizontal = false; + private boolean started = false; + private boolean stop = false; + private boolean stopCoil = false; + private boolean extending = false; + private int length = 0; + private int fullLength = 0; + private long lastExtendTime; + private Block source; + private Block lastBlock; + private final List tblocks = new ArrayList<>(); + + public MetalShred(Player player) { + super(player); + + if (hasAbility(player, MetalShred.class)) { + getAbility(player, MetalShred.class).remove(); + } + + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + if (selectSource()) { + if (horizontal) { + raiseBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); + } else { + shiftBlock(source, GeneralMethods.getDirection(player.getLocation(), source.getLocation())); + } + + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + selectRange = config.getInt("Abilities.Earth.MetalShred.SourceRange"); + extendTick = config.getInt("Abilities.Earth.MetalShred.ExtendTick"); + damage = config.getDouble("Abilities.Earth.MetalShred.Damage"); + } + + public boolean selectSource() { + Block b = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.SHIFT_DOWN); + + if (EarthAbility.getMovedEarth().containsKey(b)) + return false; + + if (!isMetal(b)) + return false; + + source = b; + + if (ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType()) && !isMetal(source.getRelative(BlockFace.DOWN))) { + horizontal = true; + } + + return true; + } + + public void raiseBlock(Block b, Vector d) { + Block up = b.getRelative(BlockFace.UP); + Block away = b.getRelative(GeneralMethods.getCardinalDirection(d)); + Block awayup = away.getRelative(BlockFace.UP); + Block deeperb = b.getRelative(BlockFace.DOWN); + Block deepera = away.getRelative(BlockFace.DOWN); + + for (TempBlock tb : tblocks) { + if (!ElementalAbility.isAir(tb.getBlock().getType())) + tb.setType(Material.AIR); + } + + if (!up.getType().isSolid()) { + TempBlock tbu = new TempBlock(up, b.getBlockData()); + tblocks.add(tbu); + } + + if (!awayup.getType().isSolid()) { + TempBlock tbau = new TempBlock(awayup, away.getBlockData()); + tblocks.add(tbau); + } + + if (isMetal(b)) { + TempBlock tbd = new TempBlock(b, Material.AIR.createBlockData()); + tblocks.add(tbd); + } + + if (isMetal(away)) { + TempBlock tba = new TempBlock(away, Material.AIR.createBlockData()); + tblocks.add(tba); + } + + if (isMetal(deeperb)) { + TempBlock tbdb = new TempBlock(deeperb, Material.AIR.createBlockData()); + tblocks.add(tbdb); + } + + if (isMetal(deepera)) { + TempBlock tbda = new TempBlock(deepera, Material.AIR.createBlockData()); + tblocks.add(tbda); + } + + playMetalbendingSound(b.getLocation()); + } + + public void shiftBlock(Block b, Vector d) { + Block under = b.getRelative(BlockFace.DOWN); + Block side = b.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); + Block underside = under.getRelative(GeneralMethods.getCardinalDirection(d).getOppositeFace()); + + for (TempBlock tb : tblocks) { + if (!ElementalAbility.isAir(tb.getBlock().getType())) + tb.setType(Material.AIR); + } + + if (!side.getType().isSolid()) { + TempBlock tbs = new TempBlock(side, b.getBlockData()); + tblocks.add(tbs); + } + + if (!underside.getType().isSolid()) { + TempBlock tbus = new TempBlock(underside, under.getBlockData()); + tblocks.add(tbus); + } + + if (isMetal(b)) { + TempBlock tb1 = new TempBlock(b, Material.AIR.createBlockData()); + tblocks.add(tb1); + } + + if (isMetal(under)) { + TempBlock tb2 = new TempBlock(under, Material.AIR.createBlockData()); + tblocks.add(tb2); + } + + playMetalbendingSound(b.getLocation()); + } + + private void peelCoil(Block b) { + Block under = b.getRelative(BlockFace.DOWN); + + if (length <= 0) + return; + + if (!b.getType().isSolid()) { + TempBlock tbb = new TempBlock(b, Material.IRON_BLOCK.createBlockData()); + tblocks.add(tbb); + } + + else + stopCoil = true; + + if (!under.getType().isSolid()) { + TempBlock tbu = new TempBlock(under, Material.IRON_BLOCK.createBlockData()); + tblocks.add(tbu); + } + + else + stopCoil = true; + + playMetalbendingSound(b.getLocation()); + + length--; + } + + public static void startShred(Player player) { + if (hasAbility(player, MetalShred.class)) { + getAbility(player, MetalShred.class).startShred(); + } + } + + private void startShred() { + started = true; + } + + public static void extend(Player player) { + if (hasAbility(player, MetalShred.class)) { + getAbility(player, MetalShred.class).extend(); + } + } + + private void extend() { + if (extending) { + extending = false; + return; + } + + if (!stop) + return; + + lastExtendTime = System.currentTimeMillis(); + fullLength = length; + if (lastBlock != null) + lastBlock = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(player.getLocation(), lastBlock.getLocation())).getOppositeFace()); + else { + return; + } + extending = true; + } + + @Override + public void progress() { + if (!player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + + if (!player.isSprinting()) { + if (started) + stop = true; + } + + if (!horizontal && stop && !stopCoil && extending && System.currentTimeMillis() > lastExtendTime + extendTick) { + lastExtendTime = System.currentTimeMillis(); + if (length > 0) { + + Block b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(lastBlock.getLocation(), GeneralMethods.getTargetedLocation(player, fullLength)))); + + peelCoil(b); + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(b.getLocation(), 2)) { + if (!(e instanceof LivingEntity) || e.getEntityId() == player.getEntityId()) { + continue; + } + if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))) { + continue; + } + DamageHandler.damageEntity(e, damage, this); + GeneralMethods.setVelocity(this, e, e.getVelocity().add(player.getLocation().getDirection().add(new Vector(0, 0.1, 0)))); + } + + lastBlock = b; + } + + return; + } + + if (stop || !started) + return; + + Block b; + + if (lastBlock != null) { + b = lastBlock.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); + } + + else { + b = source.getRelative(GeneralMethods.getCardinalDirection(player.getLocation().getDirection())); + } + + if (!isMetal(b)) { + if (!ElementalAbility.isAir(b.getType())) { + remove(); + } + return; + } + + if (b.getLocation().getX() == player.getLocation().getBlockX() || b.getLocation().getZ() == player.getLocation().getBlockZ()) { + if (horizontal) + raiseBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); + else + shiftBlock(b, GeneralMethods.getDirection(player.getLocation(), b.getLocation())); + + length++; + lastBlock = b; + } + } + + private void revertAll() { + for (TempBlock tb : tblocks) { + tb.revertBlock(); + } + } + + @Override + public void remove() { + revertAll(); + super.remove(); + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MetalShred"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MetalShred.Description"); + } + + public int getSelectRange() { + return selectRange; + } + + public void setSelectRange(int selectRange) { + this.selectRange = selectRange; + } + + public int getExtendTick() { + return extendTick; + } + + public void setExtendTick(int extendTick) { + this.extendTick = extendTick; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public boolean isHorizontal() { + return horizontal; + } + + public void setHorizontal(boolean horizontal) { + this.horizontal = horizontal; + } + + @Override + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + + public boolean isStop() { + return stop; + } + + public void setStop(boolean stop) { + this.stop = stop; + } + + public boolean isStopCoil() { + return stopCoil; + } + + public void setStopCoil(boolean stopCoil) { + this.stopCoil = stopCoil; + } + + public boolean isExtending() { + return extending; + } + + public void setExtending(boolean extending) { + this.extending = extending; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public int getFullLength() { + return fullLength; + } + + public void setFullLength(int fullLength) { + this.fullLength = fullLength; + } + + public long getLastExtendTime() { + return lastExtendTime; + } + + public void setLastExtendTime(long lastExtendTime) { + this.lastExtendTime = lastExtendTime; + } + + public Block getSource() { + return source; + } + + public void setSource(Block source) { + this.source = source; + } + + public Block getLastBlock() { + return lastBlock; + } + + public void setLastBlock(Block lastBlock) { + this.lastBlock = lastBlock; + } + + public List getTblocks() { + return tblocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MetalShred.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java new file mode 100644 index 0000000..98ce05e --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java @@ -0,0 +1,660 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionUtil; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.stream.Collectors; + +public class MudSurge extends EarthAbility implements AddonAbility { + private int prepareRange; + private int blindChance; + private int blindTicks; + private boolean multipleHits; + @Attribute(Attribute.DAMAGE) + private double damage; + private int waves; + private int waterSearchRadius; + private boolean wetSource; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("CollisionRadius") + private double collisionRadius; + + public static int surgeInterval = 300; + public static int mudPoolRadius = 2; + public static Set mudTypes = new HashSet<>(); + private static Material mudType; + + static { + mudType = Material.valueOf("BROWN_TERRACOTTA"); + mudTypes.addAll(Arrays.asList(Material.SAND, Material.RED_SAND, Material.CLAY, Material.TERRACOTTA, Material.BLACK_TERRACOTTA, Material.BLUE_TERRACOTTA, + Material.BROWN_TERRACOTTA, Material.CYAN_TERRACOTTA, Material.GRAY_TERRACOTTA, Material.GREEN_TERRACOTTA, + Material.LIGHT_BLUE_TERRACOTTA, Material.LIGHT_GRAY_TERRACOTTA, Material.LIME_TERRACOTTA, + Material.MAGENTA_TERRACOTTA, Material.ORANGE_TERRACOTTA, Material.PINK_TERRACOTTA, + Material.PURPLE_TERRACOTTA, Material.RED_TERRACOTTA, Material.WHITE_TERRACOTTA, Material.YELLOW_TERRACOTTA, + Material.GRASS_BLOCK, Material.DIRT, Material.MYCELIUM, Material.COARSE_DIRT, + Material.SOUL_SAND, Material.SOUL_SOIL, Material.RED_SANDSTONE, Material.SANDSTONE, Material.CHISELED_SANDSTONE, + Material.CHISELED_RED_SANDSTONE, Material.SMOOTH_SANDSTONE, Material.SMOOTH_RED_SANDSTONE, Material.CUT_SANDSTONE, + Material.CUT_RED_SANDSTONE)); + if (GeneralMethods.getMCVersion() >= 1170) { + mudTypes.add(Material.getMaterial("ROOTED_DIRT")); + } + if (GeneralMethods.getMCVersion() >= 1190) { + mudTypes.add(Material.getMaterial("MUD")); + mudTypes.add(Material.getMaterial("MUDDY_MANGROVE_ROOTS")); + mudTypes.add(Material.getMaterial("PACKED_MUD")); + mudType = Material.valueOf("MUD"); + } + } + + private CompositeRemovalPolicy removalPolicy; + + private Block source; + + private int wavesOnTheRun = 0; + private boolean mudFormed = false; + private boolean doNotSurge = false; + public boolean started = false; + + private final List mudArea = new ArrayList<>(); + private ListIterator mudAreaItr; + private final List mudBlocks = new ArrayList<>(); + private final List blind = new ArrayList<>(); + private final List affectedEntities = new ArrayList<>(); + + private final List fallingBlocks = new ArrayList<>(); + + private final Random rand = new Random(); + + public MudSurge(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, MudSurge.class)) { + MudSurge ms = getAbility(player, MudSurge.class); + if (!ms.hasStarted()) { + ms.remove(); + } else { + return; + } + } + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new OutOfRangeRemovalPolicy(this.player, 25.0, () -> this.source.getLocation()), + new SwappedSlotsRemovalPolicy<>(bPlayer, MudSurge.class) + ); + + setFields(); + + if (getSource()) { + start(); + if (!isRemoved()) { + loadMudPool(); + } + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + this.removalPolicy.load(config); + + prepareRange = config.getInt("Abilities.Earth.MudSurge.SourceRange"); + blindChance = config.getInt("Abilities.Earth.MudSurge.BlindChance"); + damage = config.getDouble("Abilities.Earth.MudSurge.Damage"); + waves = config.getInt("Abilities.Earth.MudSurge.Waves"); + waterSearchRadius = config.getInt("Abilities.Earth.MudSurge.WaterSearchRadius"); + wetSource = config.getBoolean("Abilities.Earth.MudSurge.WetSourceOnly"); + cooldown = config.getLong("Abilities.Earth.MudSurge.Cooldown"); + blindTicks = config.getInt("Abilities.Earth.MudSurge.BlindTicks"); + multipleHits = config.getBoolean("Abilities.Earth.MudSurge.MultipleHits"); + collisionRadius = config.getDouble("Abilities.Earth.MudSurge.CollisionRadius"); + } + + @Override + public void progress() { + if (removalPolicy.shouldRemove()) { + remove(); + return; + } + + long lastSurgeTime = 0; + if (mudFormed && started && System.currentTimeMillis() > lastSurgeTime + surgeInterval) { + surge(); + affect(); + if (TempFallingBlock.getFromAbility(this).isEmpty()) { + remove(); + return; + } + return; + } + + if (!mudFormed) { + createMudPool(); + } + } + + private boolean getSource() { + Block block = getMudSourceBlock(prepareRange); + + if (block != null) { + if (isMudBlock(block)) { + boolean water = true; + + if (wetSource) { + water = false; + List nearby = GeneralMethods.getBlocksAroundPoint(block.getLocation(), waterSearchRadius); + + for (Block b : nearby) { + if (b.getType() == Material.WATER) { + water = true; + break; + } + } + } + + if (water) { + this.source = block; + return true; + } + } + } + + return false; + } + + private boolean isValidMudSource(Block block) { + return block != null && !EarthAbility.getMovedEarth().containsKey(block); + } + + private void startSurge() { + started = true; + this.bPlayer.addCooldown(this); + + // Clear out the policies that only apply while sourcing. + this.removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); + this.removalPolicy.removePolicyType(OutOfRangeRemovalPolicy.class); + this.removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); + } + + private boolean hasStarted() { + return this.started; + } + + public static boolean isSurgeBlock(Block block) { + if (block.getType() != Material.MUD) { + return false; + } + + for (MudSurge surge : CoreAbility.getAbilities(MudSurge.class)) { + if (surge.mudArea.contains(block)) { + return true; + } + } + + return false; + } + + // Returns true if the event should be cancelled. + public static boolean onFallDamage(Player player) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null || !bPlayer.hasElement(Element.EARTH)) { + return false; + } + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + boolean fallDamage = config.getBoolean("Abilities.Earth.MudSurge.AllowFallDamage"); + if (fallDamage) { + return false; + } + + Block block = player.getLocation().clone().subtract(0, 0.1, 0).getBlock(); + return isSurgeBlock(block); + } + + public static void mudSurge(Player player) { + if (!hasAbility(player, MudSurge.class)) + return; + + getAbility(player, MudSurge.class).startSurge(); + } + + private Block getMudSourceBlock(int range) { + Block testBlock = GeneralMethods.getTargetedLocation(player, range, ElementalAbility.getTransparentMaterials()).getBlock(); + if (isMudBlock(testBlock)) + return testBlock; + + Location loc = player.getEyeLocation(); + Vector dir = player.getEyeLocation().getDirection().clone().normalize(); + + for (int i = 0; i <= range; i++) { + Block block = loc.clone().add(dir.clone().multiply(i == 0 ? 1 : i)).getBlock(); + if (RegionProtection.isRegionProtected(player, block.getLocation(), this)) + continue; + + if (isMudBlock(block)) + return block; + } + + return null; + } + + private boolean isMudBlock(Block block) { + for (Material mat : mudTypes) { + if (mat.name().equalsIgnoreCase(block.getType().name())) + return true; + } + + return false; + } + + private void createMud(Block block) { + mudBlocks.add(new TempBlock(block, mudType.createBlockData())); + } + + private void loadMudPool() { + List area = GeneralMethods.getCircle(source.getLocation(), mudPoolRadius, 3, false, true, 0); + + for (Location l : area) { + Block b = l.getBlock(); + + if (isMudBlock(b)) { + if (isTransparent(b.getRelative(BlockFace.UP))) { + boolean water = true; + + if (wetSource) { + water = false; + List nearby = GeneralMethods.getBlocksAroundPoint(l, waterSearchRadius); + + for (Block block : nearby) { + if (block.getType() == Material.WATER) { + water = true; + break; + } + } + } + + if (water) { + mudArea.add(b); + playEarthbendingSound(b.getLocation()); + } + } + } + } + + Collections.shuffle(mudArea); + mudAreaItr = mudArea.listIterator(); + } + + private void createMudPool() { + if (!mudAreaItr.hasNext()) { + mudFormed = true; + return; + } + + Block b = mudAreaItr.next(); + + if (b != null) + createMud(b); + } + + private void revertMudPool() { + for (TempBlock tb : mudBlocks) + tb.revertBlock(); + + mudBlocks.clear(); + } + + private void surge() { + if (wavesOnTheRun >= waves) { + doNotSurge = true; + return; + } + + if (doNotSurge) + return; + + for (TempBlock tb : mudBlocks) { + Vector direction = GeneralMethods.getDirection(tb.getLocation().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, 30)).multiply(0.07); + + double x = rand.nextDouble() / 5; + double z = rand.nextDouble() / 5; + + x = (rand.nextBoolean()) ? -x : x; + z = (rand.nextBoolean()) ? -z : z; + + fallingBlocks.add(new TempFallingBlock(tb.getLocation().add(0.5, 1, 0.5), mudType.createBlockData(), direction.clone().add(new Vector(x, 0.2, z)), this)); + + playEarthbendingSound(tb.getLocation()); + } + + wavesOnTheRun++; + } + + private void affect() { + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fb = tfb.getFallingBlock(); + if (fb.isDead()) { + tfb.remove(); + continue; + } + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(fb.getLocation(), 1.5)) { + if (fb.isDead()) { + tfb.remove(); + continue; + } + if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))){ + continue; + } + + if (e instanceof LivingEntity) { + if (this.multipleHits || !this.affectedEntities.contains(e)) { + DamageHandler.damageEntity(e, damage, this); + if (!this.multipleHits) { + this.affectedEntities.add(e); + } + } + + if (e instanceof Player) { + if (e.getEntityId() == player.getEntityId()) + continue; + + if (rand.nextInt(100) < blindChance && !blind.contains(e)) { + ((Player) e).addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, this.blindTicks, 2)); + } + + blind.add((Player) e); + } + + e.setVelocity(fb.getVelocity().multiply(0.8)); + tfb.remove(); + } + } + } + } + + @Override + public void remove() { + revertMudPool(); + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); + } + + @Override + public void handleCollision(Collision collision) { + CollisionUtil.handleFallingBlockCollisions(collision, fallingBlocks); + } + + @Override + public double getCollisionRadius() { + return collisionRadius; + } + + @Override + public String getName() { + return "MudSurge"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.MudSurge.Description"); + } + + public int getPrepareRange() { + return prepareRange; + } + + public void setPrepareRange(int prepareRange) { + this.prepareRange = prepareRange; + } + + public int getBlindChance() { + return blindChance; + } + + public void setBlindChance(int blindChance) { + this.blindChance = blindChance; + } + + public int getBlindTicks() { + return blindTicks; + } + + public void setBlindTicks(int blindTicks) { + this.blindTicks = blindTicks; + } + + public boolean isMultipleHits() { + return multipleHits; + } + + public void setMultipleHits(boolean multipleHits) { + this.multipleHits = multipleHits; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public int getWaves() { + return waves; + } + + public void setWaves(int waves) { + this.waves = waves; + } + + public int getWaterSearchRadius() { + return waterSearchRadius; + } + + public void setWaterSearchRadius(int waterSearchRadius) { + this.waterSearchRadius = waterSearchRadius; + } + + public boolean isWetSource() { + return wetSource; + } + + public void setWetSource(boolean wetSource) { + this.wetSource = wetSource; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public void setCollisionRadius(double collisionRadius) { + this.collisionRadius = collisionRadius; + } + + public static int getSurgeInterval() { + return surgeInterval; + } + + public static void setSurgeInterval(int surgeInterval) { + MudSurge.surgeInterval = surgeInterval; + } + + public static int getMudPoolRadius() { + return mudPoolRadius; + } + + public static void setMudPoolRadius(int mudPoolRadius) { + MudSurge.mudPoolRadius = mudPoolRadius; + } + + public static Material[] getMudTypes() { + return mudTypes.toArray(new Material[0]); + } + + public static Set getMudTypesSet() { + return mudTypes; + } + + public static void setMudTypes(Material[] mudTypes) { + MudSurge.mudTypes.clear(); + MudSurge.mudTypes.addAll(Arrays.asList(mudTypes)); + } + + public CompositeRemovalPolicy getRemovalPolicy() { + return removalPolicy; + } + + public void setRemovalPolicy(CompositeRemovalPolicy removalPolicy) { + this.removalPolicy = removalPolicy; + } + + public void setSource(Block source) { + this.source = source; + } + + public int getWavesOnTheRun() { + return wavesOnTheRun; + } + + public void setWavesOnTheRun(int wavesOnTheRun) { + this.wavesOnTheRun = wavesOnTheRun; + } + + public boolean isMudFormed() { + return mudFormed; + } + + public void setMudFormed(boolean mudFormed) { + this.mudFormed = mudFormed; + } + + public boolean isDoNotSurge() { + return doNotSurge; + } + + public void setDoNotSurge(boolean doNotSurge) { + this.doNotSurge = doNotSurge; + } + + @Override + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + + public List getMudArea() { + return mudArea; + } + + public ListIterator getMudAreaItr() { + return mudAreaItr; + } + + public void setMudAreaItr(ListIterator mudAreaItr) { + this.mudAreaItr = mudAreaItr; + } + + public List getMudBlocks() { + return mudBlocks; + } + + public List getBlind() { + return blind; + } + + public List getAffectedEntities() { + return affectedEntities; + } + + public List getFallingBlocks() { + return fallingBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.MudSurge.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java b/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java new file mode 100644 index 0000000..7c00908 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/SandBlast.java @@ -0,0 +1,376 @@ +package com.jedk1.jedcore.ability.earthbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.SandAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Random; +import java.util.stream.Collectors; + +public class SandBlast extends SandAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.SELECT_RANGE) + private double sourceRange; + @Attribute(Attribute.RANGE) + private int range; + @Attribute("MaxShots") + private int maxBlasts; + @Attribute(Attribute.DAMAGE) + private static double damage; + + private Block source; + private BlockData sourceData; + private int blasts; + private boolean blasting; + private Vector direction; + private TempBlock tempBlock; + private final List affectedEntities = new ArrayList<>(); + private final List fallingBlocks = new ArrayList<>(); + + Random rand = new Random(); + + public SandBlast(Player player) { + super(player); + + if (!bPlayer.canBend(this)) { + return; + } + + if (hasAbility(player, SandBlast.class)) { + SandBlast sb = getAbility(player, SandBlast.class); + sb.remove(); + } + + setFields(); + if (prepare()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Earth.SandBlast.Cooldown"); + sourceRange = config.getDouble("Abilities.Earth.SandBlast.SourceRange"); + range = config.getInt("Abilities.Earth.SandBlast.Range"); + maxBlasts = config.getInt("Abilities.Earth.SandBlast.MaxSandBlocks"); + damage = config.getDouble("Abilities.Earth.SandBlast.Damage"); + } + + private boolean prepare() { + source = getEarthSourceBlock(sourceRange); + + if (source != null) { + if (EarthAbility.getMovedEarth().containsKey(source)) { + return false; + } + if (isSand(source) && ElementalAbility.isAir(source.getRelative(BlockFace.UP).getType())) { + this.sourceData = source.getBlockData().clone(); + if (DensityShift.isPassiveSand(source)) { + DensityShift.revertSand(source); + } + tempBlock = new TempBlock(source, Material.SANDSTONE.createBlockData()); + return true; + } + } + return false; + } + + @Override + public void progress() { + if (!hasAbility(player, SandBlast.class)) { + return; + } + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (player.getWorld() != source.getWorld()) { + remove(); + return; + } + if (blasting) { + if (blasts <= maxBlasts) { + blastSand(); + blasts++; + } else { + if (TempFallingBlock.getFromAbility(this).isEmpty()) { + remove(); + return; + } + } + affect(); + } + } + + @Override + public void remove() { + if (this.tempBlock != null) { + this.tempBlock.revertBlock(); + } + super.remove(); + } + + public static void blastSand(Player player) { + if (hasAbility(player, SandBlast.class)) { + SandBlast sb = getAbility(player, SandBlast.class); + if (sb.blasting) { + return; + } + sb.blastSand(); + } + } + + private void blastSand() { + if (!blasting) { + blasting = true; + direction = GeneralMethods.getDirection(source.getLocation().clone().add(0, 1, 0), GeneralMethods.getTargetedLocation(player, range)).multiply(0.07); + this.bPlayer.addCooldown(this); + } + tempBlock.revertBlock(); + + //FallingBlock fblock = source.getWorld().spawnFallingBlock(source.getLocation().clone().add(0, 1, 0), source.getType(), source.getData()); + + if (rand.nextInt(2) == 0) { + DensityShift.playSandbendingSound(source.getLocation().add(0, 1, 0)); + } + + double x = rand.nextDouble() / 10; + double z = rand.nextDouble() / 10; + + x = (rand.nextBoolean()) ? -x : x; + z = (rand.nextBoolean()) ? -z : z; + + //fblock.setVelocity(direction.clone().add(new Vector(x, 0.2, z))); + //fblock.setDropItem(false); + //fblocks.put(fblock, player); + + fallingBlocks.add(new TempFallingBlock(source.getLocation().add(0, 1, 0), sourceData, direction.clone().add(new Vector(x, 0.2, z)), this)); + + } + + public void affect() { + for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + FallingBlock fblock = tfb.getFallingBlock(); + if (fblock.isDead()) { + tfb.remove(); + continue; + } + + if (RegionProtection.isRegionProtected(player, fblock.getLocation(), this)) { + tfb.remove(); + continue; + } + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(fblock.getLocation(), 1.5)) { + if (entity instanceof LivingEntity && !(entity instanceof ArmorStand)) { + if (entity == this.player) continue; + if (affectedEntities.contains(entity)) continue; + + if (!entity.isDead()) { + DamageHandler.damageEntity(entity, damage, this); + + affectedEntities.add(entity); + + LivingEntity le = (LivingEntity) entity; + if (le.hasPotionEffect(PotionEffectType.BLINDNESS)) { + le.removePotionEffect(PotionEffectType.BLINDNESS); + } + + le.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 60, 1)); + } + } + } + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + return fallingBlocks.stream().map(TempFallingBlock::getLocation).collect(Collectors.toList()); + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + Location location = collision.getLocationFirst(); + + Optional collidedObject = fallingBlocks.stream().filter(temp -> temp.getLocation().equals(location)).findAny(); + + if (collidedObject.isPresent()) { + fallingBlocks.remove(collidedObject.get()); + collidedObject.get().remove(); + } + } + } + + @Override + public String getName() { + return "SandBlast"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.SandBlast.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public double getSourceRange() { + return sourceRange; + } + + public void setSourceRange(double sourceRange) { + this.sourceRange = sourceRange; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public int getMaxBlasts() { + return maxBlasts; + } + + public void setMaxBlasts(int maxBlasts) { + this.maxBlasts = maxBlasts; + } + + public static double getDamage() { + return damage; + } + + public static void setDamage(double damage) { + SandBlast.damage = damage; + } + + public Block getSource() { + return source; + } + + public void setSource(Block source) { + this.source = source; + } + + public BlockData getSourceData() { + return sourceData; + } + + public void setSourceData(BlockData sourceData) { + this.sourceData = sourceData; + } + + public int getBlasts() { + return blasts; + } + + public void setBlasts(int blasts) { + this.blasts = blasts; + } + + public boolean isBlasting() { + return blasting; + } + + public void setBlasting(boolean blasting) { + this.blasting = blasting; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public TempBlock getTempBlock() { + return tempBlock; + } + + public void setTempBlock(TempBlock tempBlock) { + this.tempBlock = tempBlock; + } + + public List getAffectedEntities() { + return affectedEntities; + } + + public List getFallingBlocks() { + return fallingBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.SandBlast.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java b/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java new file mode 100644 index 0000000..a26ae34 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/combo/Crevice.java @@ -0,0 +1,374 @@ +package com.jedk1.jedcore.ability.earthbending.combo; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ThreadLocalRandom; + +public class Crevice extends EarthAbility implements AddonAbility, ComboAbility { + private final List> columns = new ArrayList<>(); + + private Location origin; + private Location location; + private Vector direction; + private double travelled; + private boolean skip; + private int avatarDepth; + private long regenDelay; + + @Attribute(Attribute.RANGE) + private double range; + @Attribute("Depth") + private int randomDepth; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + public Crevice(Player player) { + super(player); + + if (!bPlayer.canBendIgnoreBinds(this)) { + return; + } + + setFields(); + + createInstance(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + range = config.getDouble("Abilities.Earth.EarthCombo.Crevice.Range"); + regenDelay = config.getLong("Abilities.Earth.EarthCombo.Crevice.RevertDelay"); + randomDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.Depth"); + avatarDepth = config.getInt("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth"); + cooldown = config.getLong("Abilities.Earth.EarthCombo.Crevice.Cooldown"); + } + + private void createInstance() { + origin = player.getTargetBlock(null, 6).getLocation(); + + if (isEarthbendable(origin.getBlock()) && !EarthAbility.getMovedEarth().containsKey(origin.getBlock())) { + Location tempLoc = player.getLocation().clone(); + tempLoc.setPitch(0); + + direction = tempLoc.getDirection().clone(); + origin.setDirection(tempLoc.getDirection()); // todo + location = origin.clone(); + + if (bPlayer.isAvatarState()) { + randomDepth = avatarDepth; + } + + start(); + + if (!isRemoved()) { + bPlayer.addCooldown(this); + } + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + prepareRevert(); + remove(); + return; + } + + if (travelled >= range || skip) { + if (System.currentTimeMillis() > getStartTime() + regenDelay) { + prepareRevert(); + remove(); + return; + } + return; + } + + advanceCrevice(); + } + + @Override + public void remove() { + prepareRevert(); + super.remove(); + } + + public static void closeCrevice(Player player) { + Block target = player.getTargetBlock(null, 10); + + for (Block near : GeneralMethods.getBlocksAroundPoint(target.getLocation(), 2)) { + for (Crevice c : getAbilities(Crevice.class)) { + for (List tbs : c.columns) { + for (TempBlock tb : tbs) { + if (near.getLocation().equals(tb.getLocation())) { + c.prepareRevert(); + c.remove(); + return; + } + } + } + } + } + } + + private void advanceCrevice() { + switch (ThreadLocalRandom.current().nextInt(2)) { + case 0: + if (location.getYaw() <= origin.getYaw()) { + location.setYaw(location.getYaw() + 40); + direction = location.getDirection().clone(); + } + break; + case 1: + if (location.getYaw() >= origin.getYaw()) { + location.setYaw(location.getYaw() - 40); + direction = location.getDirection().clone(); + } + break; + default: + direction = location.getDirection().clone(); + break; + } + + Location tempLoc = location.clone(); + location = location.add(direction.multiply(1)); + playEarthbendingSound(tempLoc); + location.getWorld().playSound(location, Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, (float) 0.5, (float) 0.5); + if (skip) { + return; + } + + travelled++; + if (travelled >= range) + return; + + if (RegionProtection.isRegionProtected(player, location, "RaiseEarth")) { + return; + } + + if (!isTransparent(location.getBlock().getRelative(BlockFace.UP))) { + location.add(0, 1, 0); + if (!isTransparent(location.getBlock().getRelative(BlockFace.UP)) || !isEarthbendable(location.getBlock())) { + skip = true; + return; + } + } else if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { + location.subtract(0, 1, 0); + if (isTransparent(location.getBlock()) || !isEarthbendable(location.getBlock())) { + skip = true; + return; + } + } + + removePillar(tempLoc, randInt(randomDepth + 1 - 2, randomDepth + 1 + 2)); + removePillar(GeneralMethods.getRightSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); + removePillar(GeneralMethods.getLeftSide(tempLoc, 1), randInt(randomDepth - 1, randomDepth + 1)); + } + + private int randInt(int min, int max) { + return ThreadLocalRandom.current().nextInt(max - min) + min; // todo: look into the necessity of this helper + } + + private void removePillar(Location location, int depth) { + List blocks = new ArrayList<>(); + Location tempLoc = location.clone().getBlock().getLocation(); + tempLoc.add(0, 1, 0); + for (int i = 0; i < depth + 1; i++) { + if (tempLoc.getY() < Objects.requireNonNull(tempLoc.getWorld()).getMinHeight() || tempLoc.getY() > tempLoc.getWorld().getMaxHeight()) { + break; + } + if (RegionProtection.isRegionProtected(player, tempLoc, this)) { + continue; + } + if (i == 0 && !isTransparent(tempLoc.getBlock())) { + continue; + } + if (i > 0 && (!isEarthbendable(tempLoc.getBlock()) || EarthAbility.getMovedEarth().containsKey(tempLoc.getBlock()))) { + continue; + } + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tempLoc, 1)) { + entity.setVelocity(new Vector(0, -0.75, 0)); + } + + + blocks.add(new TempBlock(tempLoc.getBlock(), Material.AIR.createBlockData())); + tempLoc.subtract(0, 1, 0); + } + + Collections.reverse(blocks); + + columns.add(blocks); + } + + private void prepareRevert() { + for (int i = 0; i < columns.size(); ++i) { + List tbs = columns.get(i); + for (TempBlock tb : tbs) { + tb.revertBlock(); + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 1)) { + entity.setVelocity(new Vector(0, 0.7, 0)); + } + new RegenTempBlock(tb.getBlock(), Material.AIR, Material.AIR.createBlockData(), i * 50L); + } + } + columns.clear(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "Crevice"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public Object createNewComboInstance(Player player) { + return new Crevice(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.Crevice.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.Crevice.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.Crevice.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public long getRegenDelay() { + return regenDelay; + } + + public void setRegenDelay(long regenDelay) { + this.regenDelay = regenDelay; + } + + public int getDepth() { + return randomDepth; + } + + public void setDepth(int depth) { + this.randomDepth = depth; + } + + public int getAvatarDepth() { + return avatarDepth; + } + + public void setAvatarDepth(int avatarDepth) { + this.avatarDepth = avatarDepth; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public double getDistanceTravelled() { + return travelled; + } + + public void setDistanceTravelled(double travelled) { + this.travelled = travelled; + } + + public List> getColumns() { + return columns; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthCombo.Crevice.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java b/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java new file mode 100644 index 0000000..9bf8012 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/earthbending/combo/MagmaBlast.java @@ -0,0 +1,617 @@ +package com.jedk1.jedcore.ability.earthbending.combo; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.MaterialUtil; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; +import com.projectkorra.projectkorra.ability.util.ComboUtil; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +public class MagmaBlast extends LavaAbility implements AddonAbility, ComboAbility { + private static final int PARTICLE_COUNT = 20; + private static final int RAISE_HEIGHT = 3; + + private final Set sources = new HashSet<>(); + private final List blocks = new ArrayList<>(); + private final List firedBlocks = new ArrayList<>(); + + private double fireSpeed; + // How far away the player is allowed to be from the sources before the ability is destroyed. + private double maxDistanceFromSources; + private float explosionRadius = 2.0f; + // This will destroy the instance if LavaFlow is on cooldown. + private boolean requireLavaFlow; + private boolean playerCollisions; + private boolean entitySelection; + private Location origin; + private int counter; + private long canLavaFlowTime; + private long lastShot; + private boolean stopFiring; + private long shotCooldown; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long maxDuration; + @Attribute("MaxSources") + private int maxSources; + @Attribute(Attribute.SELECT_RANGE) + private int sourceRange; + @Attribute(Attribute.SELECT_RANGE) + private double selectRange; + @Attribute(Attribute.DAMAGE) + private double damage; + + public MagmaBlast(Player player) { + super(player); + setFields(); + + if (!bPlayer.canBendIgnoreBinds(this)) { + return; + } + + origin = player.getLocation().clone(); + + if (raiseSources()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + maxSources = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots"); + sourceRange = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange"); + damage = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage"); + cooldown = config.getInt("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown"); + requireLavaFlow = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow"); + playerCollisions = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions"); + entitySelection = config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection"); + selectRange = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange"); + explosionRadius = (float) config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius"); + fireSpeed = config.getDouble("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed"); + maxDuration = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration"); + maxDistanceFromSources = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources"); + shotCooldown = config.getLong("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown"); + } + + // Select random nearby earth blocks as sources and raise them in the air. + private boolean raiseSources() { + List potentialBlocks = GeneralMethods.getBlocksAroundPoint(origin, sourceRange).stream().filter(ElementalAbility::isEarth).collect(Collectors.toList()); + + Collections.shuffle(potentialBlocks); + + for (Block newSource : potentialBlocks) { + if (!isValidSource(newSource)) continue; + + newSource.getWorld().playSound(newSource.getLocation(), Sound.ENTITY_GHAST_SHOOT, 0.8f, 0.3f); + sources.add(new TempFallingBlock(newSource.getLocation().add(0, 1, 0), Material.MAGMA_BLOCK.createBlockData(), new Vector(0, 0.9, 0), this)); + + if (sources.size() >= maxSources) { + break; + } + } + + return !sources.isEmpty(); + } + + // Checks to make sure the source block has room to fly upwards. + private boolean isValidSource(Block block) { + for (int i = 0; i <= RAISE_HEIGHT; ++i) { + if (!MaterialUtil.isTransparent(block.getRelative(BlockFace.UP, i + 1)) || block.isLiquid()) { + return false; + } + } + + return true; + } + + public boolean shouldBlockLavaFlow() { + long time = System.currentTimeMillis(); + return time < canLavaFlowTime; + } + + @Override + public void progress() { + stopFiring = false; + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + + if (System.currentTimeMillis() > this.getStartTime() + maxDuration) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreBinds(this) || !(bPlayer.getBoundAbility() instanceof LavaFlow)) { + remove(); + return; + } + + if (requireLavaFlow && !bPlayer.canBend(getAbility("LavaFlow"))) { + remove(); + return; + } + + displayAnimation(); + handleSources(); + + if (playerCollisions) { + doPlayerCollisions(); + } + + if (sources.isEmpty() && firedBlocks.isEmpty() && blocks.isEmpty()) { + remove(); + return; + } + + if (hasBlocks() && this.player.getLocation().distanceSquared(origin) > maxDistanceFromSources * maxDistanceFromSources) { + remove(); + } + } + + @Override + public void remove() { + bPlayer.addCooldown(this); + super.remove(); + + for (TempFallingBlock ftb : sources) { + ftb.remove(); + } + + for (TempBlock tb : blocks) { + tb.revertBlock(); + } + + for (TempFallingBlock tfb : firedBlocks) { + tfb.remove(); + } + } + + private void handleSources() { + if (sources.isEmpty()) return; + + for (Iterator iter = sources.iterator(); iter.hasNext();) { + TempFallingBlock tfb = iter.next(); + + if (tfb.getLocation().getBlockY() >= (origin.getBlockY() + RAISE_HEIGHT)) { + blocks.add(new TempBlock(tfb.getLocation().getBlock(), Material.MAGMA_BLOCK.createBlockData())); + iter.remove(); + tfb.remove(); + } + } + } + + private void displayAnimation() { + if (++counter == 3) { + counter = 0; + } else { + return; + } + + for (Iterator iterator = firedBlocks.iterator(); iterator.hasNext();) { + TempFallingBlock tfb = iterator.next(); + + if (!tfb.getFallingBlock().isDead()) { + playParticles(tfb.getLocation()); + } else { + tfb.remove(); + iterator.remove(); + } + } + + for (TempBlock tb : blocks) playParticles(tb.getLocation()); + } + + private void doPlayerCollisions() { + List blocksCopy = new ArrayList<>(firedBlocks); + + for (TempFallingBlock tfb : blocksCopy) { + if (!firedBlocks.contains(tfb)) continue; + + boolean didExplode = false; + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(tfb.getLocation(), this.explosionRadius)) { + if (!(e instanceof LivingEntity)) continue; + if (e == this.player) continue; + + if (blast(tfb, true)) { + didExplode = true; + } + } + + if (didExplode) { + firedBlocks.remove(tfb); + } + } + } + + private void playParticles(Location location) { + location.add(.5,.5,.5); + + ParticleEffect.LAVA.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); + ParticleEffect.SMOKE_NORMAL.display(location, 2, Math.random(), Math.random(), Math.random(), 0f); + + for (int i = 0; i < 10; i++) { + GeneralMethods.displayColoredParticle("FFA400", getOffsetLocation(location, 2)); + GeneralMethods.displayColoredParticle("FF8C00", getOffsetLocation(location, 2)); + } + } + + // Returns true if any source blocks still exist. Returns false is all of the source blocks have been fired. + public boolean hasBlocks() { + return !sources.isEmpty() || !blocks.isEmpty(); + } + + private Location getOffsetLocation(Location loc, double offset) { + return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); + } + + public static void performAction(Player player) { + MagmaBlast mb = getAbility(player, MagmaBlast.class); + + if (mb != null) { + mb.performAction(); + } + } + + private void performAction() { + long time = System.currentTimeMillis(); + + if (blocks.isEmpty() || stopFiring || time < lastShot + shotCooldown) return; + + Location target = null; + + if (entitySelection) { + Entity targetEntity = GeneralMethods.getTargetedEntity(player, selectRange); + + if (targetEntity instanceof LivingEntity) { + target = ((LivingEntity) targetEntity).getEyeLocation(); + } + } + + if (target == null) { + target = GeneralMethods.getTargetedLocation(player, selectRange, Material.MAGMA_BLOCK); + } + + TempBlock tb = getClosestSource(target); + + if (tb == null) return; + + stopFiring = true; + canLavaFlowTime = time + 1000; + blocks.remove(tb); + + Vector direction = GeneralMethods.getDirection(tb.getLocation().clone().add(0.5f, 0.5f, 0.5f), target).normalize(); + + tb.revertBlock(); + + FallingBlock fallingBlock = tb.getLocation().getWorld().spawnFallingBlock( + tb.getLocation().clone().add(0.5, 0.5, 0.5), + Material.MAGMA_BLOCK.createBlockData() + ); + + fallingBlock.setTicksLived(Integer.MAX_VALUE); + fallingBlock.setMetadata("magmablast", new FixedMetadataValue(JedCore.plugin, "1")); + fallingBlock.setDropItem(false); + fallingBlock.setCancelDrop(true); + + TempFallingBlock tfb = new TempFallingBlock(tb.getLocation(), Material.MAGMA_BLOCK.createBlockData(), direction.multiply(fireSpeed), this, true); + firedBlocks.add(tfb); + + lastShot = time; + } + + // Get the closest fireable source block to the target location. + private TempBlock getClosestSource(Location target) { + double distanceSq = Double.MAX_VALUE; + TempBlock closest = null; + + for (TempBlock tempBlock : blocks) { + Block block = tempBlock.getLocation().getBlock(); + if (EarthAbility.getMovedEarth().containsKey(block)) { + continue; + } + double currentDistSq = tempBlock.getLocation().distanceSquared(target); + + if (currentDistSq < distanceSq) { + distanceSq = currentDistSq; + closest = tempBlock; + } + } + + return closest; + } + + public static void blast(TempFallingBlock tfb) { + blast(tfb, false); + } + + public static boolean blast(TempFallingBlock tfb, boolean entityCollision) { + MagmaBlast mb = (MagmaBlast) tfb.getAbility(); + Location location = tfb.getLocation().clone().add(0.5, 0.5, 0.5); + + Block hitBlock = location.getBlock(); + if (hitBlock.getType().isSolid()) { + blastEffects(location, mb); + tfb.remove(); + mb.firedBlocks.remove(tfb); + return true; + } + + float radius = mb.explosionRadius; + boolean didHit = false; + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, radius)) { + if (!(entity instanceof LivingEntity)) continue; + if (entity == mb.player) continue; + + DamageHandler.damageEntity(entity, mb.getDamage(), mb); + ((LivingEntity) entity).setNoDamageTicks(0); + didHit = true; + } + + if (didHit || entityCollision) { + blastEffects(location, mb); + tfb.remove(); + mb.firedBlocks.remove(tfb); + return true; + } + + return false; + } + + private static void blastEffects(Location location, MagmaBlast mb) { + float radius = mb.explosionRadius; + float speed = 0.1f; + + ParticleEffect.FLAME.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); + ParticleEffect.SMOKE_LARGE.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); + ParticleEffect.FIREWORKS_SPARK.display(location, PARTICLE_COUNT, randomBinomial(radius), randomBinomial(radius), randomBinomial(radius), speed); + + ThreadLocalRandom rand = ThreadLocalRandom.current(); + + location.getWorld().playSound(location, + (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_BLAST : Sound.ENTITY_FIREWORK_ROCKET_BLAST_FAR, + 1f, 1f); + location.getWorld().playSound(location, + (rand.nextBoolean()) ? Sound.ENTITY_FIREWORK_ROCKET_TWINKLE : Sound.ENTITY_FIREWORK_ROCKET_TWINKLE_FAR, + 1f, 1f); + } + + // Generates a random number between -max and max. + private static float randomBinomial(float max) { + ThreadLocalRandom rand = ThreadLocalRandom.current(); + return (rand.nextFloat() * max) - (rand.nextFloat() * max); + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "MagmaBlast"; + } + + @Override + public boolean isHiddenAbility() { + return false; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public Object createNewComboInstance(Player player) { + return new MagmaBlast(player); + } + + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Earth.EarthCombo.MagmaBlast.Combination")); + } + + @Override + public String getInstructions() { + return JedCoreConfig.getConfig(player).getString("Abilities.Earth.EarthCombo.MagmaBlast.Instructions"); + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Earth.EarthCombo.MagmaBlast.Description"); + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + public Set getSources() { + return sources; + } + + public List getBlocks() { + return blocks; + } + + public List getFiredBlocks() { + return firedBlocks; + } + + public long getMaxDuration() { + return maxDuration; + } + + public void setMaxDuration(long maxDuration) { + this.maxDuration = maxDuration; + } + + public long getShotCooldown() { + return shotCooldown; + } + + public void setShotCooldown(long shotCooldown) { + this.shotCooldown = shotCooldown; + } + + public int getMaxSources() { + return maxSources; + } + + public void setMaxSources(int maxSources) { + this.maxSources = maxSources; + } + + public int getSourceRange() { + return sourceRange; + } + + public void setSourceRange(int sourceRange) { + this.sourceRange = sourceRange; + } + + public double getSelectRange() { + return selectRange; + } + + public void setSelectRange(double selectRange) { + this.selectRange = selectRange; + } + + public double getFireSpeed() { + return fireSpeed; + } + + public void setFireSpeed(double fireSpeed) { + this.fireSpeed = fireSpeed; + } + + public double getMaxDistanceFromSources() { + return maxDistanceFromSources; + } + + public void setMaxDistanceFromSources(double maxDistanceFromSources) { + this.maxDistanceFromSources = maxDistanceFromSources; + } + + public float getExplosionRadius() { + return explosionRadius; + } + + public void setExplosionRadius(float explosionRadius) { + this.explosionRadius = explosionRadius; + } + + public boolean isRequireLavaFlow() { + return requireLavaFlow; + } + + public void setRequireLavaFlow(boolean requireLavaFlow) { + this.requireLavaFlow = requireLavaFlow; + } + + public boolean isPlayerCollisions() { + return playerCollisions; + } + + public void setPlayerCollisions(boolean playerCollisions) { + this.playerCollisions = playerCollisions; + } + + public boolean isEntitySelection() { + return entitySelection; + } + + public void setEntitySelection(boolean entitySelection) { + this.entitySelection = entitySelection; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public long getCanLavaFlowTime() { + return canLavaFlowTime; + } + + public void setCanLavaFlowTime(long canLavaFlowTime) { + this.canLavaFlowTime = canLavaFlowTime; + } + + public long getLastShotTime() { + return lastShot; + } + + public void setLastShotTime(long lastShot) { + this.lastShot = lastShot; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Earth.EarthCombo.MagmaBlast.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/firebending/Combustion.java b/src/com/jedk1/jedcore/ability/firebending/Combustion.java new file mode 100644 index 0000000..cbad36d --- /dev/null +++ b/src/com/jedk1/jedcore/ability/firebending/Combustion.java @@ -0,0 +1,622 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.util.FireTick; +import com.jedk1.jedcore.util.MaterialUtil; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.CombustionAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +public class Combustion extends CombustionAbility implements AddonAbility { + + private State state; + private Location location; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + private CompositeRemovalPolicy removalPolicy; + + private ArrayList skipMaterials; // use a configured list of blocks to skip through + + public Combustion(Player player) { + super(player); + + if (!isEnabled()) return; + + if (this.player == null || !bPlayer.canBend(this) || !bPlayer.canCombustionbend()) { + return; + } + + if (hasAbility(player, Combustion.class)) { + Combustion c = getAbility(player, Combustion.class); + if (c.state instanceof ChargeState) + return; + } + + setFields(); + + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.Combustion.Cooldown"); + + this.location = null; + this.state = new ChargeState(); + + this.removalPolicy = new CompositeRemovalPolicy(this, + new CannotBendRemovalPolicy(this.bPlayer, this, true, true), + new IsOfflineRemovalPolicy(this.player), + new IsDeadRemovalPolicy(this.player), + new SwappedSlotsRemovalPolicy<>(bPlayer, Combustion.class) + ); + + this.removalPolicy.load(config, "Abilities.Fire.Combustion"); + + this.skipMaterials = loadSkipMaterials(); + } + + @Override + public void progress() { + if (this.removalPolicy.shouldRemove()) { + remove(); + return; + } + + state.update(); + } + + public static void combust(Player player) { + if(hasAbility(player, Combustion.class)) { + Combustion c = getAbility(player, Combustion.class); + + c.selfCombust(); + } + } + + public void selfCombust() { + if (this.state instanceof TravelState) { + this.state = new CombustState(location); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + // Only enable the collision while traveling. + if (state instanceof TravelState) { + return location; + } + + return null; + } + + @Override + public double getCollisionRadius() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getDouble("Abilities.Fire.Combustion.AbilityCollisionRadius"); + } + + @Override + public String getName() { + return "Combustion"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.Combustion.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.Combustion.Enabled"); + } + + private ArrayList loadSkipMaterials() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + ArrayList skipList = new ArrayList<>(); + + if (config.contains("Abilities.Fire.Combustion.SkipMaterials")) { + List configuredSkipList = config.getStringList("Abilities.Fire.Combustion.SkipMaterials"); + + for (String entry : configuredSkipList) { + if (entry.startsWith("#")) { + String tagName = entry.substring(1).toLowerCase(); + + NamespacedKey tagKey = NamespacedKey.minecraft(tagName); + Tag materialTag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, tagKey, Material.class); + + if (materialTag != null) { + skipList.addAll(materialTag.getValues().stream() + .map(material -> material.name().toLowerCase()) + .collect(Collectors.toList())); + } + } else { + skipList.add(entry.toLowerCase()); + } + } + } + + return skipList; + } + + private interface State { + void update(); + } + + // This is the initial state of Combustion. + // It's used to render the particle ring that happens during charging. + // This state transitions to TravelState if the player stops sneaking after charging is done. + // This state transitions to CombustState if the player takes damage while charging. + private class ChargeState implements State { + private final long startTime; + private int currPoint = (int) player.getLocation().getYaw() + 90; + private final long warmup; + private final double playerStartHealth; + private final boolean instantExplodeIfHit; + + public ChargeState() { + this.startTime = System.currentTimeMillis(); + this.playerStartHealth = player.getHealth(); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + this.instantExplodeIfHit = config.getBoolean("Abilities.Fire.Combustion.InstantExplodeIfHit"); + this.warmup = config.getLong("Abilities.Fire.Combustion.Warmup"); + } + + @Override + public void update() { + long time = System.currentTimeMillis(); + + boolean charged = time >= this.startTime + warmup; + + if (player.isSneaking()) { + if (!bPlayer.canBendIgnoreBinds(Combustion.this)) { + remove(); + return; + } + + playParticleRing(60, 1.75F, 2); + + if (instantExplodeIfHit && player.getHealth() < playerStartHealth) { + // Remove and combust at player's location + state = new CombustState(player.getLocation(), true); + bPlayer.addCooldown(Combustion.this); + return; + } + + if (charged) { + ParticleEffect.SMOKE_LARGE.display(player.getLocation(), 1, Math.random(), Math.random(), Math.random(), 0.1); + } + } else { + if (charged) { + state = new TravelState(); + bPlayer.addCooldown(Combustion.this); + } else { + remove(); + } + } + } + + private void playParticleRing(int points, float size, int speed) { + for (int i = 0; i < speed; ++i) { + currPoint += 360 / points; + + if (currPoint > 360) { + currPoint = 0; + } + + double angle = currPoint * 3.141592653589793D / 180.0D; + double x = size * Math.cos(angle); + double z = size * Math.sin(angle); + + Location loc = player.getLocation().add(x, 1.0D, z); + playFirebendingParticles(loc, 3, 0.0, 0.0, 0.0); + ParticleEffect.SMOKE_NORMAL.display(loc, 4, 0.0, 0.0, 0.0, 0.01); + JCMethods.emitLight(loc); + } + } + } + + // This state is used after the player releases a charged Combustion. + // It's used for moving and rendering the projectile. + // This state transitions to CombustState when it collides with terrain or an entity. + private class TravelState implements State { + private Vector direction; + private final int range; + private final double speed; + private final boolean explodeOnDeath; + private final double entityCollisionRadius; + private double distanceTraveled; + + public TravelState() { + removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); + + Location origin = player.getEyeLocation().clone(); + origin.setY(origin.getY() - 0.8D); + location = origin.clone(); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + range = config.getInt("Abilities.Fire.Combustion.Range"); + speed = config.getDouble("Abilities.Fire.Combustion.Speed"); + explodeOnDeath = config.getBoolean("Abilities.Fire.Combustion.ExplodeOnDeath"); + entityCollisionRadius = config.getDouble("Abilities.Fire.Combustion.EntityCollisionRadius"); + + if (explodeOnDeath) { + removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); + removalPolicy.removePolicyType(IsDeadRemovalPolicy.class); + } + + direction = player.getEyeLocation().getDirection().normalize(); + distanceTraveled = 0; + } + + @Override + public void update() { + if (explodeOnDeath && player.isDead()) { + state = new CombustState(location); + return; + } + + // Manually handle the region protection check because the CannotBendRemovalPolicy no longer checks it + // when explodeOnDeath is true. This stops players from firing Combustion and then walking into a + // protected area. + if (explodeOnDeath) { + if (RegionProtection.isRegionProtected(Combustion.this, player.getLocation())) { + remove(); + return; + } + } + + if (distanceTraveled >= range) { + remove(); + return; + } + + travel(); + } + + private void travel() { + double stepDistance = speed; + + for (int i = 0; i < (int) (speed * 5); ++i) { + render(); + + Sphere collider = new Sphere(location.toVector(), entityCollisionRadius); + + boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { + location = entity.getLocation(); + state = new CombustState(location); + return true; + }); + + if (hit) { + return; + } + + if (!MaterialUtil.isTransparent(location.getBlock()) || isWater(location.getBlock())) { + Material blockMaterial = location.getBlock().getType(); + String blockMaterialName = blockMaterial.name().toLowerCase(); + + boolean shouldSkip = skipMaterials.contains(blockMaterialName); + + if (!shouldSkip) { + state = new CombustState(location); + return; + } + } + + direction = player.getEyeLocation().getDirection().normalize(); + location = location.add(direction.clone().multiply(stepDistance)); + + distanceTraveled += stepDistance; + + if (distanceTraveled >= range) { + remove(); + return; + } + } + } + + private void render() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + ParticleEffect.SOUL_FIRE_FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); + } else { + ParticleEffect.FLAME.display(location, 1, 0.0, 0.0, 0.0, 0.03); + } + ParticleEffect.SMOKE_LARGE.display(location, 1, 0.0, 0.0, 0.0F, 0.06); + ParticleEffect.FIREWORKS_SPARK.display(location, 1, 0.0, 0.0, 0.0F, 0.06); + + location.getWorld().playSound(location, Sound.ENTITY_FIREWORK_ROCKET_BLAST, 1.0F, 0.01F); + + JCMethods.emitLight(location); + } + } + + @Override + public void handleCollision(final Collision collision) { + super.handleCollision(collision); + + if (collision.isRemovingFirst()) { + state = new CombustState(collision.getLocationFirst()); + } + } + + // This state is used for doing the explosion. + // ChargeState can transition to this state if the player takes damage while charging. + // TravelState can transition to this state if the projectile collides with terrain, entity, or collidable ability. + private class CombustState implements State { + private final long startTime; + private final long regenTime; + private boolean waitForRegen; + + public CombustState(Location location) { + this(location, false); + } + + public CombustState(Location location, boolean misfire) { + removalPolicy.removePolicyType(SwappedSlotsRemovalPolicy.class); + // This stops players from moving into a protected area to bypass the regen wait time. + removalPolicy.removePolicyType(CannotBendRemovalPolicy.class); + + ConfigurationSection config = JedCoreConfig.getConfig(player); + + this.startTime = System.currentTimeMillis(); + this.regenTime = config.getLong("Abilities.Fire.Combustion.RegenTime"); + this.waitForRegen = config.getBoolean("Abilities.Fire.Combustion.WaitForRegen"); + + double damage = config.getDouble("Abilities.Fire.Combustion.Damage"); + int fireTick = config.getInt("Abilities.Fire.Combustion.FireTick"); + int power = config.getInt("Abilities.Fire.Combustion.Power"); + boolean damageBlocks = config.getBoolean("Abilities.Fire.Combustion.DamageBlocks"); + boolean regenBlocks = config.getBoolean("Abilities.Fire.Combustion.RegenBlocks"); + + ExplosionMethod explosionMethod; + if (regenBlocks) { + explosionMethod = new RegenExplosionMethod(damageBlocks, regenTime); + } else { + explosionMethod = new PermanentExplosionMethod(damageBlocks); + } + + // Don't wait for regen if the blocks aren't even being destroyed. + if (!damageBlocks) { + waitForRegen = false; + } + + double modifier = 0; + if (misfire) { + modifier = config.getInt("Abilities.Fire.Combustion.MisfireModifier"); + } + + int destroyedCount = explosionMethod.explode(location, power + modifier, damage + modifier, fireTick); + + // Don't wait for regen if nothing was actually destroyed. + if (destroyedCount <= 0) { + waitForRegen = false; + } + + AirAbility.removeAirSpouts(location, power, player); + WaterAbility.removeWaterSpouts(location, power, player); + } + + @Override + public void update() { + if (!waitForRegen || System.currentTimeMillis() >= (this.startTime + this.regenTime)) { + remove(); + } + } + } + + private interface ExplosionMethod { + // Returns how many blocks were destroyed. + int explode(Location location, double size, double damage, int fireTick); + } + + private abstract class AbstractExplosionMethod implements ExplosionMethod { + protected List blocks = Arrays.asList( + Material.AIR, Material.VOID_AIR, Material.CAVE_AIR, Material.BEDROCK, Material.CHEST, Material.TRAPPED_CHEST, Material.OBSIDIAN, + Material.NETHER_PORTAL, Material.END_PORTAL, Material.END_PORTAL_FRAME, Material.FIRE, + Material.WATER, Material.LAVA, Material.DROPPER, Material.FURNACE, + Material.DISPENSER, Material.HOPPER, Material.BEACON, Material.BARRIER, Material.SPAWNER + ); + + private final boolean destroy; + private final Random rand = new Random(); + + public AbstractExplosionMethod(boolean destroy) { + this.destroy = destroy; + } + + public int explode(Location location, double size, double damage, int fireTick) { + render(location); + + if (!destroy) { + return 0; + } + + location.getWorld().createExplosion(location, 0.0F); + int destroyCount = destroyBlocks(location, (int)size); + damageEntities(location, size, damage, fireTick); + + return destroyCount; + } + + private void render(Location location) { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + ParticleEffect.SOUL_FIRE_FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + } else { + ParticleEffect.FLAME.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + } + ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + ParticleEffect.FIREWORKS_SPARK.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + ParticleEffect.SMOKE_LARGE.display(location, 20, Math.random(), Math.random(), Math.random()); + ParticleEffect.EXPLOSION_HUGE.display(location, 20, Math.random(), Math.random(), Math.random(), 0.5); + + location.getWorld().playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 1f, 1f); + } + + private int destroyBlocks(Location location, int size) { + int count = 0; + + for (Location l : GeneralMethods.getCircle(location, size, size, false, true, 0)) { + if (!RegionProtection.isRegionProtected(Combustion.this, l)) { + if (destroyBlock(l)) { + ++count; + } + } + } + + return count; + } + + private void damageEntities(Location location, double size, double damage, int fireTick) { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, size)) { + if (e instanceof LivingEntity) { + if (!RegionProtection.isRegionProtected(Combustion.this, e.getLocation())) { + DamageHandler.damageEntity(e, damage, Combustion.this); + FireTick.set(e, fireTick); + } + } + } + } + + protected void placeRandomFire(Location location) { + int chance = rand.nextInt(3); + + if ((!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) || (chance != 0)) + return; + + location.getBlock().setType(Material.FIRE); + } + + protected void placeRandomBlock(Location location) { + int chance = rand.nextInt(3); + + if (!(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType().isSolid())) + return; + + Material block = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()).getType(); + + if (chance == 0) + location.getBlock().setType(block); + } + + // Returns how many blocks were destroyed. + public abstract boolean destroyBlock(Location location); + } + + private class RegenExplosionMethod extends AbstractExplosionMethod { + private final long regenTime; + + public RegenExplosionMethod(boolean destroy, long regenTime) { + super(destroy); + this.regenTime = regenTime; + } + + @Override + public boolean destroyBlock(Location l) { + Block block = l.getBlock(); + + if (TempBlock.isTempBlock(block)) + TempBlock.revertBlock(block, Material.AIR); + if (TempBlock.isTempBlock(block)) + TempBlock.removeBlock(block); + + if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { + new RegenTempBlock(block, Material.AIR, Material.AIR.createBlockData(), regenTime, false); + placeRandomBlock(l); + placeRandomFire(l); + + return true; + } + + return false; + } + } + + private class PermanentExplosionMethod extends AbstractExplosionMethod { + public PermanentExplosionMethod(boolean destroy) { + super(destroy); + } + + @Override + public boolean destroyBlock(Location l) { + Block block = l.getBlock(); + + if (!MaterialUtil.isTransparent(block) && !blocks.contains(block.getType()) && !MaterialUtil.isSign(block)) { + Block newBlock = l.getWorld().getBlockAt(l); + newBlock.setType(Material.AIR); + placeRandomBlock(l); + placeRandomFire(l); + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/ability/firebending/Discharge.java b/src/com/jedk1/jedcore/ability/firebending/Discharge.java similarity index 99% rename from src/ability/firebending/Discharge.java rename to src/com/jedk1/jedcore/ability/firebending/Discharge.java index 49e62dc..1f27388 100644 --- a/src/ability/firebending/Discharge.java +++ b/src/com/jedk1/jedcore/ability/firebending/Discharge.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.configuration.ConfigurationSection; diff --git a/src/ability/firebending/FireBall.java b/src/com/jedk1/jedcore/ability/firebending/FireBall.java similarity index 99% rename from src/ability/firebending/FireBall.java rename to src/com/jedk1/jedcore/ability/firebending/FireBall.java index 7d739f0..2631565 100644 --- a/src/ability/firebending/FireBall.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireBall.java @@ -1,16 +1,26 @@ package com.jedk1.jedcore.ability.firebending; import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.collision.CollisionDetector; import com.jedk1.jedcore.collision.Sphere; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.AirShieldReflector; import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.airbending.AirShield; import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.BlazeArc; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Entity; @@ -18,17 +28,6 @@ import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.Element.SubElement; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.BlueFireAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.firebending.BlazeArc; -import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; - public class FireBall extends FireAbility implements AddonAbility { private Location location; diff --git a/src/com/jedk1/jedcore/ability/firebending/FireBreath.java b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java new file mode 100644 index 0000000..f6fdd7c --- /dev/null +++ b/src/com/jedk1/jedcore/ability/firebending/FireBreath.java @@ -0,0 +1,422 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.listener.CommandListener; +import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.BlueFireAbility; +import com.projectkorra.projectkorra.ability.FireAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.BlazeArc; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.ChatUtil; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.*; + +public class FireBreath extends FireAbility implements AddonAbility { + + public static List rainbowPlayer = new ArrayList<>(); + + private int ticks; + Random rand = new Random(); + private final List locations = new ArrayList<>(); + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + private int particles; + @Attribute("Player" + Attribute.DAMAGE) + private double playerDamage; + @Attribute("Mob" + Attribute.DAMAGE) + private double mobDamage; + @Attribute(Attribute.DURATION) + private int fireDuration; + @Attribute(Attribute.RANGE) + private int range; + private boolean spawnFire; + private boolean meltEnabled; + private int meltChance; + + + public FireBreath(Player player) { + super(player); + if (!bPlayer.canBend(this) || hasAbility(player, FireBreath.class)) { + return; + } + + setFields(); + + if (bPlayer.isAvatarState()) { + range = range * 2; + playerDamage = playerDamage * 1.5; + mobDamage = mobDamage * 2; + duration = duration * 3; + } else if (JCMethods.isSozinsComet(player.getWorld())) { + range = range * 2; + playerDamage = playerDamage * 1.5; + mobDamage = mobDamage * 2; + } + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.FireBreath.Cooldown"); + duration = config.getLong("Abilities.Fire.FireBreath.Duration"); + particles = config.getInt("Abilities.Fire.FireBreath.Particles"); + playerDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Player"); + mobDamage = config.getDouble("Abilities.Fire.FireBreath.Damage.Mob"); + fireDuration = config.getInt("Abilities.Fire.FireBreath.FireDuration"); + range = config.getInt("Abilities.Fire.FireBreath.Range"); + spawnFire = config.getBoolean("Abilities.Fire.FireBreath.Avatar.FireEnabled"); + meltEnabled = config.getBoolean("Abilities.Fire.FireBreath.Melt.Enabled"); + meltChance = config.getInt("Abilities.Fire.FireBreath.Melt.Chance"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + cooldown *= BlueFireAbility.getCooldownFactor(); + range *= BlueFireAbility.getRangeFactor(); + playerDamage *= BlueFireAbility.getDamageFactor(); + mobDamage *= BlueFireAbility.getDamageFactor(); + } + + if (isDay(player.getWorld())) { + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + range = (int) getDayFactor(range); + playerDamage = getDayFactor(playerDamage); + mobDamage = getDayFactor(mobDamage); + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (!player.isSneaking()) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (System.currentTimeMillis() < getStartTime() + duration) { + createBeam(); + } else { + bPlayer.addCooldown(this); + remove(); + } + } + + private boolean isLocationSafe(Location loc) { + Block block = loc.getBlock(); + if (RegionProtection.isRegionProtected(player, loc, this)) { + return false; + } + if (!isTransparent(block)) { + return false; + } + return !isWater(block); + } + + private void createBeam() { + Location loc = player.getEyeLocation(); + Vector dir = player.getLocation().getDirection(); + double step = 1; + double size = 0; + double offset = 0; + double damageRegion = 1.5; + + locations.clear(); + + for (double k = 0; k < range; k += step) { + loc = loc.add(dir.clone().multiply(step)); + size += 0.005; + offset += 0.3; + damageRegion += 0.01; + if (meltEnabled) { + for (Block b : GeneralMethods.getBlocksAroundPoint(loc, damageRegion)) { + if (isIce(b) && rand.nextInt(meltChance) == 0) { + if (TempBlock.isTempBlock(b)) { + TempBlock temp = TempBlock.get(b); + if (PhaseChange.getFrozenBlocksMap().containsKey(temp)) { + temp.revertBlock(); + PhaseChange.getFrozenBlocksMap().remove(temp); + } + } + } + } + } + if (!isLocationSafe(loc)) + return; + + locations.add(loc); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + if (entity instanceof Player) { + FireTick.set(entity, fireDuration / 50); + DamageHandler.damageEntity(entity, playerDamage, this); + } else { + FireTick.set(entity, fireDuration / 50); + DamageHandler.damageEntity(entity, mobDamage, this); + } + } + } + + playFirebendingSound(loc); + if (bPlayer.isAvatarState() && spawnFire) { + new BlazeArc(player, loc, dir, 2); + } + + if (rainbowPlayer.contains(player.getUniqueId())) { + ticks++; + if (ticks >= 301) + ticks = 0; + if (isInRange(ticks, 0, 50)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 140, 32, 32); + } else if (isInRange(ticks, 51, 100)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 196, 93, 0); + } else if (isInRange(ticks, 101, 150)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 186, 166, 37); + } else if (isInRange(ticks, 151, 200)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 36, 171, 47); + } else if (isInRange(ticks, 201, 250)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 36, 142, 171); + } else if (isInRange(ticks, 251, 300)) { + for (int i = 0; i < 6; i++) + displayParticle(getOffsetLocation(loc, offset), 1, 128, 36, 171); + } + } else { + playFirebendingParticles(loc, particles, Math.random(), Math.random(), Math.random()); + ParticleEffect.SMOKE_NORMAL.display(loc, particles, Math.random(), Math.random(), Math.random(), size); + JCMethods.emitLight(loc); + } + } + } + + private void displayParticle(Location location, int amount, int r, int g, int b) { + ParticleEffect.REDSTONE.display(location, amount, 0, 0, 0, 0.005, new Particle.DustOptions(Color.fromRGB(r, g, b), 1)); + JCMethods.emitLight(location); + } + + private boolean isInRange(int x, int min, int max) { + return min <= x && x <= max; + } + + /** + * Generates an offset location around a given location with variable offset + * amount. + */ + private Location getOffsetLocation(Location loc, double offset) { + return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); + } + + public static void toggleRainbowBreath(Player player, boolean activate) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + + boolean easterEgg = config.getBoolean("Abilities.Fire.FireBreath.RainbowBreath.Enabled"); + String bindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "")); + String unbindMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "")); + String deniedMsg = ChatUtil.color(config.getString("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "")); + + if (easterEgg && (player.hasPermission("bending.ability.FireBreath.RainbowBreath") + || Arrays.asList(CommandListener.developers).contains(player.getUniqueId().toString()))) { + if (activate) { + if (!rainbowPlayer.contains(player.getUniqueId())) { + rainbowPlayer.add(player.getUniqueId()); + if (!bindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + bindMsg); + } + } else { + if (rainbowPlayer.contains(player.getUniqueId())) { + rainbowPlayer.remove(player.getUniqueId()); + if (!unbindMsg.equals("")) player.sendMessage(Element.FIRE.getColor() + unbindMsg); + } + } + } else if (!deniedMsg.equals("")) { + player.sendMessage(Element.FIRE.getColor() + deniedMsg); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return player.getLocation(); + } + + @Override + public List getLocations() { + return locations; + } + + @Override + public String getName() { + return "FireBreath"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireBreath.Description"); + } + + public static List getRainbowPlayer() { + return rainbowPlayer; + } + + public static void setRainbowPlayer(List rainbowPlayer) { + FireBreath.rainbowPlayer = rainbowPlayer; + } + + public int getTicks() { + return ticks; + } + + public void setTicks(int ticks) { + this.ticks = ticks; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public int getParticles() { + return particles; + } + + public void setParticles(int particles) { + this.particles = particles; + } + + public double getPlayerDamage() { + return playerDamage; + } + + public void setPlayerDamage(double playerDamage) { + this.playerDamage = playerDamage; + } + + public double getMobDamage() { + return mobDamage; + } + + public void setMobDamage(double mobDamage) { + this.mobDamage = mobDamage; + } + + public int getFireDuration() { + return fireDuration; + } + + public void setFireDuration(int fireDuration) { + this.fireDuration = fireDuration; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public boolean isSpawnFire() { + return spawnFire; + } + + public void setSpawnFire(boolean spawnFire) { + this.spawnFire = spawnFire; + } + + public boolean isMeltEnabled() { + return meltEnabled; + } + + public void setMeltEnabled(boolean meltEnabled) { + this.meltEnabled = meltEnabled; + } + + public int getMeltChance() { + return meltChance; + } + + public void setMeltChance(int meltChance) { + this.meltChance = meltChance; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FireBreath.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/firebending/FireComet.java b/src/com/jedk1/jedcore/ability/firebending/FireComet.java similarity index 99% rename from src/ability/firebending/FireComet.java rename to src/com/jedk1/jedcore/ability/firebending/FireComet.java index d49f2d4..2cdd262 100644 --- a/src/ability/firebending/FireComet.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireComet.java @@ -13,7 +13,6 @@ import com.projectkorra.projectkorra.region.RegionProtection; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; - import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/ability/firebending/FirePunch.java b/src/com/jedk1/jedcore/ability/firebending/FirePunch.java similarity index 99% rename from src/ability/firebending/FirePunch.java rename to src/com/jedk1/jedcore/ability/firebending/FirePunch.java index 8dfc35c..c80d53c 100644 --- a/src/ability/firebending/FirePunch.java +++ b/src/com/jedk1/jedcore/ability/firebending/FirePunch.java @@ -1,11 +1,6 @@ package com.jedk1.jedcore.ability.firebending; import com.jedk1.jedcore.JCMethods; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; - import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.FireTick; @@ -18,6 +13,10 @@ import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.inventory.MainHand; public class FirePunch extends FireAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/firebending/FireShots.java b/src/com/jedk1/jedcore/ability/firebending/FireShots.java new file mode 100644 index 0000000..39f7332 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/firebending/FireShots.java @@ -0,0 +1,411 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.collision.Sphere; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.AirShieldReflector; +import com.jedk1.jedcore.util.FireTick; +import com.projectkorra.projectkorra.Element.SubElement; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.airbending.AirShield; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.firebending.util.FireDamageTimer; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.MainHand; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class FireShots extends FireAbility implements AddonAbility { + + private final List shots = new ArrayList<>(); + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute("MaxShots") + private int startAmount; + @Attribute(Attribute.FIRE_TICK) + private int fireticks; + @Attribute(Attribute.RANGE) + private int range; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute("CollisionRadius") + private double collisionRadius; + private Boolean flameInMainHand = null; + + public int amount; + + public FireShots(Player player){ + super(player); + + if (!bPlayer.canBend(this) || hasAbility(player, FireShots.class)) { + return; + } + + if (!player.hasGravity()) + player.setGravity(true); + + setFields(); + + amount = startAmount; + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.FireShots.Cooldown"); + startAmount = config.getInt("Abilities.Fire.FireShots.FireBalls"); + fireticks = config.getInt("Abilities.Fire.FireShots.FireDuration"); + range = config.getInt("Abilities.Fire.FireShots.Range"); + damage = config.getDouble("Abilities.Fire.FireShots.Damage"); + collisionRadius = config.getDouble("Abilities.Fire.FireShots.CollisionRadius"); + + applyModifiers(); + } + + private void applyModifiers() { + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + cooldown *= BlueFireAbility.getCooldownFactor(); + range *= BlueFireAbility.getRangeFactor(); + damage *= BlueFireAbility.getDamageFactor(); + } + + if (isDay(player.getWorld())) { + cooldown -= ((long) getDayFactor(cooldown) - cooldown); + range = (int) getDayFactor(range); + damage = getDayFactor(damage); + } + } + + public class FireShot { + + private final Ability ability; + private final Player player; + private Location location; + private final int range; + private final int fireTicks; + private double distanceTravelled; + private final double damage; + private Vector direction = null; + + public FireShot(Ability ability, Player player, Location location, int range, int fireTicks, double damage) { + this.ability = ability; + this.player = player; + this.location = location; + this.range = range; + this.fireTicks = fireTicks; + this.damage = damage; + } + + public boolean progress() { + if (player.isDead() || !player.isOnline()) { + return false; + } + if (distanceTravelled >= range) { + return false; + } + for (int i = 0; i < 2; i++) { + distanceTravelled ++; + if (distanceTravelled >= range) + return false; + + Vector dir = direction; + if (dir == null) { + dir = this.player.getLocation().getDirection().clone(); + } + + location = location.add(dir); + + if (GeneralMethods.isSolid(location.getBlock()) || isWater(location.getBlock())){ + return false; + } + + if (bPlayer.canUseSubElement(SubElement.BLUE_FIRE)) { + ParticleEffect.SOUL_FIRE_FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); + } else { + ParticleEffect.FLAME.display(location, 5, 0.0, 0.0, 0.0, 0.02); + } + ParticleEffect.SMOKE_NORMAL.display(location, 2, 0.0, 0.0, 0.0, 0.01); + + JCMethods.emitLight(location); + + Sphere collider = new Sphere(location.toVector(), collisionRadius); + + boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { + DamageHandler.damageEntity(entity, damage, ability); + FireTick.set(entity, Math.round(fireTicks / 50F)); + new FireDamageTimer(entity, player, FireShots.this); + return true; + }); + + if (hit) { + return false; + } + } + return true; + } + + public Ability getAbility() { + return ability; + } + + public Player getPlayer() { + return player; + } + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getRange() { + return range; + } + + public int getFireTicks() { + return fireTicks; + } + + public double getDistanceTravelled() { + return distanceTravelled; + } + + public void setDistanceTravelled(double distanceTravelled) { + this.distanceTravelled = distanceTravelled; + } + + public double getDamage() { + return damage; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (!bPlayer.canBendIgnoreCooldowns(this)) { + amount = 0; + if (!bPlayer.isOnCooldown(this)) { + bPlayer.addCooldown(this); + } + } + + shots.removeIf(shot -> !shot.progress()); + + if (amount <= 0 && shots.isEmpty()) { + remove(); + return; + } + + if (amount > 0) { + displayFireBalls(); + } + } + + public static void fireShot(Player player) { + FireShots fs = getAbility(player, FireShots.class); + if (fs != null) { + fs.fireShot(); + } + } + + public static void swapHands(Player player) { + FireShots fs = getAbility(player, FireShots.class); + if (fs == null) + return; + if (fs.flameInMainHand == null) + fs.flameInMainHand = true; + else fs.flameInMainHand = !fs.flameInMainHand; + } + + public void fireShot() { + if (amount >= 1) { + if (--amount <= 0) { + bPlayer.addCooldown(this); + } + shots.add(new FireShot(this, player, getRightHandPos(), range, fireticks, damage)); + } + } + + public Location getRightHandPos() { + return (player.getMainHand()==MainHand.RIGHT == ((flameInMainHand == null) || flameInMainHand) ? + GeneralMethods.getRightSide(player.getLocation(), .55) : + GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); + } + + private void displayFireBalls() { + playFirebendingParticles(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0); + ParticleEffect.SMOKE_NORMAL.display(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld()), 3, 0, 0, 0, 0.01); + JCMethods.emitLight(getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.8D)).toLocation(player.getWorld())); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public List getLocations() { + List list = shots.stream().map(shot -> shot.location).collect(Collectors.toList()); + list.add(getRightHandPos()); + return list; + } + + @Override + public void handleCollision(Collision collision) { + if (collision.isRemovingFirst()) { + Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); + + collidedShot.ifPresent(shots::remove); + } else { + CoreAbility second = collision.getAbilitySecond(); + if (second instanceof AirShield) { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + boolean reflect = config.getBoolean("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); + + if (reflect) { + Optional collidedShot = shots.stream().filter(shot -> shot.location.equals(collision.getLocationFirst())).findAny(); + + if (collidedShot.isPresent()) { + FireShot fireShot = collidedShot.get(); + AirShield shield = (AirShield) second; + + fireShot.direction = player.getLocation().getDirection().clone(); + AirShieldReflector.reflect(shield, fireShot.location, fireShot.direction); + } + } + } + } + } + + @Override + public String getName() { + return "FireShots"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.FireShots.Description"); + } + + public List getShots() { + return shots; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public int getStartAmount() { + return startAmount; + } + + public void setStartAmount(int startAmount) { + this.startAmount = startAmount; + } + + public int getFireticks() { + return fireticks; + } + + public void setFireticks(int fireticks) { + this.fireticks = fireticks; + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + @Override + public double getCollisionRadius() { + return collisionRadius; + } + + public void setCollisionRadius(double collisionRadius) { + this.collisionRadius = collisionRadius; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.FireShots.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/firebending/FireSki.java b/src/com/jedk1/jedcore/ability/firebending/FireSki.java similarity index 99% rename from src/ability/firebending/FireSki.java rename to src/com/jedk1/jedcore/ability/firebending/FireSki.java index 0b5648d..d43de8a 100644 --- a/src/ability/firebending/FireSki.java +++ b/src/com/jedk1/jedcore/ability/firebending/FireSki.java @@ -12,7 +12,6 @@ import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.Location; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; diff --git a/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java b/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java new file mode 100644 index 0000000..270f657 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/firebending/LightningBurst.java @@ -0,0 +1,369 @@ +package com.jedk1.jedcore.ability.firebending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.LightningAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; + +public class LightningBurst extends LightningAbility implements AddonAbility { + + private static final ConcurrentHashMap BOLTS = new ConcurrentHashMap<>(); + + Random rand = new Random(); + @Attribute(Attribute.COOLDOWN) + private long cooldown, avatarCooldown; + @Attribute(Attribute.CHARGE_DURATION) + private long chargeUp, avatarChargeup; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.RADIUS) + private double radius; + + private boolean charged; + private static int ID = Integer.MIN_VALUE; + + private float soundVolume; + private int soundInterval; + + public LightningBurst(Player player) { + super(player); + if (!bPlayer.canBend(this) || hasAbility(player, LightningBurst.class)) { + return; + } + + setFields(); + if (bPlayer.isAvatarState() || JCMethods.isSozinsComet(player.getWorld())) { + chargeUp = avatarChargeup; + cooldown = avatarCooldown; + } + + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Fire.LightningBurst.Cooldown"); + chargeUp = config.getLong("Abilities.Fire.LightningBurst.ChargeUp"); + avatarCooldown = config.getLong("Abilities.Fire.LightningBurst.AvatarCooldown"); + avatarChargeup = config.getLong("Abilities.Fire.LightningBurst.AvatarChargeUp"); + damage = config.getDouble("Abilities.Fire.LightningBurst.Damage"); + radius = config.getDouble("Abilities.Fire.LightningBurst.Radius"); + + soundVolume = (float) config.getDouble("Abilities.Fire.LightningBurst.Sound.Volume"); + soundInterval = config.getInt("Abilities.Fire.LightningBurst.Sound.Interval"); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + if (RegionProtection.isRegionProtected(player, player.getLocation(), this)) { + remove(); + return; + } + if (!player.isSneaking()) { + if (!isCharging()) { + Location fake = player.getLocation().add(0, -2, 0); + fake.setPitch(0); + for (int i = -180; i < 180; i += 55) { + fake.setYaw(i); + for (double j = -180; j <= 180; j += 55) { + Location temp = fake.clone(); + Vector dir = fake.getDirection().clone().multiply(2 * Math.cos(Math.toRadians(j))); + temp.add(dir); + temp.setY(temp.getY() + 2 + (2 * Math.sin(Math.toRadians(j)))); + dir = GeneralMethods.getDirection(player.getLocation().add(0, 0, 0), temp); + spawnBolt(player.getLocation().clone().add(0, 1, 0).setDirection(dir), radius, 1, 20, true); + } + } + bPlayer.addCooldown(this); + } + remove(); + } else if (System.currentTimeMillis() > getStartTime() + chargeUp){ + setCharging(false); + displayCharging(); + } + } + + private void spawnBolt(Location location, double max, double gap, int arc, boolean doDamage) { + int id = ID; + BOLTS.put(id, new Bolt(this, location, id, max, gap, arc, doDamage)); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + } + + private void displayCharging() { + Location fake = player.getLocation().add(0, 0, 0); + fake.setPitch(0); + for (int i = -180; i < 180; i += 55) { + fake.setYaw(i); + for (double j = -180; j <= 180; j += 55) { + if (rand.nextInt(100) == 0) { + Location temp = fake.clone(); + Vector dir = fake.getDirection().clone().multiply(1.2 * Math.cos(Math.toRadians(j))); + temp.add(dir); + temp.setY(temp.getY() + 1.2 + (1.2 * Math.sin(Math.toRadians(j)))); + dir = GeneralMethods.getDirection(temp, player.getLocation().add(0, 1, 0)); + spawnBolt(temp.setDirection(dir), 1, 0.2, 20, false); + } + } + } + } + + public static void progressAll() { + BOLTS.values().forEach(Bolt::progress); + } + + public boolean isCharging() { + return !charged; + } + + public void setCharging(boolean charging) { + this.charged = !charging; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "LightningBurst"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Fire.LightningBurst.Description"); + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getAvatarCooldown() { + return avatarCooldown; + } + + public void setAvatarCooldown(long avatarCooldown) { + this.avatarCooldown = avatarCooldown; + } + + public long getChargeUp() { + return chargeUp; + } + + public void setChargeUp(long chargeUp) { + this.chargeUp = chargeUp; + } + + public long getAvatarChargeup() { + return avatarChargeup; + } + + public void setAvatarChargeup(long avatarChargeup) { + this.avatarChargeup = avatarChargeup; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + public boolean isCharged() { + return charged; + } + + public void setCharged(boolean charged) { + this.charged = charged; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Fire.LightningBurst.Enabled"); + } + + public class Bolt { + + private final LightningBurst ability; + private Location location; + private final float initYaw; + private final float initPitch; + private double step; + private final double max; + private final double gap; + private final int id; + private final int arc; + private final boolean doDamage; + + public Bolt(LightningBurst ability, Location location, int id, double max, double gap, int arc, boolean doDamage) { + this.ability = ability; + this.location = location; + this.id = id; + this.max = max; + this.arc = arc; + this.gap = gap; + this.doDamage = doDamage; + initYaw = location.getYaw(); + initPitch = location.getPitch(); + } + + private void progress() { + if (this.step >= max) { + BOLTS.remove(id); + return; + } + if (RegionProtection.isRegionProtected(player, location, LightningBurst.this) || !isTransparent(location.getBlock())) { + BOLTS.remove(id); + return; + } + double step = 0.2; + for (double i = 0; i < gap; i+= step) { + this.step += step; + location = location.add(location.getDirection().clone().multiply(step)); + + playLightningbendingParticle(location, 0f, 0f, 0f); + JCMethods.emitLight(location); + } + switch (rand.nextInt(3)) { + case 0: + location.setYaw(initYaw - arc); + break; + case 1: + location.setYaw(initYaw + arc); + break; + default: + location.setYaw(initYaw); + break; + } + switch (rand.nextInt(3)) { + case 0: + location.setPitch(initPitch - arc); + break; + case 1: + location.setPitch(initPitch + arc); + break; + default: + location.setPitch(initPitch); + break; + } + + if (rand.nextInt(soundInterval) == 0) { + location.getWorld().playSound(location, Sound.ENTITY_BEE_HURT, soundVolume, 0.2f); + } + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, 2)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && doDamage) { + DamageHandler.damageEntity(entity, damage, ability); + } + } + } + + public LightningBurst getAbility() { + return ability; + } + + public Location getLocation() { + return location; + } + + public float getInitYaw() { + return initYaw; + } + + public float getInitPitch() { + return initPitch; + } + + public double getStep() { + return step; + } + + public double getMax() { + return max; + } + + public double getGap() { + return gap; + } + + public int getId() { + return id; + } + + public int getArc() { + return arc; + } + + public boolean isDoDamage() { + return doDamage; + } + } +} \ No newline at end of file diff --git a/src/ability/passive/WallRun.java b/src/com/jedk1/jedcore/ability/passive/WallRun.java similarity index 99% rename from src/ability/passive/WallRun.java rename to src/com/jedk1/jedcore/ability/passive/WallRun.java index a60418f..816dab9 100644 --- a/src/ability/passive/WallRun.java +++ b/src/com/jedk1/jedcore/ability/passive/WallRun.java @@ -10,7 +10,6 @@ import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; diff --git a/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java b/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java new file mode 100644 index 0000000..7a48f32 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/BloodPuppet.java @@ -0,0 +1,512 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.BloodAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class BloodPuppet extends BloodAbility implements AddonAbility { + + private boolean nightOnly; + private boolean fullMoonOnly; + private boolean undeadMobs; + private boolean bloodPuppetThroughBlocks; + private boolean requireBound; + private int distance; + @Attribute(Attribute.DURATION) + private long holdTime; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + private long endTime; + + public LivingEntity puppet; + private long lastDamageTime = 0; + + Random rand = new Random(); + + public BloodPuppet(Player player) { + super(player); + if (!isEligible(player, true)) { + return; + } + + setFields(); + endTime = System.currentTimeMillis() + holdTime; + + if (grab()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + nightOnly = config.getBoolean("Abilities.Water.BloodPuppet.NightOnly"); + fullMoonOnly = config.getBoolean("Abilities.Water.BloodPuppet.FullMoonOnly"); + undeadMobs = config.getBoolean("Abilities.Water.BloodPuppet.UndeadMobs"); + bloodPuppetThroughBlocks = config.getBoolean("Abilities.Water.BloodPuppet.IgnoreWalls"); + requireBound = config.getBoolean("Abilities.Water.BloodPuppet.RequireBound"); + distance = config.getInt("Abilities.Water.BloodPuppet.Distance"); + holdTime = config.getLong("Abilities.Water.BloodPuppet.HoldTime"); + cooldown = config.getLong("Abilities.Water.BloodPuppet.Cooldown"); + } + + public boolean isEligible(Player player, boolean hasAbility) { + if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, BloodPuppet.class))) { + return false; + } + if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { + return false; + } + return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); + } + + private boolean canAttack() { + switch (puppet.getType()) { + case SKELETON: + case SPIDER: + case GIANT: + case ZOMBIE: + case SLIME: + case GHAST: + case PIGLIN: + case ZOMBIFIED_PIGLIN: + case ENDERMAN: + case CAVE_SPIDER: + case SILVERFISH: + case BLAZE: + case MAGMA_CUBE: + case WITCH: + case ENDERMITE: + case DROWNED: + case PLAYER: + return true; + default: + return false; + } + } + + private boolean grab() { + List entities = new ArrayList<>(); + for (int i = 1; i < distance; i++) { + Location location; + if (bloodPuppetThroughBlocks) { + location = player.getTargetBlock(null, i).getLocation(); + } else { + location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); + } + entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); + entities.remove(player); + if (!entities.isEmpty() && !entities.contains(player)) { + break; + } + } + if (entities.isEmpty()) { + return false; + } + Entity e = entities.get(0); + + if (e == null) + return false; + + if (!(e instanceof LivingEntity)) + return false; + + if (!undeadMobs && GeneralMethods.isUndead(e)) + return false; + + if ((e instanceof Player) && !canBeBloodbent((Player) e)) { + return false; + } + if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { + return false; + } + + for (BloodPuppet bb : getAbilities(BloodPuppet.class)) { + if (bb.puppet.getEntityId() == e.getEntityId()) { + return false; + } + } + + puppet = (LivingEntity) e; + DamageHandler.damageEntity(puppet, 0, this); + if (puppet instanceof Creature) + ((Creature) puppet).setTarget(null); + + if (e instanceof Player && BendingPlayer.getBendingPlayer((Player) e) != null) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer((Player) e); + bPlayer.blockChi(); + } + + return true; + } + + private boolean canBeBloodbent(Player player) { + if (Commands.invincible.contains(player.getName())) { + return false; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (requireBound) { + if (bPlayer.getAbilities().containsValue("Bloodbending")) { + return false; + } + return !bPlayer.getAbilities().containsValue("BloodPuppet"); + } else { + if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { + return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); + } + } + return true; + } + + public static void attack(Player player) { + if (hasAbility(player, BloodPuppet.class)) { + getAbility(player, BloodPuppet.class).attack(); + } + } + + private void attack() { + if (!canAttack()) + return; + + long damageCd = 0; + if (System.currentTimeMillis() > lastDamageTime + damageCd) { + lastDamageTime = System.currentTimeMillis(); + + if (puppet instanceof Skeleton) { + Skeleton skelly = (Skeleton) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(skelly.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); + Arrow a = puppet.getWorld().spawnArrow(loc, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()), 0.6f, 12); + a.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else if (puppet instanceof Creeper) { + Creeper creep = (Creeper) puppet; + creep.setPowered(true); + } + + else if (puppet instanceof Ghast) { + Ghast gaga = (Ghast) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(gaga.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); + Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); + fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.25)); + fb.setIsIncendiary(true); + fb.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else if (puppet instanceof Blaze) { + Blaze balawalaze = (Blaze) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(balawalaze.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + Location loc = puppet.getLocation().getBlock().getRelative(GeneralMethods.getCardinalDirection(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()))).getLocation(); + Fireball fb = puppet.getWorld().spawn(loc, Fireball.class); + fb.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.5)); + fb.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else if (puppet instanceof Witch) { + Witch missmagus = (Witch) puppet; + List nearby = GeneralMethods.getEntitiesAroundPoint(missmagus.getLocation(), 5); + nearby.remove(puppet); + if (nearby.size() < 1) + return; + int randy = rand.nextInt(nearby.size()); + Entity target = nearby.get(randy); + if (target instanceof LivingEntity) { + LivingEntity e = (LivingEntity) target; + ThrownPotion tp = missmagus.launchProjectile(ThrownPotion.class, GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation())); + ItemStack potionItem = new ItemStack(Material.SPLASH_POTION, 1); + PotionMeta potion = (PotionMeta) potionItem.getItemMeta(); + potion.setBasePotionType(JedCore.plugin.getPotionEffectAdapter().getHarmingPotionType()); + potionItem.setItemMeta(potion); + tp.setItem(potionItem); + tp.setVelocity(GeneralMethods.getDirection(puppet.getEyeLocation(), e.getEyeLocation()).multiply(0.125)); + tp.setShooter(puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + + else { + for (Entity e : GeneralMethods.getEntitiesAroundPoint(puppet.getLocation(), 2)) { + if (e.getEntityId() == puppet.getEntityId()) + continue; + + if (e instanceof LivingEntity) { + int damage = 2; + if (puppet instanceof Player) { + Player p = (Player) puppet; + + switch (p.getInventory().getItemInMainHand().getType()) { + case WOODEN_SWORD: + case GOLDEN_SWORD: + damage = 5; + break; + case STONE_SWORD: + damage = 6; + break; + case IRON_SWORD: + damage = 7; + break; + case DIAMOND_SWORD: + damage = 8; + break; + default: + break; + } + } + ((LivingEntity) e).damage(damage, puppet); + if (e instanceof Creature) + ((Creature) e).setTarget(puppet); + } + } + } + } + } + + @Override + public void progress() { + if (player == null || !player.isOnline() || player.isDead()) { + remove(); + return; + } + if (!isEligible(player, false)) { + remove(); + return; + } + + if (!player.isSneaking()) { + remove(); + return; + } + + if (System.currentTimeMillis() > endTime) { + remove(); + return; + } + + if ((puppet instanceof Player && !((Player) puppet).isOnline()) || puppet.isDead()) { + remove(); + return; + } + + Location newLocation = puppet.getLocation(); + + Location location = GeneralMethods.getTargetedLocation(player, distance + 1); + double distance = location.distance(newLocation); + double dx, dy, dz; + dx = location.getX() - newLocation.getX(); + dy = location.getY() - newLocation.getY(); + dz = location.getZ() - newLocation.getZ(); + Vector vector = new Vector(dx, dy, dz); + if (distance > .5) { + puppet.setVelocity(vector.normalize().multiply(.5)); + } else { + puppet.setVelocity(new Vector(0, 0, 0)); + } + puppet.setFallDistance(0); + if (puppet instanceof Creature) { + ((Creature) puppet).setTarget(null); + } + AirAbility.breakBreathbendingHold(puppet); + } + + @Override + public void remove() { + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + if (puppet instanceof Player && ((Player) puppet).isOnline()) { + BendingPlayer.getBendingPlayer((Player) puppet).unblockChi(); + } + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "BloodPuppet"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.BloodPuppet.Description"); + } + + public boolean isNightOnly() { + return nightOnly; + } + + public void setNightOnly(boolean nightOnly) { + this.nightOnly = nightOnly; + } + + public boolean isFullMoonOnly() { + return fullMoonOnly; + } + + public void setFullMoonOnly(boolean fullMoonOnly) { + this.fullMoonOnly = fullMoonOnly; + } + + public boolean isUndeadMobs() { + return undeadMobs; + } + + public void setUndeadMobs(boolean undeadMobs) { + this.undeadMobs = undeadMobs; + } + + public boolean canBloodPuppetThroughBlocks() { + return bloodPuppetThroughBlocks; + } + + public void setCanBloodPuppetThroughBlocks(boolean bloodPuppetThroughBlocks) { + this.bloodPuppetThroughBlocks = bloodPuppetThroughBlocks; + } + + public boolean requiresBound() { + return requireBound; + } + + public void setRequireBound(boolean requireBound) { + this.requireBound = requireBound; + } + + public int getDistance() { + return distance; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public long getHoldTime() { + return holdTime; + } + + public void setHoldTime(long holdTime) { + this.holdTime = holdTime; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public LivingEntity getPuppet() { + return puppet; + } + + public void setPuppet(LivingEntity puppet) { + this.puppet = puppet; + } + + public long getLastDamageTime() { + return lastDamageTime; + } + + public void setLastDamageTime(long lastDamageTime) { + this.lastDamageTime = lastDamageTime; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.BloodPuppet.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java b/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java new file mode 100644 index 0000000..122265a --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/Bloodbending.java @@ -0,0 +1,376 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.ThrownEntityTracker; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.BloodAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.*; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Bloodbending extends BloodAbility implements AddonAbility { + + private boolean nightOnly; + private boolean fullMoonOnly; + private boolean undeadMobs; + private boolean bloodbendingThroughBlocks; + private boolean requireBound; + private int distance; + @Attribute(Attribute.DURATION) + private long holdTime; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + private long time; + public LivingEntity victim; + private BendingPlayer victimBPlayer; + private boolean grabbed; + + public Bloodbending(Player player) { + super(player); + if (this.player == null || !isEligible(player, true)) { + return; + } + setFields(); + time = System.currentTimeMillis() + holdTime; + if (grab()) { + start(); + } + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + nightOnly = config.getBoolean("Abilities.Water.Bloodbending.NightOnly"); + fullMoonOnly = config.getBoolean("Abilities.Water.Bloodbending.FullMoonOnly"); + undeadMobs = config.getBoolean("Abilities.Water.Bloodbending.UndeadMobs"); + bloodbendingThroughBlocks = config.getBoolean("Abilities.Water.Bloodbending.IgnoreWalls"); + requireBound = config.getBoolean("Abilities.Water.Bloodbending.RequireBound"); + distance = config.getInt("Abilities.Water.Bloodbending.Distance"); + holdTime = config.getLong("Abilities.Water.Bloodbending.HoldTime"); + cooldown = config.getLong("Abilities.Water.Bloodbending.Cooldown"); + } + + public boolean isEligible(Player player, boolean hasAbility) { + if (!bPlayer.canBend(this) || !bPlayer.canBloodbend() || (hasAbility && hasAbility(player, Bloodbending.class))) { + return false; + } + if (nightOnly && !isNight(player.getWorld()) && !bPlayer.canBloodbendAtAnytime()) { + return false; + } + return !fullMoonOnly || isFullMoon(player.getWorld()) || bPlayer.canBloodbendAtAnytime(); + } + + public static void launch(Player player) { + if (hasAbility(player, Bloodbending.class)) { + getAbility(player, Bloodbending.class).launch(); + } + } + + private void launch() { + if (Arrays.asList(ElementalAbility.getTransparentMaterials()).contains(player.getEyeLocation().getBlock().getType())) { + Vector direction = GeneralMethods.getDirection(player.getEyeLocation(), GeneralMethods.getTargetedLocation(player, 20, ElementalAbility.getTransparentMaterials())).normalize().multiply(3); + if (!victim.isDead()) { + victim.setVelocity(direction); + + new HorizontalVelocityTracker(victim, player, 200L, this); + new ThrownEntityTracker(this, victim, player, 200L); + } + remove(); + } + } + + private boolean grab() { + List entities = new ArrayList<>(); + for (int i = 1; i < distance; i++) { + Location location; + if (bloodbendingThroughBlocks) { + location = player.getTargetBlock(null, i).getLocation(); + } else { + location = GeneralMethods.getTargetedLocation(player, i, ElementalAbility.getTransparentMaterials()); + } + entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7); + entities.remove(player); + + if (!entities.isEmpty() && !entities.contains(player)) { + break; + } + } + if (entities.isEmpty()) { + return false; + } + Entity e = entities.get(0); + if (e == null) { + return false; + } + if (!(e instanceof LivingEntity)) { + return false; + } + if (e instanceof ArmorStand) { + return false; + } + if (!undeadMobs && GeneralMethods.isUndead(e)) { + return false; + } + if ((e instanceof Player) && !canBeBloodbent((Player) e)) { + return false; + } + if (RegionProtection.isRegionProtected(player, e.getLocation(), this)) { + return false; + } + for (Bloodbending bb : getAbilities(Bloodbending.class)) { + if (bb.victim.getEntityId() == e.getEntityId()) { + return false; + } + } + + victim = (LivingEntity) e; + DamageHandler.damageEntity(victim, 0, this); + HorizontalVelocityTracker.remove(victim); + if (victim instanceof Creature) { + ((Creature) victim).setTarget(null); + } + if ((e instanceof Player) && BendingPlayer.getBendingPlayer((Player) e) != null) { + victimBPlayer = BendingPlayer.getBendingPlayer((Player) e); + } + return true; + } + + private boolean canBeBloodbent(Player player) { + if (Commands.invincible.contains(player.getName())) { + return false; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (requireBound) { + if (bPlayer.getAbilities().containsValue("Bloodbending")) { + return false; + } + return !bPlayer.getAbilities().containsValue("BloodPuppet"); + } else { + if (bPlayer.canBind(getAbility("Bloodbending")) && bPlayer.canBloodbend()) { + return isDay(player.getWorld()) && !bPlayer.canBloodbendAtAnytime(); + } + } + return true; + } + + @Override + public void progress() { + if (!isEligible(player, false)) { + remove(); + return; + } + if (!grabbed) { + if (victim instanceof Player && victimBPlayer != null) { + victimBPlayer.blockChi(); + grabbed = true; + } + } + + if (!player.isSneaking()) { + remove(); + return; + } + if (!player.isOnline() || player.isDead()) { + remove(); + return; + } + if (System.currentTimeMillis() > time) { + remove(); + return; + } + if (victim.isDead()) { + remove(); + return; + } + if ((victim instanceof Player) && !((Player) victim).isOnline()) { + remove(); + return; + } + Location oldLocation = victim.getLocation(); + Location loc = GeneralMethods.getTargetedLocation(player, (int) player.getLocation().distance(oldLocation)); + double distance = loc.distance(oldLocation); + Vector v = GeneralMethods.getDirection(oldLocation, GeneralMethods.getTargetedLocation(player, 10)); + if (distance > 1.2D) { + victim.setVelocity(v.normalize().multiply(0.8D)); + } else { + victim.setVelocity(new Vector(0, 0, 0)); + } + victim.setFallDistance(0.0F); + if (victim instanceof Creature) { + ((Creature) victim).setTarget(null); + } + AirAbility.breakBreathbendingHold(victim); + } + + @Override + public void remove() { + if (player.isOnline()) { + bPlayer.addCooldown(this); + } + if (victim instanceof Player && victimBPlayer != null) { + victimBPlayer.unblockChi(); + } + super.remove(); + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "Bloodbending"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.Bloodbending.Description"); + } + + public boolean isNightOnly() { + return nightOnly; + } + + public void setNightOnly(boolean nightOnly) { + this.nightOnly = nightOnly; + } + + public boolean isFullMoonOnly() { + return fullMoonOnly; + } + + public void setFullMoonOnly(boolean fullMoonOnly) { + this.fullMoonOnly = fullMoonOnly; + } + + public boolean isUndeadMobs() { + return undeadMobs; + } + + public void setUndeadMobs(boolean undeadMobs) { + this.undeadMobs = undeadMobs; + } + + public boolean isBloodbendingThroughBlocks() { + return bloodbendingThroughBlocks; + } + + public void setBloodbendingThroughBlocks(boolean bloodbendingThroughBlocks) { + this.bloodbendingThroughBlocks = bloodbendingThroughBlocks; + } + + public boolean isRequireBound() { + return requireBound; + } + + public void setRequireBound(boolean requireBound) { + this.requireBound = requireBound; + } + + public int getDistance() { + return distance; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public long getHoldTime() { + return holdTime; + } + + public void setHoldTime(long holdTime) { + this.holdTime = holdTime; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public LivingEntity getVictim() { + return victim; + } + + public void setVictim(LivingEntity victim) { + this.victim = victim; + } + + public BendingPlayer getVictimBPlayer() { + return victimBPlayer; + } + + public void setVictimBPlayer(BendingPlayer victimBPlayer) { + this.victimBPlayer = victimBPlayer; + } + + public boolean isGrabbed() { + return grabbed; + } + + public void setGrabbed(boolean grabbed) { + this.grabbed = grabbed; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.Bloodbending.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/Drain.java b/src/com/jedk1/jedcore/ability/waterbending/Drain.java new file mode 100644 index 0000000..7354bdc --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/Drain.java @@ -0,0 +1,598 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.ElementalAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.util.WaterReturn; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.block.data.Waterlogged; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.*; + +public class Drain extends WaterAbility implements AddonAbility { + + private final List locations = new ArrayList<>(); + static final Set WATER_TEMPS = new HashSet<>(); + + //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. + private static float MAX_TEMP = 1.0F; + private static float MIN_HUMIDITY = 0.01F; + + private long regenDelay; + @Attribute(Attribute.DURATION) + private long duration; // 2000 + @Attribute(Attribute.COOLDOWN) + private long cooldown; // 2000 + private double absorbSpeed; // 0.1 + @Attribute(Attribute.RADIUS) + private int radius; // 6 + @Attribute("Chance") + private int chance; // 20 + private int absorbRate; // 6 + private int holdRange; // 2 + private boolean blastsEnabled; // true + private int maxBlasts; + private boolean keepSrc; // false + private boolean useRain; + private boolean usePlants; + + private double blastRange; // 20 + private double blastDamage; // 1.5 + private double blastSpeed; // 2 + + private boolean drainTemps; + + private long endTime; + private int absorbed = 0; + private int charge = 7; + private boolean noFill; + private int blasts; + private boolean hasCharge; + private final Material[] fillables = { Material.GLASS_BOTTLE, Material.BUCKET }; + + Random rand = new Random(); + + public Drain(Player player) { + super(player); + if (!bPlayer.canBend(this) || hasAbility(player, Drain.class)) { + return; + } + setFields(); + this.usePlants = bPlayer.canPlantbend(); + endTime = System.currentTimeMillis() + duration; + if (!canFill()) { + if (!blastsEnabled) + return; + noFill = true; + } + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + regenDelay = config.getLong("Abilities.Water.Drain.RegenDelay"); + duration = config.getLong("Abilities.Water.Drain.Duration"); + cooldown = config.getLong("Abilities.Water.Drain.Cooldown"); + absorbSpeed = config.getDouble("Abilities.Water.Drain.AbsorbSpeed"); + radius = config.getInt("Abilities.Water.Drain.Radius"); + chance = config.getInt("Abilities.Water.Drain.AbsorbChance"); + absorbRate = config.getInt("Abilities.Water.Drain.AbsorbRate"); + holdRange = config.getInt("Abilities.Water.Drain.HoldRange"); + blastsEnabled = config.getBoolean("Abilities.Water.Drain.BlastsEnabled"); + maxBlasts = config.getInt("Abilities.Water.Drain.MaxBlasts"); + keepSrc = config.getBoolean("Abilities.Water.Drain.KeepSource"); + blastRange = config.getDouble("Abilities.Water.Drain.BlastRange"); + blastDamage = config.getDouble("Abilities.Water.Drain.BlastDamage"); + blastSpeed = config.getDouble("Abilities.Water.Drain.BlastSpeed"); + useRain = config.getBoolean("Abilities.Water.Drain.AllowRainSource"); + drainTemps = config.getBoolean("Abilities.Water.Drain.DrainTempBlocks"); + + applyModifiers(); + } + + private void applyModifiers() { + if (isNight(player.getWorld())) { + cooldown -= ((long) getNightFactor(cooldown) - cooldown); + blastRange = getNightFactor(blastRange); + blastDamage = getNightFactor(blastDamage); + } + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (!noFill) { + if (!player.isSneaking()) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (!canFill()) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (System.currentTimeMillis() > endTime) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (absorbed >= absorbRate) { + fill(); + absorbed = 0; + } + checkForValidSource(); + } else { + if (blasts >= maxBlasts) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (player.isSneaking()) { + if (charge >= 2) { + checkForValidSource(); + } + if (absorbed >= absorbRate) { + hasCharge = true; + absorbed = 0; + if (charge >= 3) { + charge -= 2; + } + } + } else if (!hasCharge || !keepSrc) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (hasCharge) { + displayWaterSource(); + } + } + dragWater(); + } + + public static void fireBlast(Player player) { + if (hasAbility(player, Drain.class)) { + getAbility(player, Drain.class).fireBlast(); + } + } + + private void fireBlast() { + if (charge <= 1) { + hasCharge = false; + charge = 7; + blasts++; + new DrainBlast(player, blastRange, blastDamage, blastSpeed, holdRange); + } + } + + private void displayWaterSource() { + Location location = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)); + Block block = location.getBlock(); + if (!GeneralMethods.isSolid(block) || isTransparent(block)) { + TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(charge)), 100L); + WATER_TEMPS.add(tb); + tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); + } + } + + private boolean canFill() { + for (ItemStack items : player.getInventory()) { + if (items != null && Arrays.asList(fillables).contains(items.getType())) { + return true; + } + } + return false; + } + + private void fill() { + for (int x = 0; x < absorbed; x++) { + for (Material fillable : fillables) { + int slot = player.getInventory().first(fillable); + if (slot == -1){ + continue; + } + if (player.getInventory().getItem(slot).getAmount() > 1) { + player.getInventory().getItem(slot).setAmount(player.getInventory().getItem(slot).getAmount() - 1); + + ItemStack filled = getFilled(fillable); + HashMap cantfit = player.getInventory().addItem(filled); + for (int id : cantfit.keySet()) { + player.getWorld().dropItem(player.getEyeLocation(), cantfit.get(id)); + } + } else { + player.getInventory().setItem(slot, getFilled(fillable)); + } + break; + } + } + } + + private ItemStack getFilled(Material type) { + ItemStack filled = null; + if (type == Material.GLASS_BOTTLE) { + filled = WaterReturn.waterBottleItem(); + } else if (type == Material.BUCKET) { + filled = new ItemStack(Material.WATER_BUCKET, 1); + } + + return filled; + } + + private void checkForValidSource() { + List locs = GeneralMethods.getCircle(player.getLocation(), radius, radius, false, true, 0); + for (int i = 0; i < locs.size(); i++) { + Block block = locs.get(rand.nextInt(locs.size()-1)).getBlock(); + if (rand.nextInt(chance) == 0) { + Location pLoc = player.getLocation(); + World world = pLoc.getWorld(); + double temp = world.getTemperature(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); + double humidity = world.getHumidity(pLoc.getBlockX(), pLoc.getBlockY(), pLoc.getBlockZ()); + if (block.getY() > world.getMinHeight() && block.getY() < world.getMaxHeight()) { + Location bLoc = block.getLocation(); + if (useRain && world.hasStorm() && !(temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { + if (pLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { + if (bLoc.getY() >= world.getHighestBlockAt(pLoc).getLocation().getY()) { + locations.add(bLoc.clone().add(.5, .5, .5)); + return; + } + } + } + if (usePlants && JCMethods.isSmallPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { + drainPlant(block); + } else if (usePlants && ElementalAbility.isPlant(block) && !isObstructed(bLoc, player.getEyeLocation())) { + locations.add(bLoc.clone().add(.5, .5, .5)); + new TempBlock(block, Material.AIR.createBlockData(), regenDelay); + } else if (isWater(block)) { + TempBlock tb = TempBlock.get(block); + if ((tb == null || (drainTemps && !WATER_TEMPS.contains(tb)))) { + drainWater(block); + } + } + } + } + } + } + + private boolean isObstructed(Location location1, Location location2) { + Vector loc1 = location1.toVector(); + Vector loc2 = location2.toVector(); + + Vector direction = loc2.subtract(loc1); + direction.normalize(); + + Location loc; + + double max = location1.distance(location2); + + for (double i = 1; i <= max; i++) { + loc = location1.clone().add(direction.clone().multiply(i)); + if (!isTransparent(loc.getBlock())) + return true; + } + + return false; + } + + private void drainPlant(Block block) { + if (JCMethods.isSmallPlant(block)) { + if (JCMethods.isSmallPlant(block.getRelative(BlockFace.DOWN))) { + if (JCMethods.isDoublePlant(block.getType())) { + block = block.getRelative(BlockFace.DOWN); + locations.add(block.getLocation().clone().add(.5, .5, .5)); + new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); + return; + } + block = block.getRelative(BlockFace.DOWN); + } + locations.add(block.getLocation().clone().add(.5, .5, .5)); + new TempBlock(block, Material.DEAD_BUSH.createBlockData(), regenDelay); + } + } + + private void drainWater(Block block) { + if (isTransparent(block.getRelative(BlockFace.UP)) && !isWater(block.getRelative(BlockFace.UP))) { + locations.add(block.getLocation().clone().add(.5, .5, .5)); + if (block.getBlockData() instanceof Waterlogged) { + new TempBlock(block, block.getType().createBlockData(bd -> ((Waterlogged) bd).setWaterlogged(false)), regenDelay); + } else { + TempBlock tb = new TempBlock(block, Material.WATER.createBlockData(bd -> ((Levelled) bd).setLevel(1)), regenDelay); + WATER_TEMPS.add(tb); + tb.setRevertTask(() -> WATER_TEMPS.remove(tb)); + } + } + } + + private void dragWater() { + List toRemove = new ArrayList<>(); + if (!locations.isEmpty()) { + for (Location l : locations) { + Location playerLoc = player.getLocation().add(0, 1, 0); + if (noFill) + playerLoc = player.getEyeLocation().add(player.getLocation().getDirection().multiply(holdRange)).subtract(0, .8, 0); + Vector dir = GeneralMethods.getDirection(l, playerLoc); + l = l.add(dir.multiply(absorbSpeed)); + ParticleEffect.WATER_SPLASH.display(l, 1, 0, 0, 0, 0); + GeneralMethods.displayColoredParticle("0099FF", l); + if (l.distance(playerLoc) < 1) { + toRemove.add(locations.indexOf(l)); + absorbed++; + } + } + } + if (!toRemove.isEmpty()) { + for (int i : toRemove) { + if (i < locations.size()) + locations.remove(i); + } + toRemove.clear(); + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "Drain"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.Drain.Description"); + } + + @Override + public List getLocations() { + return locations; + } + + public long getRegenDelay() { + return regenDelay; + } + + public void setRegenDelay(long regenDelay) { + this.regenDelay = regenDelay; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public double getAbsorbSpeed() { + return absorbSpeed; + } + + public void setAbsorbSpeed(double absorbSpeed) { + this.absorbSpeed = absorbSpeed; + } + + public int getRadius() { + return radius; + } + + public void setRadius(int radius) { + this.radius = radius; + } + + public int getChance() { + return chance; + } + + public void setChance(int chance) { + this.chance = chance; + } + + public int getAbsorbRate() { + return absorbRate; + } + + public void setAbsorbRate(int absorbRate) { + this.absorbRate = absorbRate; + } + + public int getHoldRange() { + return holdRange; + } + + public void setHoldRange(int holdRange) { + this.holdRange = holdRange; + } + + public boolean isBlastsEnabled() { + return blastsEnabled; + } + + public void setBlastsEnabled(boolean blastsEnabled) { + this.blastsEnabled = blastsEnabled; + } + + public int getMaxBlasts() { + return maxBlasts; + } + + public void setMaxBlasts(int maxBlasts) { + this.maxBlasts = maxBlasts; + } + + public boolean isKeepSrc() { + return keepSrc; + } + + public void setKeepSrc(boolean keepSrc) { + this.keepSrc = keepSrc; + } + + public boolean isUseRain() { + return useRain; + } + + public void setUseRain(boolean useRain) { + this.useRain = useRain; + } + + public boolean isUsePlants() { + return usePlants; + } + + public void setUsePlants(boolean usePlants) { + this.usePlants = usePlants; + } + + public double getBlastRange() { + return blastRange; + } + + public void setBlastRange(double blastRange) { + this.blastRange = blastRange; + } + + public double getBlastDamage() { + return blastDamage; + } + + public void setBlastDamage(double blastDamage) { + this.blastDamage = blastDamage; + } + + public double getBlastSpeed() { + return blastSpeed; + } + + public void setBlastSpeed(double blastSpeed) { + this.blastSpeed = blastSpeed; + } + + public boolean isDrainTemps() { + return drainTemps; + } + + public void setDrainTemps(boolean drainTemps) { + this.drainTemps = drainTemps; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public int getAbsorbed() { + return absorbed; + } + + public void setAbsorbed(int absorbed) { + this.absorbed = absorbed; + } + + public int getCharge() { + return charge; + } + + public void setCharge(int charge) { + this.charge = charge; + } + + public boolean isNoFill() { + return noFill; + } + + public void setNoFill(boolean noFill) { + this.noFill = noFill; + } + + public int getBlasts() { + return blasts; + } + + public void setBlasts(int blasts) { + this.blasts = blasts; + } + + public boolean isHasCharge() { + return hasCharge; + } + + public void setHasCharge(boolean hasCharge) { + this.hasCharge = hasCharge; + } + + public Material[] getFillables() { + return fillables; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.Drain.Enabled"); + } +} \ No newline at end of file diff --git a/src/ability/waterbending/DrainBlast.java b/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java similarity index 99% rename from src/ability/waterbending/DrainBlast.java rename to src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java index 7656c6f..1912d14 100644 --- a/src/ability/waterbending/DrainBlast.java +++ b/src/com/jedk1/jedcore/ability/waterbending/DrainBlast.java @@ -8,7 +8,6 @@ import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.TempBlock; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.data.Levelled; diff --git a/src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java b/src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java new file mode 100644 index 0000000..3ca79fa --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/FrostBreath.java @@ -0,0 +1,439 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.IceAbility; +import com.projectkorra.projectkorra.command.Commands; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FrostBreath extends IceAbility implements AddonAbility { + + private static final List INVALID_MATERIALS = new ArrayList(){{ + addAll(Arrays.asList( + Material.ICE, + Material.LAVA, + Material.AIR, + Material.VOID_AIR, + Material.CAVE_AIR)); + if (GeneralMethods.getMCVersion() >= 1170) { + add(Material.getMaterial("LIGHT")); + } + }}; + + //Savannas are 1.0 temp with 0 humidity. Deserts are 2.0 temp with 0 humidity. + private static float MAX_TEMP = 1.0F; + private static float MIN_HUMIDITY = 0.01F; + + public Config config; + + private State state; + private final List frozenBlocks = new ArrayList<>(); + + public FrostBreath(Player player) { + super(player); + + if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { + return; + } + + this.config = new Config(player); + this.state = new BeamState(); + + double temp = player.getLocation().getWorld().getTemperature(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); + double humidity = player.getLocation().getWorld().getHumidity(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()); + + if (config.restrictBiomes && (temp >= MAX_TEMP || humidity <= MIN_HUMIDITY)) { + return; + } + + start(); + } + + @Override + public void progress() { + if (!state.update()) { + remove(); + } + + long time = System.currentTimeMillis(); + + frozenBlocks.removeIf(frozen -> { + if (time >= frozen.endTime) { + removeFrozenBlock(frozen.tempBlock); + frozen.tempBlock.revertBlock(); + return true; + } + + return false; + }); + } + + @Override + public void remove() { + super.remove(); + + frozenBlocks.forEach(fb -> { + removeFrozenBlock(fb.tempBlock); + fb.tempBlock.revertBlock(); + }); + frozenBlocks.clear(); + } + + @Override + public long getCooldown() { + return config.cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "FrostBreath"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.FrostBreath.Description"); + } + + public static List getInvalidMaterials() { + return INVALID_MATERIALS; + } + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + public List getFrozenBlocks() { + return frozenBlocks; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.FrostBreath.Enabled"); + } + + private void addFrozenBlock(TempBlock tempBlock) { + PhaseChange.getFrozenBlocksMap().put(tempBlock, player); + } + + private void removeFrozenBlock(TempBlock tempBlock) { + PhaseChange.getFrozenBlocksMap().remove(tempBlock); + } + + private interface State { + boolean update(); + } + + private class BeamState implements State { + @Override + public boolean update() { + if (player == null || !player.isOnline()) { + return transition(); + } + + if (!bPlayer.canBendIgnoreCooldowns(FrostBreath.this)) { + return transition(); + } + + if (!player.isSneaking() || player.isDead()) { + return transition(); + } + + if (System.currentTimeMillis() >= getStartTime() + config.duration) { + return transition(); + } + + createBeam(); + + return true; + } + + private boolean transition() { + state = new SnowMeltingState(); + + return true; + } + + private boolean isLocationSafe(Location loc) { + Block block = loc.getBlock(); + + if (RegionProtection.isRegionProtected(player, loc, FrostBreath.this)) { + return false; + } + + return isTransparent(block); + } + + private boolean isFreezable(Location location, Entity entity) { + if (RegionProtection.isRegionProtected(FrostBreath.this, location)) { + return false; + } + + if (entity instanceof Player && Commands.invincible.contains(entity.getName())) { + return false; + } + + return !location.getBlock().getType().isSolid(); + } + + private void createBeam() { + Location loc = player.getEyeLocation(); + Vector dir = player.getLocation().getDirection(); + double step = 1; + double size = 0; + double offset = 0; + double damageRegion = 1.5; + + for (double i = 0; i < config.range; i += step) { + loc = loc.add(dir.clone().multiply(step)); + size += 0.005; + offset += 0.3; + damageRegion += 0.01; + + if (!isLocationSafe(loc)) + return; + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, damageRegion)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId()) { + for (Location cageLocation : createCage(entity.getLocation())) { + if (isFreezable(cageLocation, entity)) { + Block block = cageLocation.getBlock(); + + updateFrozenBlock(block, Material.ICE, config.freezeDuration); + } + } + + if (config.slowEnabled) { + ((LivingEntity) entity).addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect((int) config.slowDuration, 5)); + } + + if (config.damageEnabled) { + if (entity instanceof Player) { + DamageHandler.damageEntity(entity, config.playerDamage, FrostBreath.this); + } else { + DamageHandler.damageEntity(entity, config.mobDamage, FrostBreath.this); + } + } + } + } + + if (config.snowEnabled) { + freezeGround(loc); + } + + ParticleEffect.SNOW_SHOVEL.display(loc, config.particles, Math.random(), Math.random(), Math.random(), size); + + JCMethods.displayColoredParticles("#DCDCDC", loc, 1, Math.random(), Math.random(), Math.random(), 0.003f); + JCMethods.displayColoredParticles("#9696FF", loc, 1, Math.random(), Math.random(), Math.random(), 0.0035f); + } + } + + private Location getOffsetLocation(Location loc, double offset) { + return loc.clone().add((float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset), (float) ((Math.random() - 0.5) * offset)); + } + + private void freezeGround(Location loc) { + for (Location l : GeneralMethods.getCircle(loc, 2, 2, false, true, 0)) { + if (!RegionProtection.isRegionProtected(player, l, FrostBreath.this)) { + Block block = l.getBlock(); + + if (isWater(l.getBlock())) { + updateFrozenBlock(block, Material.ICE, config.frozenWaterDuration); + } else if (isTransparent(l.getBlock()) && l.clone().add(0, -1, 0).getBlock().getType().isSolid() && !INVALID_MATERIALS.contains(l.clone().add(0, -1, 0).getBlock().getType())) { + if (config.bendSnow) { + updateFrozenBlock(block, Material.SNOW, config.snowDuration); + } else { + TempBlock current = TempBlock.get(block); + + // Refresh any existing TempBlock so the timer resets. + if (current != null) { + current.revertBlock(); + } + + TempBlock tempBlock = new TempBlock(block, Material.SNOW.createBlockData()); + tempBlock.setRevertTime(config.snowDuration); + } + } + } + } + } + + private void updateFrozenBlock(Block block, Material type, long duration) { + // Store the TempBlock as a FrozenBlock block so it can be reverted later. + for (FrozenBlock fb : frozenBlocks) { + if (fb.tempBlock.getBlock().equals(block)) { + if (fb.tempBlock.getBlockData().getMaterial() != type) { + // Completely overwrite this FrozenBlock if the new type doesn't match the old one. + removeFrozenBlock(fb.tempBlock); + fb.tempBlock.revertBlock(); + frozenBlocks.remove(fb); + break; + } + + fb.endTime = System.currentTimeMillis() + duration; + return; + } + } + + TempBlock tempBlock = new TempBlock(block, type.createBlockData()); + + frozenBlocks.add(new FrozenBlock(tempBlock, System.currentTimeMillis() + duration)); + + // Add the TempBlock to a ProjectKorra block list so it can be used as a water source. + // I don't believe there exists a way to make a TempBlock water bendable right now, so this + // is a hack to make it work. + addFrozenBlock(tempBlock); + } + + private List createCage(Location centerBlock) { + List selectedBlocks = new ArrayList<>(); + + int bX = centerBlock.getBlockX(); + int bY = centerBlock.getBlockY(); + int bZ = centerBlock.getBlockZ(); + + for (int x = bX - 1; x <= bX + 1; x++) { + for (int y = bY - 1; y <= bY + 1; y++) { + Location l = new Location(centerBlock.getWorld(), x, y, bZ); + selectedBlocks.add(l); + } + } + + for (int y = bY - 1; y <= bY + 2; y++) { + Location l = new Location(centerBlock.getWorld(), bX, y, bZ); + selectedBlocks.add(l); + } + + for (int z = bZ - 1; z <= bZ + 1; z++) { + for (int y = bY - 1; y <= bY + 1; y++) { + Location l = new Location(centerBlock.getWorld(), bX, y, z); + selectedBlocks.add(l); + } + } + + for (int x = bX - 1; x <= bX + 1; x++) { + for (int z = bZ - 1; z <= bZ + 1; z++) { + Location l = new Location(centerBlock.getWorld(), x, bY, z); + selectedBlocks.add(l); + } + } + + return selectedBlocks; + } + } + + // Wait for the frozen blocks to melt and remove it from bendable water list. + private class SnowMeltingState implements State { + SnowMeltingState() { + bPlayer.addCooldown(FrostBreath.this); + } + + @Override + public boolean update() { + return !frozenBlocks.isEmpty(); + } + } + + private static class FrozenBlock { + TempBlock tempBlock; + long endTime; + + FrozenBlock(TempBlock tempBlock, long endTime) { + this.tempBlock = tempBlock; + this.endTime = endTime; + } + } + + public static class Config { + long cooldown; + long duration; + int particles; + int freezeDuration; + int snowDuration; + int frozenWaterDuration; + int range; + boolean snowEnabled; + boolean bendSnow; + boolean damageEnabled; + double playerDamage; + double mobDamage; + boolean slowEnabled; + long slowDuration; + boolean restrictBiomes; + + Config(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + + cooldown = config.getLong("Abilities.Water.FrostBreath.Cooldown"); + duration = config.getLong("Abilities.Water.FrostBreath.Duration"); + particles = config.getInt("Abilities.Water.FrostBreath.Particles"); + freezeDuration = config.getInt("Abilities.Water.FrostBreath.FrostDuration"); + snowDuration = config.getInt("Abilities.Water.FrostBreath.SnowDuration"); + frozenWaterDuration = config.getInt("Abilities.Water.FrostBreath.FrozenWaterDuration"); + range = config.getInt("Abilities.Water.FrostBreath.Range"); + snowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Snow"); + bendSnow = config.getBoolean("Abilities.Water.FrostBreath.BendableSnow"); + damageEnabled = config.getBoolean("Abilities.Water.FrostBreath.Damage.Enabled"); + playerDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Player"); + mobDamage = config.getDouble("Abilities.Water.FrostBreath.Damage.Mob"); + slowEnabled = config.getBoolean("Abilities.Water.FrostBreath.Slow.Enabled"); + slowDuration = config.getLong("Abilities.Water.FrostBreath.Slow.Duration"); + restrictBiomes = config.getBoolean("Abilities.Water.FrostBreath.RestrictBiomes"); + } + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java b/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java new file mode 100644 index 0000000..07a5192 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/HealingWaters.java @@ -0,0 +1,268 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.LightManagerUtil; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.HealingAbility; +import com.projectkorra.projectkorra.chiblocking.Smokescreen; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.util.WaterReturn; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Random; + +public class HealingWaters extends HealingAbility implements AddonAbility { + + private static long time = 0; + private static boolean enabled = true; + + public HealingWaters(Player player) { + super(player); + } + + public static void heal(Server server) { + if (enabled) { + if (System.currentTimeMillis() - time >= 1000) { + time = System.currentTimeMillis(); + for (Player player : server.getOnlinePlayers()) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer != null && bPlayer.canBend(getAbility("HealingWaters"))) { + heal(player); + } + } + } + } + } + + @SuppressWarnings("deprecation") + private static void heal(Player player) { + if (inWater(player)) { + if (player.isSneaking()) { + Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); + if (entity instanceof LivingEntity && inWater(entity)) { + Location playerLoc = entity.getLocation(); + playerLoc.add(0, 1, 0); + JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHPToEntity((LivingEntity) entity); + emitLight(playerLoc); + emitLight(entity.getLocation()); + } + } else { + Location playerLoc = player.getLocation(); + playerLoc.add(0, 1, 0); + JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHP(player); + emitLight(playerLoc); + } + + } else if(hasWaterSupply(player) && player.isSneaking()) { + Entity entity = GeneralMethods.getTargetedEntity(player, getRange(player), new ArrayList<>()); + if (entity != null) { + if (entity instanceof LivingEntity) { + Damageable dLe = (Damageable) entity; + if (dLe.getHealth() < dLe.getMaxHealth()) { + Location playerLoc = entity.getLocation(); + playerLoc.add(0, 1, 0); + JCMethods.displayColoredParticles("#9696E1", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHPToEntity((LivingEntity) entity); + entity.setFireTicks(0); + Random rand = new Random(); + if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); + emitLight(playerLoc); + emitLight(entity.getLocation()); + } + } + } else { + Location playerLoc = player.getLocation(); + playerLoc.add(0, 1, 0); + + JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f, 50); + JCMethods.displayColoredParticles("#FFFFFF", playerLoc, 3, Math.random(), Math.random(), Math.random(), 0f); + + ParticleEffect.WATER_WAKE.display(playerLoc, 25, 0, 0, 0, 0.05F); + giveHP(player); + player.setFireTicks(0); + Random rand = new Random(); + if (rand.nextInt(getDrainChance(player)) == 0) drainWaterSupply(player); + emitLight(playerLoc); + } + } + } + + @SuppressWarnings("deprecation") + private static void giveHPToEntity(LivingEntity le) { + if (!le.isDead() && le.getHealth() < le.getMaxHealth()) { + applyHealingToEntity(le); + } + for (PotionEffect effect : le.getActivePotionEffects()) { + if (isNegativeEffect(effect.getType())) { + le.removePotionEffect(effect.getType()); + } + } + } + + private static void giveHP(Player player){ + if (!player.isDead() && player.getHealth() < 20) { + applyHealing(player); + } + for(PotionEffect effect : player.getActivePotionEffects()) { + if(isNegativeEffect(effect.getType())) { + if((effect.getType() == PotionEffectType.BLINDNESS) && Smokescreen.getBlindedTimes().containsKey(player.getName())) { + return; + } + player.removePotionEffect(effect.getType()); + } + } + } + + + + private static boolean inWater(Entity entity) { + Block block = entity.getLocation().getBlock(); + return isWater(block) && !TempBlock.isTempBlock(block); + } + + private static boolean hasWaterSupply(Player player){ + ItemStack heldItem = player.getInventory().getItemInMainHand(); + return (heldItem.isSimilar(WaterReturn.waterBottleItem()) || heldItem.getType() == Material.WATER_BUCKET); + + } + + private static void drainWaterSupply(Player player){ + ItemStack heldItem = player.getInventory().getItemInMainHand(); + ItemStack emptyBottle = new ItemStack(Material.GLASS_BOTTLE, 1); + if (heldItem.isSimilar(WaterReturn.waterBottleItem())) { + if (heldItem.getAmount() > 1) { + heldItem.setAmount(heldItem.getAmount() - 1); + HashMap cantFit = player.getInventory().addItem(emptyBottle); + for (int id : cantFit.keySet()) { + player.getWorld().dropItem(player.getEyeLocation(), cantFit.get(id)); + } + } else { + player.getInventory().setItemInMainHand(emptyBottle); + } + } + } + + @SuppressWarnings("deprecation") + private static void applyHealing(Player player) { + if (!RegionProtection.isRegionProtected(player, player.getLocation(), "HealingWaters")) + if(player.getHealth() < player.getMaxHealth()) { + player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, getPower(player))); + AirAbility.breakBreathbendingHold(player); + } + } + + @SuppressWarnings("deprecation") + private static void applyHealingToEntity(LivingEntity le) { + if (le.getHealth() < le.getMaxHealth()) { + le.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 70, 1)); + AirAbility.breakBreathbendingHold(le); + } + } + + public static int getPower(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + return config.getInt("Abilities.Water.HealingWaters.Power"); + } + + public static double getRange(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + return config.getDouble("Abilities.Water.HealingWaters.Range"); + } + + public static int getDrainChance(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + return config.getInt("Abilities.Water.HealingWaters.DrainChance"); + } + + public static void emitLight(Location loc) { + ConfigurationSection config = JedCoreConfig.getConfig((Player)null); + if (config.getBoolean("Abilities.Water.HealingWaters.DynamicLight.Enabled")) { + int brightness = config.getInt("Abilities.Water.HealingWaters.DynamicLight.Brightness"); + long keepAlive = config.getLong("Abilities.Water.HealingWaters.DynamicLight.KeepAlive"); + + LightManagerUtil.createLight(loc).brightness(brightness).timeUntilFadeout(keepAlive).emit(); + } + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "HealingWaters"; + } + + @Override + public boolean isHarmlessAbility() { + return true; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.HealingWaters.Description"); + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + enabled = config.getBoolean("Abilities.Water.HealingWaters.Enabled"); + return enabled; + } + + @Override + public void progress() {} +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java b/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java new file mode 100644 index 0000000..a9142b5 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/IceClaws.java @@ -0,0 +1,330 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.IceAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.MainHand; +import org.bukkit.potion.PotionEffectType; + +public class IceClaws extends IceAbility implements AddonAbility { + + @Attribute(Attribute.COOLDOWN) + private long punchCooldown; + @Attribute(Attribute.COOLDOWN) + private long throwCooldown; + @Attribute(Attribute.CHARGE_DURATION) + private long chargeUp; + private int punchSlowDur; + private int throwSlowDur; + private int punchSlownessLevel; + private int throwSlownessLevel; + @Attribute(Attribute.DAMAGE) + private double punchDamage; + @Attribute(Attribute.DAMAGE) + private double throwDamage; + @Attribute(Attribute.RANGE) + private double range; + private boolean throwable; + private double throwSpeed; + + private Location head; + private Location origin; + private boolean launched; + + private Boolean iceInMainHand = null; + + public IceClaws(Player player) { + super(player); + if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) { + return; + } + + if (hasAbility(player, IceClaws.class)) { + IceClaws ic = getAbility(player, IceClaws.class); + if (!ic.throwable) { + ic.remove(); + } + return; + } + + setFields(); + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + punchCooldown = config.getLong("Abilities.Water.IceClaws.Punch.Cooldown", 4000); + punchDamage = config.getDouble("Abilities.Water.IceClaws.Punch.Damage", 2.0); + punchSlownessLevel = config.getInt("Abilities.Water.IceClaws.Punch.Slowness", 3); + punchSlowDur = config.getInt("Abilities.Water.IceClaws.Punch.SlowDuration", 5000); + + throwCooldown = config.getLong("Abilities.Water.IceClaws.Throw.Cooldown", 4000); + throwDamage = config.getDouble("Abilities.Water.IceClaws.Throw.Damage", 2.0); + throwSlownessLevel = config.getInt("Abilities.Water.IceClaws.Throw.Slowness", 3); + throwSlowDur = config.getInt("Abilities.Water.IceClaws.Throw.SlowDuration", 5000); + throwSpeed = config.getDouble("Abilities.Water.IceClaws.Throw.Speed", 1.0); + + chargeUp = config.getLong("Abilities.Water.IceClaws.ChargeTime", 1000); + range = config.getDouble("Abilities.Water.IceClaws.Range", 10); + throwable = config.getBoolean("Abilities.Water.IceClaws.Throwable", true); + + applyModifiers(); + } + + private void applyModifiers() { + punchCooldown -= ((long) getNightFactor(punchCooldown) - punchCooldown); + throwCooldown -= ((long) getNightFactor(throwCooldown) - throwCooldown); + punchDamage = getNightFactor(punchDamage); + throwDamage = getNightFactor(throwDamage); + range = getNightFactor(range); + } + + @Override + public void progress() { + if (player == null || player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this)) { + remove(); + return; + } + if (System.currentTimeMillis() > getStartTime() + chargeUp) { + if (!launched && throwable) { + displayClaws(); + } else { + if (!shoot()) { + remove(); + } + } + } else if (player.isSneaking()) { + displayChargeUp(); + } else { + remove(); + } + } + + + public static void swapHands(Player player) { + ConfigurationSection config = JedCoreConfig.getConfig(player); + if (!config.getBoolean("Abilities.Water.IceClaws.AllowHandSwap", true)) return; + IceClaws ic = getAbility(player, IceClaws.class); + if (ic == null) + return; + if (ic.iceInMainHand == null) + ic.iceInMainHand = true; + else ic.iceInMainHand = !ic.iceInMainHand; + } + + public Location getRightHandPos() { + return (player.getMainHand() == MainHand.RIGHT == ((iceInMainHand == null) || iceInMainHand) ? + GeneralMethods.getRightSide(player.getLocation(), .55) : + GeneralMethods.getLeftSide(player.getLocation(), .55)).add(0, 1.2, 0); + } + + public boolean shoot() { + for (double i = 0; i < 1; i += throwSpeed) { + head.add(origin.clone().getDirection().multiply(throwSpeed)); + if (origin.distance(head) >= range) return false; + if (!isTransparent(head.getBlock())) return false; + GeneralMethods.displayColoredParticle("66FFFF", head); + GeneralMethods.displayColoredParticle("CCFFFF", head); + ParticleEffect.SNOW_SHOVEL.display(head, 1, 0, 0, 0, 0); + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(head, 1.5)) { + if (entity instanceof LivingEntity && entity.getEntityId() != player.getEntityId() && !(entity instanceof ArmorStand)) { + freezeEntity((LivingEntity) entity, false); + return false; + } + } + } + return true; + } + + public static void throwClaws(Player player) { + if (hasAbility(player, IceClaws.class)) { + IceClaws ic = getAbility(player, IceClaws.class); + if (!ic.launched && player.isSneaking()) { + ic.launched = true; + ic.origin = ic.player.getEyeLocation(); + ic.head = ic.origin.clone(); + } + } + } + + private void displayClaws() { + Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); + GeneralMethods.displayColoredParticle("66FFFF", location); + GeneralMethods.displayColoredParticle("CCFFFF", location); + } + + private void displayChargeUp() { + Location location = getRightHandPos().toVector().add(player.getEyeLocation().getDirection().clone().multiply(.75D)).toLocation(player.getWorld()); + ParticleEffect.WATER_SPLASH.display(location, 1, Math.random()/3, Math.random()/3, Math.random()/3, 0.0); + } + + public static boolean freezeEntity(Player player, LivingEntity entity) { + if (hasAbility(player, IceClaws.class)) { + getAbility(player, IceClaws.class).freezeEntity(entity); + return true; + } + return false; + } + + private void freezeEntity(LivingEntity entity) { + freezeEntity(entity, true); + } + + private void freezeEntity(LivingEntity entity, boolean isPunch) { + if (entity.hasPotionEffect(PotionEffectType.SPEED)) { + entity.removePotionEffect(PotionEffectType.SPEED); + } + int duration = isPunch ? punchSlowDur : throwSlowDur; + int level = isPunch ? punchSlownessLevel : throwSlownessLevel; + entity.addPotionEffect(JedCore.plugin.getPotionEffectAdapter().getSlownessEffect(duration, level)); + bPlayer.addCooldown(this); + remove(); + DamageHandler.damageEntity(entity, isPunch ? punchDamage : throwDamage, this); + } + + @Override + public long getCooldown() { + return launched ? throwCooldown : punchCooldown; + } + + @Override + public Location getLocation() { + return head; + } + + @Override + public String getName() { + return "IceClaws"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.IceClaws.Description"); + } + + public void setPunchCooldown(long punchCooldown) { this.punchCooldown = punchCooldown; } + public long getPunchCooldown() { return punchCooldown; } + public void setThrowCooldown(long throwCooldown) { this.throwCooldown = throwCooldown; } + public long getThrowCooldown() { return throwCooldown; } + public void setPunchDamage(double punchDamage) { this.punchDamage = punchDamage; } + public double getPunchDamage() { return punchDamage; } + public void setThrowDamage(double throwDamage) { this.throwDamage = throwDamage; } + public double getThrowDamage() { return throwDamage; } + public void setPunchSlowDur(int punchSlowDur) { this.punchSlowDur = punchSlowDur; } + public int getPunchSlowDur() { return punchSlowDur; } + public void setThrowSlowDur(int throwSlowDur) { this.throwSlowDur = throwSlowDur; } + public int getThrowSlowDur() { return throwSlowDur; } + + public double getRange() { + return range; + } + + public void setRange(double range) { + this.range = range; + } + + public boolean isThrowable() { + return throwable; + } + + public void setThrowable(boolean throwable) { + this.throwable = throwable; + } + + public Location getHead() { + return head; + } + + public void setHead(Location head) { + this.head = head; + } + + public Location getOrigin() { + return origin; + } + + public void setOrigin(Location origin) { + this.origin = origin; + } + + public boolean isLaunched() { + return launched; + } + + public void setLaunched(boolean launched) { + this.launched = launched; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.IceClaws.Enabled"); + } + + public int getPunchSlownessLevel() { + return punchSlownessLevel; + } + + public void setPunchSlownessLevel(int punchSlownessLevel) { + this.punchSlownessLevel = punchSlownessLevel; + } + + public int getThrowSlownessLevel() { + return throwSlownessLevel; + } + + public void setThrowSlownessLevel(int throwSlownessLevel) { + this.throwSlownessLevel = throwSlownessLevel; + } + + public double getThrowSpeed() { + return throwSpeed; + } + + public void setThrowSpeed(double throwSpeed) { + this.throwSpeed = throwSpeed; + } +} \ No newline at end of file diff --git a/src/ability/waterbending/IcePassive.java b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java similarity index 98% rename from src/ability/waterbending/IcePassive.java rename to src/com/jedk1/jedcore/ability/waterbending/IcePassive.java index 37478f0..794225a 100644 --- a/src/ability/waterbending/IcePassive.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java @@ -6,13 +6,11 @@ import com.projectkorra.projectkorra.Element; import com.projectkorra.projectkorra.ability.IceAbility; import com.projectkorra.projectkorra.util.ParticleEffect; - import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; -import org.bukkit.permissions.Permission; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; diff --git a/src/com/jedk1/jedcore/ability/waterbending/IceWall.java b/src/com/jedk1/jedcore/ability/waterbending/IceWall.java new file mode 100644 index 0000000..b9b0f87 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/IceWall.java @@ -0,0 +1,610 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.jedk1.jedcore.util.ThreadUtil; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.earthbending.EarthSmash; +import com.projectkorra.projectkorra.firebending.FireBlast; +import com.projectkorra.projectkorra.firebending.FireBlastCharged; +import com.projectkorra.projectkorra.firebending.lightning.Lightning; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.Torrent; +import com.projectkorra.projectkorra.waterbending.ice.IceBlast; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +public class IceWall extends IceAbility implements AddonAbility { + public static List instances = new ArrayList<>(); + + @Attribute(Attribute.HEIGHT) + private int maxHeight; + private int minHeight; + + @Attribute(Attribute.WIDTH) + private int width; + + @Attribute(Attribute.RANGE) + private int range; + + @Attribute("Health") + private int maxHealth; + private int minHealth; + + @Attribute(Attribute.DAMAGE) + private double damage; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + + public static boolean stackable; + + public static boolean lifetimeEnabled; + public static long lifetimeTime; + + public int torrentDamage; + public int torrentFreezeDamage; + public int iceBlastDamage; + public int fireBlastDamage; + public int fireBlastChargedDamage; + public int lightningDamage; + public int combustionDamage; + public int earthSmashDamage; + public int airBlastDamage; + + public boolean isWallDoneFor = false; + public List affectedBlocks = new ArrayList<>(); + + private boolean rising = false; + private long lastDamageTime = 0; + private long lifetime = 0; + private int wallHealth; + private int tankedDamage; + + private final List lastBlocks = new ArrayList<>(); + private final List tempBlocks = new ArrayList<>(); + + Random rand = new Random(); + + public IceWall(Player player) { + super(player); + if (!bPlayer.canBendIgnoreCooldowns(this) || !bPlayer.canIcebend()) { + return; + } + + setFields(); + Block b = getSourceBlock(player, (int) (range * getNightFactor(player.getWorld()))); + if (b == null) return; + + for (IceWall iw : instances) { + if (iw.affectedBlocks.contains(b)) { + iw.collapse(player, false); + return; + } + } + + if (!bPlayer.canBend(this) || !isWaterbendable(b)) return; + + wallHealth = (int) (((rand.nextInt((maxHealth - minHealth) + 1)) + minHealth) * getNightFactor(player.getWorld())); + loadAffectedBlocks(player, b); + lifetime = System.currentTimeMillis() + lifetimeTime; + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + maxHeight = (config.getInt("Abilities.Water.IceWall.MaxHeight")); + minHeight = (config.getInt("Abilities.Water.IceWall.MinHeight")); + width = (config.getInt("Abilities.Water.IceWall.Width")); + range = config.getInt("Abilities.Water.IceWall.Range"); + maxHealth = config.getInt("Abilities.Water.IceWall.MaxWallHealth"); + minHealth = config.getInt("Abilities.Water.IceWall.MinWallHealth"); + damage = config.getDouble("Abilities.Water.IceWall.Damage"); + cooldown = config.getLong("Abilities.Water.IceWall.Cooldown"); + stackable = config.getBoolean("Abilities.Water.IceWall.Stackable"); + lifetimeEnabled = config.getBoolean("Abilities.Water.IceWall.LifeTime.Enabled"); + lifetimeTime = config.getLong("Abilities.Water.IceWall.LifeTime.Duration"); + torrentDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Torrent"); + torrentFreezeDamage = config.getInt("Abilities.Water.IceWall.WallDamage.TorrentFreeze"); + iceBlastDamage = config.getInt("Abilities.Water.IceWall.WallDamage.IceBlast"); + fireBlastDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Fireblast"); + fireBlastChargedDamage = config.getInt("Abilities.Water.IceWall.WallDamage.FireblastCharged"); + lightningDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Lightning"); + combustionDamage = config.getInt("Abilities.Water.IceWall.WallDamage.Combustion"); + earthSmashDamage = config.getInt("Abilities.Water.IceWall.WallDamage.EarthSmash"); + airBlastDamage = config.getInt("Abilities.Water.IceWall.WallDamage.AirBlast"); + } + + public Block getSourceBlock(Player player, int range) { + Vector direction = player.getEyeLocation().getDirection().normalize(); + + for (int i = 0; i <= range; i++) { + Block b = player.getEyeLocation().add(direction.clone().multiply((double) i)).getBlock(); + + if (isBendable(b)) return b; + } + + return null; + } + + public boolean isBendable(Block b) { + return isWater(b) || isIce(b.getType()) || isSnow(b.getType()); + } + + public void loadAffectedBlocks(Player player, Block block) { + Vector direction = player.getEyeLocation().getDirection().normalize(); + + double ox, oy, oz; + ox = -direction.getZ(); + oy = 0; + oz = direction.getX(); + + Vector orth = new Vector(ox, oy, oz); + orth = orth.normalize(); + + Location origin = block.getLocation(); + + World world = origin.getWorld(); + + int width = (int) (getWidth() * getNightFactor(world)); + int minHeight = (int) (getMinHeight() * getNightFactor(world)); + int maxHeight = (int) (getMaxHeight() * getNightFactor(world)); + + int height = minHeight; + boolean increasingHeight = true; + for (int i = -(width / 2); i < width / 2; i++) { + Block b = world.getBlockAt(origin.clone().add(orth.clone().multiply((double) i))); + + if (ElementalAbility.isAir(b.getType())) { + while (ElementalAbility.isAir(b.getType())) { + if (b.getY() < world.getMinHeight()) + return; + + b = b.getRelative(BlockFace.DOWN); + } + } + + if (!ElementalAbility.isAir(b.getRelative(BlockFace.UP).getType())) { + while (!ElementalAbility.isAir(b.getRelative(BlockFace.UP).getType())) { + if (b.getY() > b.getWorld().getMaxHeight()) + return; + + b = b.getRelative(BlockFace.UP); + } + } + + if (!stackable && isIceWallBlock(b)) { + continue; + } + + if (isBendable(b)) { + affectedBlocks.add(b); + for (int h = 1; h <= height; h++) { + Block up = b.getRelative(BlockFace.UP, h); + if (ElementalAbility.isAir(up.getType())) { + affectedBlocks.add(up); + } + } + + if (height < maxHeight && increasingHeight) + height++; + + if (i == 0) + increasingHeight = false; + + if (!increasingHeight && height > minHeight) + height--; + + lastBlocks.add(b); + } + + } + + bPlayer.addCooldown(this); + rising = true; + instances.add(this); + } + + @Override + public void progress() { + if (rising) { + if (lastBlocks.isEmpty()) { + rising = false; + } else { + List theseBlocks = new ArrayList<>(lastBlocks); + lastBlocks.clear(); + + for (Block b : theseBlocks) { + TempBlock tb = new TempBlock(b, Material.ICE.createBlockData()); + tempBlocks.add(tb); + + playIcebendingSound(b.getLocation()); + + Block up = b.getRelative(BlockFace.UP); + + if (affectedBlocks.contains(up)) + lastBlocks.add(up); + } + } + } + + if (System.currentTimeMillis() > lifetime && lifetimeEnabled) { + collapse(player, false); + } + } + + public void damageWall(Player player, int damage) { + long noDamageTicks = 1000; + if (System.currentTimeMillis() < lastDamageTime + noDamageTicks) + return; + + lastDamageTime = System.currentTimeMillis(); + tankedDamage += damage; + + if (tankedDamage >= wallHealth) { + collapse(player, true); + } + } + + public void collapse(Player player, boolean forceful) { + if (rising) return; + + for (TempBlock tb : tempBlocks) { + tb.revertBlock(); + tb.getLocation().getWorld().spawnParticle(Particle.BLOCK_CRACK, tb.getLocation(), 5, 0, 0, 0, 0, Material.PACKED_ICE.createBlockData()); + tb.getLocation().getWorld().playSound(tb.getLocation(), Sound.BLOCK_GLASS_BREAK, 5f, 5f); + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(tb.getLocation(), 2.5)) { + if (e.getEntityId() != player.getEntityId() && e instanceof LivingEntity) { + DamageHandler.damageEntity(e, damage * getNightFactor(player.getWorld()), this); + if (forceful) { + ((LivingEntity) e).setNoDamageTicks(0); + } + } + } + } + + tempBlocks.clear(); + isWallDoneFor = true; + } + + @Override + public void remove() { + super.remove(); + } + + public static void collisionDamage(Entity entity, double travelledDistance, Vector difference, Player instigator) { + for (IceWall iw : IceWall.instances) { + for (Block b : iw.affectedBlocks) { + if (entity.getLocation().getWorld() == b.getLocation().getWorld() && entity.getLocation().distance(b.getLocation()) < 2) { + double damage = ((travelledDistance - 5.0) < 0 ? 0 : travelledDistance - 5.0) / (difference.length()); + iw.damageWall(instigator, (int) damage); + } + } + } + } + + public static boolean checkExplosions(Location location, Entity entity) { + for (IceWall iw : IceWall.instances) { + for (Block b : iw.affectedBlocks) { + if (location.getWorld() == b.getLocation().getWorld() && location.distance(b.getLocation()) < 2) { + + for (Entity e : GeneralMethods.getEntitiesAroundPoint(location, 3)) { + if (e instanceof LivingEntity) { + LivingEntity livingEntity = (LivingEntity) e; + ThreadUtil.ensureEntity(livingEntity, () -> livingEntity.damage(7, entity)); + } + } + return true; + } + } + } + return false; + } + + public static boolean isIceWallBlock(Block block) { + for (IceWall iw : IceWall.instances) { + if (iw.affectedBlocks.contains(block)) { + return true; + } + } + return false; + } + + public static void progressAll() { + for (IceWall iw : new ArrayList<>(instances)) { + if (iw.isWallDoneFor) continue; // Skip already collapsed walls + for (Torrent t : getAbilities(Torrent.class)) { + if (t.getLocation() == null) continue; + for (int i = 0; i < t.getLaunchedBlocks().size(); i++) { + TempBlock tb = t.getLaunchedBlocks().get(i); + + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == tb.getLocation().getWorld() && ice.getLocation().distance(tb.getLocation()) <= 2) { + if (t.isFreeze()) + iw.damageWall(t.getPlayer(), (int) (iw.torrentFreezeDamage * getNightFactor(ice.getWorld()))); + else + iw.damageWall(t.getPlayer(), (int) (iw.torrentDamage * getNightFactor(ice.getWorld()))); + + if (!iw.isWallDoneFor) + t.setFreeze(false); + } + } + } + } + + for (IceBlast ib : getAbilities(IceBlast.class)) { + if (ib.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ib.source == null) + break; + + if (ice.getLocation().getWorld() == ib.source.getLocation().getWorld() && ice.getLocation().distance(ib.source.getLocation()) <= 2) { + iw.damageWall(ib.getPlayer(), (int) (iw.iceBlastDamage * getNightFactor(ice.getWorld()))); + + if (!iw.isWallDoneFor) + ib.remove(); + } + } + } + + for (FireBlastCharged fb : getAbilities(FireBlastCharged.class)) { + if (fb.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { + iw.damageWall(fb.getPlayer(), iw.fireBlastChargedDamage); + + if (!iw.isWallDoneFor) + fb.remove(); + } + } + } + + for (FireBlast fb : getAbilities(FireBlast.class)) { + if (fb.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == fb.getLocation().getWorld() && fb.getLocation().distance(ice.getLocation()) <= 1.5) { + iw.damageWall(fb.getPlayer(), iw.fireBlastDamage); + + if (!iw.isWallDoneFor) + fb.remove(); + } + } + } + + for (EarthSmash es : getAbilities(EarthSmash.class)) { + if (es.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (es.getState() == EarthSmash.State.SHOT) { + for (int j = 0; j < es.getBlocks().size(); j++) { + Block b = es.getBlocks().get(j); + if (ice.getLocation().getWorld() == b.getLocation().getWorld() && b.getLocation().distance(ice.getLocation()) <= 2) { + iw.damageWall(es.getPlayer(), iw.earthSmashDamage); + + if (!iw.isWallDoneFor) { + for (Block block : es.getBlocksIncludingInner()) { + if (block != null && !ElementalAbility.isAir(block.getType())) { + ParticleEffect.BLOCK_CRACK.display(block.getLocation(), 5, 0, 0, 0, 0, block.getBlockData().clone()); + } + } + es.remove(); + } + } + } + } + } + } + + for (Lightning l : getAbilities(Lightning.class)) { + for (Lightning.Arc arc : l.getArcs()) { + for (Block ice : iw.affectedBlocks) { + for (Location loc : arc.getPoints()) { + if (ice.getLocation().getWorld() == loc.getWorld() && loc.distance(ice.getLocation()) <= 1.5) { + iw.damageWall(l.getPlayer(), (int) (FireAbility.getDayFactor(iw.lightningDamage, ice.getWorld()))); + + if (!iw.isWallDoneFor) + l.remove(); + } + } + } + } + } + + for (CoreAbility ca : getAbilities(getAbility("Combustion").getClass())) { + if (ca.getLocation() == null) continue; + for (Block ice : iw.affectedBlocks) { + if (ice.getLocation().getWorld() == ca.getLocation().getWorld() && ca.getLocation().distance(ice.getLocation()) <= 1.5) { + iw.damageWall(ca.getPlayer(), iw.combustionDamage); + if (!iw.isWallDoneFor) ca.remove(); + } + } + } + } + + Iterator it = instances.iterator(); + while (it.hasNext()) { + IceWall iw = it.next(); + if (iw.isWallDoneFor) { + iw.affectedBlocks.clear(); + it.remove(); + } + } + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public String getName() { + return "IceWall"; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.IceWall.Description"); + } + + public int getRange() { + return range; + } + + public void setRange(int range) { + this.range = range; + } + + public int getMaxHealth() { + return maxHealth; + } + + public void setMaxHealth(int maxHealth) { + this.maxHealth = maxHealth; + } + + public int getMinHealth() { + return minHealth; + } + + public void setMinHealth(int minHealth) { + this.minHealth = minHealth; + } + + public double getDamage() { + return damage; + } + + public void setDamage(double damage) { + this.damage = damage; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public boolean isRising() { + return rising; + } + + public void setRising(boolean rising) { + this.rising = rising; + } + + public long getLastDamageTime() { + return lastDamageTime; + } + + public void setLastDamageTime(long lastDamageTime) { + this.lastDamageTime = lastDamageTime; + } + + public long getLifetime() { + return lifetime; + } + + public void setLifetime(long lifetime) { + this.lifetime = lifetime; + } + + public int getWallHealth() { + return wallHealth; + } + + public void setWallHealth(int wallHealth) { + this.wallHealth = wallHealth; + } + + public int getTankedDamage() { + return tankedDamage; + } + + public void setTankedDamage(int tankedDamage) { + this.tankedDamage = tankedDamage; + } + + public List getLastBlocks() { + return lastBlocks; + } + + public List getTempBlocks() { + return tempBlocks; + } + + public int getMaxHeight() { + return maxHeight; + } + + public void setMaxHeight(int maxHeight) { + this.maxHeight = maxHeight; + } + + public int getMinHeight() { + return minHeight; + } + + public void setMinHeight(int minHeight) { + this.minHeight = minHeight; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.IceWall.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java b/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java new file mode 100644 index 0000000..9d746ac --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/WakeFishing.java @@ -0,0 +1,235 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.configuration.JedCoreConfig; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.util.BlockSource; +import com.projectkorra.projectkorra.util.ClickType; +import com.projectkorra.projectkorra.util.ParticleEffect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class WakeFishing extends WaterAbility implements AddonAbility { + + private final static Material[] FISH_TYPES = { + Material.COD, Material.PUFFERFISH, Material.TROPICAL_FISH, Material.SALMON + }; + + private Block focusedBlock; + private Location location; + private int point; + + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.DURATION) + private long duration; + @Attribute(Attribute.RANGE) + private long range; + + Random rand = new Random(); + + public WakeFishing(Player player) { + super(player); + if (!bPlayer.canBend(this)) { + return; + } + + setFields(); + + if (prepare()) + start(); + } + + public void setFields() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + + cooldown = config.getLong("Abilities.Water.WakeFishing.Cooldown"); + duration = config.getLong("Abilities.Water.WakeFishing.Duration"); + range = config.getLong("Abilities.Water.WakeFishing.Range"); + + applyModifiers(); + } + + private void applyModifiers() { + if (isNight(player.getWorld())) { + cooldown -= ((long) getNightFactor(cooldown) - cooldown); + range = (long) getNightFactor(range); + } + } + + private boolean prepare() { + Block block = BlockSource.getWaterSourceBlock(player, range, ClickType.SHIFT_DOWN, true, false, false); + if (isWater(block)) { + focusedBlock = block; + location = focusedBlock.getLocation(); + return true; + } + return false; + } + + private boolean isFocused() { + Block block = BlockSource.getWaterSourceBlock(player, range, ClickType.SHIFT_DOWN, true, false, false); + return block != null && block.equals(focusedBlock); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline() || !player.isSneaking()) { + remove(); + return; + } + if (!bPlayer.canBendIgnoreCooldowns(this) || !isFocused()) { + bPlayer.addCooldown(this); + remove(); + return; + } + if (System.currentTimeMillis() > getStartTime() + duration) { + bPlayer.addCooldown(this); + remove(); + return; + } + displayParticles(); + spawnFishRandom(); + } + + private void displayParticles() { + point++; + if (point == 32) + point = 0; + for (int i = 0; i < 4; i++) { + ParticleEffect.WATER_SPLASH.display(getCirclePoints(focusedBlock.getLocation().clone().add(0.5, 0, 0.5), 32, (i * 90), 1).get(point), 3, 0, 0, 0, 0.05); + ParticleEffect.WATER_WAKE.display(getCirclePoints(focusedBlock.getLocation().clone().add(0.5, -0.6, 0.5), 32, (i * 90), 1).get(point), 1, 0, 0, 0, 0.02); + } + + ParticleEffect.SMOKE_NORMAL.display(focusedBlock.getLocation().clone().add(.5, .5, .5), 2, 0, 0, 0, 0.001); + } + + private void spawnFishRandom() { + if (rand.nextInt(50) == 0) { + Material fishType = FISH_TYPES[rand.nextInt(FISH_TYPES.length)]; + ItemStack fish = new ItemStack(fishType, 1); + + Item item = player.getWorld().dropItemNaturally(focusedBlock.getLocation().clone().add(.5, 1.5, .5), fish); + Vector v = player.getEyeLocation().toVector().subtract(focusedBlock.getLocation().clone().add(.5, 1.5, .5).toVector()); + item.setVelocity(v.multiply(.15)); + } + } + + private List getCirclePoints(Location location, int points, int startAngle, double size) { + List locations = new ArrayList(); + for (int i = 0; i < 360; i += 360 / points) { + double angle = (i * Math.PI / 180); + double x = size * Math.cos(angle + startAngle); + double z = size * Math.sin(angle + startAngle); + Location loc = location.clone(); + loc.add(x, 1, z); + locations.add(loc); + } + return locations; + } + + @Override + public long getCooldown() { + return cooldown; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public String getName() { + return "WakeFishing"; + } + + @Override + public boolean isHarmlessAbility() { + return true; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return "* JedCore Addon *\n" + config.getString("Abilities.Water.WakeFishing.Description"); + } + + public Block getFocusedBlock() { + return focusedBlock; + } + + public void setFocusedBlock(Block focusedBlock) { + this.focusedBlock = focusedBlock; + } + + public void setLocation(Location location) { + this.location = location; + } + + public int getPoint() { + return point; + } + + public void setPoint(int point) { + this.point = point; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public long getRange() { + return range; + } + + public void setRange(long range) { + this.range = range; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + ConfigurationSection config = JedCoreConfig.getConfig(this.player); + return config.getBoolean("Abilities.Water.WakeFishing.Enabled"); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java b/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java new file mode 100644 index 0000000..c459181 --- /dev/null +++ b/src/com/jedk1/jedcore/ability/waterbending/WaterBlast.java @@ -0,0 +1,244 @@ +package com.jedk1.jedcore.ability.waterbending; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.collision.AABB; +import com.jedk1.jedcore.collision.CollisionDetector; +import com.jedk1.jedcore.util.CollisionInitializer; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.Ability; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; +import com.projectkorra.projectkorra.attribute.Attribute; +import com.projectkorra.projectkorra.region.RegionProtection; +import com.projectkorra.projectkorra.util.DamageHandler; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Levelled; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public class WaterBlast extends WaterAbility implements AddonAbility { + + private Location location; + private Vector direction; + private final Ability ability; + private double travelled; + + @Attribute(Attribute.RANGE) + private final double range; + @Attribute(Attribute.DAMAGE) + private final double damage; + @Attribute(Attribute.SPEED) + private final double speed; + @Attribute("CollisionRadius") + private final double entityCollisionRadius; + @Attribute("CollisionRadius") + private final double abilityCollisionRadius; + + static { + CollisionInitializer.abilityMap.put("WaterBlast", "WaterGimbal"); + } + + public WaterBlast(Player player, Location origin, double range, double damage, double speed, double entityCollisionRadius, double abilityCollisionRadius, Ability ability) { + super(player); + + this.range = range; + this.damage = damage; + this.speed = speed; + this.ability = ability; + this.location = origin; + this.entityCollisionRadius = entityCollisionRadius; + this.abilityCollisionRadius = abilityCollisionRadius; + + start(); + } + + @Override + public void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (travelled >= range) { + remove(); + return; + } + + if (!advanceAttack()) { + remove(); + } + } + + private boolean advanceAttack() { + int steps = (int)Math.ceil(speed); + // This is how much the last step should move by. + double remainder = speed - Math.floor(speed); + + // Move in discrete steps so each block can be checked for collisions. + for (int i = 0; i < steps; i++) { + double stepSpeed = 1.0; + + if (remainder > 0 && i == steps - 1) { + // The last step should only move by the remainder because there are Math.ceil(speed) steps. + stepSpeed = remainder; + } + + travelled += stepSpeed; + + if (travelled >= range) { + return false; + } + + if (!player.isDead()) { + Location target = GeneralMethods.getTargetedLocation(player, range, Material.WATER); + if (location.distanceSquared(target) <= 1) { + // Make sure the WaterBlast moves in to the solid block. + target = target.add(player.getLocation().getDirection()); + } + direction = GeneralMethods.getDirection(location, target).normalize(); + } + + location = location.add(direction.clone().multiply(stepSpeed)); + + if (GeneralMethods.isSolid(location.getBlock())) { + if (!GeneralMethods.isSolid(location.getBlock().getRelative(BlockFace.UP))) { + location.add(0, 1, 0); + } else { + return false; + } + } + + if (!isTransparent(location.getBlock()) || RegionProtection.isRegionProtected(this, location)) { + return false; + } + + playWaterbendingSound(location); + + new RegenTempBlock(location.getBlock(), Material.WATER, Material.WATER.createBlockData(bd -> ((Levelled)bd).setLevel(0)), 250); + + // Only damage entities that are more than 3 blocks away. + if (travelled >= 3) { + AABB collider = AABB.BlockBounds.at(location).scale(entityCollisionRadius * 2); + + boolean hit = CollisionDetector.checkEntityCollisions(player, collider, (entity) -> { + DamageHandler.damageEntity(entity, damage, ability); + return true; + }); + + if (hit) { + return false; + } + } + } + + return true; + } + + @Override + public long getCooldown() { + return 0; + } + + @Override + public Location getLocation() { + return location; + } + + @Override + public double getCollisionRadius() { + return abilityCollisionRadius; + } + + @Override + public String getName() { + return "WaterBlast"; + } + + @Override + public boolean isHiddenAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public boolean isSneakAbility() { + return false; + } + + @Override + public String getAuthor() { + return JedCore.dev; + } + + @Override + public String getVersion() { + return JedCore.version; + } + + @Override + public String getDescription() { + return null; + } + + public void setLocation(Location location) { + this.location = location; + } + + public Vector getDirection() { + return direction; + } + + public void setDirection(Vector direction) { + this.direction = direction; + } + + public Ability getAbility() { + return ability; + } + + public double getTravelled() { + return travelled; + } + + public void setTravelled(double travelled) { + this.travelled = travelled; + } + + public double getRange() { + return range; + } + + public double getDamage() { + return damage; + } + + public double getSpeed() { + return speed; + } + + public double getEntityCollisionRadius() { + return entityCollisionRadius; + } + + public double getAbilityCollisionRadius() { + return abilityCollisionRadius; + } + + @Override + public void load() {} + + @Override + public void stop() {} + + @Override + public boolean isEnabled() { + return true; + } +} \ No newline at end of file diff --git a/src/ability/waterbending/combo/Maelstrom.java b/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java similarity index 99% rename from src/ability/waterbending/combo/Maelstrom.java rename to src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java index ec02664..55c0a35 100644 --- a/src/ability/waterbending/combo/Maelstrom.java +++ b/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java @@ -14,7 +14,6 @@ import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.waterbending.Torrent; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; diff --git a/src/ability/waterbending/combo/WaterFlow.java b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java similarity index 98% rename from src/ability/waterbending/combo/WaterFlow.java rename to src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java index ee9c1f8..c1adb24 100644 --- a/src/ability/waterbending/combo/WaterFlow.java +++ b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterFlow.java @@ -6,7 +6,10 @@ import com.jedk1.jedcore.util.MaterialUtil; import com.jedk1.jedcore.util.RegenTempBlock; import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.AirAbility; +import com.projectkorra.projectkorra.ability.ComboAbility; +import com.projectkorra.projectkorra.ability.WaterAbility; import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; import com.projectkorra.projectkorra.ability.util.ComboUtil; import com.projectkorra.projectkorra.airbending.AirSpout; @@ -19,7 +22,6 @@ import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.waterbending.WaterManipulation; import com.projectkorra.projectkorra.waterbending.WaterSpout; - import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.util.WaterReturn; import org.bukkit.Location; diff --git a/src/ability/waterbending/combo/WaterGimbal.java b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java similarity index 99% rename from src/ability/waterbending/combo/WaterGimbal.java rename to src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java index 6fe64ca..9fed934 100644 --- a/src/ability/waterbending/combo/WaterGimbal.java +++ b/src/com/jedk1/jedcore/ability/waterbending/combo/WaterGimbal.java @@ -17,9 +17,8 @@ import com.projectkorra.projectkorra.util.BlockSource; import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.WaterManipulation; import com.projectkorra.projectkorra.waterbending.Torrent; - +import com.projectkorra.projectkorra.waterbending.WaterManipulation; import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.util.WaterReturn; diff --git a/src/com/jedk1/jedcore/collision/AABB.java b/src/com/jedk1/jedcore/collision/AABB.java new file mode 100644 index 0000000..a32398e --- /dev/null +++ b/src/com/jedk1/jedcore/collision/AABB.java @@ -0,0 +1,183 @@ +package com.jedk1.jedcore.collision; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.util.Vector; + +import java.util.Optional; + +public class AABB implements Collider { + public static AABB PlayerBounds = new AABB(new Vector(-0.3, 0.0, -0.3), new Vector(0.3, 1.8, 0.3)); + public static AABB BlockBounds = new AABB(new Vector(0.0, 0.0, 0.0), new Vector(1.0, 1.0, 1.0)); + + private Vector min; + private Vector max; + private boolean hasVolume; + + public AABB(Block block) { + this.min = min(block); + this.max = max(block); + + this.hasVolume = max.clone().subtract(min).lengthSquared() > 0; + } + + public AABB(Entity entity) { + this.min = min(entity); + this.max = max(entity); + + this.hasVolume = max.clone().subtract(min).lengthSquared() > 0; + } + + public AABB(Vector min, Vector max) { + this.min = min; + this.max = max; + + if (min != null && max != null) { + this.hasVolume = max.clone().subtract(min).lengthSquared() > 0; + } + } + + public boolean hasVolume() { + return this.hasVolume; + } + + public AABB at(Vector pos) { + if (min == null || max == null) return new AABB(null, null); + + return new AABB(min.clone().add(pos), max.clone().add(pos)); + } + + public AABB at(Location location) { + if (min == null || max == null) return new AABB(null, null); + + return at(location.toVector()); + } + + public AABB grow(double x, double y, double z) { + Vector change = new Vector(x, y, z); + + return new AABB(min.clone().subtract(change), max.clone().add(change)); + } + + public AABB scale(double x, double y, double z) { + Vector extents = getHalfExtents(); + Vector newExtents = extents.clone().multiply(new Vector(x, y, z)); + + Vector diff = newExtents.clone().subtract(extents); + return grow(diff.getX(), diff.getY(), diff.getZ()); + } + + public AABB scale(double amount) { + Vector extents = getHalfExtents(); + Vector newExtents = extents.clone().multiply(amount); + + Vector diff = newExtents.clone().subtract(extents); + return grow(diff.getX(), diff.getY(), diff.getZ()); + } + + public Vector min() { + return this.min; + } + + public Vector max() { + return this.max; + } + + public Vector mid() { + return this.min.clone().add(this.max().clone().subtract(this.min()).multiply(0.5)); + } + + public boolean contains(Vector test) { + if (min == null || max == null || !hasVolume) return false; + + return (test.getX() >= min.getX() && test.getX() <= max.getX()) && + (test.getY() >= min.getY() && test.getY() <= max.getY()) && + (test.getZ() >= min.getZ() && test.getZ() <= max.getZ()); + } + + public Optional intersects(Ray ray) { + if (min == null || max == null || !hasVolume) return Optional.empty(); + + double t1 = (min.getX() - ray.origin.getX()) * ray.directionReciprocal.getX(); + double t2 = (max.getX() - ray.origin.getX()) * ray.directionReciprocal.getX(); + + double t3 = (min.getY() - ray.origin.getY()) * ray.directionReciprocal.getY(); + double t4 = (max.getY() - ray.origin.getY()) * ray.directionReciprocal.getY(); + + double t5 = (min.getZ() - ray.origin.getZ()) * ray.directionReciprocal.getZ(); + double t6 = (max.getZ() - ray.origin.getZ()) * ray.directionReciprocal.getZ(); + + double tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6)); + double tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6)); + + if (tmax < 0 || tmin > tmax) { + return Optional.empty(); + } + + return Optional.of(tmin); + } + + public boolean intersects(AABB other) { + if (min == null || max == null || other.min == null || other.max == null || !hasVolume || !other.hasVolume) { + return false; + } + + return (max.getX() > other.min.getX() && + min.getX() < other.max.getX() && + max.getY() > other.min.getY() && + min.getY() < other.max.getY() && + max.getZ() > other.min.getZ() && + min.getZ() < other.max.getZ()); + } + + public boolean intersects(Sphere sphere) { + if (!this.hasVolume) return false; + + return sphere.intersects(this); + } + + @Override + public Vector getPosition() { + return mid(); + } + + @Override + public Vector getHalfExtents() { + Vector half = max.clone().subtract(min).multiply(0.5); + // Return a vector of half extents that reach from mid to box sides. + return new Vector(Math.abs(half.getX()), Math.abs(half.getY()), Math.abs(half.getZ())); + } + + private Vector min(Entity entity) { + Vector worldMin = entity.getBoundingBox().getMin(); + + return worldMin.clone().subtract(entity.getLocation().toVector()); + } + + private Vector max(Entity entity) { + Vector worldMax = entity.getBoundingBox().getMax(); + + return worldMax.clone().subtract(entity.getLocation().toVector()); + } + + private Vector min(Block block) { + if (block.isPassable()) { + return new Vector(0, 0, 0); + } + + Vector worldMin = block.getBoundingBox().getMin(); + + return worldMin.clone().subtract(block.getLocation().toVector()); + } + + private Vector max(Block block) { + if (block.isPassable()) { + return new Vector(0, 0, 0); + } + + Vector worldMax = block.getBoundingBox().getMax(); + + return worldMax.clone().subtract(block.getLocation().toVector()); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/collision/Collider.java b/src/com/jedk1/jedcore/collision/Collider.java new file mode 100644 index 0000000..5b15d49 --- /dev/null +++ b/src/com/jedk1/jedcore/collision/Collider.java @@ -0,0 +1,12 @@ +package com.jedk1.jedcore.collision; + +import org.bukkit.util.Vector; + +public interface Collider { + boolean intersects(AABB aabb); + boolean intersects(Sphere sphere); + Vector getPosition(); + Vector getHalfExtents(); + + boolean contains(Vector point); +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/collision/CollisionDetector.java b/src/com/jedk1/jedcore/collision/CollisionDetector.java new file mode 100644 index 0000000..457dee4 --- /dev/null +++ b/src/com/jedk1/jedcore/collision/CollisionDetector.java @@ -0,0 +1,127 @@ +package com.jedk1.jedcore.collision; + +import com.projectkorra.projectkorra.ability.ElementalAbility; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.Collections; +import java.util.Optional; +import java.util.Set; + +public class CollisionDetector { + public static boolean checkEntityCollisions(Player player, Collider collider, CollisionCallback function) { + return checkEntityCollisions(player, collider, function, true); + } + + // Checks a collider to see if it's hitting any entities near it. + // Calls the CollisionCallback when hitting a target. + // Returns true if it hits a target. + public static boolean checkEntityCollisions(Player player, Collider collider, CollisionCallback callback, boolean livingOnly) { + // This is used to increase the lookup volume for nearby entities. + // Entity locations can be out of the collider volume while still intersecting. + final double ExtentBuffer = 4.0; + + // Create the extent vector to use as size of bounding box to find nearby entities. + Vector extent = collider.getHalfExtents().add(new Vector(ExtentBuffer, ExtentBuffer, ExtentBuffer)); + + World world = player.getWorld(); + Vector pos = collider.getPosition(); + Location location = new Location(world, pos.getX(), pos.getY(), pos.getZ()); + + boolean hit = false; + + for (Entity entity : location.getWorld().getNearbyEntities(location, extent.getX(), extent.getY(), extent.getZ())) { + if (entity == player) continue; + if (entity instanceof ArmorStand) continue; + + if (entity instanceof Player && ((Player) entity).getGameMode().equals(GameMode.SPECTATOR)) { + continue; + } + + if (livingOnly && !(entity instanceof LivingEntity)) { + continue; + } + + AABB entityBounds = new AABB(entity).at(entity.getLocation()); + + if (collider.intersects(entityBounds)) { + if (callback.onCollision(entity)) { + return true; + } + + hit = true; + } + } + + return hit; + } + + // Checks if the entity is on the ground. Uses NMS bounding boxes for accuracy. + public static boolean isOnGround(Entity entity) { + final double epsilon = 0.01; + + Location location = entity.getLocation(); + AABB entityBounds = new AABB(entity).at(location.clone().subtract(0, epsilon, 0)); + + for (int x = -1; x <= 1; ++x) { + for (int z = -1; z <= 1; ++z) { + Block checkBlock = location.clone().add(x, -epsilon, z).getBlock(); + if (ElementalAbility.isAir(checkBlock.getType())) continue; + + AABB checkBounds = new AABB(checkBlock).at(checkBlock.getLocation()); + + if (entityBounds.intersects(checkBounds)) { + return true; + } + } + } + + return false; + } + + public static double distanceAboveGround(Entity entity) { + return distanceAboveGround(entity, Collections.emptySet()); + } + + // Cast a ray down to find how far above the ground this entity is. + public static double distanceAboveGround(Entity entity, Set groundMaterials) { + Location location = entity.getLocation().clone(); + Ray ray = new Ray(location, new Vector(0, -1, 0)); + + for (double y = location.getY() - 1; y >= 0; --y) { + location.setY(y); + + Block block = location.getBlock(); + AABB checkBounds; + + if (groundMaterials.contains(block.getType())) { + checkBounds = AABB.BlockBounds; + } else { + checkBounds = new AABB(block); + } + + checkBounds = checkBounds.at(block.getLocation()); + + Optional rayHit = checkBounds.intersects(ray); + + if (rayHit.isPresent()) { + return rayHit.get(); + } + } + + return Double.MAX_VALUE; + } + + public interface CollisionCallback { + // return true to break out of the loop + boolean onCollision(Entity e); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/collision/CollisionUtil.java b/src/com/jedk1/jedcore/collision/CollisionUtil.java new file mode 100644 index 0000000..caad776 --- /dev/null +++ b/src/com/jedk1/jedcore/collision/CollisionUtil.java @@ -0,0 +1,34 @@ +package com.jedk1.jedcore.collision; + +import com.projectkorra.projectkorra.ability.util.Collision; +import com.projectkorra.projectkorra.util.TempFallingBlock; +import org.bukkit.Location; + +import java.util.Iterator; +import java.util.List; + +public final class CollisionUtil { + private CollisionUtil() { + + } + + public static void handleFallingBlockCollisions(Collision collision, List fallingBlocks) { + if (collision.isRemovingFirst()) { + Location location = collision.getLocationSecond(); + double firstRadius = collision.getAbilityFirst().getCollisionRadius(); + double secondRadius = collision.getAbilitySecond().getCollisionRadius(); + double collisionRadiusSq = (firstRadius + secondRadius) * (firstRadius + secondRadius); + + // Loop through all falling blocks because the collision system stops on the first collision. + for (Iterator iterator = fallingBlocks.iterator(); iterator.hasNext();) { + TempFallingBlock tfb = iterator.next(); + + // Check if this falling block is within collision radius + if (tfb.getLocation().distanceSquared(location) <= collisionRadiusSq) { + tfb.remove(); + iterator.remove(); + } + } + } + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/collision/Ray.java b/src/com/jedk1/jedcore/collision/Ray.java new file mode 100644 index 0000000..251b095 --- /dev/null +++ b/src/com/jedk1/jedcore/collision/Ray.java @@ -0,0 +1,38 @@ +package com.jedk1.jedcore.collision; + +import org.bukkit.Location; +import org.bukkit.util.Vector; + +public class Ray { + public Vector origin; + public Vector direction; + public Vector directionReciprocal; + + public Ray(Vector origin, Vector direction) { + this.direction = direction; + this.origin = origin; + this.directionReciprocal = new Vector(0, 0, 0); + + if (direction.getX() == 0.0) { + directionReciprocal.setX(Double.MAX_VALUE); + } else { + directionReciprocal.setX(1.0 / direction.getX()); + } + + if (direction.getY() == 0.0) { + directionReciprocal.setY(Double.MAX_VALUE); + } else { + directionReciprocal.setY(1.0 / direction.getY()); + } + + if (direction.getZ() == 0.0) { + directionReciprocal.setZ(Double.MAX_VALUE); + } else { + directionReciprocal.setZ(1.0 / direction.getZ()); + } + } + + public Ray(Location origin, Vector direction) { + this(origin.toVector(), direction); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/collision/Sphere.java b/src/com/jedk1/jedcore/collision/Sphere.java new file mode 100644 index 0000000..0f87a18 --- /dev/null +++ b/src/com/jedk1/jedcore/collision/Sphere.java @@ -0,0 +1,53 @@ +package com.jedk1.jedcore.collision; + +import org.bukkit.util.Vector; + +public class Sphere implements Collider { + public Vector center; + public double radius; + + public Sphere(Vector center, double radius) { + this.center = center; + this.radius = radius; + } + + public Sphere at(Vector newCenter) { + return new Sphere(newCenter, radius); + } + + public boolean intersects(AABB aabb) { + Vector min = aabb.min(); + Vector max = aabb.max(); + + // Get the point closest to sphere center on the aabb. + double x = Math.max(min.getX(), Math.min(center.getX(), max.getX())); + double y = Math.max(min.getY(), Math.min(center.getY(), max.getY())); + double z = Math.max(min.getZ(), Math.min(center.getZ(), max.getZ())); + + // Check if that point is inside of the sphere. + return contains(new Vector(x, y, z)); + } + + public boolean intersects(Sphere other) { + double distSq = other.center.distanceSquared(center); + double rsum = radius + other.radius; + + // Spheres will be colliding if their distance apart is less than the sum of the radii. + return distSq <= rsum * rsum; + } + + @Override + public Vector getPosition() { + return center.clone(); + } + + @Override + public Vector getHalfExtents() { + return new Vector(radius, radius, radius); + } + + public boolean contains(Vector point) { + double distSq = center.distanceSquared(point); + return distSq <= radius * radius; + } +} \ No newline at end of file diff --git a/src/command/Commands.java b/src/com/jedk1/jedcore/command/Commands.java similarity index 100% rename from src/command/Commands.java rename to src/com/jedk1/jedcore/command/Commands.java diff --git a/src/command/JedCoreCommand.java b/src/com/jedk1/jedcore/command/JedCoreCommand.java similarity index 99% rename from src/command/JedCoreCommand.java rename to src/com/jedk1/jedcore/command/JedCoreCommand.java index b4b750a..7fad625 100644 --- a/src/command/JedCoreCommand.java +++ b/src/com/jedk1/jedcore/command/JedCoreCommand.java @@ -1,15 +1,14 @@ package com.jedk1.jedcore.command; -import java.util.List; -import java.util.Set; -import java.util.UUID; - +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.command.PKCommand; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.command.PKCommand; +import java.util.List; +import java.util.Set; +import java.util.UUID; public class JedCoreCommand extends PKCommand { diff --git a/src/configuration/Config.java b/src/com/jedk1/jedcore/configuration/Config.java similarity index 99% rename from src/configuration/Config.java rename to src/com/jedk1/jedcore/configuration/Config.java index d4c427b..14aebfd 100644 --- a/src/configuration/Config.java +++ b/src/com/jedk1/jedcore/configuration/Config.java @@ -1,7 +1,6 @@ package com.jedk1.jedcore.configuration; import com.jedk1.jedcore.JedCore; - import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; diff --git a/src/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java similarity index 100% rename from src/configuration/JedCoreConfig.java rename to src/com/jedk1/jedcore/configuration/JedCoreConfig.java diff --git a/src/configuration/SubsectionConfigurationDecorator.java b/src/com/jedk1/jedcore/configuration/SubsectionConfigurationDecorator.java similarity index 100% rename from src/configuration/SubsectionConfigurationDecorator.java rename to src/com/jedk1/jedcore/configuration/SubsectionConfigurationDecorator.java diff --git a/src/event/PKCommandEvent.java b/src/com/jedk1/jedcore/event/PKCommandEvent.java similarity index 100% rename from src/event/PKCommandEvent.java rename to src/com/jedk1/jedcore/event/PKCommandEvent.java diff --git a/src/com/jedk1/jedcore/listener/AbilityListener.java b/src/com/jedk1/jedcore/listener/AbilityListener.java new file mode 100644 index 0000000..1e0f109 --- /dev/null +++ b/src/com/jedk1/jedcore/listener/AbilityListener.java @@ -0,0 +1,545 @@ +package com.jedk1.jedcore.listener; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.ability.airbending.*; +import com.jedk1.jedcore.ability.avatar.SpiritBeam; +import com.jedk1.jedcore.ability.avatar.elementsphere.ElementSphere; +import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; +import com.jedk1.jedcore.ability.earthbending.*; +import com.jedk1.jedcore.ability.earthbending.combo.Crevice; +import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; +import com.jedk1.jedcore.ability.firebending.*; +import com.jedk1.jedcore.ability.passive.WallRun; +import com.jedk1.jedcore.ability.waterbending.*; +import com.jedk1.jedcore.ability.waterbending.combo.WaterFlow; +import com.jedk1.jedcore.ability.waterbending.combo.WaterGimbal; +import com.jedk1.jedcore.util.ThreadUtil; +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ProjectKorra; +import com.projectkorra.projectkorra.ability.*; +import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; +import com.projectkorra.projectkorra.airbending.Suffocate; +import com.projectkorra.projectkorra.earthbending.EarthArmor; +import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; +import com.projectkorra.projectkorra.firebending.FireJet; +import com.projectkorra.projectkorra.util.MovementHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.waterbending.blood.Bloodbending; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerToggleSneakEvent; +import org.bukkit.inventory.EquipmentSlot; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class AbilityListener implements Listener { + + JedCore plugin; + + public AbilityListener(JedCore plugin) { + this.plugin = plugin; + } + + private final List recentlyDropped = new ArrayList<>(); + + @EventHandler(priority = EventPriority.LOWEST) + // Abilities that should bypass punch cancels should be handled here. + public void onPlayerSwingBypassCancel(PlayerInteractEvent event) { + Player player = event.getPlayer(); + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { + return; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null) { + return; + } + + if (Suffocate.isBreathbent(player) || bPlayer.isChiBlocked()) { + return; + } + + if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { + return; + } + + CoreAbility coreAbil = bPlayer.getBoundAbility(); + if (coreAbil == null) { + return; + } + + if (!bPlayer.canBendIgnoreCooldowns(coreAbil)) { + return; + } + + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { + return; + } + + // FireSki bypasses punch cancel because the normal version is activated from sneaking alone. + // The punch activation exists just so people don't accidentally activate it, so they should have the same + // requirements for activation. + if (coreAbil instanceof FireJet && FireSki.isPunchActivated(player.getWorld())) { + if (player.isSneaking()) { + FireSki ski = new FireSki(player); + if (ski.isStarted() && !bPlayer.isOnCooldown("FireJet")) { + // The event only needs to be cancelled when FireSki is set to have no cooldown. + // This is to prevent FireJet from activating from the same swing event. + event.setCancelled(true); + } + } + } + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerDropItemEvent(PlayerDropItemEvent event) { + recentlyDropped.add(event.getPlayer().getUniqueId()); + + // FirePunch item burn effect + Player player = event.getPlayer(); + FirePunch fp = FirePunch.getAbility(player, FirePunch.class); + boolean burnEnabled = com.jedk1.jedcore.configuration.JedCoreConfig.getConfig((Player)null).getBoolean("Abilities.Fire.FirePunch.BurnsDroppedItems", true); + if (fp != null && burnEnabled) { + var item = event.getItemDrop(); + var loc = fp.getRightHandPos(); + ParticleEffect.LAVA.display(loc, 5, 0.1, 0.1, 0.1, 0.05); + ParticleEffect.FLAME.display(loc, 3, 0.1, 0.1, 0.1, 0.01); + ParticleEffect.SMOKE_NORMAL.display(loc, 2, 0.05, 0.05, 0.05, 0.01); + loc.getWorld().playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, 0.3f, 1.4f); + ThreadUtil.ensureEntity(item, item::remove); + } + + ThreadUtil.runGlobalLater(() -> recentlyDropped.remove(event.getPlayer().getUniqueId()), 2L); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerInventoryInteract(InventoryClickEvent event) { + InventoryAction action = event.getAction(); + if (action == InventoryAction.DROP_ALL_CURSOR || + action == InventoryAction.DROP_ALL_SLOT || + action == InventoryAction.DROP_ONE_CURSOR || + action == InventoryAction.DROP_ONE_SLOT || + action == InventoryAction.UNKNOWN) { + + recentlyDropped.add(event.getWhoClicked().getUniqueId()); + + ThreadUtil.runGlobalLater(() -> { + recentlyDropped.remove(event.getWhoClicked().getUniqueId()); + }, 2L); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerSwing(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (recentlyDropped.contains(player.getUniqueId())) return; + + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { + return; + } + if (event.getAction() == Action.LEFT_CLICK_BLOCK && event.isCancelled()){ + return; + } + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null) { + return; + } + + if (Suffocate.isBreathbent(player)) { + event.setCancelled(true); + return; + } else if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { + event.setCancelled(true); + return; + } else if (bPlayer.isChiBlocked()) { + event.setCancelled(true); + return; + } else if (GeneralMethods.isInteractable(player.getTargetBlock((Set)null, 5))) { + return; + } + + if (bPlayer.isToggled()) { + new WallRun(player); + } + + CoreAbility coreAbil = bPlayer.getBoundAbility(); + if (coreAbil == null) { + if (MultiAbilityManager.hasMultiAbilityBound(player)){ + String abil = MultiAbilityManager.getBoundMultiAbility(player); + if (abil.equalsIgnoreCase("elementsphere")) { + new ElementSphere(player); + } + } + return; + } + + String abilName = bPlayer.getBoundAbilityName(); + Class abilClass = coreAbil.getClass(); + + if (bPlayer.canBendIgnoreCooldowns(coreAbil)) { + + if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(AirBlade.class)) { + new AirBlade(player); + } + if (abilClass.equals(AirPunch.class)) { + new AirPunch(player); + } + } + + if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(EarthArmor.class)) { + new MetalArmor(player); + } + if (abilClass.equals(EarthLine.class)) { + EarthLine.shootLine(player); + } + if (abilClass.equals(EarthShard.class)) { + EarthShard.throwShard(player); + } + if (abilClass.equals(EarthSurf.class)) { + new EarthSurf(player); + } + if (abilClass.equals(Fissure.class)) { + new Fissure(player); + } + if (abilClass.equals(LavaFlux.class)) { + new LavaFlux(player); + } + if (abilClass.equals(LavaThrow.class)) { + LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); + if (lt != null) { + lt.createBlast(); + } + } + if (abilClass.equals(MetalFragments.class)) { + MetalFragments.shootFragment(player); + } + if (abilClass.equals(MetalHook.class)) { + new MetalHook(player); + } + if (abilClass.equals(MetalShred.class)) { + MetalShred.extend(player); + } + if (abilClass.equals(MudSurge.class)) { + MudSurge.mudSurge(player); + } + if (abilClass.equals(SandBlast.class)) { + SandBlast.blastSand(player); + } + if (abilClass.equals(LavaFlow.class)) { + MagmaBlast.performAction(player); + } + if (abilClass.equals(MagnetShield.class)) { + new MagnetShield(player, true); + } + } + + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(Combustion.class)) { + Combustion.combust(player); + } + if (abilClass.equals(Discharge.class)) { + new Discharge(player); + } + if (abilClass.equals(FireBall.class)) { + new FireBall(player); + } + if (abilClass.equals(FirePunch.class)) { + new FirePunch(player); + } + if (abilClass.equals(FireShots.class)) { + FireShots.fireShot(player); + } + } + + if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.WATER.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { + com.jedk1.jedcore.ability.waterbending.Bloodbending.launch(player); + } + if (abilClass.equals(BloodPuppet.class)) { + BloodPuppet.attack(player); + } + if (abilClass.equals(IceClaws.class)) { + IceClaws.throwClaws(player); + } + if (abilName.equals("Drain")) { + Drain.fireBlast(player); + } + if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { + WaterGimbal.prepareBlast(player); + } + if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { + WaterFlow.freeze(player); + } + } + if (coreAbil instanceof ChiAbility && bPlayer.isElementToggled(Element.CHI)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Chi.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(DaggerThrow.class)) { + new DaggerThrow(player); + } + } + + if (coreAbil instanceof AvatarAbility) { + if (abilClass.equals(ElementSphere.class)) { + new ElementSphere(player); + } + } + } + } + + public static ConcurrentHashMap recent = new ConcurrentHashMap(); + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerSneak(PlayerToggleSneakEvent event) { + Player player = event.getPlayer(); + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + + if (event.isCancelled() || bPlayer == null) { + return; + } + + String abilName = bPlayer.getBoundAbilityName(); + if (Suffocate.isBreathbent(player)) { + if (!abilName.equalsIgnoreCase("AirSwipe") + && !abilName.equalsIgnoreCase("FireBlast") + && !abilName.equalsIgnoreCase("EarthBlast") + && !abilName.equalsIgnoreCase("WaterManipulation")) { + if(!player.isSneaking()) { + event.setCancelled(true); + } + } + } + + if (MovementHandler.isStopped(player) || Bloodbending.isBloodbent(player)) { + event.setCancelled(true); + return; + } + + CoreAbility coreAbil = bPlayer.getBoundAbility(); + if (coreAbil == null) { + return; + } + + Class abilClass = coreAbil.getClass(); + + if (bPlayer.isChiBlocked()) { + event.setCancelled(true); + return; + } + + if (player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (abilClass.equals(FireShots.class)) { + FireShots.swapHands(player); + } + + if (abilClass.equals(FirePunch.class)) { + FirePunch.swapHands(player); + } + } + } + + if (!player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { + if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(AirBreath.class)) { + new AirBreath(player); + } + if (abilClass.equals(AirGlide.class)) { + new AirGlide(player); + } + if (abilClass.equals(Meditate.class)) { + new Meditate(player); + } + if (abilClass.equals(SonicBlast.class)) { + new SonicBlast(player); + } + } + + if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(EarthKick.class)) { + new EarthKick(player); + } + if (abilClass.equals(EarthLine.class)) { + new EarthLine(player); + } + if (abilClass.equals(EarthPillar.class)) { + new EarthPillar(player); + } + if (abilClass.equals(EarthShard.class)) { + new EarthShard(player); + } + if (abilClass.equals(Fissure.class)) { + Fissure.performAction(player); + } + if (abilClass.equals(LavaDisc.class)) { + new LavaDisc(player); + } + if (abilClass.equals(MagnetShield.class)) { + new MagnetShield(player, false); + } + if (abilClass.equals(MetalFragments.class)) { + new MetalFragments(player); + } + if (abilClass.equals(MetalShred.class)) { + new MetalShred(player); + } + if (abilClass.equals(MudSurge.class)) { + new MudSurge(player); + } + if (abilClass.equals(SandBlast.class)) { + new SandBlast(player); + } + if (abilClass.equals(Crevice.class)) { + Crevice.closeCrevice(player); + } + if (abilClass.equals(LavaThrow.class)) { + LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); + if (lt == null) { + new LavaThrow(player); + } + } + } + + if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(Combustion.class)) { + new Combustion(event.getPlayer()); + } + if (abilClass.equals(FireBreath.class)) { + new FireBreath(player); + } + if (abilClass.equals(FireComet.class)) { + new FireComet(player); + } + if (abilClass.equals(FireJet.class)) { + if (FireSki.isPunchActivated(player.getWorld())) { + FireSki fs = CoreAbility.getAbility(player, FireSki.class); + + if (fs != null) { + ThreadUtil.ensureEntity(player, fs::remove); + } + } else { + new FireSki(player); + } + } + if (abilClass.equals(FireShots.class)) { + new FireShots(player); + } + if (abilClass.equals(LightningBurst.class)) { + new LightningBurst(player); + } + } + + if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { + if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Water.CanBendWithWeapons")) { + return; + } + if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { + new com.jedk1.jedcore.ability.waterbending.Bloodbending(player); + } + if (abilClass.equals(BloodPuppet.class)) { + new BloodPuppet(player); + } + if (abilClass.equals(FrostBreath.class)) { + new FrostBreath(player); + } + if (abilClass.equals(IceClaws.class)) { + new IceClaws(player); + IceClaws.swapHands(player); + } + if (abilClass.equals(IceWall.class)) { + new IceWall(player); + } + if (abilName.equals("Drain")) { + new Drain(player); + } + if (abilClass.equals(WakeFishing.class)) { + new WakeFishing(player); + } + } + + if (coreAbil instanceof AvatarAbility) { + if (abilClass.equals(SpiritBeam.class)) { + new SpiritBeam(player); + } + } + } + } + + @EventHandler + public void onArrowHit(EntityDamageByEntityEvent event) { + if (event.getDamager().getType() == EntityType.ARROW) { + Arrow arrow = (Arrow) event.getDamager(); + if (arrow.getShooter() instanceof Player && arrow.hasMetadata("daggerthrow")) { + Player player = (Player) arrow.getShooter(); + event.setDamage(0.0D); + player.playSound(player.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 1.0f); + } + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerInteraction(PlayerInteractEvent event) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + MetalFragments.shootFragment(event.getPlayer()); + } + } + + @EventHandler + public void onChange(EntityChangeBlockEvent event) { + if (event.getEntity() instanceof FallingBlock) { + if (event.getEntity().hasMetadata("magmablast")) event.setCancelled(true); + } + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/listener/CommandListener.java b/src/com/jedk1/jedcore/listener/CommandListener.java new file mode 100644 index 0000000..abdc6ca --- /dev/null +++ b/src/com/jedk1/jedcore/listener/CommandListener.java @@ -0,0 +1,73 @@ +package com.jedk1.jedcore.listener; + +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.command.JedCoreCommand; +import com.jedk1.jedcore.event.PKCommandEvent; +import com.jedk1.jedcore.event.PKCommandEvent.CommandType; +import com.jedk1.jedcore.util.ThreadUtil; +import com.projectkorra.projectkorra.command.PKCommand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +import java.util.Arrays; +import java.util.UUID; + +public class CommandListener implements Listener { + + JedCore plugin; + String[] cmdaliases = {"/bending", "/bend", "/b", "/pk", "/projectkorra", "/korra", "/mtla", "/tla"}; + public static String[] developers = { + "4eb6315e-9dd1-49f7-b582-c1170e497ab0", //jedk1 + "d57565a5-e6b0-44e3-a026-979d5de10c4d", //s3xi + "e98a2f7d-d571-4900-a625-483cbe6774fe", //Aztl + "b6bd2ceb-4922-4707-9173-8a02044e9069", //Cozmyc + "b1318b21-5956-445c-a328-bad3175c1c7a" //Hihelloy + }; + + public CommandListener(JedCore plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerCommand(PlayerCommandPreprocessEvent event) { + String cmd = event.getMessage().toLowerCase(); + String[] args = cmd.split("\\s+"); + if (Arrays.asList(cmdaliases).contains(args[0]) && args.length >= 2) { + PKCommandEvent new_event = new PKCommandEvent(event.getPlayer(), args, null); + for (PKCommand command : PKCommand.instances.values()) { + if (Arrays.asList(command.getAliases()).contains(args[1].toLowerCase())) { + new_event = new PKCommandEvent(event.getPlayer(), args, CommandType.getType(command.getName())); + } + } + Bukkit.getServer().getPluginManager().callEvent(new_event); + } + } + + CommandType[] types = {CommandType.ADD, CommandType.BIND, CommandType.CHOOSE, CommandType.CLEAR, CommandType.PRESET, CommandType.REMOVE}; + + @EventHandler(priority = EventPriority.NORMAL) + public void onPKCommand(final PKCommandEvent event) { + ThreadUtil.runGlobalLater(() -> { + if (event.getType() != null) { + if (event.getType().equals(CommandType.WHO) && event.getSender().hasPermission("bending.command.who")) { + if (event.getArgs().length == 3) { + if (Bukkit.getPlayer(event.getArgs()[2]) != null) { + UUID uuid = Bukkit.getPlayer(event.getArgs()[2]).getUniqueId(); + if (Arrays.asList(developers).contains(uuid.toString())) { + event.getSender().sendMessage(ChatColor.DARK_AQUA + "JedCore Developer"); + } + } + } + return; + } + if (event.getType().equals(CommandType.VERSION) && event.getSender().hasPermission("bending.command.version")) { + JedCoreCommand.sendBuildInfo(event.getSender()); + } + } + }, 1); + } +} \ No newline at end of file diff --git a/src/com/jedk1/jedcore/listener/JCListener.java b/src/com/jedk1/jedcore/listener/JCListener.java new file mode 100644 index 0000000..c17ba3a --- /dev/null +++ b/src/com/jedk1/jedcore/listener/JCListener.java @@ -0,0 +1,239 @@ +package com.jedk1.jedcore.listener; + +import com.jedk1.jedcore.JCMethods; +import com.jedk1.jedcore.JedCore; +import com.jedk1.jedcore.ability.chiblocking.Backstab; +import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; +import com.jedk1.jedcore.ability.earthbending.*; +import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; +import com.jedk1.jedcore.ability.firebending.FireBreath; +import com.jedk1.jedcore.ability.firebending.FirePunch; +import com.jedk1.jedcore.ability.firebending.FireSki; +import com.jedk1.jedcore.ability.waterbending.IceClaws; +import com.jedk1.jedcore.ability.waterbending.IceWall; +import com.jedk1.jedcore.util.LightManager; +import com.jedk1.jedcore.util.RegenTempBlock; +import com.jedk1.jedcore.util.ThreadUtil; +import com.projectkorra.projectkorra.ProjectKorra; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.ability.IceAbility; +import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; +import com.projectkorra.projectkorra.event.AbilityStartEvent; +import com.projectkorra.projectkorra.event.BendingReloadEvent; +import com.projectkorra.projectkorra.event.HorizontalVelocityChangeEvent; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.TempBlock; +import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerToggleSprintEvent; + +public class JCListener implements Listener { + + JedCore plugin; + + public JCListener(JedCore plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onAbilityStart(AbilityStartEvent event) { + if (event.isCancelled()) return; + + if (event.getAbility() instanceof LavaFlow) { + Player player = event.getAbility().getPlayer(); + MagmaBlast mb = CoreAbility.getAbility(player, MagmaBlast.class); + + if (mb != null && (mb.hasBlocks() || mb.shouldBlockLavaFlow())) { + event.setCancelled(true); + LavaFlow flow = (LavaFlow) event.getAbility(); + + // Reset the cooldown of LavaFlow that was set before the call to start(). + flow.getBendingPlayer().removeCooldown(flow); + } + } else if (event.getAbility() instanceof PlantRegrowth) { + PlantRegrowth regrowth = (PlantRegrowth)event.getAbility(); + + // Stop PlantRegrowth from creating permanent snow when used against FrostBreath snow. + if (regrowth.getType() == Material.SNOW && TempBlock.isTempBlock(regrowth.getBlock())) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onFlow(BlockFromToEvent event) { + if (!LavaDisc.canFlowFrom(event.getBlock())) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onPlayerFallDamage(EntityDamageEvent event) { + if (event.isCancelled() || event.getCause() != DamageCause.FALL || !(event.getEntity() instanceof Player)) { + return; + } + + Player player = (Player)event.getEntity(); + + if (MudSurge.onFallDamage(player)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onEntityDamage(EntityDamageEvent event) { + if (event.getCause().equals(DamageCause.SUFFOCATION)) { + if (event.getEntity() instanceof LivingEntity) { + LivingEntity entity = (LivingEntity) event.getEntity(); + Block block = entity.getEyeLocation().getBlock(); + if (RegenTempBlock.blocks.containsKey(block) && IceAbility.isIce(block)) { + event.setCancelled(true); + return; + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getDamager() instanceof Player && event.getEntity() instanceof LivingEntity) { + if (event.getCause() == DamageCause.ENTITY_ATTACK && event.getDamager().getWorld().equals(event.getEntity().getWorld())) { + double distSq = event.getDamager().getLocation().distanceSquared(event.getEntity().getLocation()); + + // Only activate these in melee range + if (distSq <= 5 * 5) { + FirePunch fp = CoreAbility.getAbility((Player) event.getDamager(), FirePunch.class); + if (fp != null) { + fp.punch((LivingEntity) event.getEntity()); + event.setCancelled(true); + return; + } + + if (Backstab.punch((Player) event.getDamager(), (LivingEntity) event.getEntity())) { + event.setCancelled(true); + double damage = Backstab.getDamage(event.getDamager().getWorld()); + DamageHandler.damageEntity(event.getEntity(), (Player) event.getDamager(), damage, CoreAbility.getAbility("BackStab")); + return; + } + } + } + + if (IceClaws.freezeEntity((Player) event.getDamager(), (LivingEntity) event.getEntity())) { + event.setCancelled(true); + return; + } + } + + if (event.getDamager() instanceof Arrow arrow) { + if (event.getEntity() instanceof LivingEntity) { + if (arrow.hasMetadata("daggerthrow")) { + event.setDamage(0); + if (!(arrow.getShooter() instanceof Player shooter)) return; + if (!CoreAbility.hasAbility(shooter, DaggerThrow.class)) return; + DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); + if (daggerThrow != null) { + daggerThrow.damageEntityFromArrow(((LivingEntity) event.getEntity()), arrow); + ThreadUtil.ensureEntity(arrow, arrow::remove); + event.setCancelled(true); + } + } + if (arrow.hasMetadata("metalhook")) { + event.setDamage(0); + ThreadUtil.ensureEntity(arrow, arrow::remove); + event.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onBlockBreak(BlockBreakEvent event) { + MetalFragments.remove(event.getPlayer(), event.getBlock()); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onEntityExplode(EntityExplodeEvent event){ + if (IceWall.checkExplosions(event.getLocation(), event.getEntity())) { + event.blockList().clear(); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onCollisionWithEntity(HorizontalVelocityChangeEvent event) { + if (event.getEntity().getWorld() != event.getInstigator().getWorld()) { + return; + } + IceWall.collisionDamage(event.getEntity(), event.getDistanceTraveled(), event.getDifference(), event.getInstigator()); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerSprint(PlayerToggleSprintEvent event) { + if (!event.isSprinting()) + return; + + if (CoreAbility.hasAbility(event.getPlayer(), EarthSurf.class)) { + event.setCancelled(true); + return; + } + + if (CoreAbility.hasAbility(event.getPlayer(), FireSki.class)) { + event.setCancelled(true); + return; + } + + MetalShred.startShred(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void projectKorraReload(BendingReloadEvent event) { + final CommandSender sender = event.getSender(); + LightManager.get().restart(); + // There's a PK bug where a new collision manager is set on reload without stopping the old task. + ProjectKorra.getCollisionManager().stopCollisionDetection(); + ThreadUtil.runGlobalLater(() -> { + JCMethods.reload(); + sender.sendMessage(ChatColor.DARK_AQUA + "JedCore config reloaded."); + }, 1); + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onChat(AsyncPlayerChatEvent event){ + Player player = event.getPlayer(); + String msg = event.getMessage(); + + if (msg.toLowerCase().contains("bring fire and light together as one and allow the breath of color")) { + FireBreath.toggleRainbowBreath(player, true); + event.setCancelled(true); + } + + if (msg.toLowerCase().contains("split the bond of fire and light and set the color free")) { + FireBreath.toggleRainbowBreath(player, false); + event.setCancelled(true); + } + + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onItemPickup(InventoryPickupItemEvent event) { + if (event.getItem().getPickupDelay() >= Short.MAX_VALUE) { + event.setCancelled(true); + } + } +} \ No newline at end of file diff --git a/src/policies/removal/CannotBendRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/CannotBendRemovalPolicy.java similarity index 100% rename from src/policies/removal/CannotBendRemovalPolicy.java rename to src/com/jedk1/jedcore/policies/removal/CannotBendRemovalPolicy.java diff --git a/src/policies/removal/CompositeRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/CompositeRemovalPolicy.java similarity index 100% rename from src/policies/removal/CompositeRemovalPolicy.java rename to src/com/jedk1/jedcore/policies/removal/CompositeRemovalPolicy.java diff --git a/src/policies/removal/IsDeadRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/IsDeadRemovalPolicy.java similarity index 100% rename from src/policies/removal/IsDeadRemovalPolicy.java rename to src/com/jedk1/jedcore/policies/removal/IsDeadRemovalPolicy.java diff --git a/src/policies/removal/IsOfflineRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/IsOfflineRemovalPolicy.java similarity index 100% rename from src/policies/removal/IsOfflineRemovalPolicy.java rename to src/com/jedk1/jedcore/policies/removal/IsOfflineRemovalPolicy.java diff --git a/src/policies/removal/OutOfRangeRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/OutOfRangeRemovalPolicy.java similarity index 100% rename from src/policies/removal/OutOfRangeRemovalPolicy.java rename to src/com/jedk1/jedcore/policies/removal/OutOfRangeRemovalPolicy.java diff --git a/src/policies/removal/RemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/RemovalPolicy.java similarity index 100% rename from src/policies/removal/RemovalPolicy.java rename to src/com/jedk1/jedcore/policies/removal/RemovalPolicy.java diff --git a/src/policies/removal/SwappedSlotsRemovalPolicy.java b/src/com/jedk1/jedcore/policies/removal/SwappedSlotsRemovalPolicy.java similarity index 100% rename from src/policies/removal/SwappedSlotsRemovalPolicy.java rename to src/com/jedk1/jedcore/policies/removal/SwappedSlotsRemovalPolicy.java diff --git a/src/util/AbilitySelector.java b/src/com/jedk1/jedcore/util/AbilitySelector.java similarity index 92% rename from src/util/AbilitySelector.java rename to src/com/jedk1/jedcore/util/AbilitySelector.java index 6b3ca40..5ce3da1 100644 --- a/src/util/AbilitySelector.java +++ b/src/com/jedk1/jedcore/util/AbilitySelector.java @@ -1,12 +1,13 @@ package com.jedk1.jedcore.util; -import com.jedk1.jedcore.ability.waterbending.BloodShot; import com.jedk1.jedcore.ability.waterbending.WaterBlast; import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.earthbending.*; import com.projectkorra.projectkorra.firebending.*; import com.projectkorra.projectkorra.waterbending.*; -import com.projectkorra.projectkorra.waterbending.ice.*; +import com.projectkorra.projectkorra.waterbending.ice.IceSpikeBlast; +import com.projectkorra.projectkorra.waterbending.ice.IceSpikePillar; +import com.projectkorra.projectkorra.waterbending.ice.IceSpikePillarField; import java.util.HashMap; import java.util.Map; @@ -40,7 +41,6 @@ public class AbilitySelector { specialAbilities.put("CollapseWall", CoreAbility.getAbility(CollapseWall.class)); specialAbilities.put("WaterGimbal", CoreAbility.getAbility(WaterBlast.class)); - specialAbilities.put("BloodShot", CoreAbility.getAbility(BloodShot.class)); } public static CoreAbility getAbility(String abilityName) { @@ -51,4 +51,4 @@ public static CoreAbility getAbility(String abilityName) { return CoreAbility.getAbility(abilityName); } -} +} \ No newline at end of file diff --git a/src/util/AirShieldReflector.java b/src/com/jedk1/jedcore/util/AirShieldReflector.java similarity index 100% rename from src/util/AirShieldReflector.java rename to src/com/jedk1/jedcore/util/AirShieldReflector.java diff --git a/src/util/BlockUtil.java b/src/com/jedk1/jedcore/util/BlockUtil.java similarity index 100% rename from src/util/BlockUtil.java rename to src/com/jedk1/jedcore/util/BlockUtil.java diff --git a/src/util/ChiRestrictor.java b/src/com/jedk1/jedcore/util/ChiRestrictor.java similarity index 94% rename from src/util/ChiRestrictor.java rename to src/com/jedk1/jedcore/util/ChiRestrictor.java index 8869cc8..5b34e98 100644 --- a/src/util/ChiRestrictor.java +++ b/src/com/jedk1/jedcore/util/ChiRestrictor.java @@ -1,6 +1,5 @@ package com.jedk1.jedcore.util; -import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.event.AbilityStartEvent; @@ -10,7 +9,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.scheduler.BukkitRunnable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -35,11 +33,9 @@ public class ChiRestrictor implements Listener { @EventHandler public void onBendingReload(BendingReloadEvent event) { - new BukkitRunnable() { - public void run() { - reloadConfig(); - } - }.runTaskLater(JedCore.plugin, 1); + ThreadUtil.runGlobalLater(() -> { + reloadConfig(); + }, 1); } public static void reloadConfig() { @@ -133,4 +129,4 @@ private static Entity getTarget(ChiAbility ability) { return null; } } -} +} \ No newline at end of file diff --git a/src/util/CollisionInitializer.java b/src/com/jedk1/jedcore/util/CollisionInitializer.java similarity index 100% rename from src/util/CollisionInitializer.java rename to src/com/jedk1/jedcore/util/CollisionInitializer.java diff --git a/src/util/FireTick.java b/src/com/jedk1/jedcore/util/FireTick.java similarity index 100% rename from src/util/FireTick.java rename to src/com/jedk1/jedcore/util/FireTick.java diff --git a/src/util/LightManager.java b/src/com/jedk1/jedcore/util/LightManager.java similarity index 92% rename from src/util/LightManager.java rename to src/com/jedk1/jedcore/util/LightManager.java index a48727d..f9b5a3f 100644 --- a/src/util/LightManager.java +++ b/src/com/jedk1/jedcore/util/LightManager.java @@ -1,7 +1,6 @@ package com.jedk1.jedcore.util; import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ProjectKorra; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -30,8 +29,6 @@ public class LightManager { // Default LIGHT BlockData private final Map lightDataMap = new HashMap<>(); private final Map waterloggedLightDataMap = new HashMap<>(); - - // Scheduler with threads equal to the number of available processors, this handles reverting expired lights private ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors()); /** @@ -57,7 +54,7 @@ private LightManager() { /** * Retrieves the current time and iterates over all light data in the light map. If the current time is greater * than or equal to the expiry time of a light data, it fades the light out and removes the light data from the map. - * This is running periodically, or every 50ms, via the scheduled thread pool executor. + * This runs periodically via SchedulerUtil for Folia compatibility. */ private void revertExpiredLights() { long currentTime = System.currentTimeMillis(); @@ -111,7 +108,10 @@ private void startLightReverter() { scheduler = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors()); } - scheduler.scheduleAtFixedRate(this::revertExpiredLights, 0, 50, TimeUnit.MILLISECONDS); + // Use SchedulerUtil for main thread tasks (revertExpiredLights) + ThreadUtil.runGlobalTimer(this::revertExpiredLights, 0, 1); + + // Use ScheduledThreadPoolExecutor for client-side operations (sendBlockChange) scheduler.scheduleAtFixedRate(this::processBlockChanges, 0, 50, TimeUnit.MILLISECONDS); } @@ -123,28 +123,22 @@ private void startLightReverter() { */ private void fadeLight(LightData lightData) { int brightness = lightData.brightness; + fadeLightRecursive(lightData, brightness); + } - class TaskHolder { - ScheduledFuture future; + private void fadeLightRecursive(LightData lightData, int currentBrightness) { + if (currentBrightness <= 0) { + revertLight(lightData); + return; } - TaskHolder taskHolder = new TaskHolder(); - - Runnable task = new Runnable() { - private int currentBrightness = brightness; - - @Override - public void run() { - currentBrightness--; - if (currentBrightness > 0) { - sendLightChange(lightData.location, currentBrightness, lightData.observers); - } else { - revertLight(lightData); - taskHolder.future.cancel(false); - } - } - }; - taskHolder.future = scheduler.scheduleAtFixedRate(task, 0, 50, TimeUnit.MILLISECONDS); + // Process the light change (client-side only) + sendLightChange(lightData.location, currentBrightness, lightData.observers); + + // Schedule next fade step using the thread pool + scheduler.schedule(() -> { + fadeLightRecursive(lightData, currentBrightness - 1); + }, 50, TimeUnit.MILLISECONDS); } /** @@ -170,9 +164,8 @@ private void processBlockChanges() { while ((blockChange = blockChangeQueue.poll()) != null) { Player player = blockChange.getPlayer(); BlockChange finalBlockChange = blockChange; - Bukkit.getScheduler().runTaskAsynchronously(ProjectKorra.plugin, () -> { - player.sendBlockChange(finalBlockChange.getLocation(), finalBlockChange.getBlockData()); - }); + // sendBlockChange is client-side only, so we can call it directly from the thread pool + player.sendBlockChange(finalBlockChange.getLocation(), finalBlockChange.getBlockData()); } } diff --git a/src/com/jedk1/jedcore/util/LightManagerUtil.java b/src/com/jedk1/jedcore/util/LightManagerUtil.java new file mode 100644 index 0000000..e098afc --- /dev/null +++ b/src/com/jedk1/jedcore/util/LightManagerUtil.java @@ -0,0 +1,108 @@ +package com.jedk1.jedcore.util; + +import com.jedk1.jedcore.configuration.JedCoreConfig; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public class LightManagerUtil { + + private static final boolean PROJECTKORRA_LIGHTMANAGER_AVAILABLE; + + static { + boolean available = false; + try { + Class.forName("com.projectkorra.projectkorra.util.LightManager"); + available = true; + } catch (ClassNotFoundException e) { + // ProjectKorra LightManager not available, fallback to built-in LightManager + } + PROJECTKORRA_LIGHTMANAGER_AVAILABLE = available; + } + + public static void emitFirebendingLight(final Location location) { + if (!JedCoreConfig.getConfig((Player)null).getBoolean("Properties.Fire.DynamicLight.Enabled")) { + return; + } + + int brightness = JedCoreConfig.getConfig((Player)null).getInt("Properties.Fire.DynamicLight.Brightness"); + long keepAlive = JedCoreConfig.getConfig((Player)null).getLong("Properties.Fire.DynamicLight.KeepAlive"); + + if (brightness < 1 || brightness > 15) { + throw new IllegalArgumentException("Properties.Fire.DynamicLight.Brightness must be between 1 and 15."); + } + + createLight(location).brightness(brightness).timeUntilFadeout(keepAlive).emit(); + } + + public static LightBuilder createLight(Location location) { + return new LightBuilder(location); + } + + public static boolean isProjectKorraLightManagerAvailable() { + return PROJECTKORRA_LIGHTMANAGER_AVAILABLE; + } + + public static class LightBuilder { + private final Location location; + private int brightness = 15; // default brightness + private long timeUntilFade = 50; // default expiry time in ms + private Collection observers = null; // null means all players + + public LightBuilder(Location location) { + this.location = location; + } + + public LightBuilder brightness(int brightness) { + this.brightness = Math.max(1, Math.min(15, brightness)); + return this; + } + + public LightBuilder timeUntilFadeout(long expiry) { + this.timeUntilFade = expiry; + return this; + } + + public LightBuilder observers(Collection observers) { + this.observers = observers; + return this; + } + + public void emit() { + if (PROJECTKORRA_LIGHTMANAGER_AVAILABLE) { + emitWithProjectKorraLightManager(); + } else { + emitWithJedCoreLightManager(); + } + } + + private void emitWithProjectKorraLightManager() { + try { + com.projectkorra.projectkorra.util.LightManager.LightBuilder lightBuilder = + com.projectkorra.projectkorra.util.LightManager.createLight(location); + + lightBuilder = lightBuilder.brightness(brightness); + lightBuilder = lightBuilder.timeUntilFadeout(timeUntilFade); + + if (observers != null) { + lightBuilder = lightBuilder.observers(observers); + } + + lightBuilder.emit(); + + } catch (Exception e) { + // Fallback to JedCore's LightManager if ProjectKorra's fails + emitWithJedCoreLightManager(); + } + } + + private void emitWithJedCoreLightManager() { + if (observers != null) { + LightManager.get().createLight(location).brightness(brightness).timeUntilFadeout(timeUntilFade).observers(observers).emit(); + } else { + LightManager.get().createLight(location).brightness(brightness).timeUntilFadeout(timeUntilFade).emit(); + } + } + } +} \ No newline at end of file diff --git a/src/util/MaterialUtil.java b/src/com/jedk1/jedcore/util/MaterialUtil.java similarity index 99% rename from src/util/MaterialUtil.java rename to src/com/jedk1/jedcore/util/MaterialUtil.java index 25d74c7..527a153 100644 --- a/src/util/MaterialUtil.java +++ b/src/com/jedk1/jedcore/util/MaterialUtil.java @@ -1,7 +1,6 @@ package com.jedk1.jedcore.util; import com.projectkorra.projectkorra.GeneralMethods; - import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Block; diff --git a/src/util/MetricsLite.java b/src/com/jedk1/jedcore/util/MetricsLite.java similarity index 98% rename from src/util/MetricsLite.java rename to src/com/jedk1/jedcore/util/MetricsLite.java index b93fb90..42317a5 100644 --- a/src/util/MetricsLite.java +++ b/src/com/jedk1/jedcore/util/MetricsLite.java @@ -37,13 +37,7 @@ import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.scheduler.BukkitTask; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.io.*; import java.lang.reflect.Method; import java.net.Proxy; import java.net.URL; @@ -159,7 +153,7 @@ public boolean start() { } // Begin hitting the server with glorious data - task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { + task = (BukkitTask) ThreadUtil.runAsyncTimer(new Runnable() { private boolean firstPost = true; @@ -273,10 +267,10 @@ public File getConfigFile() { // return => base/plugins/PluginMetrics/config.yml return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); } - + /** * Gets the online player (backwards compatibility) - * + * * @return online player amount */ private int getOnlinePlayers() { @@ -292,7 +286,7 @@ private int getOnlinePlayers() { Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); } } - + return 0; } diff --git a/src/util/RegenTempBlock.java b/src/com/jedk1/jedcore/util/RegenTempBlock.java similarity index 99% rename from src/util/RegenTempBlock.java rename to src/com/jedk1/jedcore/util/RegenTempBlock.java index 56794f6..adbaf62 100644 --- a/src/util/RegenTempBlock.java +++ b/src/com/jedk1/jedcore/util/RegenTempBlock.java @@ -2,7 +2,6 @@ import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.util.TempBlock; - import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockState; diff --git a/src/util/TempFallingBlock.java b/src/com/jedk1/jedcore/util/TempFallingBlock.java similarity index 97% rename from src/util/TempFallingBlock.java rename to src/com/jedk1/jedcore/util/TempFallingBlock.java index 0590657..f2eb206 100644 --- a/src/util/TempFallingBlock.java +++ b/src/com/jedk1/jedcore/util/TempFallingBlock.java @@ -1,151 +1,152 @@ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by FernFlower decompiler) -// - -package com.jedk1.jedcore.util; - -import com.projectkorra.projectkorra.ability.CoreAbility; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; -import org.bukkit.entity.FallingBlock; -import org.bukkit.util.Vector; - -public class TempFallingBlock { - public static ConcurrentHashMap instances = new ConcurrentHashMap(); - public static ConcurrentHashMap> instancesByAbility = new ConcurrentHashMap(); - private FallingBlock fallingblock; - private CoreAbility ability; - private long creation; - private boolean expire; - private Consumer onPlace; - - public TempFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability) { - this(location, data, velocity, ability, false); - } - - public TempFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability, boolean expire) { - this.fallingblock = location.getWorld().spawnFallingBlock(location, data.clone()); - this.fallingblock.setVelocity(velocity); - this.fallingblock.setDropItem(false); - this.ability = ability; - this.creation = System.currentTimeMillis(); - this.expire = expire; - instances.put(this.fallingblock, this); - if (!instancesByAbility.containsKey(ability)) { - instancesByAbility.put(ability, new HashSet()); - } - - ((Set)instancesByAbility.get(ability)).add(this); - } - - public static void manage() { - long time = System.currentTimeMillis(); - - for(TempFallingBlock tfb : instances.values()) { - if (tfb.canExpire() && time > tfb.getCreationTime() + 5000L) { - tfb.remove(); - } else if (time > tfb.getCreationTime() + 120000L) { - tfb.remove(); - } - } - - } - - public static TempFallingBlock get(FallingBlock fallingblock) { - return isTempFallingBlock(fallingblock) ? (TempFallingBlock)instances.get(fallingblock) : null; - } - - public static boolean isTempFallingBlock(FallingBlock fallingblock) { - return instances.containsKey(fallingblock); - } - - public static void removeFallingBlock(FallingBlock fallingblock) { - if (isTempFallingBlock(fallingblock)) { - TempFallingBlock tempFallingBlock = (TempFallingBlock)instances.get(fallingblock); - Objects.requireNonNull(fallingblock); - ThreadUtil.ensureEntity(fallingblock, fallingblock::remove); - instances.remove(fallingblock); - ((Set)instancesByAbility.get(tempFallingBlock.ability)).remove(tempFallingBlock); - if (((Set)instancesByAbility.get(tempFallingBlock.ability)).isEmpty()) { - instancesByAbility.remove(tempFallingBlock.ability); - } - } - - } - - public static void removeAllFallingBlocks() { - for(FallingBlock fallingblock : instances.keySet()) { - Objects.requireNonNull(fallingblock); - ThreadUtil.ensureEntity(fallingblock, fallingblock::remove); - } - - instances.clear(); - instancesByAbility.clear(); - } - - public static Set getFromAbility(CoreAbility ability) { - return (Set)instancesByAbility.getOrDefault(ability, new HashSet()); - } - - public void remove() { - FallingBlock var10000 = this.fallingblock; - FallingBlock var10001 = this.fallingblock; - Objects.requireNonNull(var10001); - ThreadUtil.ensureEntity(var10000, var10001::remove); - instances.remove(this.fallingblock); - } - - public FallingBlock getFallingBlock() { - return this.fallingblock; - } - - public CoreAbility getAbility() { - return this.ability; - } - - public Material getMaterial() { - return this.fallingblock.getBlockData().getMaterial(); - } - - public BlockData getMaterialData() { - return this.fallingblock.getBlockData(); - } - - public BlockData getData() { - return this.fallingblock.getBlockData(); - } - - public Location getLocation() { - return this.fallingblock.getLocation(); - } - - public long getCreationTime() { - return this.creation; - } - - public boolean canExpire() { - return this.expire; - } - - public void tryPlace() { - if (this.onPlace != null) { - this.onPlace.accept(this); - } - - } - - public Consumer getOnPlace() { - return this.onPlace; - } - - public void setOnPlace(Consumer onPlace) { - this.onPlace = onPlace; - } -} +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package com.jedk1.jedcore.util; + +import com.projectkorra.projectkorra.ability.CoreAbility; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.FallingBlock; +import org.bukkit.util.Vector; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +public class TempFallingBlock { + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap> instancesByAbility = new ConcurrentHashMap(); + private FallingBlock fallingblock; + private CoreAbility ability; + private long creation; + private boolean expire; + private Consumer onPlace; + + public TempFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability) { + this(location, data, velocity, ability, false); + } + + public TempFallingBlock(Location location, BlockData data, Vector velocity, CoreAbility ability, boolean expire) { + this.fallingblock = location.getWorld().spawnFallingBlock(location, data.clone()); + this.fallingblock.setVelocity(velocity); + this.fallingblock.setDropItem(false); + this.ability = ability; + this.creation = System.currentTimeMillis(); + this.expire = expire; + instances.put(this.fallingblock, this); + if (!instancesByAbility.containsKey(ability)) { + instancesByAbility.put(ability, new HashSet()); + } + + ((Set)instancesByAbility.get(ability)).add(this); + } + + public static void manage() { + long time = System.currentTimeMillis(); + + for(TempFallingBlock tfb : instances.values()) { + if (tfb.canExpire() && time > tfb.getCreationTime() + 5000L) { + tfb.remove(); + } else if (time > tfb.getCreationTime() + 120000L) { + tfb.remove(); + } + } + + } + + public static TempFallingBlock get(FallingBlock fallingblock) { + return isTempFallingBlock(fallingblock) ? (TempFallingBlock)instances.get(fallingblock) : null; + } + + public static boolean isTempFallingBlock(FallingBlock fallingblock) { + return instances.containsKey(fallingblock); + } + + public static void removeFallingBlock(FallingBlock fallingblock) { + if (isTempFallingBlock(fallingblock)) { + TempFallingBlock tempFallingBlock = (TempFallingBlock)instances.get(fallingblock); + Objects.requireNonNull(fallingblock); + ThreadUtil.ensureEntity(fallingblock, fallingblock::remove); + instances.remove(fallingblock); + ((Set)instancesByAbility.get(tempFallingBlock.ability)).remove(tempFallingBlock); + if (((Set)instancesByAbility.get(tempFallingBlock.ability)).isEmpty()) { + instancesByAbility.remove(tempFallingBlock.ability); + } + } + + } + + public static void removeAllFallingBlocks() { + for(FallingBlock fallingblock : instances.keySet()) { + Objects.requireNonNull(fallingblock); + ThreadUtil.ensureEntity(fallingblock, fallingblock::remove); + } + + instances.clear(); + instancesByAbility.clear(); + } + + public static Set getFromAbility(CoreAbility ability) { + return (Set)instancesByAbility.getOrDefault(ability, new HashSet()); + } + + public void remove() { + FallingBlock var10000 = this.fallingblock; + FallingBlock var10001 = this.fallingblock; + Objects.requireNonNull(var10001); + ThreadUtil.ensureEntity(var10000, var10001::remove); + instances.remove(this.fallingblock); + } + + public FallingBlock getFallingBlock() { + return this.fallingblock; + } + + public CoreAbility getAbility() { + return this.ability; + } + + public Material getMaterial() { + return this.fallingblock.getBlockData().getMaterial(); + } + + public BlockData getMaterialData() { + return this.fallingblock.getBlockData(); + } + + public BlockData getData() { + return this.fallingblock.getBlockData(); + } + + public Location getLocation() { + return this.fallingblock.getLocation(); + } + + public long getCreationTime() { + return this.creation; + } + + public boolean canExpire() { + return this.expire; + } + + public void tryPlace() { + if (this.onPlace != null) { + this.onPlace.accept(this); + } + + } + + public Consumer getOnPlace() { + return this.onPlace; + } + + public void setOnPlace(Consumer onPlace) { + this.onPlace = onPlace; + } +} diff --git a/src/util/TemporaryFallingBlock.java b/src/com/jedk1/jedcore/util/TemporaryFallingBlock.java similarity index 100% rename from src/util/TemporaryFallingBlock.java rename to src/com/jedk1/jedcore/util/TemporaryFallingBlock.java diff --git a/src/com/jedk1/jedcore/util/ThreadUtil.java b/src/com/jedk1/jedcore/util/ThreadUtil.java new file mode 100644 index 0000000..df4434d --- /dev/null +++ b/src/com/jedk1/jedcore/util/ThreadUtil.java @@ -0,0 +1,375 @@ +package com.jedk1.jedcore.util; + + + + +import com.cjcrafter.foliascheduler.TaskImplementation; +import com.cjcrafter.foliascheduler.folia.FoliaTask; +import com.jedk1.jedcore.JedCore; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import java.util.logging.Level; + +import static com.jedk1.jedcore.JedCore.*; + + +/** + * Utility class for ensuring that a task is run on the correct thread. + * Ensures compatibility between Folia and non-Folia servers. */ +public class ThreadUtil { + + private static AtomicBoolean SHUTTING_DOWN = new AtomicBoolean(false); + + public ThreadUtil(Plugin plugin) { + + } + + /** + * Runs a task on the same thread as an entity. On Spigot, this is the main + * thread. On Folia, this is the thread that the entity is on.

+ * + * @param entity The entity to run the task on. + * @param runnable The task to run. + */ + public static void ensureEntity(@NotNull Entity entity, @NotNull Runnable runnable) { + if (entity instanceof Player && !((Player)entity).isOnline()) return; + + if (isFolia()) { + if (scheduler.isOwnedByCurrentRegion(entity) || SHUTTING_DOWN.get()) { + runCatch(runnable, "Error in ensureEntity task on shutdown"); + return; + } + scheduler.entity(entity).execute(runnable, null, 1L); + } else { + if (Bukkit.isPrimaryThread()) { + runCatch(runnable, "Error in ensureEntity task"); + return; + } + Bukkit.getScheduler().runTask(plugin, runnable); + } + } + + /** + * Runs a task on the same thread as an entity after a delay. On Spigot, this is the main + * thread. On Folia, this is the thread that the entity is on. + * @param entity The entity to run the task on. + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static Object ensureEntityLater(@NotNull Entity entity, @NotNull Runnable runnable, long delay) { + if (entity instanceof Player && !((Player)entity).isOnline()) return null; + delay = Math.max(1, delay); + if (isFolia()) { + return scheduler.entity(entity).execute(runnable, null, delay); + } else { + return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); + } + } + + /** + * Runs a task on the same thread as an entity after a delay and repeats it until cancelled. + * On Spigot, this is the main thread. On Folia, this is the thread that the entity is on. + * @param entity The entity to run the task on. + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @param repeat The delay in ticks between each repeat of the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static Object ensureEntityTimer(@NotNull Entity entity, @NotNull Runnable runnable, long delay, long repeat) { + if (entity instanceof Player && !((Player)entity).isOnline()) return null; + delay = Math.max(1, delay); + repeat = Math.max(1, repeat); + if (isFolia()) { + return scheduler.entity(entity).runAtFixedRate((task) -> { + if (!runCatch(runnable, "Error in ensureEntityTimer task")) { + task.cancel(); + } + }, null, delay, repeat); + } else { + return Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, repeat); + } + } + + /** + * Runs a task on the same thread as a location. On Spigot, this is the main + * thread. On Folia, this is the thread that the location is in. + * @param location The location to run the task on. + * @param runnable The task to run. + */ + public static void ensureLocation(@NotNull Location location, @NotNull Runnable runnable) { + if (isFolia()) { + if (scheduler.isOwnedByCurrentRegion(location) || SHUTTING_DOWN.get()) { + runCatch(runnable, "Error in ensureLocation task on shutdown"); + return; + } + + scheduler.region(location).execute(runnable); + } else { + if (Bukkit.isPrimaryThread()) { + runCatch(runnable, "Error in ensureLocation task on shutdown"); + return; + } + Bukkit.getScheduler().runTask(plugin, runnable); + } + } + + /** + * Runs a task on the same thread as a location after a delay. On Spigot, this is the main + * thread. On Folia, this is the thread that the location is in. + * @param location The location to run the task on. + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static @NotNull Object ensureLocationLater(@NotNull Location location, @NotNull Runnable runnable, long delay) { + delay = Math.max(1, delay); + if (isFolia()) { + return scheduler.region(location).runDelayed((task) -> { + if (!runCatch(runnable, "Error in ensureLocationLater")) { + task.cancel(); + } + }, delay); + } else { + return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); + } + } + + /** + * Runs a task on the same thread as a location after a delay and repeats it until cancelled. + * On Spigot, this is the main thread. On Folia, this is the thread that the location is in. + * @param location The location to run the task on. + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @param repeat The delay in ticks between each repeat of the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static @NotNull Object ensureLocationTimer(@NotNull Location location, @NotNull Runnable runnable, long delay, long repeat) { + delay = Math.max(1, delay); + repeat = Math.max(1, repeat); + if (isFolia()) { + + return scheduler.region(location).runAtFixedRate((task) -> { + if (!runCatch(runnable, "Error in ensureLocationTimer task")) + task.cancel(); + }, delay, repeat); + } else { + return Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, repeat); + } + } + + /** + * Runs a task asynchronously. + * @param runnable The task to run. + */ + public static void runAsync(@NotNull Runnable runnable) { + if (isFolia()) { + if (SHUTTING_DOWN.get()) { + runCatch(runnable, "Error in runAsync task on shutdown"); + return; + } + + scheduler.async().runNow((task) -> { + if (!runCatch(runnable, "Error in runAsync task")) { + task.cancel(); + } + }); + } else { + Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable); + } + } + + /** + * Runs a task asynchronously after a delay. + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static @NotNull Object runAsyncLater(@NotNull Runnable runnable, long delay) { + delay = Math.max(1, delay); + if (isFolia()) { + return scheduler.async().runDelayed((task) -> { + if (!runCatch(runnable, "Error in runAsyncLater task")) { + task.cancel(); + } + }, delay * 50, TimeUnit.MILLISECONDS); + } else { + return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); + } + } + + /** + * Runs a task asynchronously after a delay and repeats it until cancelled. + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @param repeat The delay in ticks between each repeat of the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static @NotNull Object runAsyncTimer(@NotNull Runnable runnable, long delay, long repeat) { + delay = Math.max(1, delay); + if (isFolia()) { + return scheduler.async().runAtFixedRate((Consumer>) (task) -> runnable.run(), delay * 50, repeat * 50, TimeUnit.MILLISECONDS); + } else { + return Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, repeat); + } + } + + /** + * Runs a task synchronously. On Spigot, this is on the main thread. On Folia, + * this is on the global region thread.

+ * + * Warning: This should only be used for tasks that affect the world itself! Such as + * modifying gamerules, the weather, world time, etc. It should not be used for tasks + * that modify entities or the world, as those should be run using {@link #ensureEntity(Entity, Runnable)} + * or {@link #ensureLocation(Location, Runnable)}. + * + * @param runnable The task to run. + */ + public static void runGlobal(@NotNull Runnable runnable) { + if (isFolia()) { + if (SHUTTING_DOWN.get()) { + runCatch(runnable, "Error in runGlobal task on shutdown"); + return; + } + scheduler.global().run((task) -> { + if (!runCatch(runnable, "Error in runGlobal task")) { + task.cancel(); + } + }); + } else { + Bukkit.getScheduler().runTask(plugin, runnable); + } + } + + /** + * Runs a task synchronously after a delay. On Spigot, this is on the main thread. + * On Folia, this is on the global region thread.

+ * + * Warning: This should only be used for tasks that affect the world itself! Such as + * modifying gamerules, the weather, world time, etc. It should not be used for tasks + * that modify entities or the world, as those should be run using {@link #ensureEntityLater(Entity, Runnable, long)} + * or {@link #ensureLocationLater(Location, Runnable, long)}. + * + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static @NotNull Object runGlobalLater(@NotNull Runnable runnable, long delay) { + delay = Math.max(1, delay); + if (isFolia()) { + return scheduler.global().runDelayed((task) -> { + if (!runCatch(runnable, "Error in runGlobalLater task")) { + task.cancel(); + } + }, delay); + } else { + return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); + } + } + + /** + * Runs a task synchronously after a delay and repeats it until cancelled. + * On Spigot, this is on the main thread. On Folia, this is on the global region thread.

+ * + * Warning: This should only be used for tasks that affect the world itself! Such as + * modifying gamerules, the weather, world time, etc. It should not be used for tasks + * that modify entities or the world, as those should be run using + * {@link #ensureEntityTimer(Entity, Runnable, long, long)} + * or {@link #ensureLocationTimer(Location, Runnable, long, long)} + * + * @param runnable The task to run. + * @param delay The delay in ticks before running the task. + * @param repeat The delay in ticks between each repeat of the task. + * @return The task object that can be used to cancel the task. Is a + * {@link FoliaTask} on Folia and a + * {@link org.bukkit.scheduler.BukkitTask} on Spigot. + */ + public static @NotNull Object runGlobalTimer(@NotNull Runnable runnable, long delay, long repeat) { + delay = Math.max(1, delay); + if (isFolia()) { + return scheduler.global().runAtFixedRate((task) -> { + if (!runCatch(runnable, "Error in runGlobalTimer task")) { + task.cancel(); + } + }, delay, repeat); + } else { + return Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, repeat); + } + } + + /** + * Cancels a task that was created with either timers or delayed tasks. + * @param task The task to cancel. This is the object returned from + * {@link #ensureLocationTimer(Location, Runnable, long, long)} or + * {@link #ensureEntityTimer(Entity, Runnable, long, long)}. + * @return True if the task was cancelled successfully, false otherwise. + */ + public static boolean cancelTask(Object task) { + if (task == null) return false; + if (isFolia()) { + if (task instanceof FoliaTask) { + ((FoliaTask) task).cancel(); + return true; + } + } else { + if (task instanceof org.bukkit.scheduler.BukkitTask) { + ((org.bukkit.scheduler.BukkitTask) task).cancel(); + return true; + } + } + return false; + } + + /** + * Checks if a task is cancelled. + * @return True if the task is cancelled, false otherwise. + */ + public static boolean isTaskCancelled(Object task) { + if (task == null) return true; + if (isFolia()) { + if (task instanceof FoliaTask) { + return ((FoliaTask) task).isCancelled(); + } + } else { + if (task instanceof org.bukkit.scheduler.BukkitTask) { + return ((org.bukkit.scheduler.BukkitTask) task).isCancelled(); + } + } + return false; + } + + private static boolean runCatch(Runnable runnable, String error) { + try { + runnable.run(); + return true; + } catch (Exception e) { + JedCore.log.log(Level.WARNING, error, e); + return false; + } + } + + public static void shutdown() { + SHUTTING_DOWN.set(true); + } +} \ No newline at end of file diff --git a/src/util/ThrownEntityTracker.java b/src/com/jedk1/jedcore/util/ThrownEntityTracker.java similarity index 99% rename from src/util/ThrownEntityTracker.java rename to src/com/jedk1/jedcore/util/ThrownEntityTracker.java index a2ac646..9d98376 100644 --- a/src/util/ThrownEntityTracker.java +++ b/src/com/jedk1/jedcore/util/ThrownEntityTracker.java @@ -4,7 +4,6 @@ import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.Ability; import com.projectkorra.projectkorra.util.DamageHandler; - import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; diff --git a/src/util/versionadapter/ParticleAdapter.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter.java similarity index 100% rename from src/util/versionadapter/ParticleAdapter.java rename to src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter.java diff --git a/src/util/versionadapter/ParticleAdapterFactory.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapterFactory.java similarity index 100% rename from src/util/versionadapter/ParticleAdapterFactory.java rename to src/com/jedk1/jedcore/util/versionadapter/ParticleAdapterFactory.java diff --git a/src/util/versionadapter/ParticleAdapter_1_20_4.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_4.java similarity index 95% rename from src/util/versionadapter/ParticleAdapter_1_20_4.java rename to src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_4.java index 4d29090..d19b3f3 100644 --- a/src/util/versionadapter/ParticleAdapter_1_20_4.java +++ b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_4.java @@ -1,6 +1,7 @@ package com.jedk1.jedcore.util.versionadapter; -import org.bukkit.*; +import org.bukkit.Location; +import org.bukkit.Particle; public class ParticleAdapter_1_20_4 implements ParticleAdapter { diff --git a/src/util/versionadapter/ParticleAdapter_1_20_5.java b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_5.java similarity index 92% rename from src/util/versionadapter/ParticleAdapter_1_20_5.java rename to src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_5.java index 0813924..6c43638 100644 --- a/src/util/versionadapter/ParticleAdapter_1_20_5.java +++ b/src/com/jedk1/jedcore/util/versionadapter/ParticleAdapter_1_20_5.java @@ -1,6 +1,8 @@ package com.jedk1.jedcore.util.versionadapter; -import org.bukkit.*; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; public class ParticleAdapter_1_20_5 implements ParticleAdapter { @@ -23,4 +25,4 @@ private int[] hexToRgb(String hex) { Integer.valueOf(hex.substring(5, 7), 16) }; } -} +} \ No newline at end of file diff --git a/src/util/versionadapter/PotionEffectAdapter.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter.java similarity index 100% rename from src/util/versionadapter/PotionEffectAdapter.java rename to src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter.java diff --git a/src/util/versionadapter/PotionEffectAdapterFactory.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapterFactory.java similarity index 100% rename from src/util/versionadapter/PotionEffectAdapterFactory.java rename to src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapterFactory.java diff --git a/src/util/versionadapter/PotionEffectAdapter_1_20_4.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_4.java similarity index 100% rename from src/util/versionadapter/PotionEffectAdapter_1_20_4.java rename to src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_4.java diff --git a/src/util/versionadapter/PotionEffectAdapter_1_20_5.java b/src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_5.java similarity index 100% rename from src/util/versionadapter/PotionEffectAdapter_1_20_5.java rename to src/com/jedk1/jedcore/util/versionadapter/PotionEffectAdapter_1_20_5.java diff --git a/src/util/versionadapter/PotionMetaUtil.java b/src/com/jedk1/jedcore/util/versionadapter/PotionMetaUtil.java similarity index 100% rename from src/util/versionadapter/PotionMetaUtil.java rename to src/com/jedk1/jedcore/util/versionadapter/PotionMetaUtil.java diff --git a/src/listener/AbilityListener.java b/src/listener/AbilityListener.java deleted file mode 100644 index 91d7590..0000000 --- a/src/listener/AbilityListener.java +++ /dev/null @@ -1,569 +0,0 @@ -package com.jedk1.jedcore.listener; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.ability.airbending.AirBlade; -import com.jedk1.jedcore.ability.airbending.AirBreath; -import com.jedk1.jedcore.ability.airbending.AirGlide; -import com.jedk1.jedcore.ability.airbending.AirPunch; -import com.jedk1.jedcore.ability.airbending.Meditate; -import com.jedk1.jedcore.ability.airbending.SonicBlast; -import com.jedk1.jedcore.ability.avatar.SpiritBeam; -import com.jedk1.jedcore.ability.avatar.elementsphere.ElementSphere; -import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; -import com.jedk1.jedcore.ability.earthbending.EarthKick; -import com.jedk1.jedcore.ability.earthbending.EarthLine; -import com.jedk1.jedcore.ability.earthbending.EarthPillar; -import com.jedk1.jedcore.ability.earthbending.EarthShard; -import com.jedk1.jedcore.ability.earthbending.EarthSurf; -import com.jedk1.jedcore.ability.earthbending.Fissure; -import com.jedk1.jedcore.ability.earthbending.LavaDisc; -import com.jedk1.jedcore.ability.earthbending.LavaFlux; -import com.jedk1.jedcore.ability.earthbending.LavaThrow; -import com.jedk1.jedcore.ability.earthbending.MagnetShield; -import com.jedk1.jedcore.ability.earthbending.MetalArmor; -import com.jedk1.jedcore.ability.earthbending.MetalFragments; -import com.jedk1.jedcore.ability.earthbending.MetalHook; -import com.jedk1.jedcore.ability.earthbending.MetalShred; -import com.jedk1.jedcore.ability.earthbending.MudSurge; -import com.jedk1.jedcore.ability.earthbending.SandBlast; -import com.jedk1.jedcore.ability.earthbending.combo.Crevice; -import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; -import com.jedk1.jedcore.ability.firebending.Combustion; -import com.jedk1.jedcore.ability.firebending.Discharge; -import com.jedk1.jedcore.ability.firebending.FireBall; -import com.jedk1.jedcore.ability.firebending.FireBreath; -import com.jedk1.jedcore.ability.firebending.FireComet; -import com.jedk1.jedcore.ability.firebending.FirePunch; -import com.jedk1.jedcore.ability.firebending.FireShots; -import com.jedk1.jedcore.ability.firebending.FireSki; -import com.jedk1.jedcore.ability.firebending.LightningBurst; -import com.jedk1.jedcore.ability.passive.WallRun; -import com.jedk1.jedcore.ability.waterbending.*; -import com.jedk1.jedcore.ability.waterbending.combo.WaterFlow; -import com.jedk1.jedcore.ability.waterbending.combo.WaterGimbal; -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ProjectKorra; -import com.projectkorra.projectkorra.ability.AirAbility; -import com.projectkorra.projectkorra.ability.AvatarAbility; -import com.projectkorra.projectkorra.ability.ChiAbility; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.ability.FireAbility; -import com.projectkorra.projectkorra.ability.WaterAbility; -import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; -import com.projectkorra.projectkorra.airbending.Suffocate; -import com.projectkorra.projectkorra.earthbending.EarthArmor; -import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; -import com.projectkorra.projectkorra.firebending.FireJet; -import com.projectkorra.projectkorra.util.MovementHandler; -import com.projectkorra.projectkorra.waterbending.blood.Bloodbending; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerAnimationEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerToggleSneakEvent; -import org.bukkit.inventory.EquipmentSlot; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class AbilityListener implements Listener { - - JedCore plugin; - - public AbilityListener(JedCore plugin) { - this.plugin = plugin; - } - - private final List recentlyDropped = new ArrayList<>(); - - @EventHandler(priority = EventPriority.LOWEST) - // Abilities that should bypass punch cancels should be handled here. - public void onPlayerSwingBypassCancel(PlayerInteractEvent event) { - Player player = event.getPlayer(); - if (event.getHand() != EquipmentSlot.HAND) { - return; - } - if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { - return; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null) { - return; - } - - if (Suffocate.isBreathbent(player) || bPlayer.isChiBlocked()) { - return; - } - - if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { - return; - } - - CoreAbility coreAbil = bPlayer.getBoundAbility(); - if (coreAbil == null) { - return; - } - - if (!bPlayer.canBendIgnoreCooldowns(coreAbil)) { - return; - } - - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { - return; - } - - // FireSki bypasses punch cancel because the normal version is activated from sneaking alone. - // The punch activation exists just so people don't accidentally activate it, so they should have the same - // requirements for activation. - if (coreAbil instanceof FireJet && FireSki.isPunchActivated(player.getWorld())) { - if (player.isSneaking()) { - FireSki ski = new FireSki(player); - if (ski.isStarted() && !bPlayer.isOnCooldown("FireJet")) { - // The event only needs to be cancelled when FireSki is set to have no cooldown. - // This is to prevent FireJet from activating from the same swing event. - event.setCancelled(true); - } - } - } - } - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerDropItemEvent(PlayerDropItemEvent event) { - recentlyDropped.add(event.getPlayer().getUniqueId()); - Bukkit.getScheduler().runTaskLater(ProjectKorra.plugin, () -> recentlyDropped.remove(event.getPlayer().getUniqueId()), 2L); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerInventoryInteract(InventoryClickEvent event) { - InventoryAction action = event.getAction(); - if (action == InventoryAction.DROP_ALL_CURSOR || - action == InventoryAction.DROP_ALL_SLOT || - action == InventoryAction.DROP_ONE_CURSOR || - action == InventoryAction.DROP_ONE_SLOT || - action == InventoryAction.UNKNOWN) { - - recentlyDropped.add(event.getWhoClicked().getUniqueId()); - - Bukkit.getScheduler().runTaskLater(ProjectKorra.plugin, () -> { - recentlyDropped.remove(event.getWhoClicked().getUniqueId()); - }, 2L); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerSwing(PlayerInteractEvent event) { - Player player = event.getPlayer(); - - if (recentlyDropped.contains(player.getUniqueId())) return; - - if (event.getHand() != EquipmentSlot.HAND) { - return; - } - if (event.getAction() != Action.LEFT_CLICK_BLOCK && event.getAction() != Action.LEFT_CLICK_AIR) { - return; - } - if (event.getAction() == Action.LEFT_CLICK_BLOCK && event.isCancelled()){ - return; - } - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null) { - return; - } - - if (Suffocate.isBreathbent(player)) { - event.setCancelled(true); - return; - } else if (Bloodbending.isBloodbent(player) || MovementHandler.isStopped(player)) { - event.setCancelled(true); - return; - } else if (bPlayer.isChiBlocked()) { - event.setCancelled(true); - return; - } else if (GeneralMethods.isInteractable(player.getTargetBlock((Set)null, 5))) { - return; - } - - if (bPlayer.isToggled()) { - new WallRun(player); - } - - CoreAbility coreAbil = bPlayer.getBoundAbility(); - if (coreAbil == null) { - if (MultiAbilityManager.hasMultiAbilityBound(player)){ - String abil = MultiAbilityManager.getBoundMultiAbility(player); - if (abil.equalsIgnoreCase("elementsphere")) { - new ElementSphere(player); - } - } - return; - } - - String abilName = bPlayer.getBoundAbilityName(); - Class abilClass = coreAbil.getClass(); - - if (bPlayer.canBendIgnoreCooldowns(coreAbil)) { - - if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(AirBlade.class)) { - new AirBlade(player); - } - if (abilClass.equals(AirPunch.class)) { - new AirPunch(player); - } - } - - if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(EarthArmor.class)) { - new MetalArmor(player); - } - if (abilClass.equals(EarthLine.class)) { - EarthLine.shootLine(player); - } - if (abilClass.equals(EarthShard.class)) { - for (EarthShard shard : CoreAbility.getAbilities(player, EarthShard.class)) { - shard.throwShard(); // call the instance method - } - } - if (abilClass.equals(EarthSurf.class)) { - new EarthSurf(player); - } - if (abilClass.equals(Fissure.class)) { - new Fissure(player); - } - if (abilClass.equals(LavaFlux.class)) { - new LavaFlux(player); - } - if (abilClass.equals(LavaThrow.class)) { - LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); - if (lt != null) { - lt.createBlast(); - } - } - if (abilClass.equals(MetalFragments.class)) { - MetalFragments.shootFragment(player); - } - if (abilClass.equals(MetalHook.class)) { - new MetalHook(player); - } - if (abilClass.equals(MetalShred.class)) { - MetalShred.extend(player); - } - if (abilClass.equals(MudSurge.class)) { - MudSurge.mudSurge(player); - } - if (abilClass.equals(SandBlast.class)) { - SandBlast.blastSand(player); - } - if (abilClass.equals(LavaFlow.class)) { - MagmaBlast.performAction(player); - } - if (abilClass.equals(MagnetShield.class)) { - new MagnetShield(player, true); - } - } - - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(Combustion.class)) { - Combustion.combust(player); - } - if (abilClass.equals(Discharge.class)) { - new Discharge(player); - } - if (abilClass.equals(FireBall.class)) { - new FireBall(player); - } - if (abilClass.equals(FirePunch.class)) { - new FirePunch(player); - } - if (abilClass.equals(FireShots.class)) { - FireShots.fireShot(player); - } - } - - if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.WATER.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { - com.jedk1.jedcore.ability.waterbending.Bloodbending.launch(player); - } - if (abilClass.equals(BloodPuppet.class)) { - BloodPuppet.attack(player); - } - if (abilClass.equals(BloodShot.class)) { - new BloodShot(player); - } - if (abilClass.equals(IceClaws.class)) { - IceClaws.throwClaws(player); - } - if (abilName.equals("Drain")) { - Drain.fireBlast(player); - } - if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { - WaterGimbal.prepareBlast(player); - } - if (coreAbil.getName().equalsIgnoreCase("watermanipulation")) { - WaterFlow.freeze(player); - } - } - if (coreAbil instanceof ChiAbility && bPlayer.isElementToggled(Element.CHI)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Chi.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(DaggerThrow.class)) { - new DaggerThrow(player); - } - } - - if (coreAbil instanceof AvatarAbility) { - if (abilClass.equals(ElementSphere.class)) { - new ElementSphere(player); - } - } - } - } - - public static ConcurrentHashMap recent = new ConcurrentHashMap(); - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerSneak(PlayerToggleSneakEvent event) { - Player player = event.getPlayer(); - BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - - if (event.isCancelled() || bPlayer == null) { - return; - } - - String abilName = bPlayer.getBoundAbilityName(); - if (Suffocate.isBreathbent(player)) { - if (!abilName.equalsIgnoreCase("AirSwipe") - && !abilName.equalsIgnoreCase("FireBlast") - && !abilName.equalsIgnoreCase("EarthBlast") - && !abilName.equalsIgnoreCase("WaterManipulation")) { - if(!player.isSneaking()) { - event.setCancelled(true); - } - } - } - - if (MovementHandler.isStopped(player) || Bloodbending.isBloodbent(player)) { - event.setCancelled(true); - return; - } - - CoreAbility coreAbil = bPlayer.getBoundAbility(); - if (coreAbil == null) { - return; - } - - Class abilClass = coreAbil.getClass(); - - if (bPlayer.isChiBlocked()) { - event.setCancelled(true); - return; - } - - if (player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (abilClass.equals(FireShots.class)) { - FireShots.swapHands(player); - } - - if (abilClass.equals(FirePunch.class)) { - FirePunch.swapHands(player); - } - } - } - - if (!player.isSneaking() && bPlayer.canBendIgnoreCooldowns(coreAbil)) { - if (coreAbil instanceof AirAbility && bPlayer.isElementToggled(Element.AIR)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(AirBreath.class)) { - new AirBreath(player); - } - if (abilClass.equals(AirGlide.class)) { - new AirGlide(player); - } - if (abilClass.equals(Meditate.class)) { - new Meditate(player); - } - if (abilClass.equals(SonicBlast.class)) { - new SonicBlast(player); - } - } - - if (coreAbil instanceof EarthAbility && bPlayer.isElementToggled(Element.EARTH)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(EarthKick.class)) { - new EarthKick(player); - } - if (abilClass.equals(EarthLine.class)) { - new EarthLine(player); - } - if (abilClass.equals(EarthPillar.class)) { - new EarthPillar(player); - } - if (abilClass.equals(EarthShard.class)) { - new EarthShard(player); - } - if (abilClass.equals(Fissure.class)) { - Fissure.performAction(player); - } - if (abilClass.equals(LavaDisc.class)) { - new LavaDisc(player); - } - if (abilClass.equals(MagnetShield.class)) { - new MagnetShield(player, false); - } - if (abilClass.equals(MetalFragments.class)) { - new MetalFragments(player); - } - if (abilClass.equals(MetalShred.class)) { - new MetalShred(player); - } - if (abilClass.equals(MudSurge.class)) { - new MudSurge(player); - } - if (abilClass.equals(SandBlast.class)) { - new SandBlast(player); - } - if (abilClass.equals(Crevice.class)) { - Crevice.closeCrevice(player); - } - if (abilClass.equals(LavaThrow.class)) { - LavaThrow lt = CoreAbility.getAbility(player, LavaThrow.class); - if (lt == null) { - new LavaThrow(player); - } - } - } - - if (coreAbil instanceof FireAbility && bPlayer.isElementToggled(Element.FIRE)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(Combustion.class)) { - new Combustion(event.getPlayer()); - } - if (abilClass.equals(FireBreath.class)) { - new FireBreath(player); - } - if (abilClass.equals(FireComet.class)) { - new FireComet(player); - } - if (abilClass.equals(FireJet.class)) { - if (FireSki.isPunchActivated(player.getWorld())) { - FireSki fs = CoreAbility.getAbility(player, FireSki.class); - - if (fs != null) { - fs.remove(); - } - } else { - new FireSki(player); - } - } - if (abilClass.equals(FireShots.class)) { - new FireShots(player); - } - if (abilClass.equals(LightningBurst.class)) { - new LightningBurst(player); - } - } - - if (coreAbil instanceof WaterAbility && bPlayer.isElementToggled(Element.WATER)) { - if (GeneralMethods.isWeapon(player.getInventory().getItemInMainHand().getType()) && !ProjectKorra.plugin.getConfig().getBoolean("Properties.Water.CanBendWithWeapons")) { - return; - } - if (abilClass.equals(com.jedk1.jedcore.ability.waterbending.Bloodbending.class)) { - new com.jedk1.jedcore.ability.waterbending.Bloodbending(player); - } - if (abilClass.equals(BloodPuppet.class)) { - new BloodPuppet(player); - } - if (abilClass.equals(FrostBreath.class)) { - new FrostBreath(player); - } - if (abilClass.equals(IceClaws.class)) { - new IceClaws(player); - IceClaws.swapHands(player); - } - if (abilClass.equals(IceWall.class)) { - new IceWall(player); - } - if (abilName.equals("Drain")) { - new Drain(player); - } - if (abilClass.equals(WakeFishing.class)) { - new WakeFishing(player); - } - } - - if (coreAbil instanceof AvatarAbility) { - if (abilClass.equals(SpiritBeam.class)) { - new SpiritBeam(player); - } - } - } - } - - @EventHandler - public void onArrowHit(EntityDamageByEntityEvent event) { - if (event.getDamager().getType() == EntityType.ARROW) { - Arrow arrow = (Arrow) event.getDamager(); - if (arrow.getShooter() instanceof Player && arrow.hasMetadata("daggerthrow")) { - Player player = (Player) arrow.getShooter(); - event.setDamage(0.0D); - player.playSound(player.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 1.0f, 1.0f); - } - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerInteraction(PlayerInteractEvent event) { - if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { - MetalFragments.shootFragment(event.getPlayer()); - } - } - - @EventHandler - public void onChange(EntityChangeBlockEvent event) { - if (event.getEntity() instanceof FallingBlock) { - if (event.getEntity().hasMetadata("magmablast")) event.setCancelled(true); - } - } -} diff --git a/src/listener/CommandListener.java b/src/listener/CommandListener.java deleted file mode 100644 index 1bfb5a2..0000000 --- a/src/listener/CommandListener.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.jedk1.jedcore.listener; - -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.command.JedCoreCommand; -import com.jedk1.jedcore.event.PKCommandEvent; -import com.jedk1.jedcore.event.PKCommandEvent.CommandType; -import com.projectkorra.projectkorra.command.PKCommand; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; - -import java.util.Arrays; -import java.util.Objects; -import java.util.UUID; - -public class CommandListener implements Listener { - - private final JedCore plugin; - private static final String[] CMD_ALIASES = { - "/bending", "/bend", "/b", "/pk", "/projectkorra", "/korra", "/mtla", "/tla" - }; - public static final String[] DEVELOPERS = { - "4eb6315e-9dd1-49f7-b582-c1170e497ab0", // jedk1 - "d57565a5-e6b0-44e3-a026-979d5de10c4d", // s3xi - "e98a2f7d-d571-4900-a625-483cbe6774fe", // Aztl - "b6bd2ceb-4922-4707-9173-8a02044e9069", // Cozmyc - "b1318b21-5956-445c-a328-bad3175c1c7a" // Hihelloy - }; - - public CommandListener(JedCore plugin) { - this.plugin = plugin; - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerCommand(PlayerCommandPreprocessEvent event) { - String cmd = event.getMessage().toLowerCase(); - String[] args = cmd.split("\\s+"); - if (Arrays.asList(CMD_ALIASES).contains(args[0]) && args.length >= 2) { - PKCommandEvent newEvent = new PKCommandEvent(event.getPlayer(), args, null); - for (PKCommand command : PKCommand.instances.values()) { - if (Arrays.asList(command.getAliases()).contains(args[1].toLowerCase())) { - newEvent = new PKCommandEvent(event.getPlayer(), args, CommandType.getType(command.getName())); - break; - } - } - Bukkit.getServer().getPluginManager().callEvent(newEvent); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPKCommand(final PKCommandEvent event) { - // Run task using Paper/Folia-compatible scheduler API - plugin.getServer().getScheduler().runTask(plugin, () -> { - if (event.getType() != null) { - if (event.getType().equals(CommandType.WHO) && event.getSender().hasPermission("bending.command.who")) { - if (event.getArgs().length == 3) { - if (Bukkit.getPlayer(event.getArgs()[2]) != null) { - UUID uuid = Objects.requireNonNull(Bukkit.getPlayer(event.getArgs()[2])).getUniqueId(); - if (Arrays.asList(DEVELOPERS).contains(uuid.toString())) { - event.getSender().sendMessage(ChatColor.DARK_AQUA + "JedCore Developer"); - } - } - } - return; - } - if (event.getType().equals(CommandType.VERSION) && event.getSender().hasPermission("bending.command.version")) { - JedCoreCommand.sendBuildInfo(event.getSender()); - } - } - }); - } -} diff --git a/src/listener/JCListener.java b/src/listener/JCListener.java deleted file mode 100644 index 4ac8166..0000000 --- a/src/listener/JCListener.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.jedk1.jedcore.listener; - -import com.jedk1.jedcore.JCMethods; -import com.jedk1.jedcore.JedCore; -import com.jedk1.jedcore.ability.chiblocking.Backstab; -import com.jedk1.jedcore.ability.chiblocking.DaggerThrow; -import com.jedk1.jedcore.ability.earthbending.*; -import com.jedk1.jedcore.ability.earthbending.combo.MagmaBlast; -import com.jedk1.jedcore.ability.firebending.FireBreath; -import com.jedk1.jedcore.ability.firebending.FirePunch; -import com.jedk1.jedcore.ability.firebending.FireSki; -import com.jedk1.jedcore.ability.waterbending.IceClaws; -import com.jedk1.jedcore.ability.waterbending.IceWall; -import com.jedk1.jedcore.util.LightManager; -import com.jedk1.jedcore.util.RegenTempBlock; -import com.projectkorra.projectkorra.ProjectKorra; -import com.projectkorra.projectkorra.ability.CoreAbility; -import com.projectkorra.projectkorra.ability.IceAbility; -import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; -import com.projectkorra.projectkorra.event.*; - -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.TempBlock; -import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.*; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.inventory.InventoryPickupItemEvent; -import org.bukkit.event.player.*; -import org.bukkit.scheduler.BukkitRunnable; - -public class JCListener implements Listener { - - JedCore plugin; - - public JCListener(JedCore plugin) { - this.plugin = plugin; - } - - @EventHandler - public void onAbilityStart(AbilityStartEvent event) { - if (event.isCancelled()) return; - - if (event.getAbility() instanceof LavaFlow) { - Player player = event.getAbility().getPlayer(); - MagmaBlast mb = CoreAbility.getAbility(player, MagmaBlast.class); - - if (mb != null && (mb.hasBlocks() || mb.shouldBlockLavaFlow())) { - event.setCancelled(true); - LavaFlow flow = (LavaFlow) event.getAbility(); - - // Reset the cooldown of LavaFlow that was set before the call to start(). - flow.getBendingPlayer().removeCooldown(flow); - } - } else if (event.getAbility() instanceof PlantRegrowth) { - PlantRegrowth regrowth = (PlantRegrowth)event.getAbility(); - - // Stop PlantRegrowth from creating permanent snow when used against FrostBreath snow. - if (regrowth.getType() == Material.SNOW && TempBlock.isTempBlock(regrowth.getBlock())) { - event.setCancelled(true); - } - } - } - - @EventHandler - public void onFlow(BlockFromToEvent event) { - if (!LavaDisc.canFlowFrom(event.getBlock())) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.LOW) - public void onPlayerFallDamage(EntityDamageEvent event) { - if (event.isCancelled() || event.getCause() != DamageCause.FALL || !(event.getEntity() instanceof Player)) { - return; - } - - Player player = (Player)event.getEntity(); - - if (MudSurge.onFallDamage(player)) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onEntityDamage(EntityDamageEvent event) { - if (event.getCause().equals(DamageCause.SUFFOCATION)) { - if (event.getEntity() instanceof LivingEntity) { - LivingEntity entity = (LivingEntity) event.getEntity(); - Block block = entity.getEyeLocation().getBlock(); - if (RegenTempBlock.blocks.containsKey(block) && IceAbility.isIce(block)) { - event.setCancelled(true); - return; - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { - if (event.getDamager() instanceof Player && event.getEntity() instanceof LivingEntity) { - if (event.getCause() == DamageCause.ENTITY_ATTACK && event.getDamager().getWorld().equals(event.getEntity().getWorld())) { - double distSq = event.getDamager().getLocation().distanceSquared(event.getEntity().getLocation()); - - // Only activate these in melee range - if (distSq <= 5 * 5) { - FirePunch fp = CoreAbility.getAbility((Player) event.getDamager(), FirePunch.class); - if (fp != null) { - fp.punch((LivingEntity) event.getEntity()); - event.setCancelled(true); - return; - } - - if (Backstab.punch((Player) event.getDamager(), (LivingEntity) event.getEntity())) { - event.setCancelled(true); - double damage = Backstab.getDamage(event.getDamager().getWorld()); - DamageHandler.damageEntity(event.getEntity(), (Player) event.getDamager(), damage, CoreAbility.getAbility("BackStab")); - return; - } - } - } - - if (IceClaws.freezeEntity((Player) event.getDamager(), (LivingEntity) event.getEntity())) { - event.setCancelled(true); - return; - } - } - - if (event.getDamager() instanceof Arrow arrow) { - if (event.getEntity() instanceof LivingEntity) { - if (arrow.hasMetadata("daggerthrow")) { - event.setDamage(0); - if (!(arrow.getShooter() instanceof Player shooter)) return; - if (!CoreAbility.hasAbility(shooter, DaggerThrow.class)) return; - DaggerThrow daggerThrow = CoreAbility.getAbility(shooter, DaggerThrow.class); - if (daggerThrow != null) { - daggerThrow.damageEntityFromArrow(((LivingEntity) event.getEntity()), arrow); - arrow.remove(); - event.setCancelled(true); - } - } - if (arrow.hasMetadata("metalhook")) { - event.setDamage(0); - arrow.remove(); - event.setCancelled(true); - } - } - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onBlockBreak(BlockBreakEvent event) { - MetalFragments.remove(event.getPlayer(), event.getBlock()); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onEntityExplode(EntityExplodeEvent event){ - if (IceWall.checkExplosions(event.getLocation(), event.getEntity())) { - event.blockList().clear(); - } - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onCollisionWithEntity(HorizontalVelocityChangeEvent event) { - if (event.getEntity().getWorld() != event.getInstigator().getWorld()) { - return; - } - IceWall.collisionDamage(event.getEntity(), event.getDistanceTraveled(), event.getDifference(), event.getInstigator()); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onPlayerSprint(PlayerToggleSprintEvent event) { - if (!event.isSprinting()) - return; - - if (CoreAbility.hasAbility(event.getPlayer(), EarthSurf.class)) { - event.setCancelled(true); - return; - } - - if (CoreAbility.hasAbility(event.getPlayer(), FireSki.class)) { - event.setCancelled(true); - return; - } - - MetalShred.startShred(event.getPlayer()); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void projectKorraReload(BendingReloadEvent event) { - final CommandSender sender = event.getSender(); - LightManager.get().restart(); - // There's a PK bug where a new collision manager is set on reload without stopping the old task. - ProjectKorra.getCollisionManager().stopCollisionDetection(); - new BukkitRunnable() { - public void run() { - JCMethods.reload(); - sender.sendMessage(ChatColor.DARK_AQUA + "JedCore config reloaded."); - } - }.runTaskLater(JedCore.plugin, 1); - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onChat(AsyncPlayerChatEvent event){ - Player player = event.getPlayer(); - String msg = event.getMessage(); - - if (msg.toLowerCase().contains("bring fire and light together as one and allow the breath of color")) { - FireBreath.toggleRainbowBreath(player, true); - event.setCancelled(true); - } - - if (msg.toLowerCase().contains("split the bond of fire and light and set the color free")) { - FireBreath.toggleRainbowBreath(player, false); - event.setCancelled(true); - } - - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onItemPickup(InventoryPickupItemEvent event) { - if (event.getItem().getPickupDelay() >= Short.MAX_VALUE) { - event.setCancelled(true); - } - } -} diff --git a/src/plugin.yml b/src/plugin.yml index 5eb7f75..4941424 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -5,7 +5,6 @@ authors: ['jedk1'] depend: [ProjectKorra] folia-supported: true api-version: '1.20' -load: POSTWORLD description: "A cool ProjectKorra addon plugin" permissions: diff --git a/src/util/PaperLib.java b/src/util/PaperLib.java deleted file mode 100644 index 1a00a91..0000000 --- a/src/util/PaperLib.java +++ /dev/null @@ -1,96 +0,0 @@ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by FernFlower decompiler) -// - -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.JedCore; -import java.util.concurrent.CompletableFuture; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; - -public class PaperLib { - private static Environment ENVIRONMENT; - - public static CompletableFuture getChunkAtAsync(Location location) { - return ENVIRONMENT.getChunkAtAsync(location); - } - - public static CompletableFuture getChunkAtAsync(Block block) { - return ENVIRONMENT.getChunkAtAsync(block); - } - - public static CompletableFuture teleportAsync(Entity entity, Location location) { - return ENVIRONMENT.teleportAsync(entity, location); - } - - public static CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { - return ENVIRONMENT.teleportAsync(entity, location, cause); - } - - static { - if (JedCore.isFolia()) { - ENVIRONMENT = new Folia(); - } else if (JedCore.isPaper()) { - ENVIRONMENT = new Paper(); - } else { - ENVIRONMENT = new Spigot(); - } - - } - - private interface Environment { - default CompletableFuture getChunkAtAsync(Location location) { - return this.getChunkAtAsync(location.getBlock()); - } - - CompletableFuture getChunkAtAsync(Block var1); - - default CompletableFuture teleportAsync(Entity entity, Location location) { - return this.teleportAsync(entity, location, TeleportCause.PLUGIN); - } - - CompletableFuture teleportAsync(Entity var1, Location var2, PlayerTeleportEvent.TeleportCause var3); - } - - static class Spigot implements Environment { - public CompletableFuture getChunkAtAsync(Block block) { - return CompletableFuture.completedFuture(block.getChunk()); - } - - public CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { - entity.teleport(location, cause); - return CompletableFuture.completedFuture(true); - } - } - - static class Paper implements Environment { - public CompletableFuture getChunkAtAsync(Block block) { - return block.getWorld().getChunkAtAsync(block); - } - - public CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { - return entity.teleportAsync(location, cause); - } - } - - static class Folia implements Environment { - public CompletableFuture getChunkAtAsync(Block block) { - CompletableFuture future = new CompletableFuture(); - ThreadUtil.ensureLocation(block.getLocation(), () -> { - Chunk chunk = block.getWorld().getChunkAt(block); - future.complete(chunk); - }); - return future; - } - - public CompletableFuture teleportAsync(Entity entity, Location location, PlayerTeleportEvent.TeleportCause cause) { - return entity.teleportAsync(location, cause); - } - } -} diff --git a/src/util/ThreadUtil.java b/src/util/ThreadUtil.java deleted file mode 100644 index ffd46d7..0000000 --- a/src/util/ThreadUtil.java +++ /dev/null @@ -1,209 +0,0 @@ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by FernFlower decompiler) -// - -package com.jedk1.jedcore.util; - -import com.jedk1.jedcore.JedCore; -import io.papermc.paper.threadedregions.scheduler.RegionScheduler; -import io.papermc.paper.threadedregions.scheduler.ScheduledTask; - -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.scheduler.BukkitTask; -import org.jetbrains.annotations.NotNull; - -public class ThreadUtil { - - public static void ensureMainThread(Runnable runnable) { - if (Bukkit.isPrimaryThread()) { - runnable.run(); - } else { - throw new IllegalStateException("Runnable must be called from the main thread in Folia/Paper"); - } - } - - public static T EnsureMainThread(Callable supplier) { - if (Bukkit.isPrimaryThread()) { - try { - return supplier.call(); - } catch (Exception e) { - throw new RuntimeException("Failed to get value on main thread", e); - } - } else { - throw new IllegalStateException("Must be called from the main thread in Folia/Paper"); - } - } - - public static T ensureMainThread2(Supplier supplier) { - if (Bukkit.isPrimaryThread()) { - return supplier.get(); - } else { - throw new IllegalStateException("Operation must be performed on the main thread."); - } - } - - public static void ensureEntity(Entity entity, Runnable runnable) { - if (JedCore.isFolia()) { - if (Bukkit.isOwnedByCurrentRegion(entity) || Bukkit.isStopping()) { - runnable.run(); - return; - } - - entity.getScheduler().execute(JedCore.plugin, runnable, (Runnable)null, 1L); - } else { - if (Bukkit.isPrimaryThread()) { - runnable.run(); - return; - } - - Bukkit.getScheduler().runTask(JedCore.plugin, runnable); - } - - } - - public static void ensureEntityDelay(Entity entity, Runnable runnable, long delay) { - delay = Math.max(1L, delay); - if (JedCore.isFolia()) { - entity.getScheduler().execute(JedCore.plugin, runnable, (Runnable)null, delay); - } else { - Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); - } - - } - - public static Object ensureEntityTimer(Entity entity, Runnable runnable, long delay, long repeat) { - delay = Math.max(1L, delay); - return JedCore.isFolia() ? entity.getScheduler().runAtFixedRate(JedCore.plugin, (task) -> runnable.run(), (Runnable)null, delay, repeat) : Bukkit.getScheduler().runTaskTimer(JedCore.plugin, runnable, delay, repeat); - } - - public static void ensureLocation(Location location, Runnable runnable) { - if (JedCore.isFolia()) { - if (Bukkit.isOwnedByCurrentRegion(location) || Bukkit.isStopping()) { - runnable.run(); - return; - } - - RegionScheduler scheduler = Bukkit.getRegionScheduler(); - scheduler.execute(JedCore.plugin, location, runnable); - } else { - if (Bukkit.isPrimaryThread()) { - runnable.run(); - return; - } - - Bukkit.getScheduler().runTask(JedCore.plugin, runnable); - } - - } - - public static void ensureLocationDelay(@NotNull Location location, Runnable runnable, long delay) { - delay = Math.max(1L, delay); - if (JedCore.isFolia()) { - RegionScheduler scheduler = Bukkit.getRegionScheduler(); - scheduler.runDelayed(JedCore.plugin, location, (task) -> runnable.run(), delay); - } else { - Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); - } - - } - - public static Object ensureLocationTimer(Location location, Runnable runnable, long delay, long repeat) { - delay = Math.max(1L, delay); - if (JedCore.isFolia()) { - RegionScheduler scheduler = Bukkit.getRegionScheduler(); - return scheduler.runAtFixedRate(JedCore.plugin, location, (task) -> runnable.run(), delay, repeat); - } else { - return Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); - } - } - - public static void runAsync(Runnable runnable) { - if (JedCore.isFolia()) { - if (Bukkit.isStopping()) { - runnable.run(); - return; - } - - Bukkit.getAsyncScheduler().runNow(JedCore.plugin, (task) -> runnable.run()); - } else { - Bukkit.getScheduler().runTaskAsynchronously(JedCore.plugin, runnable); - } - - } - - public static void runAsyncLater(Runnable runnable, long delay) { - delay = Math.max(1L, delay); - if (JedCore.isFolia()) { - Bukkit.getAsyncScheduler().runDelayed(JedCore.plugin, (task) -> runnable.run(), delay * 50L, TimeUnit.MILLISECONDS); - } else { - Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); - } - - } - - public static Object runAsyncTimer(Runnable runnable, long delay, long repeat) { - delay = Math.max(1L, delay); - return JedCore.isFolia() ? Bukkit.getAsyncScheduler().runAtFixedRate(JedCore.plugin, (task) -> runnable.run(), delay * 50L, repeat * 50L, TimeUnit.MILLISECONDS) : Bukkit.getScheduler().runTaskTimerAsynchronously(JedCore.plugin, runnable, delay, repeat); - } - - public static void runSync(Runnable runnable) { - if (JedCore.isFolia()) { - if (Bukkit.isStopping()) { - runnable.run(); - return; - } - - Bukkit.getGlobalRegionScheduler().run(JedCore.plugin, (task) -> runnable.run()); - } else { - Bukkit.getScheduler().runTask(JedCore.plugin, runnable); - } - - } - - public static Object runSyncLater(Runnable runnable, long delay) { - delay = Math.max(1L, delay); - return JedCore.isFolia() ? Bukkit.getGlobalRegionScheduler().runDelayed(JedCore.plugin, (task) -> runnable.run(), delay) : Bukkit.getScheduler().runTaskLater(JedCore.plugin, runnable, delay); - } - - public static Object runSyncTimer(Runnable runnable, long delay, long repeat) { - delay = Math.max(1L, delay); - return JedCore.isFolia() ? Bukkit.getGlobalRegionScheduler().runAtFixedRate(JedCore.plugin, (task) -> runnable.run(), delay, repeat) : Bukkit.getScheduler().runTaskTimer(JedCore.plugin, runnable, delay, repeat); - } - - public static boolean cancelTimerTask(Object task) { - if (task == null) { - return false; - } else { - if (JedCore.isFolia()) { - if (task instanceof ScheduledTask) { - ((ScheduledTask)task).cancel(); - return true; - } - } else if (task instanceof BukkitTask) { - ((BukkitTask)task).cancel(); - return true; - } - - return false; - } - } - - public static boolean isTaskCancelled(Object task) { - if (JedCore.isFolia()) { - if (task instanceof ScheduledTask) { - return ((ScheduledTask)task).isCancelled(); - } - } else if (task instanceof BukkitTask) { - return ((BukkitTask)task).isCancelled(); - } - - return false; - } -} From 2ff6f86a7d806c0bedfda254d1650b7749e74939 Mon Sep 17 00:00:00 2001 From: Hihelloy-main Date: Thu, 23 Oct 2025 20:06:40 -0700 Subject: [PATCH 53/61] Hotfix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quick little hotfix for some earth moves and server software logging 😄 --- src/com/jedk1/jedcore/JCManager.java | 2 +- src/com/jedk1/jedcore/JedCore.java | 4 ++-- .../jedcore/ability/earthbending/MudSurge.java | 16 ++++++++++++++-- .../jedcore/ability/waterbending/IcePassive.java | 3 ++- .../ability/waterbending/combo/Maelstrom.java | 11 ++++++----- src/com/jedk1/jedcore/util/MetricsLite.java | 8 +++----- src/com/jedk1/jedcore/util/ThreadUtil.java | 2 +- src/plugin.yml | 1 + 8 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/com/jedk1/jedcore/JCManager.java b/src/com/jedk1/jedcore/JCManager.java index be8b8bc..2dfa835 100644 --- a/src/com/jedk1/jedcore/JCManager.java +++ b/src/com/jedk1/jedcore/JCManager.java @@ -20,7 +20,7 @@ public void run() { LightningBurst.progressAll(); HealingWaters.heal(Bukkit.getServer()); - IcePassive.handleSkating(); + //IcePassive.handleSkating(); IceWall.progressAll(); EarthPillar.progressAll(); diff --git a/src/com/jedk1/jedcore/JedCore.java b/src/com/jedk1/jedcore/JedCore.java index bb065c2..5e5179e 100644 --- a/src/com/jedk1/jedcore/JedCore.java +++ b/src/com/jedk1/jedcore/JedCore.java @@ -66,11 +66,11 @@ public void onEnable() { luminol = true; } catch (ClassNotFoundException ignored) {} - if (isFolia) { + if (isFolia && !luminol) { getLogger().info("Server is running on Folia"); } - if (paper) { + if (paper && !luminol) { getLogger().info("Server is running on Paper"); } diff --git a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java index 98ce05e..db9a762 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java @@ -3,7 +3,12 @@ import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.collision.CollisionUtil; import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.*; +import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; +import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; +import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; +import com.jedk1.jedcore.policies.removal.OutOfRangeRemovalPolicy; +import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.Element; import com.projectkorra.projectkorra.GeneralMethods; @@ -31,7 +36,14 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Random; +import java.util.Set; import java.util.stream.Collectors; public class MudSurge extends EarthAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java index 794225a..fc28793 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java +++ b/src/com/jedk1/jedcore/ability/waterbending/IcePassive.java @@ -4,6 +4,7 @@ import com.jedk1.jedcore.configuration.JedCoreConfig; import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.Element; +import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.IceAbility; import com.projectkorra.projectkorra.util.ParticleEffect; import org.bukkit.Bukkit; @@ -41,7 +42,7 @@ public static void handleSkating() { if (JCMethods.isDisabledWorld(player.getWorld())) continue; if (!player.isOnGround()) continue; if (!player.isSprinting()) continue; - if (!IceAbility.isIce(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) continue; + if (!ElementalAbility.isIce(player.getLocation().getBlock().getRelative(BlockFace.DOWN))) continue; BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); diff --git a/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java b/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java index 55c0a35..b394f55 100644 --- a/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java +++ b/src/com/jedk1/jedcore/ability/waterbending/combo/Maelstrom.java @@ -248,12 +248,13 @@ public Object createNewComboInstance(Player player) { return new Maelstrom(player); } - @Override - public ArrayList getCombination() { - return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.Maelstrom.Combination")); - } + @Override + public ArrayList getCombination() { + return ComboUtil.generateCombinationFromList(this, JedCoreConfig.getConfig(player).getStringList("Abilities.Water.WaterCombo.Maelstrom.Combination")); + } - @Override + + @Override public String getInstructions() { return JedCoreConfig.getConfig(player).getString("Abilities.Water.WaterCombo.Maelstrom.Instructions"); } diff --git a/src/com/jedk1/jedcore/util/MetricsLite.java b/src/com/jedk1/jedcore/util/MetricsLite.java index 42317a5..46153ed 100644 --- a/src/com/jedk1/jedcore/util/MetricsLite.java +++ b/src/com/jedk1/jedcore/util/MetricsLite.java @@ -28,6 +28,7 @@ package com.jedk1.jedcore.util; +import com.cjcrafter.foliascheduler.bukkit.BukkitTask; import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.configuration.InvalidConfigurationException; @@ -35,7 +36,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.scheduler.BukkitTask; import java.io.*; import java.lang.reflect.Method; @@ -104,7 +104,7 @@ public class MetricsLite { /** * Id of the scheduled task */ - private volatile BukkitTask task = null; + private volatile Object task = null; public MetricsLite(Plugin plugin) throws IOException { if (plugin == null) { @@ -153,7 +153,7 @@ public boolean start() { } // Begin hitting the server with glorious data - task = (BukkitTask) ThreadUtil.runAsyncTimer(new Runnable() { + task = ThreadUtil.runAsyncTimer(new Runnable() { private boolean firstPost = true; @@ -163,7 +163,6 @@ public void run() { synchronized (optOutLock) { // Disable Task, if it is running and the server owner decided to opt-out if (isOptOut() && task != null) { - task.cancel(); task = null; } } @@ -245,7 +244,6 @@ public void disable() throws IOException { // Disable Task, if it is running if (task != null) { - task.cancel(); task = null; } } diff --git a/src/com/jedk1/jedcore/util/ThreadUtil.java b/src/com/jedk1/jedcore/util/ThreadUtil.java index df4434d..cdc977d 100644 --- a/src/com/jedk1/jedcore/util/ThreadUtil.java +++ b/src/com/jedk1/jedcore/util/ThreadUtil.java @@ -211,7 +211,7 @@ public static void runAsync(@NotNull Runnable runnable) { } }, delay * 50, TimeUnit.MILLISECONDS); } else { - return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); + return Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay); } } diff --git a/src/plugin.yml b/src/plugin.yml index 4941424..5eb7f75 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -5,6 +5,7 @@ authors: ['jedk1'] depend: [ProjectKorra] folia-supported: true api-version: '1.20' +load: POSTWORLD description: "A cool ProjectKorra addon plugin" permissions: From d4e186354d8a47158dea68a5fa7dd0f5a1b9ce3b Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Thu, 23 Oct 2025 20:14:07 -0700 Subject: [PATCH 54/61] Create maven.yml --- .github/workflows/maven.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..622be6b --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,35 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Java CI with Maven + +on: + push: + branches: [ "2.15.1-prerelease" ] + pull_request: + branches: [ "2.15.1-prerelease" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + + # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive + - name: Update dependency graph + uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 From 69123a7e87663e337c0b77b116a9cfec77122b7d Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Thu, 23 Oct 2025 20:15:09 -0700 Subject: [PATCH 55/61] Update maven.yml --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 622be6b..0ebe3e5 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -24,7 +24,7 @@ jobs: - name: Set up JDK 17 uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '16' distribution: 'temurin' cache: maven - name: Build with Maven From 046fb34c8be2d318bcf4ff81f871a0be5a69006a Mon Sep 17 00:00:00 2001 From: Hihelloy-main Date: Thu, 23 Oct 2025 20:17:25 -0700 Subject: [PATCH 56/61] Update to Java 17 --- .github/workflows/maven.yml | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0ebe3e5..622be6b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -24,7 +24,7 @@ jobs: - name: Set up JDK 17 uses: actions/setup-java@v4 with: - java-version: '16' + java-version: '17' distribution: 'temurin' cache: maven - name: Build with Maven diff --git a/pom.xml b/pom.xml index 9121837..8d5811f 100644 --- a/pom.xml +++ b/pom.xml @@ -73,8 +73,8 @@ maven-compiler-plugin 3.8.0 - 16 - 16 + 17 + 17 From f548af743f24583d0c1841eb037abbd13f6d6951 Mon Sep 17 00:00:00 2001 From: Hihelloy-main Date: Thu, 23 Oct 2025 20:51:23 -0700 Subject: [PATCH 57/61] AirBlade Fix --- .../jedcore/ability/airbending/AirBlade.java | 9 +- .../ability/earthbending/EarthShard.java | 165 +- .../ability/earthbending/MudSurge.java | 16 +- .../jedcore/configuration/JedCoreConfig.java | 2133 +++++++++-------- 4 files changed, 1133 insertions(+), 1190 deletions(-) diff --git a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java index feb1787..c627a35 100644 --- a/src/com/jedk1/jedcore/ability/airbending/AirBlade.java +++ b/src/com/jedk1/jedcore/ability/airbending/AirBlade.java @@ -14,11 +14,9 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; public class AirBlade extends AirAbility implements AddonAbility { @@ -72,8 +70,9 @@ public void setFields() { speed = config.getDouble("Abilities.Air.AirBlade.Speed"); knockback = config.getDouble("Abilities.Air.AirBlade.Knockback"); - ConfigurationSection cuttingConfig = config.getConfigurationSection("Abilities.Air.AirBlade.BlockCutting"); + @NotNull ConfigurationSection cuttingConfig = Objects.requireNonNull(config.getConfigurationSection("Abilities.Air.AirBlade.BlockCutting")); + assert cuttingConfig != null; blockCuttingEnabled = cuttingConfig.getBoolean("Enabled"); revertCutBlocks = cuttingConfig.getBoolean("Revert"); revertTime = cuttingConfig.getLong("RevertTime"); diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java index 6ee028d..7062adc 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java @@ -1,36 +1,34 @@ package com.jedk1.jedcore.ability.earthbending; -import com.jedk1.jedcore.JedCore; +import java.util.*; +import java.util.stream.Collectors; + import com.jedk1.jedcore.collision.AABB; import com.jedk1.jedcore.collision.CollisionDetector; import com.jedk1.jedcore.collision.CollisionUtil; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.BlockUtil; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; +import com.jedk1.jedcore.JedCore; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; public class EarthShard extends EarthAbility implements AddonAbility { @Attribute(Attribute.RANGE) @@ -56,14 +54,6 @@ public class EarthShard extends EarthAbility implements AddonAbility { private final List readyBlocksTracker = new ArrayList<>(); private final List fallingBlocks = new ArrayList<>(); - private boolean allowKnockup; - private double knockupVelocity; - private double knockupRange; - - private boolean allowKnockupSelf; - private double knockupSelfVelocity; - private double knockupSelfRange; - public EarthShard(Player player) { super(player); @@ -102,12 +92,6 @@ public void setFields() { cooldown = config.getLong("Abilities.Earth.EarthShard.Cooldown"); abilityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); entityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); - allowKnockup = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Others.Allow"); - knockupVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Velocity"); - knockupRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Range"); - allowKnockupSelf = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Self.Allow"); - knockupSelfVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Velocity"); - knockupSelfRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Range"); } public void select() { @@ -115,68 +99,53 @@ public void select() { } public void raiseEarthBlock(Block block) { - if (block == null) return; - if (EarthAbility.getMovedEarth().containsKey(block)) return; - if (tblockTracker.size() >= maxShards) return; + if (block == null) { + return; + } + + if (tblockTracker.size() >= maxShards) { + return; + } Vector blockVector = block.getLocation().toVector().toBlockVector().setY(0); + // Don't select from locations that already have an EarthShard block. for (TempBlock tempBlock : tblockTracker) { - if (tempBlock.getLocation().getWorld() != block.getWorld()) continue; + if (tempBlock.getLocation().getWorld() != block.getWorld()) { + continue; + } Vector tempBlockVector = tempBlock.getLocation().toVector().toBlockVector().setY(0); - if (tempBlockVector.equals(blockVector)) return; - } - - for (int i = 1; i < 4; i++) { - if (!isTransparent(block.getRelative(BlockFace.UP, i))) return; - } - - if (!isEarthbendable(block)) return; - if (isMetal(block)) { - playMetalbendingSound(block.getLocation()); - } else { - ParticleEffect.BLOCK_CRACK.display( - block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData() - ); - playEarthbendingSound(block.getLocation()); + if (tempBlockVector.equals(blockVector)) { + return; + } } - Material material = getCorrectType(block); - - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); + for (int i = 1; i < 4; i++) { + if (!isTransparent(block.getRelative(BlockFace.UP, i))) { + return; + } } - Location loc = block.getLocation().add(0.5, 0, 0.5); - new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); - TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); - tblockTracker.add(tb); - - handleKnockup(block); - } - - private void handleKnockup(Block origin) { - if (!allowKnockup && !allowKnockupSelf) return; - - Location originLoc = origin.getLocation(); - World world = origin.getWorld(); + if (isEarthbendable(block)) { + if (isMetal(block)) { + playMetalbendingSound(block.getLocation()); + } else { + ParticleEffect.BLOCK_CRACK.display(block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData()); + playEarthbendingSound(block.getLocation()); + } - for (Entity entity : world.getNearbyEntities(originLoc, Math.max(knockupRange, knockupSelfRange), knockupRange, knockupRange)) { - if (entity instanceof FallingBlock) continue; + Material material = getCorrectType(block); - if (entity.equals(player)) { - if (!allowKnockupSelf) continue; - if (entity.getLocation().distance(originLoc) <= knockupSelfRange) { - entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupSelfVelocity, 0))); - } - } else { - if (!allowKnockup) continue; - if (entity.getLocation().distance(originLoc) <= knockupRange) { - entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupVelocity, 0))); - } + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); } + + Location loc = block.getLocation().add(0.5, 0, 0.5); + new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); + TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); + tblockTracker.add(tb); } } @@ -466,54 +435,6 @@ public List getFallingBlocks() { return fallingBlocks; } - public boolean isAllowKnockup() { - return allowKnockup; - } - - public void setAllowKnockup(boolean allowKnockup) { - this.allowKnockup = allowKnockup; - } - - public double getKnockupVelocity() { - return knockupVelocity; - } - - public void setKnockupVelocity(double knockupVelocity) { - this.knockupVelocity = knockupVelocity; - } - - public double getKnockupRange() { - return knockupRange; - } - - public void setKnockupRange(double knockupRange) { - this.knockupRange = knockupRange; - } - - public boolean isAllowKnockupSelf() { - return allowKnockupSelf; - } - - public void setAllowKnockupSelf(boolean allowKnockupSelf) { - this.allowKnockupSelf = allowKnockupSelf; - } - - public double getKnockupSelfVelocity() { - return knockupSelfVelocity; - } - - public void setKnockupSelfVelocity(double knockupSelfVelocity) { - this.knockupSelfVelocity = knockupSelfVelocity; - } - - public double getKnockupSelfRange() { - return knockupSelfRange; - } - - public void setKnockupSelfRange(double knockupSelfRange) { - this.knockupSelfRange = knockupSelfRange; - } - @Override public void load() {} diff --git a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java index db9a762..98ce05e 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java @@ -3,12 +3,7 @@ import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.collision.CollisionUtil; import com.jedk1.jedcore.configuration.JedCoreConfig; -import com.jedk1.jedcore.policies.removal.CannotBendRemovalPolicy; -import com.jedk1.jedcore.policies.removal.CompositeRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsDeadRemovalPolicy; -import com.jedk1.jedcore.policies.removal.IsOfflineRemovalPolicy; -import com.jedk1.jedcore.policies.removal.OutOfRangeRemovalPolicy; -import com.jedk1.jedcore.policies.removal.SwappedSlotsRemovalPolicy; +import com.jedk1.jedcore.policies.removal.*; import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.Element; import com.projectkorra.projectkorra.GeneralMethods; @@ -36,14 +31,7 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.ListIterator; -import java.util.Random; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; public class MudSurge extends EarthAbility implements AddonAbility { diff --git a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java index 1983fd8..5ac523a 100644 --- a/src/com/jedk1/jedcore/configuration/JedCoreConfig.java +++ b/src/com/jedk1/jedcore/configuration/JedCoreConfig.java @@ -14,1056 +14,1091 @@ public class JedCoreConfig { - static JedCore plugin; + static JedCore plugin; public static Config board; - private static final String path = "ExtraAbilities.Hihelloy.BloodShot."; - - public JedCoreConfig(JedCore plugin) { - JedCoreConfig.plugin = plugin; - board = new Config(new File("board.yml")); - loadConfigBoard(); - loadConfigCore(); - addDeathMessages(); - setupElementSphereNames(); - } - - private void loadConfigBoard() { - FileConfiguration config; - config = board.getConfig(); - config.addDefault("Settings.Enabled", false); - config.options().copyDefaults(true); - board.saveConfig(); - } - - private void loadConfigCore() { - FileConfiguration config; - config = JedCore.plugin.getConfig(); - - config.addDefault("Settings.Updater.Check", true); - config.addDefault("Settings.Updater.Notify", true); - config.addDefault("Properties.MobCollisions.Enabled", true); - config.addDefault("Properties.AbilityCollisions.Enabled", true); - config.addDefault("Properties.PerWorldConfig", true); - config.addDefault("Properties.FireTickMethod", "larger"); - config.addDefault("Properties.LogDebug", false); - - config.addDefault("Properties.ChiRestrictor.Enabled", false); - config.addDefault("Properties.ChiRestrictor.ResetCooldown", true); - config.addDefault("Properties.ChiRestrictor.MeleeDistance", 7); - config.addDefault("Properties.ChiRestrictor.Whitelist", new ArrayList()); - - config.addDefault("Properties.Fire.DynamicLight.Enabled", true); - config.addDefault("Properties.Fire.DynamicLight.Brightness", 13); - config.addDefault("Properties.Fire.DynamicLight.KeepAlive", 600); - - config.addDefault("Abilities.Avatar.ElementSphere.Enabled", true); - config.addDefault("Abilities.Avatar.ElementSphere.Description", "ElementSphere is a very all round ability, being " - + "able to shoot attacks of each element, each with a " - + "different effect. To use, simply Left-Click. Once active, " - + "Sneak (Default: Shift) to fly around. Sneak and double " - + "Left-Click to disable the ability! " - + "To use each element, simply select hotbar slots 1-4 and Left-Click. " - + "Each element has limited uses! Once an element is used up, " - + "the element's ring will disappear!"); - config.addDefault("Abilities.Avatar.ElementSphere.Cooldown", 180000); - config.addDefault("Abilities.Avatar.ElementSphere.Duration", 60000); - config.addDefault("Abilities.Avatar.ElementSphere.MaxControlledHeight", 40); - config.addDefault("Abilities.Avatar.ElementSphere.FlySpeed", 1.5); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Knockback", 2); - config.addDefault("Abilities.Avatar.ElementSphere.Air.Speed", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactRevert", 15000); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.BurnDuration", 3000); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Speed", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Fire.Controllable", false); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Uses", 20); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Damage", 3.0); - config.addDefault("Abilities.Avatar.ElementSphere.Water.Speed", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Cooldown", 500); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Range", 40); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Knockback", 2.0); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.Damage", 12.0); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.RequiredUses", 10); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.EndAbility", true); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactCraterSize", 3); - config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactRevert", 30000); - - config.addDefault("Abilities.Avatar.SpiritBeam.Enabled", true); - config.addDefault("Abilities.Avatar.SpiritBeam.Description", "An energybending ability usable by the Avatar. " - + "To use, one must enter the AvatarState and hold down Sneak (Default: Shift). " - + "This ability lasts only for a few seconds before requiring " - + "another activation."); - config.addDefault("Abilities.Avatar.SpiritBeam.Cooldown", 15000); - config.addDefault("Abilities.Avatar.SpiritBeam.Duration", 1000); - config.addDefault("Abilities.Avatar.SpiritBeam.Range", 40); - config.addDefault("Abilities.Avatar.SpiritBeam.Damage", 10.0); - config.addDefault("Abilities.Avatar.SpiritBeam.AvatarStateOnly", true); - config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Enabled", true); - config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Radius", 3); - config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Regen", 20000); - - config.addDefault("Abilities.Air.AirBlade.Enabled", true); - config.addDefault("Abilities.Air.AirBlade.Description", "With this ability bound, Left-Click to shoot " - + "a strong blade of air at your targets to deal some damage!"); - config.addDefault("Abilities.Air.AirBlade.Cooldown", 3000); - config.addDefault("Abilities.Air.AirBlade.Range", 30.0); - config.addDefault("Abilities.Air.AirBlade.Damage", 4.0); - config.addDefault("Abilities.Air.AirBlade.EntityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirBlade.AbilityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.Enabled",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveFirst",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveSecond",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.Enabled",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveFirst",true); - config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveSecond",false); - - config.addDefault("Abilities.Air.AirBreath.Enabled", true); - config.addDefault("Abilities.Air.AirBreath.Description", "To use, hold Sneak (Default: Shift) to release " - + "a strong breath of wind, knocking your opponents " - + "back. This ability also has a longer range and " - + "stronger knockback while in AvatarState!"); - config.addDefault("Abilities.Air.AirBreath.Cooldown", 3000); - config.addDefault("Abilities.Air.AirBreath.Duration", 3000); - config.addDefault("Abilities.Air.AirBreath.Particles", 3); - config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Lava", true); - config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Fire", true); - config.addDefault("Abilities.Air.AirBreath.ExtinguishEntities", true); - config.addDefault("Abilities.Air.AirBreath.Damage.Enabled", false); - config.addDefault("Abilities.Air.AirBreath.Damage.Player", 1.0); - config.addDefault("Abilities.Air.AirBreath.Damage.Mob", 2.0); - config.addDefault("Abilities.Air.AirBreath.Knockback", 0.8); - config.addDefault("Abilities.Air.AirBreath.Range", 10); - config.addDefault("Abilities.Air.AirBreath.LaunchPower", 1.0); - config.addDefault("Abilities.Air.AirBreath.RegenTargetOxygen", true); - config.addDefault("Abilities.Air.AirBreath.Avatar.Enabled", true); - config.addDefault("Abilities.Air.AirBreath.Avatar.Range", 20); - config.addDefault("Abilities.Air.AirBreath.Avatar.Knockback", 3.5); - - config.addDefault("Abilities.Air.AirGlide.Enabled", true); - config.addDefault("Abilities.Air.AirGlide.Description", "While falling, tap Sneak for a " - + "slow and steady descent. Tap Sneak again to stop gliding."); - config.addDefault("Abilities.Air.AirGlide.Speed", 0.5); - config.addDefault("Abilities.Air.AirGlide.FallSpeed", 0.1); - config.addDefault("Abilities.Air.AirGlide.Particles", 4); - config.addDefault("Abilities.Air.AirGlide.AllowAirSpout", false); - config.addDefault("Abilities.Air.AirGlide.Cooldown", 0); - config.addDefault("Abilities.Air.AirGlide.Duration", 0); - config.addDefault("Abilities.Air.AirGlide.RequireGround", false); - - config.addDefault("Abilities.Air.AirPunch.Enabled", true); - config.addDefault("Abilities.Air.AirPunch.Description", "Left-Click in rapid succession to punch high desnity packets of air " - + "at enemies to do slight damage. A few punches can be thrown before the ability goes on cooldown."); - config.addDefault("Abilities.Air.AirPunch.Cooldown", 5000); - config.addDefault("Abilities.Air.AirPunch.Threshold", 500); - config.addDefault("Abilities.Air.AirPunch.Shots", 4); - config.addDefault("Abilities.Air.AirPunch.Range", 30); - config.addDefault("Abilities.Air.AirPunch.Damage", 1.0); - config.addDefault("Abilities.Air.AirPunch.EntityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirPunch.AbilityCollisionRadius", 1.0); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.Enabled", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveFirst", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveSecond", false); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.Enabled",true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveFirst",true); - config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveSecond",false); - config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.Enabled", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveFirst", true); - config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveSecond", false); - - config.addDefault("Abilities.Air.Meditate.Enabled", true); - config.addDefault("Abilities.Air.Meditate.Description", "Hold Sneak (Default: Shift) to start meditating. " - + "After you have focused your energy, you will obtain several buffs."); - config.addDefault("Abilities.Air.Meditate.UnfocusMessage", "You have become unfocused due to taking damage!"); - config.addDefault("Abilities.Air.Meditate.LossFocusMessage", true); - config.addDefault("Abilities.Air.Meditate.ChargeTime", 5000); - config.addDefault("Abilities.Air.Meditate.Cooldown", 60000); - config.addDefault("Abilities.Air.Meditate.BoostDuration", 20000); - config.addDefault("Abilities.Air.Meditate.ParticleDensity", 5); - config.addDefault("Abilities.Air.Meditate.AbsorptionBoost", 2); - config.addDefault("Abilities.Air.Meditate.SpeedBoost", 3); - config.addDefault("Abilities.Air.Meditate.JumpBoost", 3); - - config.addDefault("Abilities.Air.SonicBlast.Enabled", true); - config.addDefault("Abilities.Air.SonicBlast.Description", "SonicBlast is a soundbending ability, known by very few airbenders. " - + "It allows the airbender to stun and deafen an opponent by creating a sonic blast. " - + "This is achieved by creating two regions of high and low pressure and bringing them together. " - + "To use, hold Sneak (Default: Shift) in the direction of the target. Once particles appear " - + "around you, let go of Sneak to shoot a SonicBlast at your target! The technique is very powerful, " - + "even if it doesn't seem it, and comes with a short cooldown."); - config.addDefault("Abilities.Air.SonicBlast.ChargeTime", 2000); - config.addDefault("Abilities.Air.SonicBlast.Damage", 4.0); - config.addDefault("Abilities.Air.SonicBlast.Effects.BlindnessDuration", 5000); - config.addDefault("Abilities.Air.SonicBlast.Effects.NauseaDuration", 5000); - config.addDefault("Abilities.Air.SonicBlast.Cooldown", 6000); - config.addDefault("Abilities.Air.SonicBlast.EntityCollisionRadius", 1.3); - config.addDefault("Abilities.Air.SonicBlast.AbilityCollisionRadius", 1.3); - config.addDefault("Abilities.Air.SonicBlast.Range", 20); - config.addDefault("Abilities.Air.SonicBlast.ChargeSwapping", true); - - config.addDefault("Abilities.Air.AirCombo.AirSlam.Enabled", true); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Description", "Kick your enemy up into the air then blast them away!"); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Cooldown", 8000); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Power", 5.0); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Range", 8); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Combination", Arrays.asList("AirSwipe:SHIFT_DOWN", "AirBlast:SHIFT_UP", "AirBlast:SHIFT_DOWN")); - config.addDefault("Abilities.Air.AirCombo.AirSlam.Instructions", "AirSwipe (Hold sneak) > AirBlast (Release sneak) > AirBlast (Hold sneak)"); - - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Enabled", true); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Description", "Create a stream of air as you fly which causes nearby " - + "entities to be thrown in your direction."); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.DragFactor", 1.5); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Duration", 2000); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Cooldown", 6000); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Combination", Arrays.asList("Flight:SHIFT_DOWN", "Flight:SHIFT_UP", "Flight:SHIFT_DOWN", "Flight:SHIFT_UP")); - config.addDefault("Abilities.Air.AirCombo.SwiftStream.Instructions", "Flight (Double tap sneak)"); - - config.addDefault("Abilities.Earth.EarthArmor.Enabled", true); - config.addDefault("Abilities.Earth.EarthArmor.Description", "If the block is metal, then you will get metal armor!"); - config.addDefault("Abilities.Earth.EarthArmor.Resistance.Strength", 2); - config.addDefault("Abilities.Earth.EarthArmor.Resistance.Duration", 4000); - config.addDefault("Abilities.Earth.EarthArmor.UseIronArmor", false); - - config.addDefault("Abilities.Earth.EarthKick.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Description", "This move enables an earthbender to create a " - + "large earthen cover, ideal for defense. " - + "To use, Sneak (Default: Shift) at an earth " - + "source and it will raise and launch towards " - + "your foe!"); - config.addDefault("Abilities.Earth.EarthKick.Cooldown", 2000); - config.addDefault("Abilities.Earth.EarthKick.EarthBlocks", 10); - - double oldDamage = 0.0; - if (config.contains("Abilities.Earth.EarthKick.Damage")) { - oldDamage = config.getDouble("Abilities.Earth.EarthKick.Damage"); - config.set("Abilities.Earth.EarthKick.Damage", null); - } - - config.addDefault("Abilities.Earth.EarthKick.Damage.Normal", oldDamage > 0.0 ? oldDamage : 2.0); - config.addDefault("Abilities.Earth.EarthKick.Damage.Metal", 3.0); - config.addDefault("Abilities.Earth.EarthKick.EntityCollisionRadius", 1.5); - config.addDefault("Abilities.Earth.EarthKick.AbilityCollisionRadius", 1.5); - config.addDefault("Abilities.Earth.EarthKick.MultipleHits", true); - config.addDefault("Abilities.Earth.EarthKick.SourceRange", 2.0); - config.addDefault("Abilities.Earth.EarthKick.Spread", 20); - config.addDefault("Abilities.Earth.EarthKick.Velocity", 0.7); - config.addDefault("Abilities.Earth.EarthKick.AllowMetal", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveSecond", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.Enabled", true); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveFirst", false); - config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveSecond", true); - - - config.addDefault("Abilities.Earth.EarthLine.Enabled", true); - config.addDefault("Abilities.Earth.EarthLine.Description", "To use, place your cursor over an earth-bendable block on the ground, " - + "then Sneak (Default: Shift) to select the block. After selecting the block you may release Sneak. " - + "If you then Left-Click at an object or player, a small piece of earth will come up " - + "from the ground and move towards your target to deal damage and knock them back. " - + "Additionally, hold Sneak to control the flow of the line!"); - config.addDefault("Abilities.Earth.EarthLine.Cooldown", 0); - config.addDefault("Abilities.Earth.EarthLine.PrepareCooldown", 3000); - config.addDefault("Abilities.Earth.EarthLine.Range", 30); - config.addDefault("Abilities.Earth.EarthLine.PrepareRange", 3); - config.addDefault("Abilities.Earth.EarthLine.SourceKeepRange", 7); - config.addDefault("Abilities.Earth.EarthLine.AffectingRadius", 2); - config.addDefault("Abilities.Earth.EarthLine.AllowChangeDirection", true); - config.addDefault("Abilities.Earth.EarthLine.MaxDuration", 2500); - config.addDefault("Abilities.Earth.EarthLine.Damage", 3.0); - config.addDefault("Abilities.Earth.EarthLine.RemovalPolicy.SwappedSlots.Enabled", false); - - config.addDefault("Abilities.Earth.EarthPillar.Enabled", true); - config.addDefault("Abilities.Earth.EarthPillar.Description", "With this ability bound, tap Sneak (Default: Shift) on any Earthbendable " - + "surface to create pillar of earth in the direction of the block face!"); - config.addDefault("Abilities.Earth.EarthPillar.Height", 6); - config.addDefault("Abilities.Earth.EarthPillar.Range", 10); - - config.addDefault("Abilities.Earth.EarthShard.Enabled", true); - config.addDefault("Abilities.Earth.EarthShard.Description", "EarthShard is a variation of EarthBlast " - + "which the earthbender may use to hit a target. This " - + "ability deals a fair amount of damage and is easy to " - + "rapid-fire. To use, simply shift at an earthbendable block, " - + "and it will ascend to your eye height. Then, click towards your " - + "target and the block will launch itself towards it."); - config.addDefault("Abilities.Earth.EarthShard.Cooldown", 1000); - config.addDefault("Abilities.Earth.EarthShard.Damage.Normal", 1.0); - config.addDefault("Abilities.Earth.EarthShard.Damage.Metal", 1.5); - config.addDefault("Abilities.Earth.EarthShard.PrepareRange", 5); - config.addDefault("Abilities.Earth.EarthShard.AbilityRange", 30); - config.addDefault("Abilities.Earth.EarthShard.MaxShards", 3); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Allow", true); - config.addDefault("Abilities.Earth.EarthShard.KnockUp.Velocity", 1.0); - config.addDefault("Abilities.Earth.EarthShard.AbilityCollisionRadius", 2.0); - config.addDefault("Abilities.Earth.EarthShard.EntityCollisionRadius", 1.4); - - config.addDefault("Abilities.Earth.EarthSurf.Enabled", true); - config.addDefault("Abilities.Earth.EarthSurf.Description", "This ability allows an earth bender to " - + "ride up on a wave of earth, allowing them to travel a little faster than " - + "normal. To use, simply be in the air just above " - + "the ground, and Left Click! Additionally, if an entity just so happens to get caught in " - + "the wave, they will be moved with the wave."); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Cooldown", 3000); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown", 2000); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Scaled", true); - config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Enabled", false); - config.addDefault("Abilities.Earth.EarthSurf.Duration.Duration", 7000); - config.addDefault("Abilities.Earth.EarthSurf.Duration.Enabled", false); - config.addDefault("Abilities.Earth.EarthSurf.RelaxedCollisions", true); - config.addDefault("Abilities.Earth.EarthSurf.RemoveOnAnyDamage", false); - config.addDefault("Abilities.Earth.EarthSurf.Speed", 0.55); - config.addDefault("Abilities.Earth.EarthSurf.HeightTolerance", 3); - config.addDefault("Abilities.Earth.EarthSurf.SpringStiffness", 0.35); - - config.addDefault("Abilities.Earth.Fissure.Enabled", true); - config.addDefault("Abilities.Earth.Fissure.Description", "Fissure is an advanced Lavabending " - + "ability enabling a lavabender to tear up the ground, " - + "swallowing up any enemies. To use, simply swing at an enemy " - + "and a line of lava will crack open. " - + "Then, tap Sneak (Default: Shift) to expand the crevice. " - + "The crevice has a maximum width and depth. Once the crevice has reached it's maximum " - + "width, Sneak while looking at the crevice to close it!"); - config.addDefault("Abilities.Earth.Fissure.Cooldown", 20000); - config.addDefault("Abilities.Earth.Fissure.Duration", 15000); - config.addDefault("Abilities.Earth.Fissure.MaxWidth", 3); - config.addDefault("Abilities.Earth.Fissure.SlapRange", 12); - config.addDefault("Abilities.Earth.Fissure.SlapDelay", 50); - - config.addDefault("Abilities.Earth.LavaDisc.Enabled", true); - config.addDefault("Abilities.Earth.LavaDisc.Description", "Hold Sneak (Default: Shift) on a lava source " - + "block to generate a disc of lava at your finger tips. Releasing " - + "Sneak will shoot the disc off in the direction " - + "you are looking! If you tap or hold Sneak again, " - + "the disc will attempt to return to you!"); - String[] meltable = { - Material.COBBLESTONE.name(), Material.OAK_LOG.name(), Material.SPRUCE_LOG.name(), - Material.JUNGLE_LOG.name(), Material.DARK_OAK_LOG.name(), Material.BIRCH_LOG.name(), - Material.ACACIA_LOG.name() - }; - config.addDefault("Abilities.Earth.LavaDisc.Cooldown", 7000); - config.addDefault("Abilities.Earth.LavaDisc.Duration", 1000); - config.addDefault("Abilities.Earth.LavaDisc.Damage", 4.0); - config.addDefault("Abilities.Earth.LavaDisc.Particles", 3); - config.addDefault("Abilities.Earth.LavaDisc.ContinueAfterEntityHit", false); - config.addDefault("Abilities.Earth.LavaDisc.RecallLimit", 3); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.RegenTime", 5000); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.BlockDamage", true); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks", meltable); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.LavaTrail", true); - config.addDefault("Abilities.Earth.LavaDisc.Destroy.TrailFlow", false); - config.addDefault("Abilities.Earth.LavaDisc.Source.RegenTime", 10000); - config.addDefault("Abilities.Earth.LavaDisc.Source.LavaOnly", false); - config.addDefault("Abilities.Earth.LavaDisc.Source.Range", 4.0); - config.addDefault("Abilities.Earth.LavaDisc.RemovalPolicy.SwappedSlots.Enabled", true); - - config.addDefault("Abilities.Earth.LavaFlux.Enabled", true); - config.addDefault("Abilities.Earth.LavaFlux.Description", "This offensive ability enables a Lavabender to create a wave of lava, " - + "swiftly progressing forward and hurting/burning anything in its way. To use, " - + "simply swing your arm towards a target and the ability will activate."); - config.addDefault("Abilities.Earth.LavaFlux.Range", 12); - config.addDefault("Abilities.Earth.LavaFlux.Cooldown", 8000); - config.addDefault("Abilities.Earth.LavaFlux.Duration", 4000); - config.addDefault("Abilities.Earth.LavaFlux.Cleanup", 1000); - config.addDefault("Abilities.Earth.LavaFlux.Damage", 1.0); - config.addDefault("Abilities.Earth.LavaFlux.Speed", 1); - config.addDefault("Abilities.Earth.LavaFlux.Wave", true); - config.addDefault("Abilities.Earth.LavaFlux.KnockUp", 1.0); - config.addDefault("Abilities.Earth.LavaFlux.KnockBack", 1.0); - - config.addDefault("Abilities.Earth.LavaThrow.Enabled", true); - config.addDefault("Abilities.Earth.LavaThrow.Description", "Throwing lava is a fundamental technique for the rare subskill. " - + "Use Sneak(Deafult: Shift) while looking at a pool of lava infront of you, then " - + "Left-Click to splash the lava at your target. " - + "It can be used in rapid succession to create multiple streams of lava!"); - config.addDefault("Abilities.Earth.LavaThrow.Cooldown", 7000); - config.addDefault("Abilities.Earth.LavaThrow.MaxShots", 6); - config.addDefault("Abilities.Earth.LavaThrow.Range", 20); - config.addDefault("Abilities.Earth.LavaThrow.Damage", 1.0); - config.addDefault("Abilities.Earth.LavaThrow.SourceGrabRange", 4); - config.addDefault("Abilities.Earth.LavaThrow.SourceRegenDelay", 10000); - config.addDefault("Abilities.Earth.LavaThrow.FireTicks", 80); - config.addDefault("Abilities.Earth.LavaThrow.CurveFactor", 0.5); - - config.addDefault("Abilities.Earth.MagnetShield.Enabled", true); - config.addDefault("Abilities.Earth.MagnetShield.Description", "Repel any metal projectiles using a strong magnetic shield. " - + "To activate, simply hold sneak with this ability bound."); - config.addDefault("Abilities.Earth.MagnetShield.Materials", Arrays.asList( - "IRON_INGOT", - "IRON_HELMET", - "IRON_CHESTPLATE", - "IRON_LEGGINGS", - "IRON_BOOTS", - "IRON_BLOCK", - "IRON_AXE", - "IRON_PICKAXE", - "IRON_SWORD", - "IRON_HOE", - "IRON_SHOVEL", - "IRON_DOOR", - "IRON_NUGGET", - "IRON_BARS", - "IRON_HORSE_ARMOR", - "IRON_TRAPDOOR", - "HEAVY_WEIGHTED_PRESSURE_PLATE", - "GOLD_INGOT", - "GOLDEN_HELMET", - "GOLDEN_CHESTPLATE", - "GOLDEN_LEGGINGS", - "GOLDEN_BOOTS", - "GOLD_BLOCK", - "GOLD_NUGGET", - "GOLDEN_AXE", - "GOLDEN_PICKAXE", - "GOLDEN_SHOVEL", - "GOLDEN_SWORD", - "GOLDEN_HOE", - "GOLDEN_HORSE_ARMOR", - "LIGHT_WEIGHTED_PRESSURE_PLATE", - "CLOCK", - "COMPASS", - "RAW_GOLD_BLOCK", - "RAW_IRON_BLOCK", - "RAW_IRON", - "RAW_GOLD", - "ANVIL", - "CHIPPED_ANVIL", - "DAMAGED_ANVIL", - "IRON_ORE", - "GOLD_ORE", - "DEEPSLATE_IRON_ORE", - "DEEPSLATE_GOLD_ORE", - "SHIELD" - )); - config.addDefault("Abilities.Earth.MagnetShield.Duration", 6000); - config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Shift", 5000); - config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Click", 5000); - config.addDefault("Abilities.Earth.MagnetShield.Range", 5.0); - config.addDefault("Abilities.Earth.MagnetShield.RepelArrows", true); - config.addDefault("Abilities.Earth.MagnetShield.RepelLivingEntities", true); - config.addDefault("Abilities.Earth.MagnetShield.Velocity", 0.1); - - config.addDefault("Abilities.Earth.MetalFragments.Enabled", true); - config.addDefault("Abilities.Earth.MetalFragments.Description", "MetalFragments allows you to select a source and shoot " - + "multiple fragments of metal out of that source " - + "block towards your target, injuring them on impact. " - + "To use, tap Sneak (Default: Shift) at a metal " - + "source block and it will float up. Then, turn around " - + "and click at your target to fling metal fragments at them."); - config.addDefault("Abilities.Earth.MetalFragments.Cooldown", 5000); - config.addDefault("Abilities.Earth.MetalFragments.MaxSources", 3); - config.addDefault("Abilities.Earth.MetalFragments.SourceRange", 5); - config.addDefault("Abilities.Earth.MetalFragments.MaxFragments", 10); - config.addDefault("Abilities.Earth.MetalFragments.Damage", 4.0); - config.addDefault("Abilities.Earth.MetalFragments.Velocity", 2.0); - - config.addDefault("Abilities.Earth.MetalHook.Enabled", true); - config.addDefault("Abilities.Earth.MetalHook.Description", "This ability lets a Metalbender bend metal into " - + "grappling hooks, allowing them to easily manouver terrain. " - + "To use this ability, the user must either have Iron in their inventory " - + "or be wearing an Iron/Chainmail Chestplate. Left-Click in the direction " - + "you are looking to fire a grappling hook, several hooks can be active at once, " - + "allowing the bender to 'hang' in locations. To disengage the hooks, hold Shift (Default: Sneak) or Sprint."); - config.addDefault("Abilities.Earth.MetalHook.Cooldown", 3000); - config.addDefault("Abilities.Earth.MetalHook.Range", 30); - config.addDefault("Abilities.Earth.MetalHook.MaxHooks", 3); - config.addDefault("Abilities.Earth.MetalHook.TotalHooks", 0); - config.addDefault("Abilities.Earth.MetalHook.RequireItems", true); - config.addDefault("Abilities.Earth.MetalHook.BarrierHooking", true); - - config.addDefault("Abilities.Earth.MetalShred.Enabled", true); - config.addDefault("Abilities.Earth.MetalShred.Description", "MetalShred allows you to tear a metal surface allowing you to sneak in to the other side." - + "To use, you must find a flat metal surface. Then, Sneak(Default: Shift) " - + "at a piece of metal on that surface, and two pieces of metal " - + "will be pulled toward you. Finally, run alongside the surface to coil " - + "the metal around those two pieces. The way will be open, and the blocks " - + "will not reset until you either select a new source or you switch " - + "abilities. If you click after having torn a hole in a vertical surface, " - + "you can Left-Click in any direction and the metal will unfold in that " - + "direction. If you are fast and precise enough, the metal can bend in " - + "any shape. The length of this sheet of metal depends on how much was " - + "coiled in the first place."); - config.addDefault("Abilities.Earth.MetalShred.SourceRange", 5); + + public JedCoreConfig(JedCore plugin) { + JedCoreConfig.plugin = plugin; + board = new Config(new File("board.yml")); + loadConfigBoard(); + loadConfigCore(); + addDeathMessages(); + setupElementSphereNames(); + } + + private void loadConfigBoard() { + FileConfiguration config; + config = board.getConfig(); + config.addDefault("Settings.Enabled", false); + config.options().copyDefaults(true); + board.saveConfig(); + } + + private void loadConfigCore() { + FileConfiguration config; + config = JedCore.plugin.getConfig(); + + config.addDefault("Settings.Updater.Check", true); + config.addDefault("Settings.Updater.Notify", true); + config.addDefault("Properties.MobCollisions.Enabled", true); + config.addDefault("Properties.AbilityCollisions.Enabled", true); + config.addDefault("Properties.PerWorldConfig", true); + config.addDefault("Properties.FireTickMethod", "larger"); + config.addDefault("Properties.LogDebug", false); + + config.addDefault("Properties.ChiRestrictor.Enabled", false); + config.addDefault("Properties.ChiRestrictor.ResetCooldown", true); + config.addDefault("Properties.ChiRestrictor.MeleeDistance", 7); + config.addDefault("Properties.ChiRestrictor.Whitelist", new ArrayList()); + + config.addDefault("Properties.Fire.DynamicLight.Enabled", true); + config.addDefault("Properties.Fire.DynamicLight.Brightness", 13); + config.addDefault("Properties.Fire.DynamicLight.KeepAlive", 600); + + config.addDefault("Abilities.Avatar.ElementSphere.Enabled", true); + config.addDefault("Abilities.Avatar.ElementSphere.Description", "ElementSphere is a very all round ability, being " + + "able to shoot attacks of each element, each with a " + + "different effect. To use, simply Left-Click. Once active, " + + "Sneak (Default: Shift) to fly around. Sneak and double " + + "Left-Click to disable the ability! " + + "To use each element, simply select hotbar slots 1-4 and Left-Click. " + + "Each element has limited uses! Once an element is used up, " + + "the element's ring will disappear!"); + config.addDefault("Abilities.Avatar.ElementSphere.Cooldown", 180000); + config.addDefault("Abilities.Avatar.ElementSphere.Duration", 60000); + config.addDefault("Abilities.Avatar.ElementSphere.MaxControlledHeight", 40); + config.addDefault("Abilities.Avatar.ElementSphere.FlySpeed", 1.5); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Knockback", 2); + config.addDefault("Abilities.Avatar.ElementSphere.Air.Speed", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactCraterSize", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Earth.ImpactRevert", 15000); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.BurnDuration", 3000); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Speed", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Fire.Controllable", false); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Uses", 20); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Damage", 3.0); + config.addDefault("Abilities.Avatar.ElementSphere.Water.Speed", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Cooldown", 500); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Range", 40); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Knockback", 2.0); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.Damage", 12.0); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.RequiredUses", 10); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.EndAbility", true); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactCraterSize", 3); + config.addDefault("Abilities.Avatar.ElementSphere.Stream.ImpactRevert", 30000); + + config.addDefault("Abilities.Avatar.SpiritBeam.Enabled", true); + config.addDefault("Abilities.Avatar.SpiritBeam.Description", "An energybending ability usable by the Avatar. " + + "To use, one must enter the AvatarState and hold down Sneak (Default: Shift). " + + "This ability lasts only for a few seconds before requiring " + + "another activation."); + config.addDefault("Abilities.Avatar.SpiritBeam.Cooldown", 15000); + config.addDefault("Abilities.Avatar.SpiritBeam.Duration", 1000); + config.addDefault("Abilities.Avatar.SpiritBeam.Range", 40); + config.addDefault("Abilities.Avatar.SpiritBeam.Damage", 10.0); + config.addDefault("Abilities.Avatar.SpiritBeam.AvatarStateOnly", true); + config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Enabled", true); + config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Radius", 3); + config.addDefault("Abilities.Avatar.SpiritBeam.BlockDamage.Regen", 20000); + + config.addDefault("Abilities.Air.AirBlade.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.Description", "With this ability bound, Left-Click to shoot " + + "a strong blade of air at your targets to deal some damage!"); + config.addDefault("Abilities.Air.AirBlade.Cooldown", 3000); + config.addDefault("Abilities.Air.AirBlade.Range", 30.0); + config.addDefault("Abilities.Air.AirBlade.Damage", 4.0); + config.addDefault("Abilities.Air.AirBlade.Speed", 1.0); + config.addDefault("Abilities.Air.AirBlade.Knockback", 0.0); + config.addDefault("Abilities.Air.AirBlade.EntityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirBlade.AbilityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveFirst", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlast.RemoveSecond", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveFirst", true); + config.addDefault("Abilities.Air.AirBlade.Collisions.FireBlastCharged.RemoveSecond", false); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.Enabled", true); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.Revert", true); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.RevertTime", 5000); + config.addDefault("Abilities.Air.AirBlade.BlockCutting.Materials", Arrays.asList( + "#small_flowers", + "#flowers", + "#crops", + "#saplings", + "BIG_DRIPLEAF_STEM", + "BIG_DRIPLEAF", + "CAVE_VINES", + "CAVE_VINES_PLANT", + "VINE", + "FERN", + "LARGE_FERN", + "SHORT_GRASS", + "TALL_GRASS", + "DEAD_BUSH", + "SEA_PICKLE", + "CACTUS_FLOWER", + "BERRY_BUSH", + "RED_MUSHROOM", + "BROWN_MUSHROOM" + )); + + config.addDefault("Abilities.Air.AirBreath.Enabled", true); + config.addDefault("Abilities.Air.AirBreath.Description", "To use, hold Sneak (Default: Shift) to release " + + "a strong breath of wind, knocking your opponents " + + "back. This ability also has a longer range and " + + "stronger knockback while in AvatarState!"); + config.addDefault("Abilities.Air.AirBreath.Cooldown", 3000); + config.addDefault("Abilities.Air.AirBreath.Duration", 3000); + config.addDefault("Abilities.Air.AirBreath.Particles", 3); + config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Lava", true); + config.addDefault("Abilities.Air.AirBreath.AffectBlocks.Fire", true); + config.addDefault("Abilities.Air.AirBreath.ExtinguishEntities", true); + config.addDefault("Abilities.Air.AirBreath.Damage.Enabled", false); + config.addDefault("Abilities.Air.AirBreath.Damage.Player", 1.0); + config.addDefault("Abilities.Air.AirBreath.Damage.Mob", 2.0); + config.addDefault("Abilities.Air.AirBreath.Knockback", 0.8); + config.addDefault("Abilities.Air.AirBreath.Range", 10); + config.addDefault("Abilities.Air.AirBreath.LaunchPower", 1.0); + config.addDefault("Abilities.Air.AirBreath.RegenTargetOxygen", true); + config.addDefault("Abilities.Air.AirBreath.Avatar.Enabled", true); + config.addDefault("Abilities.Air.AirBreath.Avatar.Range", 20); + config.addDefault("Abilities.Air.AirBreath.Avatar.Knockback", 3.5); + + config.addDefault("Abilities.Air.AirGlide.Enabled", true); + config.addDefault("Abilities.Air.AirGlide.Description", "While falling, tap Sneak for a " + + "slow and steady descent. Tap Sneak again to stop gliding."); + config.addDefault("Abilities.Air.AirGlide.Speed", 0.5); + config.addDefault("Abilities.Air.AirGlide.FallSpeed", 0.1); + config.addDefault("Abilities.Air.AirGlide.Particles", 4); + config.addDefault("Abilities.Air.AirGlide.AllowAirSpout", false); + config.addDefault("Abilities.Air.AirGlide.Cooldown", 0); + config.addDefault("Abilities.Air.AirGlide.Duration", 0); + config.addDefault("Abilities.Air.AirGlide.RequireGround", false); + + config.addDefault("Abilities.Air.AirPunch.Enabled", true); + config.addDefault("Abilities.Air.AirPunch.Description", "Left-Click in rapid succession to punch high desnity packets of air " + + "at enemies to do slight damage. A few punches can be thrown before the ability goes on cooldown."); + config.addDefault("Abilities.Air.AirPunch.Cooldown", 5000); + config.addDefault("Abilities.Air.AirPunch.Threshold", 500); + config.addDefault("Abilities.Air.AirPunch.Shots", 4); + config.addDefault("Abilities.Air.AirPunch.Range", 30); + config.addDefault("Abilities.Air.AirPunch.Damage", 1.0); + config.addDefault("Abilities.Air.AirPunch.Speed", 1.0); + config.addDefault("Abilities.Air.AirPunch.EntityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirPunch.AbilityCollisionRadius", 1.0); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.Enabled", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveFirst", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlast.RemoveSecond", false); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.Enabled",true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveFirst",true); + config.addDefault("Abilities.Air.AirPunch.Collisions.FireBlastCharged.RemoveSecond",false); + config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.Enabled", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveFirst", true); + config.addDefault("Abilities.Air.AirPunch.Collisions.AirBlade.RemoveSecond", false); + + config.addDefault("Abilities.Air.Meditate.Enabled", true); + config.addDefault("Abilities.Air.Meditate.Description", "Hold Sneak (Default: Shift) to start meditating. " + + "After you have focused your energy, you will obtain several buffs."); + config.addDefault("Abilities.Air.Meditate.UnfocusMessage", "You have become unfocused due to taking damage!"); + config.addDefault("Abilities.Air.Meditate.LossFocusMessage", true); + config.addDefault("Abilities.Air.Meditate.ChargeTime", 5000); + config.addDefault("Abilities.Air.Meditate.Cooldown", 60000); + config.addDefault("Abilities.Air.Meditate.BoostDuration", 20000); + config.addDefault("Abilities.Air.Meditate.ParticleDensity", 5); + config.addDefault("Abilities.Air.Meditate.AbsorptionBoost", 2); + config.addDefault("Abilities.Air.Meditate.SpeedBoost", 3); + config.addDefault("Abilities.Air.Meditate.JumpBoost", 3); + + config.addDefault("Abilities.Air.SonicBlast.Enabled", true); + config.addDefault("Abilities.Air.SonicBlast.Description", "SonicBlast is a soundbending ability, known by very few airbenders. " + + "It allows the airbender to stun and deafen an opponent by creating a sonic blast. " + + "This is achieved by creating two regions of high and low pressure and bringing them together. " + + "To use, hold Sneak (Default: Shift) in the direction of the target. Once particles appear " + + "around you, let go of Sneak to shoot a SonicBlast at your target! The technique is very powerful, " + + "even if it doesn't seem it, and comes with a short cooldown."); + config.addDefault("Abilities.Air.SonicBlast.ChargeTime", 2000); + config.addDefault("Abilities.Air.SonicBlast.Damage", 4.0); + config.addDefault("Abilities.Air.SonicBlast.Effects.BlindnessDuration", 5000); + config.addDefault("Abilities.Air.SonicBlast.Effects.NauseaDuration", 5000); + config.addDefault("Abilities.Air.SonicBlast.Cooldown", 6000); + config.addDefault("Abilities.Air.SonicBlast.EntityCollisionRadius", 1.3); + config.addDefault("Abilities.Air.SonicBlast.AbilityCollisionRadius", 1.3); + config.addDefault("Abilities.Air.SonicBlast.Range", 20); + config.addDefault("Abilities.Air.SonicBlast.ChargeSwapping", true); + + config.addDefault("Abilities.Air.AirCombo.AirSlam.Enabled", true); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Description", "Kick your enemy up into the air then blast them away!"); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Cooldown", 8000); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Power", 5.0); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Range", 8); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Combination", Arrays.asList("AirSwipe:SHIFT_DOWN", "AirBlast:SHIFT_UP", "AirBlast:SHIFT_DOWN")); + config.addDefault("Abilities.Air.AirCombo.AirSlam.Instructions", "AirSwipe (Hold sneak) > AirBlast (Release sneak) > AirBlast (Hold sneak)"); + + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Enabled", true); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Description", "Create a stream of air as you fly which causes nearby " + + "entities to be thrown in your direction."); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.DragFactor", 1.5); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Duration", 2000); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Cooldown", 6000); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Combination", Arrays.asList("Flight:SHIFT_DOWN", "Flight:SHIFT_UP", "Flight:SHIFT_DOWN", "Flight:SHIFT_UP")); + config.addDefault("Abilities.Air.AirCombo.SwiftStream.Instructions", "Flight (Double tap sneak)"); + + config.addDefault("Abilities.Earth.EarthArmor.Enabled", true); + config.addDefault("Abilities.Earth.EarthArmor.Description", "If the block is metal, then you will get metal armor!"); + config.addDefault("Abilities.Earth.EarthArmor.Resistance.Strength", 2); + config.addDefault("Abilities.Earth.EarthArmor.Resistance.Duration", 4000); + config.addDefault("Abilities.Earth.EarthArmor.UseIronArmor", false); + + config.addDefault("Abilities.Earth.EarthKick.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Description", "This move enables an earthbender to create a " + + "large earthen cover, ideal for defense. " + + "To use, Sneak (Default: Shift) at an earth " + + "source and it will raise and launch towards " + + "your foe!"); + config.addDefault("Abilities.Earth.EarthKick.Cooldown", 2000); + config.addDefault("Abilities.Earth.EarthKick.EarthBlocks", 10); + + double oldDamage = 0.0; + if (config.contains("Abilities.Earth.EarthKick.Damage")) { + oldDamage = config.getDouble("Abilities.Earth.EarthKick.Damage"); + config.set("Abilities.Earth.EarthKick.Damage", null); + } + + config.addDefault("Abilities.Earth.EarthKick.Damage.Normal", oldDamage > 0.0 ? oldDamage : 2.0); + config.addDefault("Abilities.Earth.EarthKick.Damage.Metal", 3.0); + config.addDefault("Abilities.Earth.EarthKick.EntityCollisionRadius", 1.5); + config.addDefault("Abilities.Earth.EarthKick.AbilityCollisionRadius", 1.5); + config.addDefault("Abilities.Earth.EarthKick.MultipleHits", true); + config.addDefault("Abilities.Earth.EarthKick.SourceRange", 2.0); + config.addDefault("Abilities.Earth.EarthKick.Spread", 20); + config.addDefault("Abilities.Earth.EarthKick.Velocity", 0.7); + config.addDefault("Abilities.Earth.EarthKick.AllowMetal", true); + config.addDefault("Abilities.Earth.EarthKick.ReplaceSource", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.FireBlast.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.EarthBlast.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterManipulation.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSwipe.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.Combustion.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.WaterSpout.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirSpout.RemoveSecond", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.Enabled", true); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveFirst", false); + config.addDefault("Abilities.Earth.EarthKick.Collisions.AirWheel.RemoveSecond", true); + + + config.addDefault("Abilities.Earth.EarthLine.Enabled", true); + config.addDefault("Abilities.Earth.EarthLine.Description", "To use, place your cursor over an earth-bendable block on the ground, " + + "then Sneak (Default: Shift) to select the block. After selecting the block you may release Sneak. " + + "If you then Left-Click at an object or player, a small piece of earth will come up " + + "from the ground and move towards your target to deal damage and knock them back. " + + "Additionally, hold Sneak to control the flow of the line!"); + config.addDefault("Abilities.Earth.EarthLine.Cooldown", 3000); + config.addDefault("Abilities.Earth.EarthLine.PrepareCooldown", 0); + config.addDefault("Abilities.Earth.EarthLine.Range", 30); + config.addDefault("Abilities.Earth.EarthLine.PrepareRange", 3); + config.addDefault("Abilities.Earth.EarthLine.SourceKeepRange", 7); + config.addDefault("Abilities.Earth.EarthLine.AffectingRadius", 2); + config.addDefault("Abilities.Earth.EarthLine.AllowChangeDirection", true); + config.addDefault("Abilities.Earth.EarthLine.MaxDuration", 2500); + config.addDefault("Abilities.Earth.EarthLine.Damage", 3.0); + config.addDefault("Abilities.Earth.EarthLine.RemovalPolicy.SwappedSlots.Enabled", false); + + config.addDefault("Abilities.Earth.EarthPillar.Enabled", true); + config.addDefault("Abilities.Earth.EarthPillar.Description", "With this ability bound, tap Sneak (Default: Shift) on any Earthbendable " + + "surface to create pillar of earth in the direction of the block face!"); + config.addDefault("Abilities.Earth.EarthPillar.Height", 6); + config.addDefault("Abilities.Earth.EarthPillar.Range", 10); + + config.addDefault("Abilities.Earth.EarthShard.Enabled", true); + config.addDefault("Abilities.Earth.EarthShard.Description", "EarthShard is a variation of EarthBlast " + + "which the earthbender may use to hit a target. This " + + "ability deals a fair amount of damage and is easy to " + + "rapid-fire. To use, simply shift at an earthbendable block, " + + "and it will ascend to your eye height. Then, click towards your " + + "target and the block will launch itself towards it."); + config.addDefault("Abilities.Earth.EarthShard.Cooldown", 1000); + config.addDefault("Abilities.Earth.EarthShard.Damage.Normal", 1.0); + config.addDefault("Abilities.Earth.EarthShard.Damage.Metal", 1.5); + config.addDefault("Abilities.Earth.EarthShard.PrepareRange", 5); + config.addDefault("Abilities.Earth.EarthShard.AbilityRange", 30); + config.addDefault("Abilities.Earth.EarthShard.MaxShards", 3); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Allow", true); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Velocity", 1.0); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Others.Range", 1.5); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Allow", true); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Velocity", 1.0); + config.addDefault("Abilities.Earth.EarthShard.KnockUp.Self.Range", 1.5); +// config.addDefault("Abilities.Earth.EarthShard.KnockUp.Allow", true); +// config.addDefault("Abilities.Earth.EarthShard.KnockUp.Velocity", 1.0); + config.addDefault("Abilities.Earth.EarthShard.AbilityCollisionRadius", 2.0); + config.addDefault("Abilities.Earth.EarthShard.EntityCollisionRadius", 1.4); + + config.addDefault("Abilities.Earth.EarthSurf.Enabled", true); + config.addDefault("Abilities.Earth.EarthSurf.Description", "This ability allows an earth bender to " + + "ride up on a wave of earth, allowing them to travel a little faster than " + + "normal. To use, simply be in the air just above " + + "the ground, and Left Click! Additionally, if an entity just so happens to get caught in " + + "the wave, they will be moved with the wave."); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Cooldown", 3000); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.MinimumCooldown", 2000); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Scaled", true); + config.addDefault("Abilities.Earth.EarthSurf.Cooldown.Enabled", false); + config.addDefault("Abilities.Earth.EarthSurf.Duration.Duration", 7000); + config.addDefault("Abilities.Earth.EarthSurf.Duration.Enabled", false); + config.addDefault("Abilities.Earth.EarthSurf.RelaxedCollisions", true); + config.addDefault("Abilities.Earth.EarthSurf.RemoveOnAnyDamage", false); + config.addDefault("Abilities.Earth.EarthSurf.Speed", 0.55); + config.addDefault("Abilities.Earth.EarthSurf.HeightTolerance", 3); + config.addDefault("Abilities.Earth.EarthSurf.SpringStiffness", 0.35); + + config.addDefault("Abilities.Earth.Fissure.Enabled", true); + config.addDefault("Abilities.Earth.Fissure.Description", "Fissure is an advanced Lavabending " + + "ability enabling a lavabender to tear up the ground, " + + "swallowing up any enemies. To use, simply swing at an enemy " + + "and a line of lava will crack open. " + + "Then, tap Sneak (Default: Shift) to expand the crevice. " + + "The crevice has a maximum width and depth. Once the crevice has reached it's maximum " + + "width, Sneak while looking at the crevice to close it!"); + config.addDefault("Abilities.Earth.Fissure.Cooldown", 20000); + config.addDefault("Abilities.Earth.Fissure.Duration", 15000); + config.addDefault("Abilities.Earth.Fissure.MaxWidth", 3); + config.addDefault("Abilities.Earth.Fissure.SlapRange", 12); + config.addDefault("Abilities.Earth.Fissure.SlapDelay", 50); + + config.addDefault("Abilities.Earth.LavaDisc.Enabled", true); + config.addDefault("Abilities.Earth.LavaDisc.Description", "Hold Sneak (Default: Shift) on a lava source " + + "block to generate a disc of lava at your finger tips. Releasing " + + "Sneak will shoot the disc off in the direction " + + "you are looking! If you tap or hold Sneak again, " + + "the disc will attempt to return to you!"); + String[] meltable = { + Material.COBBLESTONE.name(), Material.OAK_LOG.name(), Material.SPRUCE_LOG.name(), + Material.JUNGLE_LOG.name(), Material.DARK_OAK_LOG.name(), Material.BIRCH_LOG.name(), + Material.ACACIA_LOG.name() + }; + config.addDefault("Abilities.Earth.LavaDisc.Cooldown", 7000); + config.addDefault("Abilities.Earth.LavaDisc.Duration", 1000); + config.addDefault("Abilities.Earth.LavaDisc.Damage", 4.0); + config.addDefault("Abilities.Earth.LavaDisc.Particles", 3); + config.addDefault("Abilities.Earth.LavaDisc.ContinueAfterEntityHit", false); + config.addDefault("Abilities.Earth.LavaDisc.RecallLimit", 3); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.RegenTime", 5000); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.BlockDamage", true); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.AdditionalMeltableBlocks", meltable); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.LavaTrail", true); + config.addDefault("Abilities.Earth.LavaDisc.Destroy.TrailFlow", false); + config.addDefault("Abilities.Earth.LavaDisc.Source.RegenTime", 10000); + config.addDefault("Abilities.Earth.LavaDisc.Source.LavaOnly", false); + config.addDefault("Abilities.Earth.LavaDisc.Source.Range", 4.0); + config.addDefault("Abilities.Earth.LavaDisc.RemovalPolicy.SwappedSlots.Enabled", true); + + config.addDefault("Abilities.Earth.LavaFlux.Enabled", true); + config.addDefault("Abilities.Earth.LavaFlux.Description", "This offensive ability enables a Lavabender to create a wave of lava, " + + "swiftly progressing forward and hurting/burning anything in its way. To use, " + + "simply swing your arm towards a target and the ability will activate."); + config.addDefault("Abilities.Earth.LavaFlux.Range", 12); + config.addDefault("Abilities.Earth.LavaFlux.Cooldown", 8000); + config.addDefault("Abilities.Earth.LavaFlux.Duration", 4000); + config.addDefault("Abilities.Earth.LavaFlux.Cleanup", 1000); + config.addDefault("Abilities.Earth.LavaFlux.Damage", 1.0); + config.addDefault("Abilities.Earth.LavaFlux.Speed", 1); + config.addDefault("Abilities.Earth.LavaFlux.Wave", true); + config.addDefault("Abilities.Earth.LavaFlux.KnockUp", 1.0); + config.addDefault("Abilities.Earth.LavaFlux.KnockBack", 1.0); + + config.addDefault("Abilities.Earth.LavaThrow.Enabled", true); + config.addDefault("Abilities.Earth.LavaThrow.Description", "Throwing lava is a fundamental technique for the rare subskill. " + + "Use Sneak(Deafult: Shift) while looking at a pool of lava infront of you, then " + + "Left-Click to splash the lava at your target. " + + "It can be used in rapid succession to create multiple streams of lava!"); + config.addDefault("Abilities.Earth.LavaThrow.Cooldown", 7000); + config.addDefault("Abilities.Earth.LavaThrow.MaxShots", 6); + config.addDefault("Abilities.Earth.LavaThrow.Range", 20); + config.addDefault("Abilities.Earth.LavaThrow.Damage", 1.0); + config.addDefault("Abilities.Earth.LavaThrow.SourceGrabRange", 4); + config.addDefault("Abilities.Earth.LavaThrow.SourceRegenDelay", 10000); + config.addDefault("Abilities.Earth.LavaThrow.FireTicks", 80); + config.addDefault("Abilities.Earth.LavaThrow.CurveFactor", 0.5); + + config.addDefault("Abilities.Earth.MagnetShield.Enabled", true); + config.addDefault("Abilities.Earth.MagnetShield.Description", "Repel any metal projectiles using a strong magnetic shield. " + + "To activate, simply hold sneak with this ability bound."); + config.addDefault("Abilities.Earth.MagnetShield.Materials", Arrays.asList( + "IRON_INGOT", + "IRON_HELMET", + "IRON_CHESTPLATE", + "IRON_LEGGINGS", + "IRON_BOOTS", + "IRON_BLOCK", + "IRON_AXE", + "IRON_PICKAXE", + "IRON_SWORD", + "IRON_HOE", + "IRON_SHOVEL", + "IRON_DOOR", + "IRON_NUGGET", + "IRON_BARS", + "IRON_HORSE_ARMOR", + "IRON_TRAPDOOR", + "HEAVY_WEIGHTED_PRESSURE_PLATE", + "GOLD_INGOT", + "GOLDEN_HELMET", + "GOLDEN_CHESTPLATE", + "GOLDEN_LEGGINGS", + "GOLDEN_BOOTS", + "GOLD_BLOCK", + "GOLD_NUGGET", + "GOLDEN_AXE", + "GOLDEN_PICKAXE", + "GOLDEN_SHOVEL", + "GOLDEN_SWORD", + "GOLDEN_HOE", + "GOLDEN_HORSE_ARMOR", + "LIGHT_WEIGHTED_PRESSURE_PLATE", + "CLOCK", + "COMPASS", + "RAW_GOLD_BLOCK", + "RAW_IRON_BLOCK", + "RAW_IRON", + "RAW_GOLD", + "ANVIL", + "CHIPPED_ANVIL", + "DAMAGED_ANVIL", + "IRON_ORE", + "GOLD_ORE", + "DEEPSLATE_IRON_ORE", + "DEEPSLATE_GOLD_ORE", + "SHIELD" + )); + config.addDefault("Abilities.Earth.MagnetShield.Duration", 6000); + config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Shift", 5000); + config.addDefault("Abilities.Earth.MagnetShield.Cooldowns.Click", 5000); + config.addDefault("Abilities.Earth.MagnetShield.Range", 5.0); + config.addDefault("Abilities.Earth.MagnetShield.RepelArrows", true); + config.addDefault("Abilities.Earth.MagnetShield.RepelLivingEntities", true); + config.addDefault("Abilities.Earth.MagnetShield.Velocity", 0.1); + + config.addDefault("Abilities.Earth.MetalFragments.Enabled", true); + config.addDefault("Abilities.Earth.MetalFragments.Description", "MetalFragments allows you to select a source and shoot " + + "multiple fragments of metal out of that source " + + "block towards your target, injuring them on impact. " + + "To use, tap Sneak (Default: Shift) at a metal " + + "source block and it will float up. Then, turn around " + + "and click at your target to fling metal fragments at them."); + config.addDefault("Abilities.Earth.MetalFragments.Cooldown", 5000); + config.addDefault("Abilities.Earth.MetalFragments.MaxSources", 3); + config.addDefault("Abilities.Earth.MetalFragments.SourceRange", 5); + config.addDefault("Abilities.Earth.MetalFragments.MaxFragments", 10); + config.addDefault("Abilities.Earth.MetalFragments.Damage", 4.0); + config.addDefault("Abilities.Earth.MetalFragments.Velocity", 2.0); + + config.addDefault("Abilities.Earth.MetalHook.Enabled", true); + config.addDefault("Abilities.Earth.MetalHook.Description", "This ability lets a Metalbender bend metal into " + + "grappling hooks, allowing them to easily manouver terrain. " + + "To use this ability, the user must either have Iron in their inventory " + + "or be wearing an Iron/Chainmail Chestplate. Left-Click in the direction " + + "you are looking to fire a grappling hook, several hooks can be active at once, " + + "allowing the bender to 'hang' in locations. To disengage the hooks, hold Shift (Default: Sneak) or Sprint."); + config.addDefault("Abilities.Earth.MetalHook.Cooldown", 3000); + config.addDefault("Abilities.Earth.MetalHook.Range", 30); + config.addDefault("Abilities.Earth.MetalHook.MaxHooks", 3); + config.addDefault("Abilities.Earth.MetalHook.TotalHooks", 0); + config.addDefault("Abilities.Earth.MetalHook.RequireItems", true); + config.addDefault("Abilities.Earth.MetalHook.BarrierHooking", true); + + config.addDefault("Abilities.Earth.MetalShred.Enabled", true); + config.addDefault("Abilities.Earth.MetalShred.Description", "MetalShred allows you to tear a metal surface allowing you to sneak in to the other side." + + "To use, you must find a flat metal surface. Then, Sneak(Default: Shift) " + + "at a piece of metal on that surface, and two pieces of metal " + + "will be pulled toward you. Finally, run alongside the surface to coil " + + "the metal around those two pieces. The way will be open, and the blocks " + + "will not reset until you either select a new source or you switch " + + "abilities. If you click after having torn a hole in a vertical surface, " + + "you can Left-Click in any direction and the metal will unfold in that " + + "direction. If you are fast and precise enough, the metal can bend in " + + "any shape. The length of this sheet of metal depends on how much was " + + "coiled in the first place."); + config.addDefault("Abilities.Earth.MetalShred.SourceRange", 5); config.addDefault("Abilities.Earth.MetalShred.ExtendTick", 80); config.addDefault("Abilities.Earth.MetalShred.Damage", 6.0); - + config.addDefault("Abilities.Earth.MudSurge.Enabled", true); - config.addDefault("Abilities.Earth.MudSurge.Description", "This ability lets an earthbender send a surge of mud " - + "in any direction, knocking back enemies and " - + "dealing moderate damage. This ability has a chance " - + "of blinding the target. To use, select " - + "a source of earth and click in any direction."); - config.addDefault("Abilities.Earth.MudSurge.Cooldown", 6000); - config.addDefault("Abilities.Earth.MudSurge.Damage", 1.0); - config.addDefault("Abilities.Earth.MudSurge.Waves", 5); - config.addDefault("Abilities.Earth.MudSurge.SourceRange", 7); - config.addDefault("Abilities.Earth.MudSurge.BlindChance", 10); - config.addDefault("Abilities.Earth.MudSurge.WetSourceOnly", false); - config.addDefault("Abilities.Earth.MudSurge.WaterSearchRadius", 5); - config.addDefault("Abilities.Earth.MudSurge.BlindTicks", 60); - config.addDefault("Abilities.Earth.MudSurge.CollisionRadius", 2.0); - config.addDefault("Abilities.Earth.MudSurge.MultipleHits", true); - config.addDefault("Abilities.Earth.MudSurge.AllowFallDamage", false); - config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.SwappedSlots.Enabled", true); - config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Enabled", true); - config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Range", 25.0); - - config.addDefault("Abilities.Earth.SandBlast.Enabled", true); - config.addDefault("Abilities.Earth.SandBlast.Description", "This ability lets an earthbender blast a bunch of sand at an enemy " - + "damaging them and temporarily blinding them! Just Sneak (Default: Shift) " - + "on a sand bendable block, then Left-Click in a direction to shoot a " - + "blast of sand!"); - config.addDefault("Abilities.Earth.SandBlast.Cooldown", 3000); - config.addDefault("Abilities.Earth.SandBlast.Damage", 3.0); - config.addDefault("Abilities.Earth.SandBlast.SourceRange", 8); - config.addDefault("Abilities.Earth.SandBlast.Range", 30); - config.addDefault("Abilities.Earth.SandBlast.MaxSandBlocks", 10); - - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Enabled", true); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Description", "Create a Crevice in the ground! Once opened, " - + "anyone can Tap Sneak with Shockwave to close the Crevice!"); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Range", 50); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.RevertDelay", 7500); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Depth", 5); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth", 8); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Cooldown", 10000); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Combination", Arrays.asList("Collapse:RIGHT_CLICK_BLOCK", "Shockwave:SHIFT_DOWN", "Shockwave:SHIFT_UP", "Shockwave:SHIFT_DOWN")); - config.addDefault("Abilities.Earth.EarthCombo.Crevice.Instructions", "Collapse (Right-click a block) > Shockwave (Tap sneak) > Shockwave (Tap sneak)"); - - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Enabled", true); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Description", "Fire balls of magma at your enemy!"); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots", 3); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage", 2.0); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange", 4); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown", 6000); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown", 1500); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow", false); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions", true); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection", true); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange", 30.0); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius", 2.0); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed", 1.5); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration", 15000); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources", 15); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Combination", Arrays.asList("EarthBlast:SHIFT_DOWN", "LavaFlow:SHIFT_UP", "LavaFlow:SHIFT_DOWN", "LavaFlow:RIGHT_CLICK_BLOCK")); - config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Instructions", "EarthBlast (Hold sneak) > LavaFlow (Release sneak) > LavaFlow (Hold sneak) > LavaFlow (Right-click a block) > LavaFlow (Left-click multiple times)"); - - ArrayList combustionSkipMaterials = new ArrayList<>(); - combustionSkipMaterials.add("#bee_growables"); - combustionSkipMaterials.add("#cave_vines"); - combustionSkipMaterials.add("#crops"); - combustionSkipMaterials.add("#flowers"); - combustionSkipMaterials.add("vine"); - combustionSkipMaterials.add("pale_hanging_moss"); - - config.addDefault("Abilities.Fire.Combustion.Enabled", true); - config.addDefault("Abilities.Fire.Combustion.Description", "Hold Shift to focus large amounts of energy into your body, " - + "Release Shift to fire Combustion. Move your mouse to " - + "direct where the beam travels. Left-Click to detonate " - + "the beam manually"); - config.addDefault("Abilities.Fire.Combustion.Damage", 4.0); - config.addDefault("Abilities.Fire.Combustion.FireTick", 100); - config.addDefault("Abilities.Fire.Combustion.MisfireModifier", -1); - config.addDefault("Abilities.Fire.Combustion.Power", 3); - config.addDefault("Abilities.Fire.Combustion.Range", 100); - config.addDefault("Abilities.Fire.Combustion.Speed", 0.65); - config.addDefault("Abilities.Fire.Combustion.Warmup", 1500); - config.addDefault("Abilities.Fire.Combustion.Cooldown", 5000); - config.addDefault("Abilities.Fire.Combustion.RegenTime", 10000); - config.addDefault("Abilities.Fire.Combustion.EntityCollisionRadius", 1.3); - config.addDefault("Abilities.Fire.Combustion.AbilityCollisionRadius", 1.3); - config.addDefault("Abilities.Fire.Combustion.DamageBlocks", true); - config.addDefault("Abilities.Fire.Combustion.RegenBlocks", true); - config.addDefault("Abilities.Fire.Combustion.WaitForRegen", true); - config.addDefault("Abilities.Fire.Combustion.InstantExplodeIfHit", true); - config.addDefault("Abilities.Fire.Combustion.ExplodeOnDeath", true); - config.addDefault("Abilities.Fire.Combustion.RemovalPolicy.SwappedSlots.Enabled", false); - config.addDefault("Abilities.Fire.Combustion.SkipMaterials", combustionSkipMaterials); - - config.addDefault("Abilities.Fire.Discharge.Enabled", true); - config.addDefault("Abilities.Fire.Discharge.Description", "Left-Click to shoot bolts of electricity out " - + "of your fingertips zapping what ever it hits!"); - config.addDefault("Abilities.Fire.Discharge.Damage", 3.0); - config.addDefault("Abilities.Fire.Discharge.Cooldown", 5000); - config.addDefault("Abilities.Fire.Discharge.AvatarCooldown", 500); - config.addDefault("Abilities.Fire.Discharge.Duration", 1000); - config.addDefault("Abilities.Fire.Discharge.SlotSwapping", false); - config.addDefault("Abilities.Fire.Discharge.EntityCollisionRadius", 1.0); - config.addDefault("Abilities.Fire.Discharge.AbilityCollisionRadius", 1.0); - config.addDefault("Abilities.Fire.Discharge.Sound.Volume", 0.6); - config.addDefault("Abilities.Fire.Discharge.Sound.Interval", 6); - - config.addDefault("Abilities.Fire.FireBall.Enabled", true); - config.addDefault("Abilities.Fire.FireBall.Description", "To use, simply Left-Click to shoot a fireball at your target!"); - config.addDefault("Abilities.Fire.FireBall.Cooldown", 3000); - config.addDefault("Abilities.Fire.FireBall.Range", 50); - config.addDefault("Abilities.Fire.FireBall.Damage", 3.0); - config.addDefault("Abilities.Fire.FireBall.FireDuration", 2000); - config.addDefault("Abilities.Fire.FireBall.Controllable", false); - config.addDefault("Abilities.Fire.FireBall.FireTrail", true); - config.addDefault("Abilities.Fire.FireBall.CollisionRadius", 1.1); - config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.Enabled", true); - config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveFirst", true); - config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Enabled", true); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveFirst", false); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Reflect", true); - - config.addDefault("Abilities.Fire.FireBreath.Enabled", true); - config.addDefault("Abilities.Fire.FireBreath.Description", "To use, hold Sneak (Default: Shift) to start breathing " - + "fire! Some Firebenders possess the power to infuse color " - + "when they breathe, it's unclear how they do this, but some suggest " - + "it can be obtained by saying \"Bring fire and light together as one and allow the breath of color\" " - + "and can be brought back to normal by saying \"Split the bond of fire " - + "and light and set the color free\"."); - config.addDefault("Abilities.Fire.FireBreath.Cooldown", 5000); - config.addDefault("Abilities.Fire.FireBreath.Duration", 3000); - config.addDefault("Abilities.Fire.FireBreath.Particles", 3); - config.addDefault("Abilities.Fire.FireBreath.Damage.Player", 1.0); - config.addDefault("Abilities.Fire.FireBreath.Damage.Mob", 2.0); - config.addDefault("Abilities.Fire.FireBreath.FireDuration", 3000); - config.addDefault("Abilities.Fire.FireBreath.Range", 10); - config.addDefault("Abilities.Fire.FireBreath.Avatar.FireEnabled", true); - config.addDefault("Abilities.Fire.FireBreath.Melt.Enabled", true); - config.addDefault("Abilities.Fire.FireBreath.Melt.Chance", 3); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.Enabled", true); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "You have bonded fire with light and can now breathe pure color."); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "You have split your bond of color and light."); - config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "You don't possess the power to bond light with fire."); - - config.addDefault("Abilities.Fire.FireComet.Enabled", true); - config.addDefault("Abilities.Fire.FireComet.Description", "Harnessing the power of Sozin's Comet, a firebender can create a great " - + "ball of fire, with much destructive power. Only useable during Sozin's Comet or while in the AvatarState, hold Sneak (Default: Shift) " - + "to start charging the ability up. Once the ability is charged, a large mass of particles will follow your cursor, until you release sneak, " - + "launching the great ball of fire in the direction you are looking."); - config.addDefault("Abilities.Fire.FireComet.Cooldown", 45000); - config.addDefault("Abilities.Fire.FireComet.ChargeUp", 7000); - config.addDefault("Abilities.Fire.FireComet.Damage", 6.0); - config.addDefault("Abilities.Fire.FireComet.BlastRadius", 3.0); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.Cooldown", 30000); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.ChargeUp", 5000); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.Damage", 12.0); - config.addDefault("Abilities.Fire.FireComet.SozinsComet.BlastRadius", 5.0); - config.addDefault("Abilities.Fire.FireComet.Range", 50); - config.addDefault("Abilities.Fire.FireComet.RegenDelay", 15000); - config.addDefault("Abilities.Fire.FireComet.SozinsCometOnly", true); - config.addDefault("Abilities.Fire.FireComet.AvatarStateBypassComet", true); - - config.addDefault("Abilities.Fire.FirePunch.Enabled", true); - config.addDefault("Abilities.Fire.FirePunch.Description", "This basic ability allows a Firebender to channel their energies into a " - + "single punch, igniting and damaging the victim."); - config.addDefault("Abilities.Fire.FirePunch.Cooldown", 4000); - config.addDefault("Abilities.Fire.FirePunch.FireTicks", 2000); - config.addDefault("Abilities.Fire.FirePunch.Damage", 2.0); - - config.addDefault("Abilities.Fire.FireShots.Enabled", true); - config.addDefault("Abilities.Fire.FireShots.Description", "To use, tap Sneak (Default: Shift) to summon a " - + "FireBalls at your hand, then Left Click to shoot off each ball! " - + "Each shot will follow the cursor until it runs out or hits something! " - + "Tap Sneak again to switch your main hand."); - config.addDefault("Abilities.Fire.FireShots.Cooldown", 3000); - config.addDefault("Abilities.Fire.FireShots.Range", 50); - config.addDefault("Abilities.Fire.FireShots.FireBalls", 4); - config.addDefault("Abilities.Fire.FireShots.FireDuration", 3000); - config.addDefault("Abilities.Fire.FireShots.Damage", 2.0); - config.addDefault("Abilities.Fire.FireShots.CollisionRadius", 0.9); - config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.Enabled", true); - config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveFirst", true); - config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Enabled", true); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveFirst", false); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveSecond", false); - config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); - - config.addDefault("Abilities.Fire.FireSki.Enabled", true); - config.addDefault("Abilities.Fire.FireSki.Cooldown", 6000); - config.addDefault("Abilities.Fire.FireSki.Duration", 6000); - config.addDefault("Abilities.Fire.FireSki.Speed", 0.7); - config.addDefault("Abilities.Fire.FireSki.IgniteEntities", true); - config.addDefault("Abilities.Fire.FireSki.FireTicks", 60); - config.addDefault("Abilities.Fire.FireSki.RequiredHeight", 0.7); - config.addDefault("Abilities.Fire.FireSki.PunchActivated", false); - - config.addDefault("Abilities.Fire.LightningBurst.Enabled", true); - config.addDefault("Abilities.Fire.LightningBurst.Description", "To use the most explosive lightning move available to a firebender, hold " - + "Sneak (Default: Shift) until blue sparks appear in front of you. Upon releasing, " - + "you will unleash an electrical sphere, shocking anyone who gets too close"); - config.addDefault("Abilities.Fire.LightningBurst.Cooldown", 25000); - config.addDefault("Abilities.Fire.LightningBurst.ChargeUp", 4000); - config.addDefault("Abilities.Fire.LightningBurst.AvatarCooldown", 1000); - config.addDefault("Abilities.Fire.LightningBurst.AvatarChargeUp", 1000); - config.addDefault("Abilities.Fire.LightningBurst.Radius", 12); - config.addDefault("Abilities.Fire.LightningBurst.Damage", 9.0); - config.addDefault("Abilities.Fire.LightningBurst.Sound.Volume", 0.6); - config.addDefault("Abilities.Fire.LightningBurst.Sound.Interval", 6); - - config.addDefault("Abilities.Water.Bloodbending.Enabled", true); - config.addDefault("Abilities.Water.Bloodbending.Description", "This ability allows a skilled waterbender " - + "to bend the water within an enemy's blood, granting them full " - + "control over the enemy's limbs. This ability is extremely dangerous " - + "and is to be used carefully. To use, sneak while looking at an entity " - + "and its body will follow your movement. If you click, you will launch " - + "the entity towards whatever you were looking at when you clicked. The " - + "entity may collide with others, injuring them and the other one further."); - config.addDefault("Abilities.Water.Bloodbending.NightOnly", false); - config.addDefault("Abilities.Water.Bloodbending.FullMoonOnly", false); - config.addDefault("Abilities.Water.Bloodbending.UndeadMobs", true); - config.addDefault("Abilities.Water.Bloodbending.IgnoreWalls", false); - config.addDefault("Abilities.Water.Bloodbending.RequireBound", false); - config.addDefault("Abilities.Water.Bloodbending.Distance", 6); - config.addDefault("Abilities.Water.Bloodbending.HoldTime", 10000); - config.addDefault("Abilities.Water.Bloodbending.Cooldown", 4000); - - config.addDefault("Abilities.Water.BloodPuppet.Enabled", true); - config.addDefault("Abilities.Water.BloodPuppet.Description", "This very high-level bloodbending ability lets " - + "a master control entities' limbs, forcing them to " - + "attack the master's target. To use this ability, you must " - + "be a bloodbender. Next, sneak while targeting " - + "a mob or player and you will start controlling them. To " - + "make the entity hit another, click. To release your " - + "target, stop sneaking. This ability has NO cooldown, but " - + "may only be usable during the night depending on the " - + "server configuration."); - config.addDefault("Abilities.Water.BloodPuppet.NightOnly", false); - config.addDefault("Abilities.Water.BloodPuppet.FullMoonOnly", false); - config.addDefault("Abilities.Water.BloodPuppet.UndeadMobs", true); - config.addDefault("Abilities.Water.BloodPuppet.IgnoreWalls", false); - config.addDefault("Abilities.Water.BloodPuppet.RequireBound", false); - config.addDefault("Abilities.Water.BloodPuppet.Distance", 6); - config.addDefault("Abilities.Water.BloodPuppet.HoldTime", 10000); - config.addDefault("Abilities.Water.BloodPuppet.Cooldown", 4000); - config.addDefault(path + "Enabled", true); - config.addDefault(path + "Cooldown", 10000); - config.addDefault(path + "Damage", 6.0); - config.addDefault(path + "Range", 12); - config.addDefault(path + "Hitradius", 3.0); - config.addDefault(path + "SelfDamage", 2.0); - config.addDefault(path + "Speed", 1.0); - - config.addDefault("Abilities.Water.Drain.Enabled", true); - config.addDefault("Abilities.Water.Drain.Description", "Inspired by how Hama drained water from the fire lilies, many benders " - + "have practiced in the skill of draining water from plants! With this ability bound, " - + "Sneak (Default: Shift) near/around plant sources to drain the water out of them to fill up any " - + "bottles/buckets in your inventory! Alternatively, if you have nothing to fill" - + " and blasts are enabled in the config, you will be able to create mini blasts " - + "of water to shoot at your targets! Aleternatively, this ability can also be used to quickly fill up " - + "bottles from straight water sources or from falling rain!"); - config.addDefault("Abilities.Water.Drain.RegenDelay", 15000); - config.addDefault("Abilities.Water.Drain.Duration", 2000); - config.addDefault("Abilities.Water.Drain.Cooldown", 2000); - config.addDefault("Abilities.Water.Drain.AbsorbSpeed", 0.1); - config.addDefault("Abilities.Water.Drain.AbsorbChance", 20); - config.addDefault("Abilities.Water.Drain.AbsorbRate", 6); - config.addDefault("Abilities.Water.Drain.Radius", 6); - config.addDefault("Abilities.Water.Drain.HoldRange", 2); - config.addDefault("Abilities.Water.Drain.AllowRainSource", true); - config.addDefault("Abilities.Water.Drain.BlastsEnabled", true); - config.addDefault("Abilities.Water.Drain.KeepSource", false); - config.addDefault("Abilities.Water.Drain.BlastSpeed", 1); - config.addDefault("Abilities.Water.Drain.BlastDamage", 1.5); - config.addDefault("Abilities.Water.Drain.BlastRange", 20); - config.addDefault("Abilities.Water.Drain.MaxBlasts", 4); - config.addDefault("Abilities.Water.Drain.DrainTempBlocks", true); - - config.addDefault("Abilities.Water.FrostBreath.Enabled", true); - config.addDefault("Abilities.Water.FrostBreath.Description", "As demonstrated by Katara, a Waterbender is able to freeze their breath, " - + "causing anything it touches to be frozen! With this ability bound, simply hold " - + "Sneak (Default: Shift) to start breathing frost!"); - config.addDefault("Abilities.Water.FrostBreath.Cooldown", 15000); - config.addDefault("Abilities.Water.FrostBreath.Duration", 3000); - config.addDefault("Abilities.Water.FrostBreath.Particles", 3); - config.addDefault("Abilities.Water.FrostBreath.FrostDuration", 5000); - config.addDefault("Abilities.Water.FrostBreath.FrozenWaterDuration", 10000); - config.addDefault("Abilities.Water.FrostBreath.Range", 10); - config.addDefault("Abilities.Water.FrostBreath.Snow", true); - config.addDefault("Abilities.Water.FrostBreath.SnowDuration", 5000); - config.addDefault("Abilities.Water.FrostBreath.BendableSnow", false); - config.addDefault("Abilities.Water.FrostBreath.Damage.Enabled", false); - config.addDefault("Abilities.Water.FrostBreath.Damage.Player", 1.0); - config.addDefault("Abilities.Water.FrostBreath.Damage.Mob", 2.0); - config.addDefault("Abilities.Water.FrostBreath.Slow.Enabled", true); - config.addDefault("Abilities.Water.FrostBreath.Slow.Duration", 4000); - config.addDefault("Abilities.Water.FrostBreath.RestrictBiomes", true); - - config.addDefault("Abilities.Water.HealingWaters.Enabled", true); - config.addDefault("Abilities.Water.HealingWaters.Description", "To use this ability, the bender has to be partially submerged " - + "in water, OR be holding either a bottle of water or a water bucket." - + " This move will heal the player automatically if they have it equipped " - + "and are standing in water. If the player sneaks while in water and is targeting" - + " another entity, the bender will heal the targeted entity. The alternate " - + "healing method requires the bender to be holding a bottle of water or a water" - + " bucket. To start healing simply sneak, however if the bender is targeting " - + "a mob while sneaking, the bender will heal the targeted mob."); - config.addDefault("Abilities.Water.HealingWaters.Power", 1); - config.addDefault("Abilities.Water.HealingWaters.Range", 5); - config.addDefault("Abilities.Water.HealingWaters.DrainChance", 5); - config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Enabled", true); - config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Brightness", 10); - config.addDefault("Abilities.Water.HealingWaters.DynamicLight.KeepAlive", 1500); - - config.addDefault("Abilities.Water.IceClaws.Enabled", true); - config.addDefault("Abilities.Water.IceClaws.Description", "As demonstrated by Hama, a Waterbender can pull water out of thin air to create claws " - + "at the tips of their fingers. With IceClaws bound, hold Sneak (Default: Shift) to " - + "start pulling water out the air until you form claws at your finger " - + "tips, then attack an enemy to slow them down and do a bit of damage!"); - config.addDefault("Abilities.Water.IceClaws.Cooldown", 6000); - config.addDefault("Abilities.Water.IceClaws.ChargeTime", 1000); - config.addDefault("Abilities.Water.IceClaws.SlowDuration", 5000); - config.addDefault("Abilities.Water.IceClaws.Damage", 3.0); - config.addDefault("Abilities.Water.IceClaws.Range", 10); - config.addDefault("Abilities.Water.IceClaws.Throwable", true); - - config.addDefault("Abilities.Water.IceWall.Enabled", true); - config.addDefault("Abilities.Water.IceWall.Description", "IceWall allows an icebender to create a wall of ice, similar to " - + "raiseearth. To use, simply sneak while targeting either water, ice, or snow. " - + "To break the wall, you must sneak again while targeting it. Be aware that " - + "other icebenders can break your own shields, and if you are too close you " - + "can get hurt by the shards."); - config.addDefault("Abilities.Water.IceWall.Cooldown", 4000); - config.addDefault("Abilities.Water.IceWall.Width", 6); - config.addDefault("Abilities.Water.IceWall.MaxHeight", 5); - config.addDefault("Abilities.Water.IceWall.MinHeight", 3); - config.addDefault("Abilities.Water.IceWall.MaxWallHealth", 12); - config.addDefault("Abilities.Water.IceWall.MinWallHealth", 8); - config.addDefault("Abilities.Water.IceWall.Range", 8); - config.addDefault("Abilities.Water.IceWall.Damage", 4.0); - config.addDefault("Abilities.Water.IceWall.CanBreak", true); - config.addDefault("Abilities.Water.IceWall.Stackable", false); - config.addDefault("Abilities.Water.IceWall.LifeTime.Enabled", false); - config.addDefault("Abilities.Water.IceWall.LifeTime.Duration", 10000); - config.addDefault("Abilities.Water.IceWall.WallDamage", true); - config.addDefault("Abilities.Water.IceWall.WallDamage.Torrent", 5); - config.addDefault("Abilities.Water.IceWall.WallDamage.TorrentFreeze", 9); - config.addDefault("Abilities.Water.IceWall.WallDamage.IceBlast", 8); - config.addDefault("Abilities.Water.IceWall.WallDamage.Fireblast", 3); - config.addDefault("Abilities.Water.IceWall.WallDamage.FireblastCharged", 5); - config.addDefault("Abilities.Water.IceWall.WallDamage.Lightning", 12); - config.addDefault("Abilities.Water.IceWall.WallDamage.Combustion", 12); - config.addDefault("Abilities.Water.IceWall.WallDamage.EarthSmash", 8); - config.addDefault("Abilities.Water.IceWall.WallDamage.AirBlast", 2); - - config.addDefault("Abilities.Water.WakeFishing.Enabled", true); - config.addDefault("Abilities.Water.WakeFishing.Description", "With this ability bound, hold Sneak (Default: Shift) at a water block and " - + "don't lose focus of that block. Eventually some fish will investigate " - + "the wake and swim out at you!"); - config.addDefault("Abilities.Water.WakeFishing.Cooldown", 10000); - config.addDefault("Abilities.Water.WakeFishing.Duration", 20000); - config.addDefault("Abilities.Water.WakeFishing.Range", 5); - - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Description", "Create a swirling mass of water that drags any entity that enters it to the bottom " - + "of the whirlpool."); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Cooldown", 25000); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Duration", 15000); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.MaxDepth", 5); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Range", 10); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Combination", Arrays.asList("PhaseChange:SHIFT_DOWN", "Torrent:LEFT_CLICK", "Torrent:LEFT_CLICK")); - config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Instructions", "PhaseChange (Hold sneak) > Torrent (Left-click) > Torrent (Left-click)"); - - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Description", "Some Waterbenders have managed to create torrents of water much stronger than a regular torrent, " - + "that can carry them selves and others, as well as being able to freeze the entire stream whenever. The bender must stay focused on the flow or else the flow will stop." - + " If you Sneak (Default: Shift) while controlling the stream, the stream will return to you."); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Cooldown", 8000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Duration", 8000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MeltDelay", 5000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.SourceRange", 10); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxRange", 40); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MinRange", 8); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Trail", 80); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.BottleSource", false); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlantSource", false); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.RemoveOnAnyDamage", false); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.Normal", 1); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.AvatarState", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonSmall", 2); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonLarge", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.IsAvatarStateToggle", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.AvatarStateDuration", 60000); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerStayNearSource", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxDistanceFromSource", 100); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Cooldown", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Duration", 2); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerRideOwnFlow", true); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Combination", Arrays.asList("WaterManipulation:SHIFT_DOWN", "WaterManipulation:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "WaterManipulation:SHIFT_UP")); - config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Instructions", "WaterManipulation (Tap sneak) > Torrent (Tap sneak) > Torrent (Hold sneak) > WaterManipulation (Release sneak)"); - - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Description", "Skilled Waterbenders are able to create two spinning rings of water around their bodies, " - + "which can be used as a defensive ability or for an offensive attack."); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Cooldown", 7000); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Damage", 3.0); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RingSize", 3.5); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Range", 40); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SourceRange", 10); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Speed", 2); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AnimationSpeed", 3); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.PlantSource", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SnowSource", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RequireAdjacentPlants", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.BottleSource", false); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AbilityCollisionRadius", 1.6); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.EntityCollisionRadius", 1.6); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.Enabled", false); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveFirst", true); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveSecond", false); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Combination", Arrays.asList("Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "WaterManipulation:SHIFT_DOWN")); - config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Instructions", "Torrent (Tap sneak) > Torrent (Tap sneak) > WaterManipulation (Hold sneak) > WaterManipulation (Left-click multiple times)"); - - config.addDefault("Abilities.Water.Ice.Passive.Skate.Enabled", true); - config.addDefault("Abilities.Water.Ice.Passive.Skate.SpeedFactor", 4); - - config.addDefault("Abilities.Chi.Backstab.Enabled", true); - config.addDefault("Abilities.Chi.Backstab.Description", "Strike your foe in the back with a hard jab, temporariliy blocking their Chi, and " - + "inflicting a lot of damage! This ability has a long cooldown. You must hit the target in the back or this ability won't work!"); - config.addDefault("Abilities.Chi.Backstab.Cooldown", 8500); - config.addDefault("Abilities.Chi.Backstab.Damage", 6.0); - config.addDefault("Abilities.Chi.Backstab.MaxActivationAngle", 90); - - config.addDefault("Abilities.Chi.DaggerThrow.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.Description", "With this ability bound, Left-Click in " - + "rapid succession to shoot arrows out of your inventory at your target!"); - config.addDefault("Abilities.Chi.DaggerThrow.Cooldown", 3000); - config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Amount", 6); - config.addDefault("Abilities.Chi.DaggerThrow.Damage", 1.0); - config.addDefault("Abilities.Chi.DaggerThrow.ParticleTrail", true); - config.addDefault("Abilities.Chi.DaggerThrow.RequireArrows", false); - config.addDefault("Abilities.Chi.DaggerThrow.AllowPickup", false); - config.addDefault("Abilities.Chi.DaggerThrow.AbilityCollisionRadius", 0.5); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Cooldown", 1000); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.HitsRequired", 1); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Enabled", true); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Cooldown", 1000); - config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.HitsRequired", 1); - - String[] invalidWallRun = {Material.BARRIER.name()}; - config.addDefault("Abilities.Passives.WallRun.Enabled", true); - config.addDefault("Abilities.Passives.WallRun.Cooldown", 6000); - config.addDefault("Abilities.Passives.WallRun.Duration", 20000); - config.addDefault("Abilities.Passives.WallRun.Particles", true); - config.addDefault("Abilities.Passives.WallRun.Air", true); - config.addDefault("Abilities.Passives.WallRun.Earth", false); - config.addDefault("Abilities.Passives.WallRun.Water", false); - config.addDefault("Abilities.Passives.WallRun.Fire", true); - config.addDefault("Abilities.Passives.WallRun.Chi", true); - config.addDefault("Abilities.Passives.WallRun.InvalidBlocks", invalidWallRun); - - config.options().copyDefaults(true); - plugin.saveConfig(); - } - - private void addDeathMessages() { - FileConfiguration lang = ConfigManager.languageConfig.get(); - - //Fire - lang.addDefault("Abilities.Fire.FireComet.DeathMessage", "{victim} was squashed under the pressure of {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FireBall.DeathMessage", "{victim} burst from {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FireBreath.DeathMessage", "{victim} was consumed {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.Discharge.DeathMessage", "{victim} couldn't take {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FirePunch.DeathMessage", "{victim} punched out from {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.FireShots.DeathMessage", "{victim} was shot by {attacker}'s {ability}"); - lang.addDefault("Abilities.Fire.LightningBurst.DeathMessage", "{victim} crackled out of existence from {attacker}'s {ability}"); - - //Water - lang.addDefault("Abilities.Water.Drain.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.FrostBreath.DeathMessage", "{victim} shattered from {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.IceClaws.DeathMessage", "{victim} was ripped to shreds by {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.IceWall.DeathMessage", "{victim} was collateral to {attacker}'s exploding {ability}"); - lang.addDefault("Abilities.Water.WaterBlast.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); - lang.addDefault("Abilities.Water.Combo.WaterGimbal.DeathMessage", "{victim} was ripped apart by {attacker}'s {ability}"); - - //Earth - lang.addDefault("Abilities.Earth.EarthKick.DeathMessage", "{victim} got too much dirt in their eye from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.EarthLine.DeathMessage", "{victim} lost their footing from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.EarthShard.DeathMessage", "{victim} got blasted apart {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.LavaDisc.DeathMessage", "{victim} sliced in half by {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.LavaFlux.DeathMessage", "{victim} couldn't take the heat from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.LavaThrow.DeathMessage", "{victim} melted from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.MetalFragments.DeathMessage", "{victim} was shredded apart from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.MetalShred.DeathMessage", "{victim} was in the way of {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.MudSurge.DeathMessage", "{victim} drowned in mud from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.SandBlast.DeathMessage", "{victim} was sandblasted to oblivion from {attacker}'s {ability}"); - lang.addDefault("Abilities.Earth.Combo.MagmaBlast.DeathMessage", "{victim} was obliterated by {attacker}'s {ability}"); - - //Air - lang.addDefault("Abilities.Air.AirBlade.DeathMessage", "{victim} was sliced in two by {attacker}'s {ability}"); - lang.addDefault("Abilities.Air.AirPunch.DeathMessage", "{victim} was exploded by {attacker}'s {ability}"); - lang.addDefault("Abilities.Air.SonicBlast.DeathMessage", "{victim}'s ears burst after {attacker}'s {ability}"); - - //Chi - lang.addDefault("Abilities.Chi.DaggerThrow.DeathMessage", "{victim} got stabbed too many times from {attacker}'s {ability}"); - lang.addDefault("Abilities.Chi.Backstab.DeathMessage", "{victim} fell victim to {attacker}'s {ability}"); - - //Avatar - lang.addDefault("Abilities.Avatar.SpiritBeam.DeathMessage", "{victim} was erased from existence by {attacker}'s {ability}"); - lang.addDefault("Abilities.Avatar.ElementSphereAir.DeathMessage", "{victim} was blasted apart by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereFire.DeathMessage", "{victim} was burnt to cinders by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereEarth.DeathMessage", "{victim} was crushed by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereWater.DeathMessage", "{victim} was sliced apart by {attacker}'s \u00A75ElementSphere"); - lang.addDefault("Abilities.Avatar.ElementSphereStream.DeathMessage", "{victim} took the full force of {attacker}'s \u00A75ElementSphere"); - - ConfigManager.languageConfig.save(); - } - - private void setupElementSphereNames() { - FileConfiguration lang = ConfigManager.languageConfig.get(); - - lang.addDefault("Abilities.Avatar.ElementSphereAir.Name", "Air"); - lang.addDefault("Abilities.Avatar.ElementSphereFire.Name", "Fire"); - lang.addDefault("Abilities.Avatar.ElementSphereEarth.Name", "Earth"); - lang.addDefault("Abilities.Avatar.ElementSphereWater.Name", "Water"); - lang.addDefault("Abilities.Avatar.ElementSphereStream.Name", "Stream"); - - ConfigManager.languageConfig.save(); - } - - public static ConfigurationSection getConfig(Player player) { - if (player == null) - return getConfig((World)null); - return getConfig(player.getWorld()); - } - - public static ConfigurationSection getConfig(World world) { - boolean perWorldConfig = plugin.getConfig().getBoolean("Properties.PerWorldConfig"); - - if (world == null || !perWorldConfig) { - return plugin.getConfig(); - } - - String prefix = "Worlds." + world.getName(); - return new SubsectionConfigurationDecorator(plugin.getConfig(), prefix); - } -} + config.addDefault("Abilities.Earth.MudSurge.Description", "This ability lets an earthbender send a surge of mud " + + "in any direction, knocking back enemies and " + + "dealing moderate damage. This ability has a chance " + + "of blinding the target. To use, select " + + "a source of earth and click in any direction."); + config.addDefault("Abilities.Earth.MudSurge.Cooldown", 6000); + config.addDefault("Abilities.Earth.MudSurge.Damage", 1.0); + config.addDefault("Abilities.Earth.MudSurge.Waves", 5); + config.addDefault("Abilities.Earth.MudSurge.SourceRange", 7); + config.addDefault("Abilities.Earth.MudSurge.BlindChance", 10); + config.addDefault("Abilities.Earth.MudSurge.WetSourceOnly", false); + config.addDefault("Abilities.Earth.MudSurge.WaterSearchRadius", 5); + config.addDefault("Abilities.Earth.MudSurge.BlindTicks", 60); + config.addDefault("Abilities.Earth.MudSurge.CollisionRadius", 2.0); + config.addDefault("Abilities.Earth.MudSurge.MultipleHits", true); + config.addDefault("Abilities.Earth.MudSurge.AllowFallDamage", false); + config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.SwappedSlots.Enabled", true); + config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Enabled", true); + config.addDefault("Abilities.Earth.MudSurge.RemovalPolicy.OutOfRange.Range", 25.0); + + config.addDefault("Abilities.Earth.SandBlast.Enabled", true); + config.addDefault("Abilities.Earth.SandBlast.Description", "This ability lets an earthbender blast a bunch of sand at an enemy " + + "damaging them and temporarily blinding them! Just Sneak (Default: Shift) " + + "on a sand bendable block, then Left-Click in a direction to shoot a " + + "blast of sand!"); + config.addDefault("Abilities.Earth.SandBlast.Cooldown", 3000); + config.addDefault("Abilities.Earth.SandBlast.Damage", 3.0); + config.addDefault("Abilities.Earth.SandBlast.SourceRange", 8); + config.addDefault("Abilities.Earth.SandBlast.Range", 30); + config.addDefault("Abilities.Earth.SandBlast.MaxSandBlocks", 10); + + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Enabled", true); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Description", "Create a Crevice in the ground! Once opened, " + + "anyone can Tap Sneak with Shockwave to close the Crevice!"); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Range", 50); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.RevertDelay", 7500); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Depth", 5); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.AvatarStateDepth", 8); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Cooldown", 10000); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Combination", Arrays.asList("Collapse:RIGHT_CLICK_BLOCK", "Shockwave:SHIFT_DOWN", "Shockwave:SHIFT_UP", "Shockwave:SHIFT_DOWN")); + config.addDefault("Abilities.Earth.EarthCombo.Crevice.Instructions", "Collapse (Right-click a block) > Shockwave (Tap sneak) > Shockwave (Tap sneak)"); + + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Enabled", true); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Description", "Fire balls of magma at your enemy!"); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxShots", 3); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ImpactDamage", 2.0); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SearchRange", 4); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Cooldown", 6000); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ShotCooldown", 1500); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.RequireLavaFlow", false); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.PlayerCollisions", true); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.EntitySelection", true); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.SelectRange", 30.0); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.ExplosionRadius", 2.0); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.FireSpeed", 1.5); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDuration", 15000); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.MaxDistanceFromSources", 15); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Combination", Arrays.asList("EarthBlast:SHIFT_DOWN", "LavaFlow:SHIFT_UP", "LavaFlow:SHIFT_DOWN", "LavaFlow:RIGHT_CLICK_BLOCK")); + config.addDefault("Abilities.Earth.EarthCombo.MagmaBlast.Instructions", "EarthBlast (Hold sneak) > LavaFlow (Release sneak) > LavaFlow (Hold sneak) > LavaFlow (Right-click a block) > LavaFlow (Left-click multiple times)"); + + ArrayList combustionSkipMaterials = new ArrayList<>(); + combustionSkipMaterials.add("#bee_growables"); + combustionSkipMaterials.add("#cave_vines"); + combustionSkipMaterials.add("#crops"); + combustionSkipMaterials.add("#flowers"); + combustionSkipMaterials.add("vine"); + combustionSkipMaterials.add("pale_hanging_moss"); + + config.addDefault("Abilities.Fire.Combustion.Enabled", true); + config.addDefault("Abilities.Fire.Combustion.Description", "Hold Shift to focus large amounts of energy into your body, " + + "Release Shift to fire Combustion. Move your mouse to " + + "direct where the beam travels. Left-Click to detonate " + + "the beam manually"); + config.addDefault("Abilities.Fire.Combustion.Damage", 4.0); + config.addDefault("Abilities.Fire.Combustion.FireTick", 100); + config.addDefault("Abilities.Fire.Combustion.MisfireModifier", -1); + config.addDefault("Abilities.Fire.Combustion.Power", 3); + config.addDefault("Abilities.Fire.Combustion.Range", 100); + config.addDefault("Abilities.Fire.Combustion.Speed", 0.65); + config.addDefault("Abilities.Fire.Combustion.Warmup", 1500); + config.addDefault("Abilities.Fire.Combustion.Cooldown", 5000); + config.addDefault("Abilities.Fire.Combustion.RegenTime", 10000); + config.addDefault("Abilities.Fire.Combustion.EntityCollisionRadius", 1.3); + config.addDefault("Abilities.Fire.Combustion.AbilityCollisionRadius", 1.3); + config.addDefault("Abilities.Fire.Combustion.DamageBlocks", true); + config.addDefault("Abilities.Fire.Combustion.RegenBlocks", true); + config.addDefault("Abilities.Fire.Combustion.WaitForRegen", true); + config.addDefault("Abilities.Fire.Combustion.InstantExplodeIfHit", true); + config.addDefault("Abilities.Fire.Combustion.ExplodeOnDeath", true); + config.addDefault("Abilities.Fire.Combustion.RemovalPolicy.SwappedSlots.Enabled", false); + config.addDefault("Abilities.Fire.Combustion.SkipMaterials", combustionSkipMaterials); + + config.addDefault("Abilities.Fire.Discharge.Enabled", true); + config.addDefault("Abilities.Fire.Discharge.Description", "Left-Click to shoot bolts of electricity out " + + "of your fingertips zapping what ever it hits!"); + config.addDefault("Abilities.Fire.Discharge.Damage", 3.0); + config.addDefault("Abilities.Fire.Discharge.Cooldown", 5000); + config.addDefault("Abilities.Fire.Discharge.AvatarCooldown", 500); + config.addDefault("Abilities.Fire.Discharge.Duration", 1000); + config.addDefault("Abilities.Fire.Discharge.SlotSwapping", false); + config.addDefault("Abilities.Fire.Discharge.EntityCollisionRadius", 1.0); + config.addDefault("Abilities.Fire.Discharge.AbilityCollisionRadius", 1.0); + config.addDefault("Abilities.Fire.Discharge.Sound.Volume", 0.6); + config.addDefault("Abilities.Fire.Discharge.Sound.Interval", 6); + + config.addDefault("Abilities.Fire.FireBall.Enabled", true); + config.addDefault("Abilities.Fire.FireBall.Description", "To use, simply Left-Click to shoot a fireball at your target!"); + config.addDefault("Abilities.Fire.FireBall.Cooldown", 3000); + config.addDefault("Abilities.Fire.FireBall.Range", 50); + config.addDefault("Abilities.Fire.FireBall.Damage", 3.0); + config.addDefault("Abilities.Fire.FireBall.FireDuration", 2000); + config.addDefault("Abilities.Fire.FireBall.Controllable", false); + config.addDefault("Abilities.Fire.FireBall.FireTrail", true); + config.addDefault("Abilities.Fire.FireBall.CollisionRadius", 1.1); + config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.Enabled", true); + config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveFirst", true); + config.addDefault("Abilities.Fire.FireBall.Collisions.FireShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Enabled", true); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveFirst", false); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireBall.Collisions.AirShield.Reflect", true); + + config.addDefault("Abilities.Fire.FireBreath.Enabled", true); + config.addDefault("Abilities.Fire.FireBreath.Description", "To use, hold Sneak (Default: Shift) to start breathing " + + "fire! Some Firebenders possess the power to infuse color " + + "when they breathe, it's unclear how they do this, but some suggest " + + "it can be obtained by saying \"Bring fire and light together as one and allow the breath of color\" " + + "and can be brought back to normal by saying \"Split the bond of fire " + + "and light and set the color free\"."); + config.addDefault("Abilities.Fire.FireBreath.Cooldown", 5000); + config.addDefault("Abilities.Fire.FireBreath.Duration", 3000); + config.addDefault("Abilities.Fire.FireBreath.Particles", 3); + config.addDefault("Abilities.Fire.FireBreath.Damage.Player", 1.0); + config.addDefault("Abilities.Fire.FireBreath.Damage.Mob", 2.0); + config.addDefault("Abilities.Fire.FireBreath.FireDuration", 3000); + config.addDefault("Abilities.Fire.FireBreath.Range", 10); + config.addDefault("Abilities.Fire.FireBreath.Avatar.FireEnabled", true); + config.addDefault("Abilities.Fire.FireBreath.Melt.Enabled", true); + config.addDefault("Abilities.Fire.FireBreath.Melt.Chance", 3); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.Enabled", true); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.EnabledMessage", "You have bonded fire with light and can now breathe pure color."); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.DisabledMessage", "You have split your bond of color and light."); + config.addDefault("Abilities.Fire.FireBreath.RainbowBreath.NoAccess", "You don't possess the power to bond light with fire."); + + config.addDefault("Abilities.Fire.FireComet.Enabled", true); + config.addDefault("Abilities.Fire.FireComet.Description", "Harnessing the power of Sozin's Comet, a firebender can create a great " + + "ball of fire, with much destructive power. Only useable during Sozin's Comet or while in the AvatarState, hold Sneak (Default: Shift) " + + "to start charging the ability up. Once the ability is charged, a large mass of particles will follow your cursor, until you release sneak, " + + "launching the great ball of fire in the direction you are looking."); + config.addDefault("Abilities.Fire.FireComet.Cooldown", 45000); + config.addDefault("Abilities.Fire.FireComet.ChargeUp", 7000); + config.addDefault("Abilities.Fire.FireComet.Damage", 6.0); + config.addDefault("Abilities.Fire.FireComet.BlastRadius", 3.0); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.Cooldown", 30000); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.ChargeUp", 5000); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.Damage", 12.0); + config.addDefault("Abilities.Fire.FireComet.SozinsComet.BlastRadius", 5.0); + config.addDefault("Abilities.Fire.FireComet.Range", 50); + config.addDefault("Abilities.Fire.FireComet.RegenDelay", 15000); + config.addDefault("Abilities.Fire.FireComet.SozinsCometOnly", true); + config.addDefault("Abilities.Fire.FireComet.AvatarStateBypassComet", true); + + config.addDefault("Abilities.Fire.FirePunch.Enabled", true); + config.addDefault("Abilities.Fire.FirePunch.Description", "This basic ability allows a Firebender to channel their energies into a " + + "single punch, igniting and damaging the victim."); + config.addDefault("Abilities.Fire.FirePunch.Cooldown", 4000); + config.addDefault("Abilities.Fire.FirePunch.FireTicks", 2000); + config.addDefault("Abilities.Fire.FirePunch.Damage", 2.0); + config.addDefault("Abilities.Fire.FirePunch.BurnsDroppedItems", true); + + config.addDefault("Abilities.Fire.FireShots.Enabled", true); + config.addDefault("Abilities.Fire.FireShots.Description", "To use, tap Sneak (Default: Shift) to summon a " + + "FireBalls at your hand, then Left Click to shoot off each ball! " + + "Each shot will follow the cursor until it runs out or hits something! " + + "Tap Sneak again to switch your main hand."); + config.addDefault("Abilities.Fire.FireShots.Cooldown", 3000); + config.addDefault("Abilities.Fire.FireShots.Range", 50); + config.addDefault("Abilities.Fire.FireShots.FireBalls", 4); + config.addDefault("Abilities.Fire.FireShots.FireDuration", 3000); + config.addDefault("Abilities.Fire.FireShots.Damage", 2.0); + config.addDefault("Abilities.Fire.FireShots.CollisionRadius", 0.9); + config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.Enabled", true); + config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveFirst", true); + config.addDefault("Abilities.Fire.FireShots.Collisions.FireShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Enabled", true); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveFirst", false); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.RemoveSecond", false); + config.addDefault("Abilities.Fire.FireShots.Collisions.AirShield.Reflect", true); + + config.addDefault("Abilities.Fire.FireSki.Enabled", true); + config.addDefault("Abilities.Fire.FireSki.Cooldown", 6000); + config.addDefault("Abilities.Fire.FireSki.Duration", 6000); + config.addDefault("Abilities.Fire.FireSki.Speed", 0.7); + config.addDefault("Abilities.Fire.FireSki.IgniteEntities", true); + config.addDefault("Abilities.Fire.FireSki.FireTicks", 60); + config.addDefault("Abilities.Fire.FireSki.RequiredHeight", 0.7); + config.addDefault("Abilities.Fire.FireSki.PunchActivated", false); + + config.addDefault("Abilities.Fire.LightningBurst.Enabled", true); + config.addDefault("Abilities.Fire.LightningBurst.Description", "To use the most explosive lightning move available to a firebender, hold " + + "Sneak (Default: Shift) until blue sparks appear in front of you. Upon releasing, " + + "you will unleash an electrical sphere, shocking anyone who gets too close"); + config.addDefault("Abilities.Fire.LightningBurst.Cooldown", 25000); + config.addDefault("Abilities.Fire.LightningBurst.ChargeUp", 4000); + config.addDefault("Abilities.Fire.LightningBurst.AvatarCooldown", 1000); + config.addDefault("Abilities.Fire.LightningBurst.AvatarChargeUp", 1000); + config.addDefault("Abilities.Fire.LightningBurst.Radius", 12); + config.addDefault("Abilities.Fire.LightningBurst.Damage", 9.0); + config.addDefault("Abilities.Fire.LightningBurst.Sound.Volume", 0.6); + config.addDefault("Abilities.Fire.LightningBurst.Sound.Interval", 6); + + config.addDefault("Abilities.Water.Bloodbending.Enabled", true); + config.addDefault("Abilities.Water.Bloodbending.Description", "This ability allows a skilled waterbender " + + "to bend the water within an enemy's blood, granting them full " + + "control over the enemy's limbs. This ability is extremely dangerous " + + "and is to be used carefully. To use, sneak while looking at an entity " + + "and its body will follow your movement. If you click, you will launch " + + "the entity towards whatever you were looking at when you clicked. The " + + "entity may collide with others, injuring them and the other one further."); + config.addDefault("Abilities.Water.Bloodbending.NightOnly", false); + config.addDefault("Abilities.Water.Bloodbending.FullMoonOnly", false); + config.addDefault("Abilities.Water.Bloodbending.UndeadMobs", true); + config.addDefault("Abilities.Water.Bloodbending.IgnoreWalls", false); + config.addDefault("Abilities.Water.Bloodbending.RequireBound", false); + config.addDefault("Abilities.Water.Bloodbending.Distance", 6); + config.addDefault("Abilities.Water.Bloodbending.HoldTime", 10000); + config.addDefault("Abilities.Water.Bloodbending.Cooldown", 4000); + + config.addDefault("Abilities.Water.BloodPuppet.Enabled", true); + config.addDefault("Abilities.Water.BloodPuppet.Description", "This very high-level bloodbending ability lets " + + "a master control entities' limbs, forcing them to " + + "attack the master's target. To use this ability, you must " + + "be a bloodbender. Next, sneak while targeting " + + "a mob or player and you will start controlling them. To " + + "make the entity hit another, click. To release your " + + "target, stop sneaking. This ability has NO cooldown, but " + + "may only be usable during the night depending on the " + + "server configuration."); + config.addDefault("Abilities.Water.BloodPuppet.NightOnly", false); + config.addDefault("Abilities.Water.BloodPuppet.FullMoonOnly", false); + config.addDefault("Abilities.Water.BloodPuppet.UndeadMobs", true); + config.addDefault("Abilities.Water.BloodPuppet.IgnoreWalls", false); + config.addDefault("Abilities.Water.BloodPuppet.RequireBound", false); + config.addDefault("Abilities.Water.BloodPuppet.Distance", 6); + config.addDefault("Abilities.Water.BloodPuppet.HoldTime", 10000); + config.addDefault("Abilities.Water.BloodPuppet.Cooldown", 4000); + + config.addDefault("Abilities.Water.Drain.Enabled", true); + config.addDefault("Abilities.Water.Drain.Description", "Inspired by how Hama drained water from the fire lilies, many benders " + + "have practiced in the skill of draining water from plants! With this ability bound, " + + "Sneak (Default: Shift) near/around plant sources to drain the water out of them to fill up any " + + "bottles/buckets in your inventory! Alternatively, if you have nothing to fill" + + " and blasts are enabled in the config, you will be able to create mini blasts " + + "of water to shoot at your targets! Aleternatively, this ability can also be used to quickly fill up " + + "bottles from straight water sources or from falling rain!"); + config.addDefault("Abilities.Water.Drain.RegenDelay", 15000); + config.addDefault("Abilities.Water.Drain.Duration", 2000); + config.addDefault("Abilities.Water.Drain.Cooldown", 2000); + config.addDefault("Abilities.Water.Drain.AbsorbSpeed", 0.1); + config.addDefault("Abilities.Water.Drain.AbsorbChance", 20); + config.addDefault("Abilities.Water.Drain.AbsorbRate", 6); + config.addDefault("Abilities.Water.Drain.Radius", 6); + config.addDefault("Abilities.Water.Drain.HoldRange", 2); + config.addDefault("Abilities.Water.Drain.AllowRainSource", true); + config.addDefault("Abilities.Water.Drain.BlastsEnabled", true); + config.addDefault("Abilities.Water.Drain.KeepSource", false); + config.addDefault("Abilities.Water.Drain.BlastSpeed", 1); + config.addDefault("Abilities.Water.Drain.BlastDamage", 1.5); + config.addDefault("Abilities.Water.Drain.BlastRange", 20); + config.addDefault("Abilities.Water.Drain.MaxBlasts", 4); + config.addDefault("Abilities.Water.Drain.DrainTempBlocks", true); + + config.addDefault("Abilities.Water.FrostBreath.Enabled", true); + config.addDefault("Abilities.Water.FrostBreath.Description", "As demonstrated by Katara, a Waterbender is able to freeze their breath, " + + "causing anything it touches to be frozen! With this ability bound, simply hold " + + "Sneak (Default: Shift) to start breathing frost!"); + config.addDefault("Abilities.Water.FrostBreath.Cooldown", 15000); + config.addDefault("Abilities.Water.FrostBreath.Duration", 3000); + config.addDefault("Abilities.Water.FrostBreath.Particles", 3); + config.addDefault("Abilities.Water.FrostBreath.FrostDuration", 5000); + config.addDefault("Abilities.Water.FrostBreath.FrozenWaterDuration", 10000); + config.addDefault("Abilities.Water.FrostBreath.Range", 10); + config.addDefault("Abilities.Water.FrostBreath.Snow", true); + config.addDefault("Abilities.Water.FrostBreath.SnowDuration", 5000); + config.addDefault("Abilities.Water.FrostBreath.BendableSnow", false); + config.addDefault("Abilities.Water.FrostBreath.Damage.Enabled", false); + config.addDefault("Abilities.Water.FrostBreath.Damage.Player", 1.0); + config.addDefault("Abilities.Water.FrostBreath.Damage.Mob", 2.0); + config.addDefault("Abilities.Water.FrostBreath.Slow.Enabled", true); + config.addDefault("Abilities.Water.FrostBreath.Slow.Duration", 4000); + config.addDefault("Abilities.Water.FrostBreath.RestrictBiomes", true); + + config.addDefault("Abilities.Water.HealingWaters.Enabled", true); + config.addDefault("Abilities.Water.HealingWaters.Description", "To use this ability, the bender has to be partially submerged " + + "in water, OR be holding either a bottle of water or a water bucket." + + " This move will heal the player automatically if they have it equipped " + + "and are standing in water. If the player sneaks while in water and is targeting" + + " another entity, the bender will heal the targeted entity. The alternate " + + "healing method requires the bender to be holding a bottle of water or a water" + + " bucket. To start healing simply sneak, however if the bender is targeting " + + "a mob while sneaking, the bender will heal the targeted mob."); + config.addDefault("Abilities.Water.HealingWaters.Power", 1); + config.addDefault("Abilities.Water.HealingWaters.Range", 5); + config.addDefault("Abilities.Water.HealingWaters.DrainChance", 5); + config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Enabled", true); + config.addDefault("Abilities.Water.HealingWaters.DynamicLight.Brightness", 10); + config.addDefault("Abilities.Water.HealingWaters.DynamicLight.KeepAlive", 1500); + + config.addDefault("Abilities.Water.IceClaws.Enabled", true); + config.addDefault("Abilities.Water.IceClaws.Description", "As demonstrated by Hama, a Waterbender can pull water out of thin air to create claws " + + "at the tips of their fingers. With IceClaws bound, hold Sneak (Default: Shift) to " + + "start pulling water out the air until you form claws at your finger " + + "tips, then attack an enemy to slow them down and do a bit of damage!"); + config.addDefault("Abilities.Water.IceClaws.Cooldown", 6000); + config.addDefault("Abilities.Water.IceClaws.ChargeTime", 1000); + config.addDefault("Abilities.Water.IceClaws.Range", 10); + config.addDefault("Abilities.Water.IceClaws.Throwable", true); + config.addDefault("Abilities.Water.IceClaws.Punch.Cooldown", 4000); + config.addDefault("Abilities.Water.IceClaws.Punch.Damage", 2.0); + config.addDefault("Abilities.Water.IceClaws.Punch.Slowness", 3); + config.addDefault("Abilities.Water.IceClaws.Punch.SlowDuration", 5000); + config.addDefault("Abilities.Water.IceClaws.Throw.Cooldown", 4000); + config.addDefault("Abilities.Water.IceClaws.Throw.Damage", 2.0); + config.addDefault("Abilities.Water.IceClaws.Throw.Slowness", 3); + config.addDefault("Abilities.Water.IceClaws.Throw.SlowDuration", 5000); + config.addDefault("Abilities.Water.IceClaws.Throw.Speed", 1.0); + config.addDefault("Abilities.Water.IceClaws.AllowHandSwap", true); + + config.addDefault("Abilities.Water.IceWall.Enabled", true); + config.addDefault("Abilities.Water.IceWall.Description", "IceWall allows an icebender to create a wall of ice, similar to " + + "raiseearth. To use, simply sneak while targeting either water, ice, or snow. " + + "To break the wall, you must sneak again while targeting it. Be aware that " + + "other icebenders can break your own shields, and if you are too close you " + + "can get hurt by the shards."); + config.addDefault("Abilities.Water.IceWall.Cooldown", 4000); + config.addDefault("Abilities.Water.IceWall.Width", 6); + config.addDefault("Abilities.Water.IceWall.MaxHeight", 5); + config.addDefault("Abilities.Water.IceWall.MinHeight", 3); + config.addDefault("Abilities.Water.IceWall.MaxWallHealth", 12); + config.addDefault("Abilities.Water.IceWall.MinWallHealth", 8); + config.addDefault("Abilities.Water.IceWall.Range", 8); + config.addDefault("Abilities.Water.IceWall.Damage", 4.0); + config.addDefault("Abilities.Water.IceWall.CanBreak", true); + config.addDefault("Abilities.Water.IceWall.Stackable", false); + config.addDefault("Abilities.Water.IceWall.LifeTime.Enabled", false); + config.addDefault("Abilities.Water.IceWall.LifeTime.Duration", 10000); + config.addDefault("Abilities.Water.IceWall.WallDamage", true); + config.addDefault("Abilities.Water.IceWall.WallDamage.Torrent", 5); + config.addDefault("Abilities.Water.IceWall.WallDamage.TorrentFreeze", 9); + config.addDefault("Abilities.Water.IceWall.WallDamage.IceBlast", 8); + config.addDefault("Abilities.Water.IceWall.WallDamage.Fireblast", 3); + config.addDefault("Abilities.Water.IceWall.WallDamage.FireblastCharged", 5); + config.addDefault("Abilities.Water.IceWall.WallDamage.Lightning", 12); + config.addDefault("Abilities.Water.IceWall.WallDamage.Combustion", 12); + config.addDefault("Abilities.Water.IceWall.WallDamage.EarthSmash", 8); + config.addDefault("Abilities.Water.IceWall.WallDamage.AirBlast", 2); + + config.addDefault("Abilities.Water.WakeFishing.Enabled", true); + config.addDefault("Abilities.Water.WakeFishing.Description", "With this ability bound, hold Sneak (Default: Shift) at a water block and " + + "don't lose focus of that block. Eventually some fish will investigate " + + "the wake and swim out at you!"); + config.addDefault("Abilities.Water.WakeFishing.Cooldown", 10000); + config.addDefault("Abilities.Water.WakeFishing.Duration", 20000); + config.addDefault("Abilities.Water.WakeFishing.Range", 5); + + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Description", "Create a swirling mass of water that drags any entity that enters it to the bottom " + + "of the whirlpool."); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Cooldown", 25000); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Duration", 15000); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.MaxDepth", 5); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Range", 10); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Combination", Arrays.asList("PhaseChange:SHIFT_DOWN", "Torrent:LEFT_CLICK", "Torrent:LEFT_CLICK")); + config.addDefault("Abilities.Water.WaterCombo.Maelstrom.Instructions", "PhaseChange (Hold sneak) > Torrent (Left-click) > Torrent (Left-click)"); + + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Description", "Some Waterbenders have managed to create torrents of water much stronger than a regular torrent, " + + "that can carry them selves and others, as well as being able to freeze the entire stream whenever. The bender must stay focused on the flow or else the flow will stop." + + " If you Sneak (Default: Shift) while controlling the stream, the stream will return to you."); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Cooldown", 8000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Duration", 8000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MeltDelay", 5000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.SourceRange", 10); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxRange", 40); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MinRange", 8); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Trail", 80); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.BottleSource", false); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlantSource", false); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.RemoveOnAnyDamage", false); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.Normal", 1); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.AvatarState", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonSmall", 2); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Size.FullmoonLarge", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.IsAvatarStateToggle", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.AvatarStateDuration", 60000); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerStayNearSource", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.MaxDistanceFromSource", 100); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Cooldown", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.FullMoon.Modifier.Duration", 2); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.PlayerRideOwnFlow", true); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Combination", Arrays.asList("WaterManipulation:SHIFT_DOWN", "WaterManipulation:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "WaterManipulation:SHIFT_UP")); + config.addDefault("Abilities.Water.WaterCombo.WaterFlow.Instructions", "WaterManipulation (Tap sneak) > Torrent (Tap sneak) > Torrent (Hold sneak) > WaterManipulation (Release sneak)"); + + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Description", "Skilled Waterbenders are able to create two spinning rings of water around their bodies, " + + "which can be used as a defensive ability or for an offensive attack."); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Cooldown", 7000); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Damage", 3.0); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RingSize", 3.5); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Range", 40); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SourceRange", 10); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Speed", 2); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AnimationSpeed", 3); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.PlantSource", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.SnowSource", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.RequireAdjacentPlants", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.BottleSource", false); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.AbilityCollisionRadius", 1.6); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.EntityCollisionRadius", 1.6); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.Enabled", false); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveFirst", true); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Collisions.FireShield.RemoveSecond", false); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Combination", Arrays.asList("Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "Torrent:SHIFT_DOWN", "Torrent:SHIFT_UP", "WaterManipulation:SHIFT_DOWN")); + config.addDefault("Abilities.Water.WaterCombo.WaterGimbal.Instructions", "Torrent (Tap sneak) > Torrent (Tap sneak) > WaterManipulation (Hold sneak) > WaterManipulation (Left-click multiple times)"); + + config.addDefault("Abilities.Water.Ice.Passive.Skate.Enabled", true); + config.addDefault("Abilities.Water.Ice.Passive.Skate.SpeedFactor", 4); + + config.addDefault("Abilities.Chi.Backstab.Enabled", true); + config.addDefault("Abilities.Chi.Backstab.Description", "Strike your foe in the back with a hard jab, temporariliy blocking their Chi, and " + + "inflicting a lot of damage! This ability has a long cooldown. You must hit the target in the back or this ability won't work!"); + config.addDefault("Abilities.Chi.Backstab.Cooldown", 8500); + config.addDefault("Abilities.Chi.Backstab.Damage", 6.0); + config.addDefault("Abilities.Chi.Backstab.MaxActivationAngle", 90); + + config.addDefault("Abilities.Chi.DaggerThrow.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.Description", "With this ability bound, Left-Click in " + + "rapid succession to shoot arrows out of your inventory at your target!"); + config.addDefault("Abilities.Chi.DaggerThrow.Cooldown", 3000); + config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.MaxDaggers.Amount", 6); + config.addDefault("Abilities.Chi.DaggerThrow.Damage", 1.0); + config.addDefault("Abilities.Chi.DaggerThrow.ParticleTrail", true); + config.addDefault("Abilities.Chi.DaggerThrow.RequireArrows", false); + config.addDefault("Abilities.Chi.DaggerThrow.AllowPickup", false); + config.addDefault("Abilities.Chi.DaggerThrow.AbilityCollisionRadius", 0.5); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.Cooldown", 1000); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.WaterSpout.HitsRequired", 1); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Enabled", true); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.Cooldown", 1000); + config.addDefault("Abilities.Chi.DaggerThrow.Interactions.AirSpout.HitsRequired", 1); + + String[] invalidWallRun = {Material.BARRIER.name()}; + config.addDefault("Abilities.Passives.WallRun.Enabled", true); + config.addDefault("Abilities.Passives.WallRun.Cooldown", 6000); + config.addDefault("Abilities.Passives.WallRun.Duration", 20000); + config.addDefault("Abilities.Passives.WallRun.Particles", true); + config.addDefault("Abilities.Passives.WallRun.Air", true); + config.addDefault("Abilities.Passives.WallRun.Earth", false); + config.addDefault("Abilities.Passives.WallRun.Water", false); + config.addDefault("Abilities.Passives.WallRun.Fire", true); + config.addDefault("Abilities.Passives.WallRun.Chi", true); + config.addDefault("Abilities.Passives.WallRun.InvalidBlocks", invalidWallRun); + + config.options().copyDefaults(true); + plugin.saveConfig(); + } + + private void addDeathMessages() { + FileConfiguration lang = ConfigManager.languageConfig.get(); + + //Fire + lang.addDefault("Abilities.Fire.FireComet.DeathMessage", "{victim} was squashed under the pressure of {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FireBall.DeathMessage", "{victim} burst from {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FireBreath.DeathMessage", "{victim} was consumed {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.Discharge.DeathMessage", "{victim} couldn't take {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FirePunch.DeathMessage", "{victim} punched out from {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.FireShots.DeathMessage", "{victim} was shot by {attacker}'s {ability}"); + lang.addDefault("Abilities.Fire.LightningBurst.DeathMessage", "{victim} crackled out of existence from {attacker}'s {ability}"); + + //Water + lang.addDefault("Abilities.Water.Drain.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.FrostBreath.DeathMessage", "{victim} shattered from {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.IceClaws.DeathMessage", "{victim} was ripped to shreds by {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.IceWall.DeathMessage", "{victim} was collateral to {attacker}'s exploding {ability}"); + lang.addDefault("Abilities.Water.WaterBlast.DeathMessage", "{victim} was blasted by {attacker}'s {ability}"); + lang.addDefault("Abilities.Water.Combo.WaterGimbal.DeathMessage", "{victim} was ripped apart by {attacker}'s {ability}"); + + //Earth + lang.addDefault("Abilities.Earth.EarthKick.DeathMessage", "{victim} got too much dirt in their eye from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.EarthLine.DeathMessage", "{victim} lost their footing from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.EarthShard.DeathMessage", "{victim} got blasted apart {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.LavaDisc.DeathMessage", "{victim} sliced in half by {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.LavaFlux.DeathMessage", "{victim} couldn't take the heat from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.LavaThrow.DeathMessage", "{victim} melted from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.MetalFragments.DeathMessage", "{victim} was shredded apart from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.MetalShred.DeathMessage", "{victim} was in the way of {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.MudSurge.DeathMessage", "{victim} drowned in mud from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.SandBlast.DeathMessage", "{victim} was sandblasted to oblivion from {attacker}'s {ability}"); + lang.addDefault("Abilities.Earth.Combo.MagmaBlast.DeathMessage", "{victim} was obliterated by {attacker}'s {ability}"); + + //Air + lang.addDefault("Abilities.Air.AirBlade.DeathMessage", "{victim} was sliced in two by {attacker}'s {ability}"); + lang.addDefault("Abilities.Air.AirPunch.DeathMessage", "{victim} was exploded by {attacker}'s {ability}"); + lang.addDefault("Abilities.Air.SonicBlast.DeathMessage", "{victim}'s ears burst after {attacker}'s {ability}"); + + //Chi + lang.addDefault("Abilities.Chi.DaggerThrow.DeathMessage", "{victim} got stabbed too many times from {attacker}'s {ability}"); + lang.addDefault("Abilities.Chi.Backstab.DeathMessage", "{victim} fell victim to {attacker}'s {ability}"); + + //Avatar + lang.addDefault("Abilities.Avatar.SpiritBeam.DeathMessage", "{victim} was erased from existence by {attacker}'s {ability}"); + lang.addDefault("Abilities.Avatar.ElementSphereAir.DeathMessage", "{victim} was blasted apart by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereFire.DeathMessage", "{victim} was burnt to cinders by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereEarth.DeathMessage", "{victim} was crushed by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereWater.DeathMessage", "{victim} was sliced apart by {attacker}'s \u00A75ElementSphere"); + lang.addDefault("Abilities.Avatar.ElementSphereStream.DeathMessage", "{victim} took the full force of {attacker}'s \u00A75ElementSphere"); + + ConfigManager.languageConfig.save(); + } + + private void setupElementSphereNames() { + FileConfiguration lang = ConfigManager.languageConfig.get(); + + lang.addDefault("Abilities.Avatar.ElementSphereAir.Name", "Air"); + lang.addDefault("Abilities.Avatar.ElementSphereFire.Name", "Fire"); + lang.addDefault("Abilities.Avatar.ElementSphereEarth.Name", "Earth"); + lang.addDefault("Abilities.Avatar.ElementSphereWater.Name", "Water"); + lang.addDefault("Abilities.Avatar.ElementSphereStream.Name", "Stream"); + + ConfigManager.languageConfig.save(); + } + + public static ConfigurationSection getConfig(Player player) { + if (player == null) + return getConfig((World)null); + return getConfig(player.getWorld()); + } + + public static ConfigurationSection getConfig(World world) { + boolean perWorldConfig = plugin.getConfig().getBoolean("Properties.PerWorldConfig"); + + if (world == null || !perWorldConfig) { + return plugin.getConfig(); + } + + String prefix = "Worlds." + world.getName(); + return new SubsectionConfigurationDecorator(plugin.getConfig(), prefix); + } +} \ No newline at end of file From 1735a39c89ed9ce30c9222a125eb197e2e5b6158 Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 26 Oct 2025 12:59:07 -0700 Subject: [PATCH 58/61] Update maven.yml --- .github/workflows/maven.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 622be6b..d697d17 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -29,7 +29,3 @@ jobs: cache: maven - name: Build with Maven run: mvn -B package --file pom.xml - - # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive - - name: Update dependency graph - uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 From 11cf0e245c9424a660607c9c9e77464afa7e83e3 Mon Sep 17 00:00:00 2001 From: Hihelloy-main Date: Sun, 26 Oct 2025 18:23:14 -0700 Subject: [PATCH 59/61] Adds CheckMaintainer() and other things (check changelog) --- src/com/jedk1/jedcore/JCMethods.java | 2 ++ src/com/jedk1/jedcore/JedCore.java | 18 ++++++++++++++---- .../jedk1/jedcore/command/JedCoreCommand.java | 4 ++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/com/jedk1/jedcore/JCMethods.java b/src/com/jedk1/jedcore/JCMethods.java index 590d3cf..abc4d74 100644 --- a/src/com/jedk1/jedcore/JCMethods.java +++ b/src/com/jedk1/jedcore/JCMethods.java @@ -1,5 +1,6 @@ package com.jedk1.jedcore; +import com.jedk1.jedcore.command.Commands; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.FireTick; import com.jedk1.jedcore.util.LightManagerUtil; @@ -352,5 +353,6 @@ public static void reload() { RegenTempBlock.revertAll(); JedCore.plugin.initializeCollisions(); FireTick.loadMethod(); + new Commands(); } } \ No newline at end of file diff --git a/src/com/jedk1/jedcore/JedCore.java b/src/com/jedk1/jedcore/JedCore.java index 5e5179e..2ae6116 100644 --- a/src/com/jedk1/jedcore/JedCore.java +++ b/src/com/jedk1/jedcore/JedCore.java @@ -66,12 +66,9 @@ public void onEnable() { luminol = true; } catch (ClassNotFoundException ignored) {} - if (isFolia && !luminol) { - getLogger().info("Server is running on Folia"); - } if (paper && !luminol) { - getLogger().info("Server is running on Paper"); + getLogger().info("Server is running on Paper/Folia"); } if (luminol) { @@ -93,6 +90,7 @@ public void onEnable() { // Repeating logic task - uses ThreadUtil ThreadUtil.runGlobalTimer(new JCManager(this), 0L, 1L); + ThreadUtil.runGlobalTimer(RegenTempBlock::manage, 0L, 1L); new Commands(); FireTick.loadMethod(); @@ -100,6 +98,8 @@ public void onEnable() { particleAdapter = new ParticleAdapterFactory().getAdapter(); potionEffectAdapter = new PotionEffectAdapterFactory().getAdapter(); + checkMaintainer(); + // Delayed combo/collision init ThreadUtil.runGlobalLater(() -> { JCMethods.registerCombos(); @@ -116,6 +116,12 @@ public void onEnable() { } } + public static void checkMaintainer() { + if (!dev.contains("Cozmyc (Maintainer), Hihelloy (Updater)")) { + dev = dev + ", Cozmyc (Maintainer), Hihelloy (Updater)"; + } + } + public void initializeCollisions() { boolean enabled = getConfig().getBoolean("Properties.AbilityCollisions.Enabled"); if (!enabled) { @@ -160,6 +166,10 @@ public PotionEffectAdapter getPotionEffectAdapter() { return potionEffectAdapter; } + /** + * + * Determines if the server is running Folia or not + */ public static boolean isFolia() { return isFolia; } diff --git a/src/com/jedk1/jedcore/command/JedCoreCommand.java b/src/com/jedk1/jedcore/command/JedCoreCommand.java index 7fad625..0e994f3 100644 --- a/src/com/jedk1/jedcore/command/JedCoreCommand.java +++ b/src/com/jedk1/jedcore/command/JedCoreCommand.java @@ -2,6 +2,7 @@ import com.jedk1.jedcore.JedCore; import com.projectkorra.projectkorra.command.PKCommand; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -30,6 +31,9 @@ public void execute(CommandSender sender, List args) { if (!correctLength(sender, args.size(), 0, 1) || (!hasPermission(sender) && !isSenderJedCoreDev(sender))) { return; } + if (isSenderJedCoreDev(sender) && sender instanceof Player) { + sender.sendMessage("Thanks for your contribution" + ((Player) sender).getUniqueId()); + } if (args.isEmpty()) { sendBuildInfo(sender); From 23180322837d6d800753ffe489629c76c0fa493e Mon Sep 17 00:00:00 2001 From: Hihelloy Date: Sun, 26 Oct 2025 18:26:03 -0700 Subject: [PATCH 60/61] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a4b8a39..4203184 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ This is my fork of Cozymc's fork of plushmonkey's fork of jedk1's JedCore addon Download releases [here](https://github.com/Hihelloy-main/JedCore/releases). Join our [Discord](https://discord.gg/gh9MfDmwZm) to discuss the plugin, suggest changes, report bugs, etc. +This fork attempts on adding Folia support. + ## Changelog ### 2.14.4 From d3dc9a209e03a991f03d9f7712f7df241a3e24ae Mon Sep 17 00:00:00 2001 From: Hihelloy-main Date: Sat, 15 Nov 2025 14:06:24 -0800 Subject: [PATCH 61/61] Finally fixes MudSurge and EarthShard when used on a server with my ProjectKorra 1.12.1 build two at: https://github.com/Hihelloy-main/ProjectKorra --- pom.xml | 16 +- .../ability/earthbending/EarthShard.java | 176 +++++++++++++----- .../ability/earthbending/MudSurge.java | 36 +++- src/com/jedk1/jedcore/util/ThreadUtil.java | 1 + 4 files changed, 169 insertions(+), 60 deletions(-) diff --git a/pom.xml b/pom.xml index 8d5811f..665826b 100644 --- a/pom.xml +++ b/pom.xml @@ -17,17 +17,21 @@ papermc https://repo.papermc.io/repository/maven-public/ + + jitpack.io + https://jitpack.io + - - com.projectkorra - projectkorra - 1.12.1-PRE-RELEASE-1 - provided - + + com.projectkorra + projectkorra + 1.12.1-PRE-RELEASE-1 + provided + org.spigotmc diff --git a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java index 7062adc..04a2fe4 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java +++ b/src/com/jedk1/jedcore/ability/earthbending/EarthShard.java @@ -1,34 +1,36 @@ package com.jedk1.jedcore.ability.earthbending; -import java.util.*; -import java.util.stream.Collectors; - +import com.jedk1.jedcore.JedCore; import com.jedk1.jedcore.collision.AABB; import com.jedk1.jedcore.collision.CollisionDetector; import com.jedk1.jedcore.collision.CollisionUtil; import com.jedk1.jedcore.configuration.JedCoreConfig; import com.jedk1.jedcore.util.BlockUtil; +import com.projectkorra.projectkorra.GeneralMethods; +import com.projectkorra.projectkorra.ability.AddonAbility; +import com.projectkorra.projectkorra.ability.EarthAbility; import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempFallingBlock; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import com.jedk1.jedcore.JedCore; -import com.projectkorra.projectkorra.GeneralMethods; -import com.projectkorra.projectkorra.ability.AddonAbility; -import com.projectkorra.projectkorra.ability.EarthAbility; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; public class EarthShard extends EarthAbility implements AddonAbility { @Attribute(Attribute.RANGE) @@ -54,6 +56,14 @@ public class EarthShard extends EarthAbility implements AddonAbility { private final List readyBlocksTracker = new ArrayList<>(); private final List fallingBlocks = new ArrayList<>(); + private boolean allowKnockup; + private double knockupVelocity; + private double knockupRange; + + private boolean allowKnockupSelf; + private double knockupSelfVelocity; + private double knockupSelfRange; + public EarthShard(Player player) { super(player); @@ -92,6 +102,12 @@ public void setFields() { cooldown = config.getLong("Abilities.Earth.EarthShard.Cooldown"); abilityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.AbilityCollisionRadius"); entityCollisionRadius = config.getDouble("Abilities.Earth.EarthShard.EntityCollisionRadius"); + allowKnockup = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Others.Allow"); + knockupVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Velocity"); + knockupRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Others.Range"); + allowKnockupSelf = config.getBoolean("Abilities.Earth.EarthShard.KnockUp.Self.Allow"); + knockupSelfVelocity = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Velocity"); + knockupSelfRange = config.getDouble("Abilities.Earth.EarthShard.KnockUp.Self.Range"); } public void select() { @@ -99,53 +115,68 @@ public void select() { } public void raiseEarthBlock(Block block) { - if (block == null) { - return; - } - - if (tblockTracker.size() >= maxShards) { - return; - } + if (block == null) return; + if (EarthAbility.getMovedEarth().containsKey(block)) return; + if (tblockTracker.size() >= maxShards) return; Vector blockVector = block.getLocation().toVector().toBlockVector().setY(0); - // Don't select from locations that already have an EarthShard block. for (TempBlock tempBlock : tblockTracker) { - if (tempBlock.getLocation().getWorld() != block.getWorld()) { - continue; - } + if (tempBlock.getLocation().getWorld() != block.getWorld()) continue; Vector tempBlockVector = tempBlock.getLocation().toVector().toBlockVector().setY(0); - - if (tempBlockVector.equals(blockVector)) { - return; - } + if (tempBlockVector.equals(blockVector)) return; } for (int i = 1; i < 4; i++) { - if (!isTransparent(block.getRelative(BlockFace.UP, i))) { - return; - } + if (!isTransparent(block.getRelative(BlockFace.UP, i))) return; } - if (isEarthbendable(block)) { - if (isMetal(block)) { - playMetalbendingSound(block.getLocation()); - } else { - ParticleEffect.BLOCK_CRACK.display(block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData()); - playEarthbendingSound(block.getLocation()); - } + if (!isEarthbendable(block)) return; - Material material = getCorrectType(block); + if (isMetal(block)) { + playMetalbendingSound(block.getLocation()); + } else { + ParticleEffect.BLOCK_CRACK.display( + block.getLocation().add(0, 1, 0), 20, 0.0, 0.0, 0.0, 0.0, block.getBlockData() + ); + playEarthbendingSound(block.getLocation()); + } - if (DensityShift.isPassiveSand(block)) { - DensityShift.revertSand(block); - } + Material material = getCorrectType(block); - Location loc = block.getLocation().add(0.5, 0, 0.5); - new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); - TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); - tblockTracker.add(tb); + if (DensityShift.isPassiveSand(block)) { + DensityShift.revertSand(block); + } + + Location loc = block.getLocation().add(0.5, 0, 0.5); + new TempFallingBlock(loc, material.createBlockData(), new Vector(0, 0.8, 0), this); + TempBlock tb = new TempBlock(block, Material.AIR.createBlockData()); + tblockTracker.add(tb); + + handleKnockup(block); + } + + private void handleKnockup(Block origin) { + if (!allowKnockup && !allowKnockupSelf) return; + + Location originLoc = origin.getLocation(); + World world = origin.getWorld(); + + for (Entity entity : world.getNearbyEntities(originLoc, Math.max(knockupRange, knockupSelfRange), knockupRange, knockupRange)) { + if (entity instanceof FallingBlock) continue; + + if (entity.equals(player)) { + if (!allowKnockupSelf) continue; + if (entity.getLocation().distance(originLoc) <= knockupSelfRange) { + entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupSelfVelocity, 0))); + } + } else { + if (!allowKnockup) continue; + if (entity.getLocation().distance(originLoc) <= knockupRange) { + entity.setVelocity(entity.getVelocity().add(new Vector(0, knockupVelocity, 0))); + } + } } } @@ -183,7 +214,8 @@ public void progress() { return; } - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + // iterate over a defensive copy to avoid ConcurrentModificationException + for (TempFallingBlock tfb : new ArrayList<>(TempFallingBlock.getFromAbility(this))) { FallingBlock fb = tfb.getFallingBlock(); if (fb.isDead() || fb.getLocation().getBlockY() == origin.getBlockY() + 2) { @@ -193,7 +225,8 @@ public void progress() { } } } else { - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + // iterate over a defensive copy to avoid ConcurrentModificationException + for (TempFallingBlock tfb : new ArrayList<>(TempFallingBlock.getFromAbility(this))) { FallingBlock fb = tfb.getFallingBlock(); AABB collider = BlockUtil.getFallingBlockBoundsFull(fb).scale(entityCollisionRadius * 2.0); @@ -282,7 +315,8 @@ public void revertBlocks() { @Override public void remove() { // Destroy any remaining falling blocks. - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + // iterate over a defensive copy to avoid ConcurrentModificationException + for (TempFallingBlock tfb : new ArrayList<>(TempFallingBlock.getFromAbility(this))) { tfb.remove(); } @@ -435,6 +469,54 @@ public List getFallingBlocks() { return fallingBlocks; } + public boolean isAllowKnockup() { + return allowKnockup; + } + + public void setAllowKnockup(boolean allowKnockup) { + this.allowKnockup = allowKnockup; + } + + public double getKnockupVelocity() { + return knockupVelocity; + } + + public void setKnockupVelocity(double knockupVelocity) { + this.knockupVelocity = knockupVelocity; + } + + public double getKnockupRange() { + return knockupRange; + } + + public void setKnockupRange(double knockupRange) { + this.knockupRange = knockupRange; + } + + public boolean isAllowKnockupSelf() { + return allowKnockupSelf; + } + + public void setAllowKnockupSelf(boolean allowKnockupSelf) { + this.allowKnockupSelf = allowKnockupSelf; + } + + public double getKnockupSelfVelocity() { + return knockupSelfVelocity; + } + + public void setKnockupSelfVelocity(double knockupSelfVelocity) { + this.knockupSelfVelocity = knockupSelfVelocity; + } + + public double getKnockupSelfRange() { + return knockupSelfRange; + } + + public void setKnockupSelfRange(double knockupSelfRange) { + this.knockupSelfRange = knockupSelfRange; + } + @Override public void load() {} @@ -446,4 +528,4 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Earth.EarthShard.Enabled"); } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java index 98ce05e..f704193 100644 --- a/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java +++ b/src/com/jedk1/jedcore/ability/earthbending/MudSurge.java @@ -323,7 +323,8 @@ private void loadMudPool() { } private void createMudPool() { - if (!mudAreaItr.hasNext()) { + // guard against a null iterator (safety) and handle empty iterator + if (mudAreaItr == null || !mudAreaItr.hasNext()) { mudFormed = true; return; } @@ -368,16 +369,34 @@ private void surge() { } private void affect() { - for (TempFallingBlock tfb : TempFallingBlock.getFromAbility(this)) { + // Copy the collection to avoid ConcurrentModificationExceptions if the underlying collection is mutated by tfb.remove() + List tempList = new ArrayList<>(TempFallingBlock.getFromAbility(this)); + + for (TempFallingBlock tfb : tempList) { FallingBlock fb = tfb.getFallingBlock(); + if (fb == null) { + // Defensive: if falling block not present, ensure TFb is removed from the original collection + try { + tfb.remove(); + } catch (Exception ignored) {} + continue; + } + if (fb.isDead()) { - tfb.remove(); + // Remove from both TFb internal registration and our local tracking if needed + try { + tfb.remove(); + } catch (Exception ignored) {} continue; } - for (Entity e : GeneralMethods.getEntitiesAroundPoint(fb.getLocation(), 1.5)) { + // Copy entity list as well just in case another plugin modifies entities mid-iteration + List entities = new ArrayList<>(GeneralMethods.getEntitiesAroundPoint(fb.getLocation(), 1.5)); + for (Entity e : entities) { if (fb.isDead()) { - tfb.remove(); + try { + tfb.remove(); + } catch (Exception ignored) {} continue; } if (RegionProtection.isRegionProtected(this, e.getLocation()) || ((e instanceof Player) && Commands.invincible.contains(e.getName()))){ @@ -403,8 +422,11 @@ private void affect() { blind.add((Player) e); } + // Apply velocity and then remove the falling block (safe because we're iterating a copy) e.setVelocity(fb.getVelocity().multiply(0.8)); - tfb.remove(); + try { + tfb.remove(); + } catch (Exception ignored) {} } } } @@ -657,4 +679,4 @@ public boolean isEnabled() { ConfigurationSection config = JedCoreConfig.getConfig(this.player); return config.getBoolean("Abilities.Earth.MudSurge.Enabled"); } -} \ No newline at end of file +} diff --git a/src/com/jedk1/jedcore/util/ThreadUtil.java b/src/com/jedk1/jedcore/util/ThreadUtil.java index cdc977d..e700175 100644 --- a/src/com/jedk1/jedcore/util/ThreadUtil.java +++ b/src/com/jedk1/jedcore/util/ThreadUtil.java @@ -11,6 +11,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean;