diff --git a/localrepo/com/songoda/kingdoms/1.2.3/kingdoms-1.2.3.jar b/localrepo/com/songoda/kingdoms/1.2.3/kingdoms-1.2.3.jar deleted file mode 100644 index 9635c970..00000000 Binary files a/localrepo/com/songoda/kingdoms/1.2.3/kingdoms-1.2.3.jar and /dev/null differ diff --git a/localrepo/com/songoda/kingdoms/1.2.3/kingdoms-1.2.3.pom b/localrepo/com/songoda/kingdoms/1.2.3/kingdoms-1.2.3.pom deleted file mode 100644 index a0dac4bc..00000000 --- a/localrepo/com/songoda/kingdoms/1.2.3/kingdoms-1.2.3.pom +++ /dev/null @@ -1,9 +0,0 @@ - - - 4.0.0 - com.songoda - kingdoms - 1.2.3 - POM was created from install:install-file - diff --git a/localrepo/com/songoda/kingdoms/maven-metadata-local.xml b/localrepo/com/songoda/kingdoms/maven-metadata-local.xml deleted file mode 100644 index 31130761..00000000 --- a/localrepo/com/songoda/kingdoms/maven-metadata-local.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - com.songoda - kingdoms - - 1.2.3 - - 1.2.3 - - 20190223101813 - - diff --git a/pom.xml b/pom.xml index 9e24473d..120eae15 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.projectkorra projectkorra - 1.9.0 + 1.9.2 ProjectKorra @@ -17,7 +17,7 @@ sk89q-repo http://maven.sk89q.com/repo/ - + jitpack.io https://jitpack.io @@ -80,8 +80,8 @@ factionsframework 1.2.0 provided - - + + com.github.TechFortress GriefPrevention @@ -121,9 +121,9 @@ - com.palmergames + com.github.TownyAdvanced Towny - 0.93.0.0 + 0.96.2.0 provided @@ -160,10 +160,16 @@ - com.songoda + com.github.cryptomorin kingdoms - 1.2.3 - provided + 1.10.19.1 + compile + + + * + * + + @@ -208,9 +214,17 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.2.4 ${project.build.directory}/dependency-reduced-pom.xml + + + com.github.cryptomorin:kingdoms + + org/kingdoms/constants/player/KingdomPermission.class + + + co.aikar.timings.lib diff --git a/src/com/projectkorra/projectkorra/BendingPlayer.java b/src/com/projectkorra/projectkorra/BendingPlayer.java index bcff7f8a..ab9a3b74 100644 --- a/src/com/projectkorra/projectkorra/BendingPlayer.java +++ b/src/com/projectkorra/projectkorra/BendingPlayer.java @@ -10,6 +10,7 @@ import java.util.Map.Entry; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import com.projectkorra.projectkorra.event.PlayerStanceChangeEvent; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -27,6 +28,7 @@ import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.util.PassiveManager; import com.projectkorra.projectkorra.avatar.AvatarState; +import com.projectkorra.projectkorra.board.BendingBoardManager; import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.configuration.ConfigManager; import com.projectkorra.projectkorra.earthbending.metal.MetalClips; @@ -132,7 +134,7 @@ public class BendingPlayer { if (cooldown <= 0) { return; } - final PlayerCooldownChangeEvent event = new PlayerCooldownChangeEvent(Bukkit.getPlayer(this.uuid), ability, cooldown, Result.ADDED); + final PlayerCooldownChangeEvent event = new PlayerCooldownChangeEvent(player, ability, cooldown, Result.ADDED); Bukkit.getServer().getPluginManager().callEvent(event); if (!event.isCancelled()) { @@ -147,9 +149,11 @@ public class BendingPlayer { final String abilityName = event.getAbility(); final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer.getBoundAbility() != null && bPlayer.getBoundAbility().equals(CoreAbility.getAbility(abilityName))) { + if (bPlayer != null && bPlayer.getBoundAbility() != null && bPlayer.getBoundAbility().equals(CoreAbility.getAbility(abilityName))) { GeneralMethods.displayMovePreview(player); } + + BendingBoardManager.updateBoard(player, event.getAbility(), true, 0); } } @@ -310,6 +314,8 @@ public class BendingPlayer { return false; } else if (!this.player.hasPermission("bending." + element.getName() + ".passive")) { return false; + } else if (!this.player.hasPermission("bending.ability." + ability.getName())) { + return false; } else if (!this.hasElement(element)) { return false; } else if (disabledWorlds != null && disabledWorlds.contains(this.player.getWorld().getName())) { @@ -803,22 +809,25 @@ public class BendingPlayer { * @param ability The ability's cooldown to remove */ public void removeCooldown(final String ability) { - if (Bukkit.getPlayer(this.uuid) == null) { - return; - } - - final PlayerCooldownChangeEvent event = new PlayerCooldownChangeEvent(Bukkit.getPlayer(this.uuid), ability, 0, Result.REMOVED); + final PlayerCooldownChangeEvent event = new PlayerCooldownChangeEvent(player, ability, 0, Result.REMOVED); Bukkit.getServer().getPluginManager().callEvent(event); if (!event.isCancelled()) { this.cooldowns.remove(ability); final Player player = event.getPlayer(); + + if (player == null) { + return; + } + final String abilityName = event.getAbility(); final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer.getBoundAbility() != null && bPlayer.getBoundAbility().equals(CoreAbility.getAbility(abilityName))) { + if (bPlayer != null && bPlayer.getBoundAbility() != null && bPlayer.getBoundAbility().equals(CoreAbility.getAbility(abilityName))) { GeneralMethods.displayMovePreview(player); } + + BendingBoardManager.updateBoard(player, event.getAbility(), false, 0); } } @@ -858,11 +867,17 @@ public class BendingPlayer { /** * Sets the player's {@link ChiAbility Chi stance} + * Also update any previews * * @param stance The player's new stance object */ public void setStance(final ChiAbility stance) { + final String oldStance = (this.stance == null) ? "" : this.stance.getName(); + final String newStance = (stance == null) ? "" : stance.getName(); this.stance = stance; + GeneralMethods.displayMovePreview(player); + final PlayerStanceChangeEvent event = new PlayerStanceChangeEvent(Bukkit.getPlayer(this.uuid), oldStance, newStance); + Bukkit.getServer().getPluginManager().callEvent(event); } /** diff --git a/src/com/projectkorra/projectkorra/GeneralMethods.java b/src/com/projectkorra/projectkorra/GeneralMethods.java index 6073360a..714a3251 100644 --- a/src/com/projectkorra/projectkorra/GeneralMethods.java +++ b/src/com/projectkorra/projectkorra/GeneralMethods.java @@ -39,28 +39,13 @@ import com.google.common.reflect.ClassPath; import com.griefcraft.lwc.LWC; import com.griefcraft.lwc.LWCPlugin; import com.griefcraft.model.Protection; -import com.palmergames.bukkit.towny.Towny; -import com.palmergames.bukkit.towny.TownyMessaging; -import com.palmergames.bukkit.towny.TownySettings; -import com.palmergames.bukkit.towny.object.Coord; -import com.palmergames.bukkit.towny.object.PlayerCache; -import com.palmergames.bukkit.towny.object.PlayerCache.TownBlockStatus; -import com.palmergames.bukkit.towny.object.TownyPermission; -import com.palmergames.bukkit.towny.object.TownyUniverse; -import com.palmergames.bukkit.towny.object.TownyWorld; -import com.palmergames.bukkit.towny.object.WorldCoord; +import com.palmergames.bukkit.towny.object.TownyPermission.ActionType; import com.palmergames.bukkit.towny.utils.PlayerCacheUtil; -import com.palmergames.bukkit.towny.war.flagwar.TownyWar; -import com.palmergames.bukkit.towny.war.flagwar.TownyWarConfig; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.flags.StateFlag; -import com.songoda.kingdoms.constants.land.Land; -import com.songoda.kingdoms.constants.land.SimpleChunkLocation; -import com.songoda.kingdoms.constants.player.KingdomPlayer; -import com.songoda.kingdoms.manager.game.GameManagement; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -87,6 +72,13 @@ import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; +import org.kingdoms.constants.kingdom.Kingdom; +import org.kingdoms.constants.kingdom.model.KingdomRelation; +import org.kingdoms.constants.land.Land; +import org.kingdoms.constants.land.structures.managers.Regulator; +import org.kingdoms.constants.land.structures.managers.Regulator.Attribute; +import org.kingdoms.constants.player.DefaultKingdomPermission; +import org.kingdoms.constants.player.KingdomPlayer; import com.projectkorra.projectkorra.Element.SubElement; import com.projectkorra.projectkorra.ability.Ability; @@ -109,9 +101,11 @@ import com.projectkorra.projectkorra.airbending.AirShield; import com.projectkorra.projectkorra.airbending.AirSpout; import com.projectkorra.projectkorra.airbending.AirSuction; import com.projectkorra.projectkorra.airbending.AirSwipe; +import com.projectkorra.projectkorra.board.BendingBoardManager; import com.projectkorra.projectkorra.configuration.ConfigManager; import com.projectkorra.projectkorra.earthbending.EarthBlast; import com.projectkorra.projectkorra.earthbending.passive.EarthPassive; +import com.projectkorra.projectkorra.event.AbilityVelocityAffectEntityEvent; import com.projectkorra.projectkorra.event.BendingPlayerCreationEvent; import com.projectkorra.projectkorra.event.BendingReloadEvent; import com.projectkorra.projectkorra.event.PlayerBindChangeEvent; @@ -125,8 +119,6 @@ import com.projectkorra.projectkorra.util.BlockCacheElement; import com.projectkorra.projectkorra.util.ColoredParticle; import com.projectkorra.projectkorra.util.MovementHandler; import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.ReflectionHandler; -import com.projectkorra.projectkorra.util.ReflectionHandler.PackageType; import com.projectkorra.projectkorra.util.TempArmor; import com.projectkorra.projectkorra.util.TempArmorStand; import com.projectkorra.projectkorra.util.TempBlock; @@ -155,25 +147,13 @@ public class GeneralMethods { private static final ArrayList INVINCIBLE = new ArrayList<>(); private static ProjectKorra plugin; - private static Method getAbsorption; - private static Method setAbsorption; - private static Method getHandle; - public GeneralMethods(final ProjectKorra plugin) { GeneralMethods.plugin = plugin; - - try { - getAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "getAbsorptionHearts"); - setAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "setAbsorptionHearts", Float.class); - getHandle = ReflectionHandler.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); - } catch (final Exception e) { - e.printStackTrace(); - } } /** * Checks to see if an AbilityExists. Uses method - * {@link #getAbility(String)} to check if it exists. + * {@link CoreAbility#getAbility(String)} to check if it exists. * * @param string Ability Name * @return true if ability exists @@ -681,26 +661,25 @@ public class GeneralMethods { ActionBar.sendActionBar(displayedMessage, player); } + /** + * Gets the number of absorption hearts of a specified {@link Player}. + * @param player the {@link Player} to get the absorption hearts of. + * @deprecated Use {@link Player#getAbsorptionAmount()}. + */ + @Deprecated public static float getAbsorbationHealth(final Player player) { - - try { - final Object entityplayer = getHandle.invoke(player); - final Object hearts = getAbsorption.invoke(entityplayer); - return (float) hearts; - } catch (final Exception e) { - e.printStackTrace(); - } - return 0; + return (float) player.getAbsorptionAmount(); } + /** + * Sets the number of absorption hearts of a specified {@link Player}. + * @param player the {@link Player} to set the absorption hearts of. + * @param hearts a float representing the number of hearts to set. + * @deprecated Use {@link Player#setAbsorptionAmount(double)} + */ + @Deprecated public static void setAbsorbationHealth(final Player player, final float hearts) { - - try { - final Object entityplayer = getHandle.invoke(player); - setAbsorption.invoke(entityplayer, hearts); - } catch (final Exception e) { - e.printStackTrace(); - } + player.setAbsorptionAmount(hearts); } public static int getArmorTier(Material mat) { @@ -1041,7 +1020,6 @@ public class GeneralMethods { * @param block The single block * @param type The Material type to change the block into * @param data The block data to change the block into - * @param breakitem Unused * @return The item drops fromt the specified block */ public static Collection getDrops(final Block block, final Material type, final BlockData data) { @@ -1297,7 +1275,7 @@ public class GeneralMethods { if (trans.contains(block.getType())) { continue; - } else if (ignoreTempBlocks && (TempBlock.isTempBlock(block) && !WaterAbility.isBendableWaterTempBlock(block))) { + } else if (ignoreTempBlocks && (TempBlock.isTempBlock(block) && !WaterAbility.isBendableWaterTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block))) { continue; } else { location.subtract(vec); @@ -1564,7 +1542,7 @@ public class GeneralMethods { final boolean respectGriefPrevention = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectGriefPrevention"); final boolean respectLWC = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectLWC"); final boolean respectResidence = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.Residence.Respect"); - final boolean respectKingdoms = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectKingdoms"); + final boolean respectKingdoms = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.Kingdoms.Respect"); final boolean respectRedProtect = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectRedProtect"); boolean isIgnite = false; @@ -1658,38 +1636,8 @@ public class GeneralMethods { } if (twnp != null && respectTowny) { - final Towny twn = (Towny) twnp; - - WorldCoord worldCoord; - - try { - final TownyWorld tWorld = TownyUniverse.getDataSource().getWorld(world.getName()); - worldCoord = new WorldCoord(tWorld.getName(), Coord.parseCoord(location)); - final boolean bBuild = PlayerCacheUtil.getCachePermission(player, location, Material.DIRT, TownyPermission.ActionType.BUILD); - - if (!bBuild) { - final PlayerCache cache = twn.getCache(player); - final TownBlockStatus status = cache.getStatus(); - - if (((status == TownBlockStatus.ENEMY) && TownyWarConfig.isAllowingAttacks())) { - try { - TownyWar.callAttackCellEvent(twn, player, location.getBlock(), worldCoord); - } catch (final Exception e) { - TownyMessaging.sendErrorMsg(player, e.getMessage()); - } - return true; - } else if (status == TownBlockStatus.WARZONE) { - - } else { - return true; - } - - if ((cache.hasBlockErrMsg())) { - TownyMessaging.sendErrorMsg(player, cache.getBlockErrMsg()); - } - } - } catch (final Exception e1) { - TownyMessaging.sendErrorMsg(player, TownySettings.getLangString("msg_err_not_configured")); + if (!PlayerCacheUtil.getCachePermission(player, location, Material.DIRT, ActionType.BUILD)) { + return true; } } @@ -1719,18 +1667,22 @@ public class GeneralMethods { } if (kingdoms != null && respectKingdoms) { - final KingdomPlayer kPlayer = GameManagement.getPlayerManager().getOfflineKingdomPlayer(player).getKingdomPlayer(); - if (kPlayer.getKingdom() != null) { - final SimpleChunkLocation chunkLocation = new SimpleChunkLocation(location.getChunk()); - final Land land = GameManagement.getLandManager().getOrLoadLand(chunkLocation); - final UUID owner = land.getOwnerUUID(); - if (owner != null) { - if (!kPlayer.getKingdom().getKing().equals(owner)) { - return true; - } + final KingdomPlayer kPlayer = KingdomPlayer.getKingdomPlayer(player); + final Land land = Land.getLand(location); + final boolean protectDuringInvasions = ConfigManager.getConfig().getBoolean("Properties.RegionProtection.Kingdoms.ProtectDuringInvasions"); + if (land != null) { + final Kingdom kingdom = land.getKingdom(); + if (kPlayer.isAdmin() + || (!protectDuringInvasions && !land.getInvasions().isEmpty() && land.getInvasions().values().stream().anyMatch(i -> i.getInvader().equals(kPlayer))) // Protection during invasions is off, and player is currently invading; allow + || (land.getStructure() != null && land.getStructure() instanceof Regulator && ((Regulator) land.getStructure()).hasAttribute(player, Attribute.BUILD))) { // There is a regulator on site which allows the player to build; allow + return false; + } + if (!kPlayer.hasKingdom() // Player has no kingdom; deny + || (kPlayer.getKingdom().equals(kingdom) && !kPlayer.hasPermission(DefaultKingdomPermission.BUILD)) // Player is a member of this kingdom but cannot build here; deny + || (!kPlayer.getKingdom().equals(kingdom) && !kPlayer.getKingdom().hasAttribute(kingdom, KingdomRelation.Attribute.BUILD))) { // Player is not a member of this kingdom and cannot build here; deny + return true; } } - } if (redprotect != null && respectRedProtect) { @@ -1928,6 +1880,7 @@ public class GeneralMethods { GeneralMethods.createBendingPlayer(player.getUniqueId(), player.getName()); PassiveManager.registerPassives(player); } + BendingBoardManager.reload(); plugin.updater.checkUpdate(); ProjectKorra.log.info("Reload complete"); } @@ -2064,7 +2017,7 @@ public class GeneralMethods { final boolean respectGriefPrevention = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectGriefPrevention"); final boolean respectLWC = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectLWC"); final boolean respectResidence = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.Residence.Respect"); - final boolean respectKingdoms = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.Kingdoms"); + final boolean respectKingdoms = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.Kingdoms.Respect"); final boolean respectRedProtect = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RedProtect"); final PluginManager pm = Bukkit.getPluginManager(); @@ -2314,39 +2267,6 @@ public class GeneralMethods { DBConnection.sql.modifyQuery("UPDATE pk_players SET permaremoved = '" + (permaRemoved ? "true" : "false") + "' WHERE uuid = '" + uuid + "'"); } - public static void setVelocity(final Entity entity, final Vector velocity) { - if (entity instanceof TNTPrimed) { - if (ConfigManager.defaultConfig.get().getBoolean("Properties.BendingAffectFallingSand.TNT")) { - velocity.multiply(ConfigManager.defaultConfig.get().getDouble("Properties.BendingAffectFallingSand.TNTStrengthMultiplier")); - } - } else if (entity instanceof FallingBlock) { - if (ConfigManager.defaultConfig.get().getBoolean("Properties.BendingAffectFallingSand.Normal")) { - velocity.multiply(ConfigManager.defaultConfig.get().getDouble("Properties.BendingAffectFallingSand.NormalStrengthMultiplier")); - } - } - - // Attempt to stop velocity from going over the packet cap. - if (velocity.getX() > 4) { - velocity.setX(4); - } else if (velocity.getX() < -4) { - velocity.setX(-4); - } - - if (velocity.getY() > 4) { - velocity.setY(4); - } else if (velocity.getY() < -4) { - velocity.setY(-4); - } - - if (velocity.getZ() > 4) { - velocity.setZ(4); - } else if (velocity.getZ() < -4) { - velocity.setZ(-4); - } - - entity.setVelocity(velocity); - } - public static FallingBlock spawnFallingBlock(final Location loc, final Material type) { return spawnFallingBlock(loc, type, type.createBlockData()); } @@ -2483,9 +2403,10 @@ public class GeneralMethods { } final File saveTo = new File(plugin.getDataFolder(), "debug.txt"); - if (!saveTo.exists()) { - saveTo.createNewFile(); + if (saveTo.exists()) { + saveTo.delete(); } + saveTo.createNewFile(); final FileWriter fw = new FileWriter(saveTo, true); final PrintWriter pw = new PrintWriter(fw); @@ -2532,4 +2453,51 @@ public class GeneralMethods { return false; } } + + @Deprecated + public static void setVelocity(Entity entity, Vector vector) { + setVelocity(null,entity,vector); + } + + public static void setVelocity(Ability ability, Entity entity, Vector vector) { + final AbilityVelocityAffectEntityEvent event = new AbilityVelocityAffectEntityEvent(ability, entity, vector); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) + return; + + Vector velocity = event.getVelocity(); + if(velocity == null || Double.isNaN(velocity.length())) + return; + + if (entity instanceof TNTPrimed) { + if (ConfigManager.defaultConfig.get().getBoolean("Properties.BendingAffectFallingSand.TNT")) { + velocity.multiply(ConfigManager.defaultConfig.get().getDouble("Properties.BendingAffectFallingSand.TNTStrengthMultiplier")); + } + } else if (entity instanceof FallingBlock) { + if (ConfigManager.defaultConfig.get().getBoolean("Properties.BendingAffectFallingSand.Normal")) { + velocity.multiply(ConfigManager.defaultConfig.get().getDouble("Properties.BendingAffectFallingSand.NormalStrengthMultiplier")); + } + } + + // Attempt to stop velocity from going over the packet cap. + if (velocity.getX() > 4) { + velocity.setX(4); + } else if (velocity.getX() < -4) { + velocity.setX(-4); + } + + if (velocity.getY() > 4) { + velocity.setY(4); + } else if (velocity.getY() < -4) { + velocity.setY(-4); + } + + if (velocity.getZ() > 4) { + velocity.setZ(4); + } else if (velocity.getZ() < -4) { + velocity.setZ(-4); + } + + event.getAffected().setVelocity(velocity); + } } diff --git a/src/com/projectkorra/projectkorra/PKListener.java b/src/com/projectkorra/projectkorra/PKListener.java index e551bf4c..f7848721 100644 --- a/src/com/projectkorra/projectkorra/PKListener.java +++ b/src/com/projectkorra/projectkorra/PKListener.java @@ -103,6 +103,7 @@ import com.projectkorra.projectkorra.airbending.Tornado; import com.projectkorra.projectkorra.airbending.flight.FlightMultiAbility; import com.projectkorra.projectkorra.airbending.passive.GracefulDescent; import com.projectkorra.projectkorra.avatar.AvatarState; +import com.projectkorra.projectkorra.board.BendingBoardManager; import com.projectkorra.projectkorra.chiblocking.AcrobatStance; import com.projectkorra.projectkorra.chiblocking.HighJump; import com.projectkorra.projectkorra.chiblocking.Paralyze; @@ -137,10 +138,15 @@ import com.projectkorra.projectkorra.earthbending.metal.MetalClips; import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.earthbending.passive.EarthPassive; import com.projectkorra.projectkorra.earthbending.passive.FerroControl; +import com.projectkorra.projectkorra.event.BendingPlayerCreationEvent; import com.projectkorra.projectkorra.event.EntityBendingDeathEvent; import com.projectkorra.projectkorra.event.HorizontalVelocityChangeEvent; +import com.projectkorra.projectkorra.event.PlayerBindChangeEvent; import com.projectkorra.projectkorra.event.PlayerChangeElementEvent; +import com.projectkorra.projectkorra.event.PlayerChangeSubElementEvent; +import com.projectkorra.projectkorra.event.PlayerCooldownChangeEvent; import com.projectkorra.projectkorra.event.PlayerJumpEvent; +import com.projectkorra.projectkorra.event.PlayerStanceChangeEvent; import com.projectkorra.projectkorra.firebending.Blaze; import com.projectkorra.projectkorra.firebending.BlazeRing; import com.projectkorra.projectkorra.firebending.FireBlast; @@ -877,7 +883,7 @@ public class PKListener implements Listener { new AirBurst(player, true); } } - + CoreAbility gd = CoreAbility.getAbility(GracefulDescent.class); CoreAbility ds = CoreAbility.getAbility(DensityShift.class); CoreAbility hs = CoreAbility.getAbility(HydroSink.class); @@ -918,7 +924,7 @@ public class PKListener implements Listener { } CoreAbility hc = CoreAbility.getAbility(HeatControl.class); - + if (hc != null && bPlayer.hasElement(Element.FIRE) && bPlayer.canBendPassive(hc) && bPlayer.canUsePassive(hc) && (event.getCause() == DamageCause.FIRE || event.getCause() == DamageCause.FIRE_TICK)) { event.setCancelled(!HeatControl.canBurn(player)); } @@ -1240,6 +1246,7 @@ public class PKListener implements Listener { @EventHandler public void onPlayerChangeWorld(final PlayerChangedWorldEvent event) { PassiveManager.registerPassives(event.getPlayer()); + BendingBoardManager.forceToggleScoreboard(event.getPlayer()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @@ -1353,6 +1360,8 @@ public class PKListener implements Listener { final Player player = event.getPlayer(); final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + BendingBoardManager.clean(player); + if (ProjectKorra.isStatisticsEnabled()) { Manager.getManager(StatisticsManager.class).store(player.getUniqueId()); } @@ -1535,6 +1544,8 @@ public class PKListener implements Listener { new EarthTunnel(player); } else if (abil.equalsIgnoreCase("Tremorsense")) { bPlayer.toggleTremorSense(); + GeneralMethods.displayMovePreview(player); + BendingBoardManager.updateAllSlots(player); } else if (abil.equalsIgnoreCase("Extraction")) { new Extraction(player); } else if (abil.equalsIgnoreCase("LavaFlow")) { @@ -1583,15 +1594,18 @@ public class PKListener implements Listener { } } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerSlotChange(final PlayerItemHeldEvent event) { final Player player = event.getPlayer(); - final int slot = event.getNewSlot() + 1; - - if (ConfigManager.defaultConfig.get().getBoolean("Properties.BendingPreview")) { - GeneralMethods.displayMovePreview(player, slot); + if (!MultiAbilityManager.canChangeSlot(player, event.getNewSlot())) { + event.setCancelled(true); + return; } - + + final int slot = event.getNewSlot() + 1; + GeneralMethods.displayMovePreview(player, slot); + BendingBoardManager.changeActiveSlot(player, event.getPreviousSlot(), event.getNewSlot()); + if (ConfigManager.defaultConfig.get().getBoolean("Abilities.Water.WaterArms.DisplayBoundMsg")) { final WaterArms waterArms = CoreAbility.getAbility(player, WaterArms.class); if (waterArms != null) { @@ -1794,6 +1808,8 @@ public class PKListener implements Listener { } else if (abil.equalsIgnoreCase("Illumination")) { if (ConfigManager.defaultConfig.get().getBoolean("Abilities.Fire.Illumination.Passive")) { bPlayer.toggleIllumination(); + GeneralMethods.displayMovePreview(player); + BendingBoardManager.updateAllSlots(player); } else { new Illumination(player); } @@ -1835,6 +1851,8 @@ public class PKListener implements Listener { if (coreAbil instanceof AvatarAbility) { if (abil.equalsIgnoreCase("AvatarState")) { new AvatarState(player); + GeneralMethods.displayMovePreview(player); + BendingBoardManager.updateAllSlots(player); } } } @@ -1906,26 +1924,26 @@ public class PKListener implements Listener { event.setCancelled(true); } } - + if (event.isCancelled()) { return; } - + if (event.getEntity() instanceof LivingEntity) { LivingEntity lent = (LivingEntity) event.getEntity(); - + if (TempArmor.hasTempArmor(lent)) { TempArmor armor = TempArmor.getVisibleTempArmor(lent); ItemStack is = event.getItem().getItemStack(); int index = GeneralMethods.getArmorIndex(is.getType()); - + if (index == -1) { return; } - + event.setCancelled(true); ItemStack prev = armor.getOldArmor()[index]; - + if (GeneralMethods.compareArmor(is.getType(), prev.getType()) > 0) { event.getEntity().getWorld().dropItemNaturally(event.getEntity().getLocation(), prev); armor.getOldArmor()[index] = is; @@ -1973,6 +1991,53 @@ public class PKListener implements Listener { } } + @EventHandler(priority = EventPriority.MONITOR) + public void onBendingElementChange(final PlayerChangeElementEvent event) { + final Player player = event.getTarget(); + final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null) return; + + if (event.getResult() == PlayerChangeElementEvent.Result.CHOOSE || event.getResult() == PlayerChangeElementEvent.Result.REMOVE || event.getResult() == PlayerChangeElementEvent.Result.PERMAREMOVE) { + BendingBoardManager.updateAllSlots(player); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onBendingSubElementChange(final PlayerChangeSubElementEvent event) { + final Player player = event.getTarget(); + final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null) return; + + if (event.getResult() == PlayerChangeSubElementEvent.Result.CHOOSE || event.getResult() == PlayerChangeSubElementEvent.Result.REMOVE || event.getResult() == PlayerChangeSubElementEvent.Result.PERMAREMOVE) { + BendingBoardManager.updateAllSlots(player); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onBindChange(final PlayerBindChangeEvent event) { + final Player player = event.getPlayer(); + if (player == null) return; + BendingBoardManager.updateBoard(player, event.getAbility(), false, event.getSlot()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerStanceChange(final PlayerStanceChangeEvent event) { + final Player player = event.getPlayer(); + if (player == null) return; + if (!event.getOldStance().isEmpty()) { + BendingBoardManager.updateBoard(player, event.getOldStance(), false, 0); + } + if (!event.getNewStance().isEmpty()) { + BendingBoardManager.updateBoard(player, event.getNewStance(), false, 0); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onBendingPlayerCreation(final BendingPlayerCreationEvent event) { + final Player player = event.getBendingPlayer().getPlayer(); + BendingBoardManager.canUseScoreboard(player); + } + public static HashMap getBendingPlayerDeath() { return BENDING_PLAYER_DEATH; } diff --git a/src/com/projectkorra/projectkorra/ProjectKorra.java b/src/com/projectkorra/projectkorra/ProjectKorra.java index 4ddfe988..231e7906 100644 --- a/src/com/projectkorra/projectkorra/ProjectKorra.java +++ b/src/com/projectkorra/projectkorra/ProjectKorra.java @@ -22,6 +22,7 @@ import com.projectkorra.projectkorra.ability.util.ComboManager; import com.projectkorra.projectkorra.ability.util.MultiAbilityManager; import com.projectkorra.projectkorra.ability.util.PassiveManager; import com.projectkorra.projectkorra.airbending.util.AirbendingManager; +import com.projectkorra.projectkorra.board.BendingBoardManager; import com.projectkorra.projectkorra.chiblocking.util.ChiblockingManager; import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.configuration.ConfigManager; @@ -77,6 +78,7 @@ public class ProjectKorra extends JavaPlugin { } Manager.startup(); + BendingBoardManager.setup(); this.getServer().getPluginManager().registerEvents(new PKListener(this), this); this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new BendingManager(), 0, 1); diff --git a/src/com/projectkorra/projectkorra/ability/CoreAbility.java b/src/com/projectkorra/projectkorra/ability/CoreAbility.java index 14b1c0eb..4cf2c043 100644 --- a/src/com/projectkorra/projectkorra/ability/CoreAbility.java +++ b/src/com/projectkorra/projectkorra/ability/CoreAbility.java @@ -90,6 +90,7 @@ public abstract class CoreAbility implements Ability { private static final Map, Map> ATTRIBUTE_FIELDS = new HashMap<>(); private static int idCounter; + private static long currentTick; protected Player player; protected BendingPlayer bPlayer; @@ -149,7 +150,6 @@ public abstract class CoreAbility implements Ability { this.startTime = System.currentTimeMillis(); this.started = false; this.id = CoreAbility.idCounter; - this.startTick = this.getCurrentTick(); if (idCounter == Integer.MAX_VALUE) { idCounter = Integer.MIN_VALUE; @@ -181,6 +181,7 @@ public abstract class CoreAbility implements Ability { this.started = true; this.startTime = System.currentTimeMillis(); + this.startTick = getCurrentTick(); final Class clazz = this.getClass(); final UUID uuid = this.player.getUniqueId(); @@ -291,6 +292,7 @@ public abstract class CoreAbility implements Ability { } } } + currentTick++; } /** @@ -745,8 +747,12 @@ public abstract class CoreAbility implements Ability { return this.startTick; } - public long getCurrentTick() { - return this.player.getWorld().getFullTime(); + public static long getCurrentTick() { + return currentTick; + } + + public long getRunningTicks() { + return currentTick - this.startTick; } public boolean isStarted() { @@ -828,7 +834,7 @@ public abstract class CoreAbility implements Ability { public String getMovePreview(final Player player) { final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - String displayedMessage = getMovePreviewWithoutCooldownTimer(player); + String displayedMessage = getMovePreviewWithoutCooldownTimer(player, false); if (bPlayer.isOnCooldown(this)) { final long cooldown = bPlayer.getCooldown(this.getName()) - System.currentTimeMillis(); displayedMessage += this.getElement().getColor() + " - " + TimeUtil.formatTime(cooldown); @@ -837,18 +843,24 @@ public abstract class CoreAbility implements Ability { return displayedMessage; } - public String getMovePreviewWithoutCooldownTimer(final Player player) { + public String getMovePreviewWithoutCooldownTimer(final Player player, boolean forceCooldown) { final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); String displayedMessage = ""; - if (bPlayer.isOnCooldown(this)) { + if (forceCooldown || bPlayer.isOnCooldown(this)) { displayedMessage = this.getElement().getColor() + "" + ChatColor.STRIKETHROUGH + this.getName(); } else { - if (bPlayer.getStance() != null && bPlayer.getStance().getName().equals(this.getName())) { + boolean isActiveStance = bPlayer.getStance() != null && bPlayer.getStance().getName().equals(this.getName()); + boolean isActiveAvatarState = bPlayer.isAvatarState() && this.getName().equals("AvatarState"); + boolean isActiveIllumination = bPlayer.isIlluminating() && this.getName().equals("Illumination"); + boolean isActiveTremorSense = bPlayer.isTremorSensing() && this.getName().equals("Tremorsense"); + + if (isActiveStance || isActiveAvatarState || isActiveIllumination || isActiveTremorSense) { displayedMessage = this.getElement().getColor() + "" + ChatColor.UNDERLINE + this.getName(); } else { displayedMessage = this.getElement().getColor() + this.getName(); } } + return displayedMessage; } diff --git a/src/com/projectkorra/projectkorra/ability/EarthAbility.java b/src/com/projectkorra/projectkorra/ability/EarthAbility.java index 200bc1c2..dbb1ac9d 100644 --- a/src/com/projectkorra/projectkorra/ability/EarthAbility.java +++ b/src/com/projectkorra/projectkorra/ability/EarthAbility.java @@ -90,6 +90,14 @@ public abstract class EarthAbility extends ElementalAbility { ParticleEffect.BLOCK_CRACK.display(collision.getLocationFirst(), 10, 1, 1, 1, 0.1, Material.DIRT.createBlockData()); } } + + public static boolean isBendableEarthTempBlock(final Block block) { + return isBendableEarthTempBlock(TempBlock.get(block)); + } + + public static boolean isBendableEarthTempBlock(final TempBlock tempBlock) { + return DensityShift.getSandBlocks().contains(tempBlock); + } public static boolean isEarthbendable(final Material material, final boolean metal, final boolean sand, final boolean lava) { return isEarth(material) || (metal && isMetal(material)) || (sand && isSand(material)) || (lava && isLava(material)); @@ -128,7 +136,7 @@ public abstract class EarthAbility extends ElementalAbility { } public boolean moveEarth(Block block, final Vector direction, final int chainlength, final boolean throwplayer) { - if (!TempBlock.isTempBlock(block) && this.isEarthbendable(block) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { + if ((!TempBlock.isTempBlock(block) || isBendableEarthTempBlock(block)) && this.isEarthbendable(block) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { boolean up = false; boolean down = false; final Vector norm = direction.clone().normalize(); @@ -170,13 +178,14 @@ public abstract class EarthAbility extends ElementalAbility { final LivingEntity lentity = (LivingEntity) entity; if (lentity.getEyeLocation().getBlockX() == affectedblock.getX() && lentity.getEyeLocation().getBlockZ() == affectedblock.getZ()) { if (!(entity instanceof FallingBlock)) { - entity.setVelocity(norm.clone().multiply(.75)); + GeneralMethods.setVelocity(this, entity, norm.clone().multiply(.75)); + } } } else { if (entity.getLocation().getBlockX() == affectedblock.getX() && entity.getLocation().getBlockZ() == affectedblock.getZ()) { if (!(entity instanceof FallingBlock)) { - entity.setVelocity(norm.clone().multiply(.75)); + GeneralMethods.setVelocity(this, entity, norm.clone().multiply(.75)); } } } diff --git a/src/com/projectkorra/projectkorra/ability/FireAbility.java b/src/com/projectkorra/projectkorra/ability/FireAbility.java index 7460a712..ed55abfb 100644 --- a/src/com/projectkorra/projectkorra/ability/FireAbility.java +++ b/src/com/projectkorra/projectkorra/ability/FireAbility.java @@ -87,7 +87,7 @@ public abstract class FireAbility extends ElementalAbility { } public double getDayFactor(final double value) { - return this.player != null ? value * getDayFactor() : 1; + return (this.player != null && isDay(player.getWorld())) ? value * getDayFactor() : value; } public static double getDayFactor() { diff --git a/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java b/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java index 5dd09165..43c336c4 100644 --- a/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java +++ b/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java @@ -33,7 +33,6 @@ public class MultiAbilityManager { waterArms.add(new MultiAbilityInfoSub("Freeze", Element.ICE)); waterArms.add(new MultiAbilityInfoSub("Spear", Element.ICE)); multiAbilityList.add(new MultiAbilityInfo("WaterArms", waterArms)); - manage(); } /** @@ -135,22 +134,7 @@ public class MultiAbilityManager { return false; } - if (playerAbilities.containsKey(player)) { - if (!playerBoundAbility.get(player).equals(multiAbility) && bPlayer.getBoundAbility() != null) { - return false; - } - return true; - } - return false; - } - - public static void manage() { - new BukkitRunnable() { - @Override - public void run() { - scrollHotBarSlots(); - } - }.runTaskTimer(ProjectKorra.plugin, 0, 1); + return playerAbilities.containsKey(player) && playerBoundAbility.get(player).equals(multiAbility); } /** @@ -176,24 +160,17 @@ public class MultiAbilityManager { /** * Keeps track of the player's selected slot while a MultiAbility is active. */ - public static void scrollHotBarSlots() { - if (!playerAbilities.isEmpty()) { - for (final Player player : playerAbilities.keySet()) { - final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); - if (bPlayer == null) { - continue; - } - if (playerBoundAbility.containsKey(player)) { - if (bPlayer.getBoundAbility() == null) { - if (multiAbilityList.contains(getMultiAbility(playerBoundAbility.get(player)))) { - if (player.getInventory().getHeldItemSlot() >= getMultiAbility(playerBoundAbility.get(player)).getAbilities().size()) { - player.getInventory().setHeldItemSlot(getMultiAbility(playerBoundAbility.get(player)).getAbilities().size() - 1); - } - } - } - } + public static boolean canChangeSlot(final Player player, int slot) { + if (playerAbilities.isEmpty()) { + return true; + } + final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer != null) { + if (bPlayer.getBoundAbility() == null && multiAbilityList.contains(getMultiAbility(playerBoundAbility.getOrDefault(player, "")))) { + return slot < getMultiAbility(playerBoundAbility.get(player)).getAbilities().size(); } } + return true; } /** diff --git a/src/com/projectkorra/projectkorra/airbending/AirBlast.java b/src/com/projectkorra/projectkorra/airbending/AirBlast.java index 7ff93428..554b57ab 100644 --- a/src/com/projectkorra/projectkorra/airbending/AirBlast.java +++ b/src/com/projectkorra/projectkorra/airbending/AirBlast.java @@ -280,8 +280,7 @@ public class AirBlast extends AirAbility { if (Math.abs(entity.getVelocity().dot(push)) > knockback && entity.getVelocity().angle(push) > Math.PI / 3) { push.normalize().add(entity.getVelocity()).multiply(knockback); } - - GeneralMethods.setVelocity(entity, push); + GeneralMethods.setVelocity(this, entity, push); if (this.source != null) { new HorizontalVelocityTracker(entity, this.player, 200l, this.source); diff --git a/src/com/projectkorra/projectkorra/airbending/AirScooter.java b/src/com/projectkorra/projectkorra/airbending/AirScooter.java index d4059ab2..22a8728b 100644 --- a/src/com/projectkorra/projectkorra/airbending/AirScooter.java +++ b/src/com/projectkorra/projectkorra/airbending/AirScooter.java @@ -201,9 +201,9 @@ public class AirScooter extends AirAbility { this.player.setSprinting(false); this.player.removePotionEffect(PotionEffectType.SPEED); if (this.useslime) { - this.slime.setVelocity(velocity); + GeneralMethods.setVelocity(this, this.slime, velocity); } else { - this.player.setVelocity(velocity); + GeneralMethods.setVelocity(this, this.player, velocity); } if (this.random.nextInt(4) == 0) { diff --git a/src/com/projectkorra/projectkorra/airbending/AirShield.java b/src/com/projectkorra/projectkorra/airbending/AirShield.java index 97ec55db..19d90ae3 100644 --- a/src/com/projectkorra/projectkorra/airbending/AirShield.java +++ b/src/com/projectkorra/projectkorra/airbending/AirShield.java @@ -162,7 +162,7 @@ public class AirShield extends AirAbility { } velocity.multiply(0.5); - GeneralMethods.setVelocity(entity, velocity); + GeneralMethods.setVelocity(this, entity, velocity); entity.setFallDistance(0); } } diff --git a/src/com/projectkorra/projectkorra/airbending/AirSuction.java b/src/com/projectkorra/projectkorra/airbending/AirSuction.java index 802b68a0..2fe3bd48 100644 --- a/src/com/projectkorra/projectkorra/airbending/AirSuction.java +++ b/src/com/projectkorra/projectkorra/airbending/AirSuction.java @@ -231,8 +231,8 @@ public class AirSuction extends AirAbility { if (Math.abs(entity.getVelocity().dot(push)) > knockback) { push.normalize().add(entity.getVelocity()).multiply(knockback); } - - GeneralMethods.setVelocity(entity, push.normalize().multiply(knockback)); + GeneralMethods.setVelocity(this, entity, push.normalize().multiply(knockback)); + new HorizontalVelocityTracker(entity, this.player, 200l, this); entity.setFallDistance(0); diff --git a/src/com/projectkorra/projectkorra/airbending/AirSwipe.java b/src/com/projectkorra/projectkorra/airbending/AirSwipe.java index 759bee6a..0800dd53 100644 --- a/src/com/projectkorra/projectkorra/airbending/AirSwipe.java +++ b/src/com/projectkorra/projectkorra/airbending/AirSwipe.java @@ -243,9 +243,7 @@ public class AirSwipe extends AirAbility { } } if (entities.size() < MAX_AFFECTABLE_ENTITIES) { - - GeneralMethods.setVelocity(entity, fDirection.multiply(AirSwipe.this.pushFactor)); - + GeneralMethods.setVelocity(AirSwipe.this, entity, fDirection.multiply(AirSwipe.this.pushFactor)); } if (!AirSwipe.this.affectedEntities.contains(entity)) { if (AirSwipe.this.damage != 0) { @@ -255,9 +253,7 @@ public class AirSwipe extends AirAbility { } breakBreathbendingHold(entity); } else if (entity.getEntityId() != AirSwipe.this.player.getEntityId() && !(entity instanceof LivingEntity)) { - - GeneralMethods.setVelocity(entity, fDirection.multiply(AirSwipe.this.pushFactor)); - + GeneralMethods.setVelocity(AirSwipe.this, entity, fDirection.multiply(AirSwipe.this.pushFactor)); } } }.runTaskLater(ProjectKorra.plugin, i / MAX_AFFECTABLE_ENTITIES); diff --git a/src/com/projectkorra/projectkorra/airbending/Tornado.java b/src/com/projectkorra/projectkorra/airbending/Tornado.java index fc41a7a5..ad540e95 100644 --- a/src/com/projectkorra/projectkorra/airbending/Tornado.java +++ b/src/com/projectkorra/projectkorra/airbending/Tornado.java @@ -169,7 +169,7 @@ public class Tornado extends AirAbility { velocity.setZ(vz); velocity.setY(vy); velocity.multiply(timefactor); - GeneralMethods.setVelocity(entity, velocity); + GeneralMethods.setVelocity(this, entity, velocity); entity.setFallDistance(0); breakBreathbendingHold(entity); diff --git a/src/com/projectkorra/projectkorra/airbending/combo/AirStream.java b/src/com/projectkorra/projectkorra/airbending/combo/AirStream.java index 02678172..3cb54ab5 100644 --- a/src/com/projectkorra/projectkorra/airbending/combo/AirStream.java +++ b/src/com/projectkorra/projectkorra/airbending/combo/AirStream.java @@ -165,7 +165,7 @@ public class AirStream extends AirAbility implements ComboAbility { continue; } final Vector force = GeneralMethods.getDirection(entity.getLocation(), this.currentLoc); - entity.setVelocity(force.clone().normalize().multiply(this.speed)); + GeneralMethods.setVelocity(this, entity, force.clone().normalize().multiply(this.speed)); entity.setFallDistance(0F); } } diff --git a/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java b/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java index 0dd9f398..6e99c085 100644 --- a/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java +++ b/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java @@ -198,7 +198,7 @@ public class AirSweep extends AirAbility implements ComboAbility { if (!entity.equals(this.player) && !(entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) { if (this.knockback != 0) { final Vector force = fstream.getLocation().getDirection(); - GeneralMethods.setVelocity(entity, force.clone().multiply(this.knockback)); + GeneralMethods.setVelocity(this, entity, force.clone().multiply(this.knockback)); new HorizontalVelocityTracker(entity, this.player, 200l, this); entity.setFallDistance(0); } diff --git a/src/com/projectkorra/projectkorra/airbending/combo/Twister.java b/src/com/projectkorra/projectkorra/airbending/combo/Twister.java index 9c18fe6f..b85d4278 100644 --- a/src/com/projectkorra/projectkorra/airbending/combo/Twister.java +++ b/src/com/projectkorra/projectkorra/airbending/combo/Twister.java @@ -146,7 +146,7 @@ public class Twister extends AirAbility implements ComboAbility { continue; } final Vector forceDir = GeneralMethods.getDirection(entity.getLocation(), this.currentLoc.clone().add(0, height, 0)); - entity.setVelocity(forceDir.clone().normalize().multiply(0.3)); + GeneralMethods.setVelocity(this, entity, forceDir.clone().normalize().multiply(0.3)); } } diff --git a/src/com/projectkorra/projectkorra/airbending/flight/FlightMultiAbility.java b/src/com/projectkorra/projectkorra/airbending/flight/FlightMultiAbility.java index ac696629..5f656db6 100644 --- a/src/com/projectkorra/projectkorra/airbending/flight/FlightMultiAbility.java +++ b/src/com/projectkorra/projectkorra/airbending/flight/FlightMultiAbility.java @@ -227,14 +227,14 @@ public class FlightMultiAbility extends FlightAbility implements MultiAbility { if (!GeneralMethods.isRegionProtectedFromBuild(this.player, e.getLocation())) { final LivingEntity le = (LivingEntity) e; DamageHandler.damageEntity(le, this.speed / 2, this); - le.setVelocity(this.player.getVelocity().clone().multiply(2 / 3)); + GeneralMethods.setVelocity(this, le, this.player.getVelocity().clone().multiply(2 / 3)); } } } } this.particles(); - this.player.setVelocity(this.player.getEyeLocation().getDirection().clone().multiply(this.multiplier)); + GeneralMethods.setVelocity(this, this.player, this.player.getEyeLocation().getDirection().clone().multiply(this.multiplier)); } else if (this.mode == FlightMode.GLIDE) { this.player.setAllowFlight(false); this.player.setFlying(false); diff --git a/src/com/projectkorra/projectkorra/attribute/AttributeModifier.java b/src/com/projectkorra/projectkorra/attribute/AttributeModifier.java index d865988b..27494f57 100644 --- a/src/com/projectkorra/projectkorra/attribute/AttributeModifier.java +++ b/src/com/projectkorra/projectkorra/attribute/AttributeModifier.java @@ -3,46 +3,46 @@ package com.projectkorra.projectkorra.attribute; public enum AttributeModifier { ADDITION((oldValue, modifier) -> { - if (oldValue instanceof Double || modifier instanceof Double) { + if (oldValue instanceof Double) { return oldValue.doubleValue() + modifier.doubleValue(); - } else if (oldValue instanceof Float || modifier instanceof Float) { + } else if (oldValue instanceof Float) { return oldValue.floatValue() + modifier.floatValue(); - } else if (oldValue instanceof Long || modifier instanceof Long) { + } else if (oldValue instanceof Long) { return oldValue.longValue() + modifier.longValue(); - } else if (oldValue instanceof Integer || modifier instanceof Integer) { + } else if (oldValue instanceof Integer) { return oldValue.intValue() + modifier.intValue(); } return 0; }), SUBTRACTION((oldValue, modifier) -> { - if (oldValue instanceof Double || modifier instanceof Double) { + if (oldValue instanceof Double) { return oldValue.doubleValue() - modifier.doubleValue(); - } else if (oldValue instanceof Float || modifier instanceof Float) { + } else if (oldValue instanceof Float) { return oldValue.floatValue() - modifier.floatValue(); - } else if (oldValue instanceof Long || modifier instanceof Long) { + } else if (oldValue instanceof Long) { return oldValue.longValue() - modifier.longValue(); - } else if (oldValue instanceof Integer || modifier instanceof Integer) { + } else if (oldValue instanceof Integer) { return oldValue.intValue() - modifier.intValue(); } return 0; }), MULTIPLICATION((oldValue, modifier) -> { - if (oldValue instanceof Double || modifier instanceof Double) { + if (oldValue instanceof Double) { return oldValue.doubleValue() * modifier.doubleValue(); - } else if (oldValue instanceof Float || modifier instanceof Float) { + } else if (oldValue instanceof Float) { return oldValue.floatValue() * modifier.floatValue(); - } else if (oldValue instanceof Long || modifier instanceof Long) { + } else if (oldValue instanceof Long) { return oldValue.longValue() * modifier.longValue(); - } else if (oldValue instanceof Integer || modifier instanceof Integer) { + } else if (oldValue instanceof Integer) { return oldValue.intValue() * modifier.intValue(); } return 0; }), DIVISION((oldValue, modifier) -> { - if (oldValue instanceof Double || modifier instanceof Double) { + if (oldValue instanceof Double) { return oldValue.doubleValue() / modifier.doubleValue(); - } else if (oldValue instanceof Float || modifier instanceof Float) { + } else if (oldValue instanceof Float) { return oldValue.floatValue() / modifier.floatValue(); - } else if (oldValue instanceof Long || modifier instanceof Long) { + } else if (oldValue instanceof Long) { return oldValue.longValue() / modifier.longValue(); - } else if (oldValue instanceof Integer || modifier instanceof Integer) { + } else if (oldValue instanceof Integer) { return oldValue.intValue() / modifier.intValue(); } return 0; diff --git a/src/com/projectkorra/projectkorra/avatar/AvatarState.java b/src/com/projectkorra/projectkorra/avatar/AvatarState.java index 308c0fb3..994ac071 100644 --- a/src/com/projectkorra/projectkorra/avatar/AvatarState.java +++ b/src/com/projectkorra/projectkorra/avatar/AvatarState.java @@ -54,7 +54,6 @@ public class AvatarState extends AvatarAbility { playAvatarSound(player.getLocation()); this.start(); - this.bPlayer.addCooldown(this, true); if (this.duration != 0) { START_TIMES.put(player.getName(), System.currentTimeMillis()); player.getUniqueId(); @@ -79,6 +78,12 @@ public class AvatarState extends AvatarAbility { this.addPotionEffects(); } + @Override + public void remove() { + this.bPlayer.addCooldown(this, true); + super.remove(); + } + private void addPotionEffects() { if (this.regenEnabled) { this.addProgressPotionEffect(PotionEffectType.REGENERATION, this.regenPower); diff --git a/src/com/projectkorra/projectkorra/board/BendingBoardInstance.java b/src/com/projectkorra/projectkorra/board/BendingBoardInstance.java new file mode 100755 index 00000000..f557c53e --- /dev/null +++ b/src/com/projectkorra/projectkorra/board/BendingBoardInstance.java @@ -0,0 +1,130 @@ +package com.projectkorra.projectkorra.board; + +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.configuration.ConfigManager; + +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.Scoreboard; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Represents a player's scoreboard for bending purposes + */ +public class BendingBoardInstance { + private final String[] cachedSlots = new String[10]; + private final Set misc = new HashSet<>(); // Stores scoreboard scores for combos and misc abilities + + private final Player player; + private final BendingPlayer bendingPlayer; + + private final Scoreboard bendingBoard; + private final Objective bendingSlots; + private int selectedSlot; + + public BendingBoardInstance(final BendingPlayer bPlayer) { + bendingPlayer = bPlayer; + player = bPlayer.getPlayer(); + selectedSlot = player.getInventory().getHeldItemSlot() + 1; + + bendingBoard = Bukkit.getScoreboardManager().getNewScoreboard(); + + String title = ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Board.Title")); + bendingSlots = bendingBoard.registerNewObjective("Board Slots", "dummy", title); + bendingSlots.setDisplaySlot(DisplaySlot.SIDEBAR); + player.setScoreboard(bendingBoard); + + Arrays.fill(cachedSlots, ""); + updateAll(); + } + + public void disableScoreboard() { + bendingBoard.clearSlot(DisplaySlot.SIDEBAR); + bendingSlots.unregister(); + player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); + } + + private void setSlot(int slot, String name, boolean cooldown) { + if (slot < 1 || slot > 9 || !player.getScoreboard().equals(bendingBoard)) return; + String prefix = ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Board.SelectionPrefix")); + StringBuilder sb = new StringBuilder(slot == selectedSlot ? prefix : String.join("", Collections.nCopies(ChatColor.stripColor(prefix).length(), " "))); + if (name == null || name.isEmpty()) { + String emptySlot = ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Board.EmptySlot").replaceAll("\\{slot_number\\}", "" + slot)); + sb.append(emptySlot); + } else { + CoreAbility coreAbility = CoreAbility.getAbility(ChatColor.stripColor(name)); + if (coreAbility == null) { // MultiAbility + if (cooldown || bendingPlayer.isOnCooldown(name)) sb.append(ChatColor.STRIKETHROUGH); + sb.append(name); + } else { + sb.append(coreAbility.getMovePreviewWithoutCooldownTimer(player, cooldown)); + } + } + sb.append(ChatColor.values()[slot].toString()); // Unique suffix + + if (!cachedSlots[slot].equals(sb.toString())) { + bendingBoard.resetScores(cachedSlots[slot]); + } + cachedSlots[slot] = sb.toString(); + bendingSlots.getScore(sb.toString()).setScore(-slot); + } + + public void updateAll() { + final Map boundAbilities = new HashMap<>(bendingPlayer.getAbilities()); + for (int i = 1; i <= 9; i++) { + setSlot(i, boundAbilities.getOrDefault(i, ""), false); + } + } + + public void clearSlot(int slot) { + setSlot(slot, null, false); + } + + public void setActiveSlot(int oldSlot, int newSlot) { + if (selectedSlot != oldSlot) { + oldSlot = selectedSlot; // Fixes bug when slot is set using setHeldItemSlot + } + selectedSlot = newSlot; + setSlot(oldSlot, bendingPlayer.getAbilities().getOrDefault(oldSlot, ""), false); + setSlot(newSlot, bendingPlayer.getAbilities().getOrDefault(newSlot, ""), false); + } + + public void setAbility(String name, boolean cooldown) { + final Map boundAbilities = bendingPlayer.getAbilities(); + boundAbilities.keySet().stream().filter(key -> name.equals(boundAbilities.get(key))).forEach(slot -> setSlot(slot, name, cooldown)); + } + + public void updateMisc(String text, boolean show, boolean isCombo) { + String selection = ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Board.SelectionPrefix")); + String prefix = String.join("", Collections.nCopies(ChatColor.stripColor(selection).length(), " ")); + + String miscSeparator = ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Board.MiscSeparator")); + String alignedText = prefix + text; + + if (show) { + if (misc.isEmpty()) { + bendingSlots.getScore(miscSeparator).setScore(-10); + } + + misc.add(alignedText); + bendingSlots.getScore(alignedText).setScore(isCombo ? -11 : -12); + } else { + misc.remove(alignedText); + bendingBoard.resetScores(alignedText); + + if (misc.isEmpty()) { + bendingBoard.resetScores(miscSeparator); + } + } + } +} diff --git a/src/com/projectkorra/projectkorra/board/BendingBoardManager.java b/src/com/projectkorra/projectkorra/board/BendingBoardManager.java new file mode 100755 index 00000000..c70e2c70 --- /dev/null +++ b/src/com/projectkorra/projectkorra/board/BendingBoardManager.java @@ -0,0 +1,200 @@ +package com.projectkorra.projectkorra.board; + +import com.projectkorra.projectkorra.BendingPlayer; +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.ability.util.MultiAbilityManager; +import com.projectkorra.projectkorra.configuration.ConfigManager; +import com.projectkorra.projectkorra.storage.DBConnection; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Manages every individual {@link BendingBoardInstance} + */ +public class BendingBoardManager { + private static final Set disabledWorlds = new HashSet<>(); + private static final Map trackedCooldowns = new ConcurrentHashMap<>(); + private static final Set disabledPlayers = Collections.synchronizedSet(new HashSet<>()); + private static final Map scoreboardPlayers = new ConcurrentHashMap<>(); + + private static boolean enabled; + + public static void setup() { + initialize(true); + Bukkit.getOnlinePlayers().forEach(BendingBoardManager::canUseScoreboard); + } + + public static void reload() { + scoreboardPlayers.values().forEach(BendingBoardInstance::disableScoreboard); + scoreboardPlayers.clear(); + initialize(false); + } + + private static void initialize(boolean initial) { + if (initial) loadDisabledPlayers(); + enabled = ConfigManager.getConfig().getBoolean("Properties.BendingBoard"); + disabledWorlds.clear(); + disabledWorlds.addAll(ConfigManager.getConfig().getStringList("Properties.DisabledWorlds")); + } + + /** + * Force toggle the scoreboard for when a player changes worlds (for example when teleporting to a world where bending is disabled) + * @param player + */ + public static void forceToggleScoreboard(Player player) { + if (disabledWorlds.contains(player.getWorld().getName())) { + if (scoreboardPlayers.containsKey(player)) { + scoreboardPlayers.get(player).disableScoreboard(); + scoreboardPlayers.remove(player); + } + } else { + canUseScoreboard(player); + } + } + + public static void toggleScoreboard(Player player) { + if (!enabled || disabledWorlds.contains(player.getWorld().getName())) { + GeneralMethods.sendBrandingMessage(player, ChatColor.RED + ConfigManager.languageConfig.get().getString("Commands.Board.Disabled")); + return; + } + + if (scoreboardPlayers.containsKey(player)) { + scoreboardPlayers.get(player).disableScoreboard(); + disabledPlayers.add(player.getUniqueId()); + scoreboardPlayers.remove(player); + GeneralMethods.sendBrandingMessage(player, ChatColor.RED + ConfigManager.languageConfig.get().getString("Commands.Board.ToggledOff")); + } else { + disabledPlayers.remove(player.getUniqueId()); + canUseScoreboard(player); + GeneralMethods.sendBrandingMessage(player, ChatColor.GREEN + ConfigManager.languageConfig.get().getString("Commands.Board.ToggledOn")); + } + } + + /** + * Checks if a player can use the bending board and creates a BendingBoardInstance if possible. + * @param player the player to check + * @return true if player can use the bending board, false otherwise + */ + public static boolean canUseScoreboard(Player player) { + if (!enabled || disabledPlayers.contains(player.getUniqueId()) || disabledWorlds.contains(player.getWorld().getName())) { + return false; + } + + if (!player.isOnline()) { + return false; + } + + if (!scoreboardPlayers.containsKey(player)) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + if (bPlayer == null) { + return false; + } + + scoreboardPlayers.put(player, new BendingBoardInstance(bPlayer)); + } + + return true; + } + + public static void updateAllSlots(Player player) { + if (canUseScoreboard(player)) { + scoreboardPlayers.get(player).updateAll(); + } + } + + public static void updateBoard(Player player, String abilityName, boolean cooldown, int slot) { + if (canUseScoreboard(player)) { + if (abilityName == null || abilityName.isEmpty()) { + scoreboardPlayers.get(player).clearSlot(slot); + return; + } + if (MultiAbilityManager.hasMultiAbilityBound(player)) { + scoreboardPlayers.get(player).updateAll(); + return; + } + CoreAbility coreAbility = CoreAbility.getAbility(abilityName); + if (coreAbility != null && ComboManager.getComboAbilities().containsKey(abilityName)) { + scoreboardPlayers.get(player).updateMisc("" + coreAbility.getElement().getColor() + ChatColor.STRIKETHROUGH + abilityName, cooldown, true); + return; + } else if (coreAbility == null && trackedCooldowns.containsKey(abilityName)) { + scoreboardPlayers.get(player).updateMisc("" + trackedCooldowns.get(abilityName) + ChatColor.STRIKETHROUGH + abilityName, cooldown, false); + return; + } + scoreboardPlayers.get(player).setAbility(abilityName, cooldown); + } + } + + public static void changeActiveSlot(Player player, int oldSlot, int newSlot) { + if (canUseScoreboard(player)) { + scoreboardPlayers.get(player).setActiveSlot(++oldSlot, ++newSlot); + } + } + + /** + * Some abilities use internal cooldowns with custom names that don't correspond to bound abilities' names. + * Adds the internal cooldown name and color to the map of tracked abilities so as they can appear on the bending board. + * @param cooldownName the internal cooldown name + * @param color the color to use when rendering the board entry + */ + public static void addCooldownToTrack(String cooldownName, ChatColor color) { + trackedCooldowns.put(cooldownName, color); + } + + /** + * Load into memory the list of players who have toggled the bending board off. + */ + public static void loadDisabledPlayers() { + Bukkit.getScheduler().runTaskAsynchronously(ProjectKorra.plugin, () -> { + Set disabled = new HashSet<>(); + try { + final ResultSet rs = DBConnection.sql.readQuery("SELECT uuid FROM pk_board where enabled = 0"); + while (rs.next()) disabled.add(UUID.fromString(rs.getString("uuid"))); + } catch (SQLException e) { + e.printStackTrace(); + } + disabledPlayers.clear(); + disabledPlayers.addAll(disabled); + }); + } + + /** + * Called on player logout + * Removes the board instance and stores the player's toggle preference for the bending board in the database + * @param player + */ + public static void clean(final Player player) { + scoreboardPlayers.remove(player); + final UUID uuid = player.getUniqueId(); + final String updateQuery = "UPDATE pk_board SET enabled = " + (disabledPlayers.contains(uuid) ? 0 : 1) + " WHERE uuid = ?"; + Bukkit.getScheduler().runTaskAsynchronously(ProjectKorra.plugin, () -> { + try { + PreparedStatement ps = DBConnection.sql.getConnection().prepareStatement("SELECT enabled FROM pk_board where uuid = ? LIMIT 1"); + ps.setString(1, uuid.toString()); + PreparedStatement ps2; + if (!ps.executeQuery().next()) { // if the entry doesn't exist in the DB, create it. + ps2 = DBConnection.sql.getConnection().prepareStatement("INSERT INTO pk_board (uuid, enabled) VALUES (?, 1)"); + } else { // if the entry exists in the DB, update it + ps2 = DBConnection.sql.getConnection().prepareStatement(updateQuery); + } + ps2.setString(1, uuid.toString()); + ps2.execute(); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + } +} diff --git a/src/com/projectkorra/projectkorra/chiblocking/AcrobatStance.java b/src/com/projectkorra/projectkorra/chiblocking/AcrobatStance.java index 1c7b6063..5af308ee 100644 --- a/src/com/projectkorra/projectkorra/chiblocking/AcrobatStance.java +++ b/src/com/projectkorra/projectkorra/chiblocking/AcrobatStance.java @@ -7,7 +7,6 @@ import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.attribute.Attribute; @@ -48,7 +47,6 @@ public class AcrobatStance extends ChiAbility { } this.start(); this.bPlayer.setStance(this); - GeneralMethods.displayMovePreview(player); player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_HURT, 0.5F, 2F); } @@ -75,7 +73,6 @@ public class AcrobatStance extends ChiAbility { super.remove(); this.bPlayer.addCooldown(this); this.bPlayer.setStance(null); - GeneralMethods.displayMovePreview(this.player); this.player.playSound(this.player.getLocation(), Sound.ENTITY_ENDER_DRAGON_SHOOT, 0.5F, 2F); this.player.removePotionEffect(PotionEffectType.SPEED); this.player.removePotionEffect(PotionEffectType.JUMP); diff --git a/src/com/projectkorra/projectkorra/chiblocking/HighJump.java b/src/com/projectkorra/projectkorra/chiblocking/HighJump.java index d4992cf1..6f5d5cd2 100644 --- a/src/com/projectkorra/projectkorra/chiblocking/HighJump.java +++ b/src/com/projectkorra/projectkorra/chiblocking/HighJump.java @@ -35,7 +35,7 @@ public class HighJump extends ChiAbility { } final Vector vec = p.getVelocity(); vec.setY(this.height); - p.setVelocity(vec); + GeneralMethods.setVelocity(this, p, vec); this.bPlayer.addCooldown(this); return; } diff --git a/src/com/projectkorra/projectkorra/chiblocking/WarriorStance.java b/src/com/projectkorra/projectkorra/chiblocking/WarriorStance.java index 6d6d0e8a..2a9b54a9 100644 --- a/src/com/projectkorra/projectkorra/chiblocking/WarriorStance.java +++ b/src/com/projectkorra/projectkorra/chiblocking/WarriorStance.java @@ -7,7 +7,6 @@ import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import com.projectkorra.projectkorra.Element; -import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.ChiAbility; import com.projectkorra.projectkorra.attribute.Attribute; @@ -42,7 +41,6 @@ public class WarriorStance extends ChiAbility { } this.start(); this.bPlayer.setStance(this); - GeneralMethods.displayMovePreview(player); player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_HURT, 0.5F, 2F); } @@ -70,7 +68,6 @@ public class WarriorStance extends ChiAbility { this.bPlayer.addCooldown(this); this.bPlayer.setStance(null); if (this.player != null) { - GeneralMethods.displayMovePreview(this.player); this.player.playSound(this.player.getLocation(), Sound.ENTITY_ENDER_DRAGON_SHOOT, 0.5F, 2F); this.player.removePotionEffect(PotionEffectType.DAMAGE_RESISTANCE); this.player.removePotionEffect(PotionEffectType.INCREASE_DAMAGE); diff --git a/src/com/projectkorra/projectkorra/command/BoardCommand.java b/src/com/projectkorra/projectkorra/command/BoardCommand.java new file mode 100755 index 00000000..ded99569 --- /dev/null +++ b/src/com/projectkorra/projectkorra/command/BoardCommand.java @@ -0,0 +1,27 @@ +package com.projectkorra.projectkorra.command; + +import java.util.List; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.projectkorra.projectkorra.board.BendingBoardManager; +import com.projectkorra.projectkorra.configuration.ConfigManager; + +/** + * Executor for /bending board. Extends {@link PKCommand}. + */ +public class BoardCommand extends PKCommand { + + public BoardCommand() { + super("board", "/bending board", ConfigManager.languageConfig.get().getString("Commands.Board.Description"), new String[]{ "bendingboard", "board", "bb" }); + } + + @Override + public void execute(final CommandSender sender, final List args) { + if (!this.hasPermission(sender) || !this.isPlayer(sender) || !this.correctLength(sender, args.size(), 0, 0)) { + return; + } + BendingBoardManager.toggleScoreboard((Player) sender); + } +} diff --git a/src/com/projectkorra/projectkorra/command/ChooseCommand.java b/src/com/projectkorra/projectkorra/command/ChooseCommand.java index feee50ef..3bfcf198 100644 --- a/src/com/projectkorra/projectkorra/command/ChooseCommand.java +++ b/src/com/projectkorra/projectkorra/command/ChooseCommand.java @@ -170,7 +170,8 @@ public class ChooseCommand extends PKCommand { GeneralMethods.sendBrandingMessage(target, color + this.chosenCFW.replace("{element}", sub.getName() + sub.getType().getBender())); } GeneralMethods.saveSubElements(bPlayer); - Bukkit.getServer().getPluginManager().callEvent(new PlayerChangeSubElementEvent(sender, target, sub, com.projectkorra.projectkorra.event.PlayerChangeSubElementEvent.Result.CHOOSE)); + GeneralMethods.removeUnusableAbilities(target.getName()); + Bukkit.getServer().getPluginManager().callEvent(new PlayerChangeSubElementEvent(sender, target, sub, PlayerChangeSubElementEvent.Result.CHOOSE)); } else { bPlayer.setElement(element); bPlayer.getSubElements().clear(); @@ -196,11 +197,9 @@ public class ChooseCommand extends PKCommand { } GeneralMethods.saveElements(bPlayer); GeneralMethods.saveSubElements(bPlayer); + GeneralMethods.removeUnusableAbilities(target.getName()); Bukkit.getServer().getPluginManager().callEvent(new PlayerChangeElementEvent(sender, target, element, Result.CHOOSE)); } - - GeneralMethods.removeUnusableAbilities(target.getName()); - } public static boolean isVowel(final char c) { diff --git a/src/com/projectkorra/projectkorra/command/Commands.java b/src/com/projectkorra/projectkorra/command/Commands.java index 8d23bcdc..6ba5bb29 100644 --- a/src/com/projectkorra/projectkorra/command/Commands.java +++ b/src/com/projectkorra/projectkorra/command/Commands.java @@ -80,6 +80,7 @@ public class Commands { new AddCommand(); new BindCommand(); new CheckCommand(); + new BoardCommand(); new ChooseCommand(); new ClearCommand(); new CopyCommand(); diff --git a/src/com/projectkorra/projectkorra/command/CopyCommand.java b/src/com/projectkorra/projectkorra/command/CopyCommand.java index 4e4e7b05..5e762b62 100644 --- a/src/com/projectkorra/projectkorra/command/CopyCommand.java +++ b/src/com/projectkorra/projectkorra/command/CopyCommand.java @@ -13,6 +13,7 @@ import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.board.BendingBoardManager; import com.projectkorra.projectkorra.configuration.ConfigManager; public class CopyCommand extends PKCommand { @@ -107,6 +108,7 @@ public class CopyCommand extends PKCommand { } } target.setAbilities(abilities); + BendingBoardManager.updateAllSlots(player2); return boundAll; } diff --git a/src/com/projectkorra/projectkorra/command/DisplayCommand.java b/src/com/projectkorra/projectkorra/command/DisplayCommand.java index 9bb6c906..af7d5a5a 100644 --- a/src/com/projectkorra/projectkorra/command/DisplayCommand.java +++ b/src/com/projectkorra/projectkorra/command/DisplayCommand.java @@ -96,9 +96,11 @@ public class DisplayCommand extends PKCommand { } final CoreAbility coreAbil = CoreAbility.getAbility(comboAbil); - if (coreAbil != null) { - comboColor = coreAbil.getElement().getColor(); + if (coreAbil == null || coreAbil.isHiddenAbility()) { + continue; } + comboColor = coreAbil.getElement().getColor(); + String message = (comboColor + comboAbil); if (coreAbil instanceof AddonAbility) { @@ -127,9 +129,10 @@ public class DisplayCommand extends PKCommand { } final CoreAbility coreAbil = CoreAbility.getAbility(comboMove); - if (coreAbil != null) { - comboColor = coreAbil.getElement().getColor(); + if (coreAbil == null || coreAbil.isHiddenAbility()) { + continue; } + comboColor = coreAbil.getElement().getColor(); String message = (comboColor + comboMove); @@ -157,9 +160,11 @@ public class DisplayCommand extends PKCommand { } final CoreAbility coreAbil = CoreAbility.getAbility(passiveAbil); - if (coreAbil != null) { - passiveColor = coreAbil.getElement().getColor(); + if (coreAbil == null || coreAbil.isHiddenAbility()) { + continue; } + passiveColor = coreAbil.getElement().getColor(); + String message = (passiveColor + passiveAbil); if (coreAbil instanceof AddonAbility) { @@ -188,9 +193,11 @@ public class DisplayCommand extends PKCommand { } final CoreAbility coreAbil = CoreAbility.getAbility(passiveAbil); - if (coreAbil != null) { - passiveColor = coreAbil.getElement().getColor(); + if (coreAbil == null || coreAbil.isHiddenAbility()) { + continue; } + passiveColor = coreAbil.getElement().getColor(); + sender.sendMessage(passiveColor + passiveAbil); } return; diff --git a/src/com/projectkorra/projectkorra/command/PresetCommand.java b/src/com/projectkorra/projectkorra/command/PresetCommand.java index 026ce425..d105c96b 100644 --- a/src/com/projectkorra/projectkorra/command/PresetCommand.java +++ b/src/com/projectkorra/projectkorra/command/PresetCommand.java @@ -132,7 +132,11 @@ public class PresetCommand extends PKCommand { } else if (Arrays.asList(bindaliases).contains(args.get(0)) && this.hasPermission(sender, "bind")) { // bending preset bind name. if (args.size() < 3) { boolean boundAll = false; - if (Preset.presetExists(player, name)) { + + if (name == null) { + GeneralMethods.sendBrandingMessage(sender, ChatColor.RED + this.invalidName); + return; + } else if (Preset.presetExists(player, name)) { final Preset preset = Preset.getPreset(player, name); GeneralMethods.sendBrandingMessage(sender, ChatColor.GREEN + this.bound.replace("{name}", ChatColor.YELLOW + preset.getName() + ChatColor.GREEN)); diff --git a/src/com/projectkorra/projectkorra/command/WhoCommand.java b/src/com/projectkorra/projectkorra/command/WhoCommand.java index 7cf2655d..53707a08 100644 --- a/src/com/projectkorra/projectkorra/command/WhoCommand.java +++ b/src/com/projectkorra/projectkorra/command/WhoCommand.java @@ -94,6 +94,10 @@ public class WhoCommand extends PKCommand { } final List players = new ArrayList(); for (final Player player : Bukkit.getOnlinePlayers()) { + if (sender instanceof Player && !((Player) sender).canSee(player)) { + continue; + } + final String playerName = player.getName(); String result = ""; BendingPlayer bp = BendingPlayer.getBendingPlayer(playerName); @@ -150,12 +154,13 @@ public class WhoCommand extends PKCommand { GeneralMethods.sendBrandingMessage(sender, ChatColor.RED + "Player not found!"); return; } - if (!player.isOnline() && !BendingPlayer.getPlayers().containsKey(player.getUniqueId())) { - GeneralMethods.sendBrandingMessage(sender, ChatColor.GRAY + this.playerOffline.replace("{player}", ChatColor.WHITE + player.getName() + ChatColor.GRAY).replace("{target}", ChatColor.WHITE + player.getName() + ChatColor.GRAY)); - } - + final Player player_ = (Player) (player.isOnline() ? player : null); BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + + if ((!player.isOnline() && !BendingPlayer.getPlayers().containsKey(player.getUniqueId())) || (sender instanceof Player && player_ != null && !((Player) sender).canSee(player_))) { + GeneralMethods.sendBrandingMessage(sender, ChatColor.GRAY + this.playerOffline.replace("{player}", ChatColor.WHITE + player.getName() + ChatColor.GRAY).replace("{target}", ChatColor.WHITE + player.getName() + ChatColor.GRAY)); + } if (bPlayer == null) { GeneralMethods.createBendingPlayer(player.getUniqueId(), playerName); diff --git a/src/com/projectkorra/projectkorra/configuration/ConfigManager.java b/src/com/projectkorra/projectkorra/configuration/ConfigManager.java index c4fdeb8d..d2316b83 100644 --- a/src/com/projectkorra/projectkorra/configuration/ConfigManager.java +++ b/src/com/projectkorra/projectkorra/configuration/ConfigManager.java @@ -43,11 +43,6 @@ public class ConfigManager { } else if (type == ConfigType.LANGUAGE) { config = languageConfig.get(); - final ArrayList helpLines = new ArrayList(); - helpLines.add("&c/bending help [Ability/Command] &eDisplay help."); - helpLines.add("&c/bending choose [Element] &eChoose an element."); - helpLines.add("&c/bending bind [Ability] # &eBind an ability."); - config.addDefault("Chat.Enable", true); config.addDefault("Chat.Format", ": "); config.addDefault("Chat.Colors.Avatar", "DARK_PURPLE"); @@ -77,6 +72,11 @@ public class ConfigManager { config.addDefault("Chat.Prefixes.Avatar", "[Avatar]"); config.addDefault("Chat.Prefixes.Nonbender", "[Nonbender]"); + config.addDefault("Board.Title", "&lAbilities"); + config.addDefault("Board.SelectionPrefix", "> &r"); + config.addDefault("Board.EmptySlot", "&8-- Slot {slot_number} --"); + config.addDefault("Board.MiscSeparator", " ------------"); + config.addDefault("Extras.Water.NightMessage", "Your waterbending has become empowered due to the moon rising."); config.addDefault("Extras.Water.DayMessage", "You feel the empowering of your waterbending subside as the moon sets."); config.addDefault("Extras.Fire.NightMessage", "You feel the empowering of your firebending subside as the sun sets."); @@ -180,6 +180,11 @@ public class ConfigManager { config.addDefault("Commands.Debug.Description", "Outputs information on the current ProjectKorra installation to /plugins/ProjectKorra/debug.txt"); config.addDefault("Commands.Debug.SuccessfullyExported", "Debug File Created as debug.txt in the ProjectKorra plugin folder.\nPut contents on pastie.org and create a bug report on the ProjectKorra forum if you need to."); + config.addDefault("Commands.Board.Description", "Toggle bending board visibility."); + config.addDefault("Commands.Board.Disabled", "Bending board is disabled."); + config.addDefault("Commands.Board.ToggledOn", "You have made your bending board visible again."); + config.addDefault("Commands.Board.ToggledOff", "You have hidden your bending board."); + config.addDefault("Commands.Copy.Description", "This command will allow the user to copy the binds of another player either for himself or assign them to if specified."); config.addDefault("Commands.Copy.PlayerNotFound", "Couldn't find player."); config.addDefault("Commands.Copy.SuccessfullyCopied", "Your binds have been set to match {target}'s!"); @@ -252,7 +257,7 @@ public class ConfigManager { config.addDefault("Abilities.Air.AirScooter.Instructions", "Sprint, jump, and left click while in the air to activate air scooter. You will then move forward in the direction you're looking."); config.addDefault("Abilities.Air.Tornado.Description", "Tornado is one of the most powerful and advanced abilities that an Airbender knows. If the tornado meets a player or mob, it will push them around. Tornado can also be used to push back projectiles and used for mobility. Use a tornado directly under you to propel yourself upwards."); config.addDefault("Abilities.Air.Tornado.Instructions", "Hold sneak and a tornado will form gradually wherever you look."); - config.addDefault("Abilities.Air.AirShield.Description", "Air Shield is one of the most powerful defensive techniques in existence. This ability is mainly used when you are low health and need protection. It's also useful when you're surrounded by mobs."); + config.addDefault("Abilities.Air.AirShield.Description", "AirShield is one of the most powerful defensive techniques in existence. This ability is mainly used when you are low health and need protection. It's also useful when you're surrounded by mobs."); config.addDefault("Abilities.Air.AirShield.Instructions", "Hold sneak and a shield of air will form around you, blocking projectiles and pushing entities back."); config.addDefault("Abilities.Air.AirSpout.Description", "This ability gives the airbender limited sustained levitation. It allows an airbender to gain a height advantage to escape from mobs, players or just to dodge from attacks. This ability is also useful for building as it allows you to reach great heights."); config.addDefault("Abilities.Air.AirSpout.Instructions", "Left click to activate a spout beneath you and hold spacebar to go higher. If you wish to go lower, simply hold sneak. To disable this ability, left click once again."); @@ -357,7 +362,7 @@ public class ConfigManager { config.addDefault("Abilities.Earth.Tremorsense.Description", "This is a pure utility ability for earthbenders. If you are in an area of low-light and are standing on top of an earthbendable block, this ability will automatically turn that block into glowstone, visible *only by you*. If you lose contact with a bendable block, the light will go out as you have lost contact with the earth and cannot 'see' until you can touch earth again. Additionally, if you click with this ability selected, smoke will appear above nearby earth with pockets of air beneath them."); config.addDefault("Abilities.Earth.Tremorsense.Instructions", "Simply left click while on an earthbendable block."); config.addDefault("Abilities.Earth.Combo.EarthDome.Description", "EarthDome allows earthbenders to surround themselves or another entity in earth, temporarily preventing anything from entering or escaping the dome."); - config.addDefault("Abilities.Earth.Combo.EarthDome.Instructions", "(Self) RaiseEarth (Right click) > Shockwave (Right click)\\n(Projection) RaiseEarth(Right click) > Shockwave (Left click)"); + config.addDefault("Abilities.Earth.Combo.EarthDome.Instructions", "(Self) RaiseEarth (Right click) > Shockwave (Right click)" + "\n" + "(Projection) RaiseEarth (Right click) > Shockwave (Left click)"); config.addDefault("Abilities.Earth.Combo.EarthPillars.Description", "Send players and entities flying into the air and possibly stunning them by raising pillars of earth under their feet, dealing damage initally as well. This combo can also be used by falling from high off the ground and landing while on the Catapult ability"); config.addDefault("Abilities.Earth.Combo.EarthPillars.Instructions", "Shockwave (Tap sneak) > Shockwave (Hold sneak) > Catapult (Release sneak)"); config.addDefault("Abilities.Earth.Passive.DensityShift.Description", "DensityShift is a passive ability which allows earthbenders to make a firm landing negating all fall damage on any earthbendable surface."); @@ -555,6 +560,7 @@ public class ConfigManager { config.addDefault("Properties.UpdateChecker", true); config.addDefault("Properties.Statistics", true); config.addDefault("Properties.DatabaseCooldowns", true); + config.addDefault("Properties.BendingBoard", true); config.addDefault("Properties.BendingPreview", true); config.addDefault("Properties.BendingAffectFallingSand.Normal", true); config.addDefault("Properties.BendingAffectFallingSand.NormalStrengthMultiplier", 1.0); @@ -580,7 +586,8 @@ public class ConfigManager { config.addDefault("Properties.RegionProtection.RespectLWC", true); config.addDefault("Properties.RegionProtection.Residence.Flag", "bending"); config.addDefault("Properties.RegionProtection.Residence.Respect", true); - config.addDefault("Properties.RegionProtection.RespectKingdoms", true); + config.addDefault("Properties.RegionProtection.Kingdoms.Respect", true); + config.addDefault("Properties.RegionProtection.Kingdoms.ProtectDuringInvasions", false); config.addDefault("Properties.RegionProtection.RespectPlotSquared", true); config.addDefault("Properties.RegionProtection.RespectRedProtect", true); config.addDefault("Properties.RegionProtection.CacheBlockTime", 5000); @@ -652,7 +659,7 @@ public class ConfigManager { config.addDefault("Properties.Fire.BlueFire.DamageFactor", 1.1); config.addDefault("Properties.Fire.BlueFire.CooldownFactor", .9); config.addDefault("Properties.Fire.BlueFire.RangeFactor", 1.2); - + config.addDefault("Properties.Chi.CanBendWithWeapons", true); final ArrayList disabledWorlds = new ArrayList(); @@ -1283,6 +1290,8 @@ public class ConfigManager { config.addDefault("Abilities.Earth.EarthSmash.Damage", 5); config.addDefault("Abilities.Earth.EarthSmash.Knockback", 3.5); config.addDefault("Abilities.Earth.EarthSmash.Knockup", 0.15); + config.addDefault("Abilities.Earth.EarthSmash.Lift.Knockup", 1.1); + config.addDefault("Abilities.Earth.EarthSmash.Lift.Range", 3.5); config.addDefault("Abilities.Earth.EarthSmash.Flight.Enabled", true); config.addDefault("Abilities.Earth.EarthSmash.Flight.Speed", 0.72); config.addDefault("Abilities.Earth.EarthSmash.Flight.Duration", 3000); @@ -1293,6 +1302,7 @@ public class ConfigManager { config.addDefault("Abilities.Earth.EarthSmash.Grab.DetectionRadius", 2.5); config.addDefault("Abilities.Earth.EarthSmash.Shoot.Range", 25); config.addDefault("Abilities.Earth.EarthSmash.Shoot.AnimationInterval", 25); + config.addDefault("Abilities.Earth.EarthSmash.Shoot.CollisionRadius", 2.5); config.addDefault("Abilities.Earth.EarthSmash.RequiredBendableBlocks", 11); config.addDefault("Abilities.Earth.EarthSmash.MaxBlocksToPassThrough", 3); config.addDefault("Abilities.Earth.EarthSmash.LiftAnimationInterval", 30); diff --git a/src/com/projectkorra/projectkorra/earthbending/Catapult.java b/src/com/projectkorra/projectkorra/earthbending/Catapult.java index 78bfe6bd..38e3da8e 100644 --- a/src/com/projectkorra/projectkorra/earthbending/Catapult.java +++ b/src/com/projectkorra/projectkorra/earthbending/Catapult.java @@ -73,7 +73,7 @@ public class Catapult extends EarthAbility { if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { continue; } - entity.setVelocity(apply); + GeneralMethods.setVelocity(this, entity, apply); } } this.moveEarth(this.origin.clone().subtract(direction), direction, 3, false); @@ -135,7 +135,7 @@ public class Catapult extends EarthAbility { final Location tar = this.origin.clone().add(direction.clone().normalize().multiply(this.stage + 0.5)); this.target = tar; final Vector apply = this.target.clone().toVector().subtract(this.origin.clone().toVector()); - this.player.setVelocity(apply); + GeneralMethods.setVelocity(this, this.player, apply); this.moveEarth(apply, direction); this.remove(); } diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthArmor.java b/src/com/projectkorra/projectkorra/earthbending/EarthArmor.java index 07bb6393..bf6ab4e7 100644 --- a/src/com/projectkorra/projectkorra/earthbending/EarthArmor.java +++ b/src/com/projectkorra/projectkorra/earthbending/EarthArmor.java @@ -45,7 +45,7 @@ public class EarthArmor extends EarthAbility { private Location legsBlockLocation; private boolean active; private PotionEffect oldAbsorbtion = null; - private float goldHearts; + private double goldHearts; @Attribute("GoldHearts") private int maxGoldHearts; private TempArmor armor; @@ -84,6 +84,10 @@ public class EarthArmor extends EarthAbility { if (!this.moveBlocks()) { return; } + if ((TempBlock.isTempBlock(oldHeadBlock) && !isBendableEarthTempBlock(oldHeadBlock)) + || (TempBlock.isTempBlock(oldLegsBlock) && !isBendableEarthTempBlock(oldLegsBlock))) { + return; + } if (isEarthRevertOn()) { addTempAirBlock(oldHeadBlock); addTempAirBlock(oldLegsBlock); @@ -141,7 +145,7 @@ public class EarthArmor extends EarthAbility { this.player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, Integer.MAX_VALUE, level, true, false)); this.goldHearts = this.maxGoldHearts * 2; - GeneralMethods.setAbsorbationHealth(this.player, this.goldHearts); + this.player.setAbsorptionAmount(this.goldHearts); } private boolean inPosition() { @@ -245,7 +249,7 @@ public class EarthArmor extends EarthAbility { if (this.formed) { if (!this.player.hasPotionEffect(PotionEffectType.ABSORPTION)) { this.player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, Integer.MAX_VALUE, 1, true, false)); - GeneralMethods.setAbsorbationHealth(this.player, this.goldHearts); + this.player.setAbsorptionAmount(this.goldHearts); } if (!this.active) { @@ -297,7 +301,7 @@ public class EarthArmor extends EarthAbility { new BukkitRunnable() { @Override public void run() { - abil.goldHearts = GeneralMethods.getAbsorbationHealth(EarthArmor.this.player); + abil.goldHearts = EarthArmor.this.player.getAbsorptionAmount(); if (abil.formed && abil.goldHearts < 0.9F) { abil.bPlayer.addCooldown(abil); @@ -597,7 +601,7 @@ public class EarthArmor extends EarthAbility { this.cooldown = cooldown; } - public float getGoldHearts() { + public double getGoldHearts() { return this.goldHearts; } @@ -605,7 +609,7 @@ public class EarthArmor extends EarthAbility { return this.maxGoldHearts; } - public void setGoldHearts(final float goldHearts) { + public void setGoldHearts(final double goldHearts) { this.goldHearts = goldHearts; } diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java b/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java index 6157139e..e68d73bd 100644 --- a/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java +++ b/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java @@ -156,7 +156,7 @@ public class EarthBlast extends EarthAbility { final Block block = BlockSource.getEarthSourceBlock(this.player, this.range, ClickType.SHIFT_DOWN); if (block == null || !this.isEarthbendable(block)) { return false; - } else if (TempBlock.isTempBlock(block)) { + } else if (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block)) { return false; } @@ -276,7 +276,7 @@ public class EarthBlast extends EarthAbility { final Location location = this.player.getEyeLocation(); final Vector vector = location.getDirection(); - entity.setVelocity(vector.normalize().multiply(this.pushFactor)); + GeneralMethods.setVelocity(this, entity, vector.normalize().multiply(this.pushFactor)); double damage = this.damage; if (isMetal(this.sourceBlock) && this.bPlayer.canMetalbend()) { diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthGrab.java b/src/com/projectkorra/projectkorra/earthbending/EarthGrab.java index 6a861982..d2c05b39 100644 --- a/src/com/projectkorra/projectkorra/earthbending/EarthGrab.java +++ b/src/com/projectkorra/projectkorra/earthbending/EarthGrab.java @@ -74,7 +74,7 @@ public class EarthGrab extends EarthAbility { return; } - if (this.bPlayer.isOnCooldown(this)) { + if (bPlayer != null && this.bPlayer.isOnCooldown(this)) { //bPlayer can be null if the ability is disabled. If it is, it just won't start() return; } @@ -320,7 +320,7 @@ public class EarthGrab extends EarthAbility { continue; } final Block b = entity.getLocation().getBlock().getRelative(BlockFace.DOWN); - entity.setVelocity(GeneralMethods.getDirection(entity.getLocation(), this.player.getLocation()).normalize().multiply(this.dragSpeed)); + GeneralMethods.setVelocity(this, entity, GeneralMethods.getDirection(entity.getLocation(), this.player.getLocation()).normalize().multiply(this.dragSpeed)); ParticleEffect.BLOCK_CRACK.display(entity.getLocation(), 2, 0, 0, 0, b.getBlockData()); playEarthbendingSound(entity.getLocation()); } diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java b/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java index e71a0d9e..c6567b6c 100644 --- a/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java +++ b/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java @@ -1,979 +1,989 @@ -package com.projectkorra.projectkorra.earthbending; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import org.bukkit.Effect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import com.projectkorra.projectkorra.BendingPlayer; -import com.projectkorra.projectkorra.GeneralMethods; -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.util.ClickType; -import com.projectkorra.projectkorra.util.DamageHandler; -import com.projectkorra.projectkorra.util.ParticleEffect; -import com.projectkorra.projectkorra.util.TempBlock; - -public class EarthSmash extends EarthAbility { - - public static enum State { - START, LIFTING, LIFTED, GRABBED, SHOT, FLYING, REMOVED - } - - @Attribute("AllowGrab") - private boolean allowGrab; - @Attribute("AllowFlight") - private boolean allowFlight; - private int animationCounter; - private int progressCounter; - private int requiredBendableBlocks; - private int maxBlocksToPassThrough; - private long delay; - @Attribute(Attribute.COOLDOWN) - private long cooldown; - @Attribute(Attribute.CHARGE_DURATION) - private long chargeTime; - @Attribute(Attribute.DURATION) - private long duration; - @Attribute("Flight" + Attribute.DURATION) - private long flightDuration; - private long flightStartTime; - private long shootAnimationInterval; - private long flightAnimationInterval; - private long liftAnimationInterval; - @Attribute(Attribute.SELECT_RANGE) - private double selectRange; - @Attribute("GrabRange") - private double grabRange; - @Attribute("ShootRange") - private double shootRange; - @Attribute(Attribute.DAMAGE) - private double damage; - @Attribute(Attribute.KNOCKBACK) - private double knockback; - @Attribute(Attribute.KNOCKUP) - private double knockup; - @Attribute(Attribute.SPEED) - private double flightSpeed; - private double grabbedDistance; - private double grabDetectionRadius; - private double flightDetectionRadius; - private State state; - private Block origin; - private Location location; - private Location destination; - private ArrayList affectedEntities; - private ArrayList currentBlocks; - private ArrayList affectedBlocks; - - public EarthSmash(final Player player, final ClickType type) { - super(player); - - this.state = State.START; - this.requiredBendableBlocks = getConfig().getInt("Abilities.Earth.EarthSmash.RequiredBendableBlocks"); - this.maxBlocksToPassThrough = getConfig().getInt("Abilities.Earth.EarthSmash.MaxBlocksToPassThrough"); - this.setFields(); - this.affectedEntities = new ArrayList<>(); - this.currentBlocks = new ArrayList<>(); - this.affectedBlocks = new ArrayList<>(); - - if (type == ClickType.SHIFT_DOWN || type == ClickType.SHIFT_UP && !player.isSneaking()) { - final EarthSmash flySmash = flyingInSmashCheck(player); - if (flySmash != null) { - flySmash.state = State.FLYING; - flySmash.player = player; - flySmash.setFields(); - flySmash.flightStartTime = System.currentTimeMillis(); - return; - } - - EarthSmash grabbedSmash = this.aimingAtSmashCheck(player, State.LIFTED); - if (grabbedSmash == null) { - if (this.bPlayer.isOnCooldown(this)) { - return; - } - grabbedSmash = this.aimingAtSmashCheck(player, State.SHOT); - } - - if (grabbedSmash != null) { - grabbedSmash.state = State.GRABBED; - grabbedSmash.grabbedDistance = 0; - if (grabbedSmash.location.getWorld().equals(player.getWorld())) { - grabbedSmash.grabbedDistance = grabbedSmash.location.distance(player.getEyeLocation()); - } - grabbedSmash.player = player; - grabbedSmash.setFields(); - return; - } - - this.start(); - } else if (type == ClickType.LEFT_CLICK && player.isSneaking()) { - for (final EarthSmash smash : getAbilities(EarthSmash.class)) { - if (smash.state == State.GRABBED && smash.player == player) { - smash.state = State.SHOT; - smash.destination = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().normalize().multiply(smash.shootRange)); - smash.location.getWorld().playEffect(smash.location, Effect.GHAST_SHOOT, 0, 10); - } - } - return; - } else if (type == ClickType.RIGHT_CLICK && player.isSneaking()) { - final EarthSmash grabbedSmash = this.aimingAtSmashCheck(player, State.GRABBED); - if (grabbedSmash != null) { - player.teleport(grabbedSmash.location.clone().add(0, 2, 0)); - grabbedSmash.state = State.FLYING; - grabbedSmash.player = player; - grabbedSmash.setFields(); - grabbedSmash.flightStartTime = System.currentTimeMillis(); - } - return; - } - } - - public void setFields() { - final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(this.player); - this.shootAnimationInterval = getConfig().getLong("Abilities.Earth.EarthSmash.Shoot.AnimationInterval"); - this.flightAnimationInterval = getConfig().getLong("Abilities.Earth.EarthSmash.Flight.AnimationInterval"); - this.liftAnimationInterval = getConfig().getLong("Abilities.Earth.EarthSmash.LiftAnimationInterval"); - this.grabDetectionRadius = getConfig().getDouble("Abilities.Earth.EarthSmash.Grab.DetectionRadius"); - this.flightDetectionRadius = getConfig().getDouble("Abilities.Earth.EarthSmash.Flight.DetectionRadius"); - this.allowGrab = getConfig().getBoolean("Abilities.Earth.EarthSmash.Grab.Enabled"); - this.allowFlight = getConfig().getBoolean("Abilities.Earth.EarthSmash.Flight.Enabled"); - this.selectRange = getConfig().getDouble("Abilities.Earth.EarthSmash.SelectRange"); - this.grabRange = getConfig().getDouble("Abilities.Earth.EarthSmash.Grab.Range"); - this.shootRange = getConfig().getDouble("Abilities.Earth.EarthSmash.Shoot.Range"); - this.damage = getConfig().getDouble("Abilities.Earth.EarthSmash.Damage"); - this.knockback = getConfig().getDouble("Abilities.Earth.EarthSmash.Knockback"); - this.knockup = getConfig().getDouble("Abilities.Earth.EarthSmash.Knockup"); - this.flightSpeed = getConfig().getDouble("Abilities.Earth.EarthSmash.Flight.Speed"); - this.chargeTime = getConfig().getLong("Abilities.Earth.EarthSmash.ChargeTime"); - this.cooldown = getConfig().getLong("Abilities.Earth.EarthSmash.Cooldown"); - this.flightDuration = getConfig().getLong("Abilities.Earth.EarthSmash.Flight.Duration"); - this.duration = getConfig().getLong("Abilities.Earth.EarthSmash.Duration"); - - if (bPlayer.isAvatarState()) { - this.selectRange = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.SelectRange"); - this.grabRange = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.GrabRange"); - this.chargeTime = getConfig().getLong("Abilities.Avatar.AvatarState.Earth.EarthSmash.ChargeTime"); - this.cooldown = getConfig().getLong("Abilities.Avatar.AvatarState.Earth.EarthSmash.Cooldown"); - this.damage = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.Damage"); - this.knockback = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.Knockback"); - this.flightSpeed = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.FlightSpeed"); - this.flightDuration = getConfig().getLong("Abilities.Avatar.AvatarState.Earth.EarthSmash.FlightTimer"); - this.shootRange = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.ShootRange"); - } - } - - @Override - public void progress() { - this.progressCounter++; - if (this.state == State.LIFTED && this.duration > 0 && System.currentTimeMillis() - this.getStartTime() > this.duration) { - this.remove(); - return; - } - - if (this.state == State.START) { - if (!this.bPlayer.canBend(this)) { - this.remove(); - return; - } - } else if (this.state == State.START || this.state == State.FLYING || this.state == State.GRABBED) { - if (!this.bPlayer.canBendIgnoreCooldowns(this)) { - this.remove(); - return; - } - } - - if (this.state == State.START && this.progressCounter > 1) { - if (!this.player.isSneaking()) { - if (System.currentTimeMillis() - this.getStartTime() >= this.chargeTime) { - this.origin = this.getEarthSourceBlock(this.selectRange); - if (this.origin == null) { - this.remove(); - return; - } - this.bPlayer.addCooldown(this); - this.location = this.origin.getLocation(); - this.state = State.LIFTING; - } else { - this.remove(); - return; - } - } else if (System.currentTimeMillis() - this.getStartTime() > this.chargeTime) { - final Location tempLoc = this.player.getEyeLocation().add(this.player.getEyeLocation().getDirection().normalize().multiply(1.2)); - tempLoc.add(0, 0.3, 0); - ParticleEffect.SMOKE_NORMAL.display(tempLoc, 4, 0.3, 0.1, 0.3, 0); - } - } else if (this.state == State.LIFTING) { - if (System.currentTimeMillis() - this.delay >= this.liftAnimationInterval) { - this.delay = System.currentTimeMillis(); - this.animateLift(); - } - } else if (this.state == State.GRABBED) { - if (this.player.isSneaking()) { - this.revert(); - final Location oldLoc = this.location.clone(); - this.location = this.player.getEyeLocation().add(this.player.getEyeLocation().getDirection().normalize().multiply(this.grabbedDistance)); - - // Check to make sure the new location is available to move to. - for (final Block block : this.getBlocks()) { - if (!ElementalAbility.isAir(block.getType()) && !this.isTransparent(block)) { - this.location = oldLoc; - break; - } - } - this.draw(); - return; - } else { - this.state = State.LIFTED; - return; - } - } else if (this.state == State.SHOT) { - if (System.currentTimeMillis() - this.delay >= this.shootAnimationInterval) { - this.delay = System.currentTimeMillis(); - if (GeneralMethods.isRegionProtectedFromBuild(this, this.location)) { - this.remove(); - return; - } - - this.revert(); - this.location.add(GeneralMethods.getDirection(this.location, this.destination).normalize().multiply(1)); - if (this.location.distanceSquared(this.destination) < 4) { - this.remove(); - return; - } - - // If an earthsmash runs into too many blocks we should remove it. - int badBlocksFound = 0; - for (final Block block : this.getBlocks()) { - if (!ElementalAbility.isAir(block.getType()) && (!this.isTransparent(block) || block.getType() == Material.WATER)) { - badBlocksFound++; - } - } - - if (badBlocksFound > this.maxBlocksToPassThrough) { - this.remove(); - return; - } - this.shootingCollisionDetection(); - this.draw(); - this.smashToSmashCollisionDetection(); - } - return; - } else if (this.state == State.FLYING) { - if (!this.player.isSneaking()) { - this.remove(); - return; - } else if (System.currentTimeMillis() - this.delay >= this.flightAnimationInterval) { - this.delay = System.currentTimeMillis(); - if (GeneralMethods.isRegionProtectedFromBuild(this, this.location)) { - this.remove(); - return; - } - this.revert(); - this.destination = this.player.getEyeLocation().clone().add(this.player.getEyeLocation().getDirection().normalize().multiply(this.shootRange)); - final Vector direction = GeneralMethods.getDirection(this.location, this.destination).normalize(); - - final List entities = GeneralMethods.getEntitiesAroundPoint(this.location.clone().add(0, 2, 0), this.flightDetectionRadius); - if (entities.size() == 0) { - this.remove(); - return; - } - for (final Entity entity : entities) { - if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { - continue; - } - entity.setVelocity(direction.clone().multiply(this.flightSpeed)); - } - - // These values tend to work well when dealing with a person aiming upward or downward. - if (direction.getY() < -0.35) { - this.location = this.player.getLocation().clone().add(0, -3.2, 0); - } else if (direction.getY() > 0.35) { - this.location = this.player.getLocation().clone().add(0, -1.7, 0); - } else { - this.location = this.player.getLocation().clone().add(0, -2.2, 0); - } - this.draw(); - } - if (System.currentTimeMillis() - this.flightStartTime > this.flightDuration) { - this.remove(); - return; - } - } - } - - /** - * Begins animating the EarthSmash from the ground. The lift animation - * consists of 3 steps, and each one has to design the shape in the ground - * that removes the Earthbendable material. We also need to make sure that - * there is a clear path for the EarthSmash to rise, and that there is - * enough Earthbendable material for it to be created. - */ - public void animateLift() { - if (this.animationCounter < 4) { - this.revert(); - this.location.add(0, 1, 0); - // Remove the blocks underneath the rising smash. - if (this.animationCounter == 0) { - // Check all of the blocks and make sure that they can be removed AND make sure there is enough dirt. - int totalBendableBlocks = 0; - for (int x = -1; x <= 1; x++) { - for (int y = -2; y <= -1; y++) { - for (int z = -1; z <= 1; z++) { - final Block block = this.location.clone().add(x, y, z).getBlock(); - if (GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { - this.remove(); - return; - } - if (this.isEarthbendable(block)) { - totalBendableBlocks++; - } - } - } - } - if (totalBendableBlocks < this.requiredBendableBlocks) { - this.remove(); - return; - } - // Make sure there is a clear path upward otherwise remove. - for (int y = 0; y <= 3; y++) { - final Block tempBlock = this.location.clone().add(0, y, 0).getBlock(); - if (!this.isTransparent(tempBlock) && !ElementalAbility.isAir(tempBlock.getType())) { - this.remove(); - return; - } - } - // Design what this EarthSmash looks like by using BlockRepresenters. - final Location tempLoc = this.location.clone().add(0, -2, 0); - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - for (int z = -1; z <= 1; z++) { - if ((Math.abs(x) + Math.abs(y) + Math.abs(z)) % 2 == 0) { - final Block block = tempLoc.clone().add(x, y, z).getBlock(); - this.currentBlocks.add(new BlockRepresenter(x, y, z, this.selectMaterialForRepresenter(block.getType()), block.getBlockData())); - } - } - } - } - - // Remove the design of the second level of removed dirt. - for (int x = -1; x <= 1; x++) { - for (int z = -1; z <= 1; z++) { - if ((Math.abs(x) + Math.abs(z)) % 2 == 1) { - final Block block = this.location.clone().add(x, -2, z).getBlock(); - if (this.isEarthbendable(block)) { - addTempAirBlock(block); - } - } - - // Remove the first level of dirt. - final Block block = this.location.clone().add(x, -1, z).getBlock(); - if (this.isEarthbendable(block)) { - addTempAirBlock(block); - } - } - } - - /* - * We needed to calculate all of the blocks based on the - * location being 1 above the initial bending block, however we - * want to animate it starting from the original bending block. - * We must readjust the location back to what it originally was. - */ - this.location.add(0, -1, 0); - - } - // Move any entities that are above the rock. - final List entities = GeneralMethods.getEntitiesAroundPoint(this.location, 2.5); - for (final Entity entity : entities) { - final org.bukkit.util.Vector velocity = entity.getVelocity(); - entity.setVelocity(velocity.add(new Vector(0, 0.36, 0))); - } - this.location.getWorld().playEffect(this.location, Effect.GHAST_SHOOT, 0, 7); - this.draw(); - } else { - this.state = State.LIFTED; - } - this.animationCounter++; - } - - /** - * Redraws the blocks for this instance of EarthSmash. - */ - public void draw() { - if (this.currentBlocks.size() == 0) { - this.remove(); - return; - } - for (final BlockRepresenter blockRep : this.currentBlocks) { - final Block block = this.location.clone().add(blockRep.getX(), blockRep.getY(), blockRep.getZ()).getBlock(); - if (block.getType().equals(Material.SAND) || block.getType().equals(Material.GRAVEL)) { // Check if block can be affected by gravity. - - } - if (this.player != null && this.isTransparent(block)) { - this.affectedBlocks.add(new TempBlock(block, blockRep.getType())); - getPreventEarthbendingBlocks().add(block); - } - } - } - - public void revert() { - this.checkRemainingBlocks(); - for (int i = 0; i < this.affectedBlocks.size(); i++) { - final TempBlock tblock = this.affectedBlocks.get(i); - getPreventEarthbendingBlocks().remove(tblock.getBlock()); - tblock.revertBlock(); - this.affectedBlocks.remove(i); - i--; - } - } - - /** - * Checks to see which of the blocks are still attached to the EarthSmash, - * remember that blocks can be broken or used in other abilities so we need - * to double check and remove any that are not still attached. - * - * Also when we remove the blocks from instances, movedearth, or tempair we - * should do it on a delay because tempair takes a couple seconds before the - * block shows up in that map. - */ - public void checkRemainingBlocks() { - for (int i = 0; i < this.currentBlocks.size(); i++) { - final BlockRepresenter brep = this.currentBlocks.get(i); - final Block block = this.location.clone().add(brep.getX(), brep.getY(), brep.getZ()).getBlock(); - // Check for grass because sometimes the dirt turns into grass. - if (block.getType() != brep.getType() && (block.getType() != Material.GRASS) && (block.getType() != Material.COBBLESTONE)) { - this.currentBlocks.remove(i); - i--; - } - } - } - - @Override - public void remove() { - super.remove(); - this.state = State.REMOVED; - this.revert(); - } - - /** - * Gets the blocks surrounding the EarthSmash's loc. This method ignores the - * blocks that should be Air, and only returns the ones that are dirt. - */ - public List getBlocks() { - final List blocks = new ArrayList(); - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - for (int z = -1; z <= 1; z++) { - if ((Math.abs(x) + Math.abs(y) + Math.abs(z)) % 2 == 0) { // Give it the cool shape. - if (this.location != null) { - blocks.add(this.location.getWorld().getBlockAt(this.location.clone().add(x, y, z))); - } - } - } - } - } - return blocks; - } - - /** - * Gets the blocks surrounding the EarthSmash's loc. This method returns all - * the blocks surrounding the loc, including dirt and air. - */ - public List getBlocksIncludingInner() { - final List blocks = new ArrayList(); - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - for (int z = -1; z <= 1; z++) { - if (this.location != null) { - blocks.add(this.location.getWorld().getBlockAt(this.location.clone().add(x, y, z))); - } - } - } - } - return blocks; - } - - /** - * Switches the Sand Material and Gravel to SandStone and stone - * respectively, since gravel and sand cannot be bent due to gravity. - */ - public static Material selectMaterial(final Material mat) { - if (mat == Material.SAND) { - return Material.SANDSTONE; - } else if (mat == Material.GRAVEL) { - return Material.STONE; - } else { - return mat; - } - } - - public Material selectMaterialForRepresenter(final Material mat) { - final Material tempMat = selectMaterial(mat); - final Random rand = new Random(); - if (!isEarthbendable(tempMat, true, true, true) && !this.isMetalbendable(tempMat)) { - if (this.currentBlocks.size() < 1) { - return Material.DIRT; - } else { - return this.currentBlocks.get(rand.nextInt(this.currentBlocks.size())).getType(); - } - } - return tempMat; - } - - /** - * Determines if a player is trying to grab an EarthSmash. A player is - * trying to grab an EarthSmash if they are staring at it and holding shift. - */ - private EarthSmash aimingAtSmashCheck(final Player player, final State reqState) { - if (!this.allowGrab) { - return null; - } - - final List blocks = GeneralMethods.getBlocksAroundPoint(GeneralMethods.getTargetedLocation(player, this.grabRange, getTransparentMaterials()), 1); - for (final EarthSmash smash : getAbilities(EarthSmash.class)) { - if (reqState == null || smash.state == reqState) { - for (final Block block : blocks) { - if (block == null || smash.getLocation() == null) { - continue; - } - if (block.getLocation().getWorld() == smash.location.getWorld() && block.getLocation().distanceSquared(smash.location) <= Math.pow(this.grabDetectionRadius, 2)) { - return smash; - } - } - } - } - return null; - } - - /** - * This method handles any collision between an EarthSmash and the - * surrounding entities, the method only applies to earthsmashes that have - * already been shot. - */ - public void shootingCollisionDetection() { - final List entities = GeneralMethods.getEntitiesAroundPoint(this.location, this.flightDetectionRadius); - for (final Entity entity : entities) { - if (entity instanceof LivingEntity && entity != this.player && !this.affectedEntities.contains(entity)) { - if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { - continue; - } - this.affectedEntities.add(entity); - final double damage = this.currentBlocks.size() / 13.0 * this.damage; - DamageHandler.damageEntity(entity, damage, this); - final Vector travelVec = GeneralMethods.getDirection(this.location, entity.getLocation()); - entity.setVelocity(travelVec.setY(this.knockup).normalize().multiply(this.knockback)); - } - } - } - - /** - * EarthSmash to EarthSmash collision can only happen when one of the - * Smashes have been shot by a player. If we find out that one of them have - * collided then we want to return since a smash can only remove 1 at a - * time. - */ - public void smashToSmashCollisionDetection() { - for (final EarthSmash smash : getAbilities(EarthSmash.class)) { - if (smash.location != null && smash != this && smash.location.getWorld() == this.location.getWorld() && smash.location.distanceSquared(this.location) < Math.pow(this.flightDetectionRadius, 2)) { - smash.remove(); - this.remove(); - return; - } - } - } - - /** - * Determines whether or not a player is trying to fly ontop of an - * EarthSmash. A player is considered "flying" if they are standing ontop of - * the earthsmash and holding shift. - */ - private static EarthSmash flyingInSmashCheck(final Player player) { - for (final EarthSmash smash : getAbilities(EarthSmash.class)) { - if (!smash.allowFlight) { - continue; - } - // Check to see if the player is standing on top of the smash. - if (smash.state == State.LIFTED) { - if (smash.location.getWorld().equals(player.getWorld()) && smash.location.clone().add(0, 2, 0).distanceSquared(player.getLocation()) <= Math.pow(smash.flightDetectionRadius, 2)) { - return smash; - } - } - } - return null; - } - - /** - * A BlockRepresenter is used to keep track of each of the individual types - * of blocks that are attached to an EarthSmash. Without the representer - * then an EarthSmash can only be made up of 1 material at a time. For - * example, an ESmash that is entirely dirt, coalore, or sandstone. Using - * the representer will allow all the materials to be mixed together. - */ - public class BlockRepresenter { - private int x, y, z; - private Material type; - private BlockData data; - - public BlockRepresenter(final int x, final int y, final int z, final Material type, final BlockData data) { - this.x = x; - this.y = y; - this.z = z; - this.type = type; - this.data = data; - } - - public int getX() { - return this.x; - } - - public int getY() { - return this.y; - } - - public int getZ() { - return this.z; - } - - public Material getType() { - return this.type; - } - - public BlockData getData() { - return this.data; - } - - public void setX(final int x) { - this.x = x; - } - - public void setY(final int y) { - this.y = y; - } - - public void setZ(final int z) { - this.z = z; - } - - public void setType(final Material type) { - this.type = type; - } - - public void setData(final BlockData data) { - this.data = data; - } - - @Override - public String toString() { - return this.x + ", " + this.y + ", " + this.z + ", " + this.type.toString(); - } - } - - public class Pair { - private F first; // first member of pair. - private S second; // second member of pair. - - public Pair(final F first, final S second) { - this.first = first; - this.second = second; - } - - public void setFirst(final F first) { - this.first = first; - } - - public void setSecond(final S second) { - this.second = second; - } - - public F getFirst() { - return this.first; - } - - public S getSecond() { - return this.second; - } - } - - @Override - public String getName() { - return "EarthSmash"; - } - - @Override - public Location getLocation() { - return this.location; - } - - @Override - public long getCooldown() { - return this.cooldown; - } - - @Override - public boolean isSneakAbility() { - return true; - } - - @Override - public boolean isHarmlessAbility() { - return false; - } - - @Override - public List getLocations() { - final ArrayList locations = new ArrayList<>(); - for (final TempBlock tblock : this.affectedBlocks) { - locations.add(tblock.getLocation()); - } - return locations; - } - - public boolean isAllowGrab() { - return this.allowGrab; - } - - public void setAllowGrab(final boolean allowGrab) { - this.allowGrab = allowGrab; - } - - public boolean isAllowFlight() { - return this.allowFlight; - } - - public void setAllowFlight(final boolean allowFlight) { - this.allowFlight = allowFlight; - } - - public int getAnimationCounter() { - return this.animationCounter; - } - - public void setAnimationCounter(final int animationCounter) { - this.animationCounter = animationCounter; - } - - public int getProgressCounter() { - return this.progressCounter; - } - - public void setProgressCounter(final int progressCounter) { - this.progressCounter = progressCounter; - } - - public int getRequiredBendableBlocks() { - return this.requiredBendableBlocks; - } - - public void setRequiredBendableBlocks(final int requiredBendableBlocks) { - this.requiredBendableBlocks = requiredBendableBlocks; - } - - public int getMaxBlocksToPassThrough() { - return this.maxBlocksToPassThrough; - } - - public void setMaxBlocksToPassThrough(final int maxBlocksToPassThrough) { - this.maxBlocksToPassThrough = maxBlocksToPassThrough; - } - - public long getDelay() { - return this.delay; - } - - public void setDelay(final long delay) { - this.delay = delay; - } - - public long getChargeTime() { - return this.chargeTime; - } - - public void setChargeTime(final long chargeTime) { - this.chargeTime = chargeTime; - } - - public long getDuration() { - return this.duration; - } - - public void setDuration(final long duration) { - this.duration = duration; - } - - public long getFlightDuration() { - return this.flightDuration; - } - - public void setFlightDuration(final long flightDuration) { - this.flightDuration = flightDuration; - } - - public long getFlightStartTime() { - return this.flightStartTime; - } - - public void setFlightStartTime(final long flightStartTime) { - this.flightStartTime = flightStartTime; - } - - public long getShootAnimationInterval() { - return this.shootAnimationInterval; - } - - public void setShootAnimationInterval(final long shootAnimationInterval) { - this.shootAnimationInterval = shootAnimationInterval; - } - - public long getFlightAnimationInterval() { - return this.flightAnimationInterval; - } - - public void setFlightAnimationInterval(final long flightAnimationInterval) { - this.flightAnimationInterval = flightAnimationInterval; - } - - public long getLiftAnimationInterval() { - return this.liftAnimationInterval; - } - - public void setLiftAnimationInterval(final long liftAnimationInterval) { - this.liftAnimationInterval = liftAnimationInterval; - } - - public double getGrabRange() { - return this.grabRange; - } - - public void setGrabRange(final double grabRange) { - this.grabRange = grabRange; - } - - public double getSelectRange() { - return this.selectRange; - } - - public void setSelectRange(final double selectRange) { - this.selectRange = selectRange; - } - - public double getShootRange() { - return this.shootRange; - } - - public void setShootRange(final double shootRange) { - this.shootRange = shootRange; - } - - public double getDamage() { - return this.damage; - } - - public void setDamage(final double damage) { - this.damage = damage; - } - - public double getKnockback() { - return this.knockback; - } - - public void setKnockback(final double knockback) { - this.knockback = knockback; - } - - public double getKnockup() { - return this.knockup; - } - - public void setKnockup(final double knockup) { - this.knockup = knockup; - } - - public double getFlightSpeed() { - return this.flightSpeed; - } - - public void setFlightSpeed(final double flightSpeed) { - this.flightSpeed = flightSpeed; - } - - public double getGrabbedDistance() { - return this.grabbedDistance; - } - - public void setGrabbedDistance(final double grabbedDistance) { - this.grabbedDistance = grabbedDistance; - } - - public double getGrabDetectionRadius() { - return this.grabDetectionRadius; - } - - public void setGrabDetectionRadius(final double grabDetectionRadius) { - this.grabDetectionRadius = grabDetectionRadius; - } - - public double getFlightDetectionRadius() { - return this.flightDetectionRadius; - } - - public void setFlightDetectionRadius(final double flightDetectionRadius) { - this.flightDetectionRadius = flightDetectionRadius; - } - - public State getState() { - return this.state; - } - - public void setState(final State state) { - this.state = state; - } - - public Block getOrigin() { - return this.origin; - } - - public void setOrigin(final Block origin) { - this.origin = origin; - } - - public Location getDestination() { - return this.destination; - } - - public void setDestination(final Location destination) { - this.destination = destination; - } - - public ArrayList getAffectedEntities() { - return this.affectedEntities; - } - - public ArrayList getCurrentBlocks() { - return this.currentBlocks; - } - - public ArrayList getAffectedBlocks() { - return this.affectedBlocks; - } - - public void setCooldown(final long cooldown) { - this.cooldown = cooldown; - } - - public void setLocation(final Location location) { - this.location = location; - } - -} +package com.projectkorra.projectkorra.earthbending; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.projectkorra.BendingPlayer; +import com.projectkorra.projectkorra.GeneralMethods; +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.util.ClickType; +import com.projectkorra.projectkorra.util.DamageHandler; +import com.projectkorra.projectkorra.util.ParticleEffect; +import com.projectkorra.projectkorra.util.TempBlock; + +public class EarthSmash extends EarthAbility { + + public static enum State { + START, LIFTING, LIFTED, GRABBED, SHOT, FLYING, REMOVED + } + + @Attribute("AllowGrab") + private boolean allowGrab; + @Attribute("AllowFlight") + private boolean allowFlight; + private int animationCounter; + private int progressCounter; + private int requiredBendableBlocks; + private int maxBlocksToPassThrough; + private long delay; + @Attribute(Attribute.COOLDOWN) + private long cooldown; + @Attribute(Attribute.CHARGE_DURATION) + private long chargeTime; + @Attribute(Attribute.DURATION) + private long duration; + @Attribute("Flight" + Attribute.DURATION) + private long flightDuration; + private long flightStartTime; + private long shootAnimationInterval; + private long flightAnimationInterval; + private long liftAnimationInterval; + @Attribute(Attribute.SELECT_RANGE) + private double selectRange; + @Attribute("GrabRange") + private double grabRange; + @Attribute("ShootRange") + private double shootRange; + @Attribute(Attribute.DAMAGE) + private double damage; + @Attribute(Attribute.KNOCKBACK) + private double knockback; + @Attribute(Attribute.KNOCKUP) + private double knockup; + private double liftKnockup; + private double liftRange; + @Attribute(Attribute.SPEED) + private double flightSpeed; + private double grabbedDistance; + private double grabDetectionRadius; + private double hitRadius; + private double flightDetectionRadius; + private State state; + private Block origin; + private Location location; + private Location destination; + private ArrayList affectedEntities; + private ArrayList currentBlocks; + private ArrayList affectedBlocks; + + public EarthSmash(final Player player, final ClickType type) { + super(player); + + this.state = State.START; + this.requiredBendableBlocks = getConfig().getInt("Abilities.Earth.EarthSmash.RequiredBendableBlocks"); + this.maxBlocksToPassThrough = getConfig().getInt("Abilities.Earth.EarthSmash.MaxBlocksToPassThrough"); + this.setFields(); + this.affectedEntities = new ArrayList<>(); + this.currentBlocks = new ArrayList<>(); + this.affectedBlocks = new ArrayList<>(); + + if (type == ClickType.SHIFT_DOWN || type == ClickType.SHIFT_UP && !player.isSneaking()) { + final EarthSmash flySmash = flyingInSmashCheck(player); + if (flySmash != null) { + flySmash.state = State.FLYING; + flySmash.player = player; + flySmash.setFields(); + flySmash.flightStartTime = System.currentTimeMillis(); + return; + } + + EarthSmash grabbedSmash = this.aimingAtSmashCheck(player, State.LIFTED); + if (grabbedSmash == null) { + if (this.bPlayer.isOnCooldown(this)) { + return; + } + grabbedSmash = this.aimingAtSmashCheck(player, State.SHOT); + } + + if (grabbedSmash != null) { + grabbedSmash.state = State.GRABBED; + grabbedSmash.grabbedDistance = 0; + if (grabbedSmash.location.getWorld().equals(player.getWorld())) { + grabbedSmash.grabbedDistance = grabbedSmash.location.distance(player.getEyeLocation()); + } + grabbedSmash.player = player; + grabbedSmash.setFields(); + return; + } + + this.start(); + } else if (type == ClickType.LEFT_CLICK && player.isSneaking()) { + for (final EarthSmash smash : getAbilities(EarthSmash.class)) { + if (smash.state == State.GRABBED && smash.player == player) { + smash.state = State.SHOT; + smash.destination = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().normalize().multiply(smash.shootRange)); + smash.location.getWorld().playEffect(smash.location, Effect.GHAST_SHOOT, 0, 10); + } + } + return; + } else if (type == ClickType.RIGHT_CLICK && player.isSneaking()) { + final EarthSmash grabbedSmash = this.aimingAtSmashCheck(player, State.GRABBED); + if (grabbedSmash != null) { + player.teleport(grabbedSmash.location.clone().add(0, 2, 0)); + grabbedSmash.state = State.FLYING; + grabbedSmash.player = player; + grabbedSmash.setFields(); + grabbedSmash.flightStartTime = System.currentTimeMillis(); + } + return; + } + } + + public void setFields() { + final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(this.player); + this.shootAnimationInterval = getConfig().getLong("Abilities.Earth.EarthSmash.Shoot.AnimationInterval"); + this.flightAnimationInterval = getConfig().getLong("Abilities.Earth.EarthSmash.Flight.AnimationInterval"); + this.liftAnimationInterval = getConfig().getLong("Abilities.Earth.EarthSmash.LiftAnimationInterval"); + this.grabDetectionRadius = getConfig().getDouble("Abilities.Earth.EarthSmash.Grab.DetectionRadius"); + this.flightDetectionRadius = getConfig().getDouble("Abilities.Earth.EarthSmash.Flight.DetectionRadius"); + this.hitRadius = getConfig().getDouble("Abilities.Earth.EarthSmash.Shoot.CollisionRadius"); + this.allowGrab = getConfig().getBoolean("Abilities.Earth.EarthSmash.Grab.Enabled"); + this.allowFlight = getConfig().getBoolean("Abilities.Earth.EarthSmash.Flight.Enabled"); + this.selectRange = getConfig().getDouble("Abilities.Earth.EarthSmash.SelectRange"); + this.grabRange = getConfig().getDouble("Abilities.Earth.EarthSmash.Grab.Range"); + this.shootRange = getConfig().getDouble("Abilities.Earth.EarthSmash.Shoot.Range"); + this.damage = getConfig().getDouble("Abilities.Earth.EarthSmash.Damage"); + this.knockback = getConfig().getDouble("Abilities.Earth.EarthSmash.Knockback"); + this.knockup = getConfig().getDouble("Abilities.Earth.EarthSmash.Knockup"); + this.liftKnockup = getConfig().getDouble("Abilities.Earth.EarthSmash.Lift.Knockup"); + this.liftRange = getConfig().getDouble("Abilities.Earth.EarthSmash.Lift.Range"); + this.flightSpeed = getConfig().getDouble("Abilities.Earth.EarthSmash.Flight.Speed"); + this.chargeTime = getConfig().getLong("Abilities.Earth.EarthSmash.ChargeTime"); + this.cooldown = getConfig().getLong("Abilities.Earth.EarthSmash.Cooldown"); + this.flightDuration = getConfig().getLong("Abilities.Earth.EarthSmash.Flight.Duration"); + this.duration = getConfig().getLong("Abilities.Earth.EarthSmash.Duration"); + + if (bPlayer.isAvatarState()) { + this.selectRange = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.SelectRange"); + this.grabRange = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.GrabRange"); + this.chargeTime = getConfig().getLong("Abilities.Avatar.AvatarState.Earth.EarthSmash.ChargeTime"); + this.cooldown = getConfig().getLong("Abilities.Avatar.AvatarState.Earth.EarthSmash.Cooldown"); + this.damage = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.Damage"); + this.knockback = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.Knockback"); + this.flightSpeed = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.FlightSpeed"); + this.flightDuration = getConfig().getLong("Abilities.Avatar.AvatarState.Earth.EarthSmash.FlightTimer"); + this.shootRange = getConfig().getDouble("Abilities.Avatar.AvatarState.Earth.EarthSmash.ShootRange"); + } + } + + @Override + public void progress() { + this.progressCounter++; + if (this.state == State.LIFTED && this.duration > 0 && System.currentTimeMillis() - this.getStartTime() > this.duration) { + this.remove(); + return; + } + + if (this.state == State.START) { + if (!this.bPlayer.canBend(this)) { + this.remove(); + return; + } + } else if (this.state == State.START || this.state == State.FLYING || this.state == State.GRABBED) { + if (!this.bPlayer.canBendIgnoreCooldowns(this)) { + this.remove(); + return; + } + } + + if (this.state == State.START && this.progressCounter > 1) { + if (!this.player.isSneaking()) { + if (System.currentTimeMillis() - this.getStartTime() >= this.chargeTime) { + this.origin = this.getEarthSourceBlock(this.selectRange); + if (this.origin == null) { + this.remove(); + return; + } else if (TempBlock.isTempBlock(this.origin) && !isBendableEarthTempBlock(this.origin)) { + this.remove(); + return; + } + this.bPlayer.addCooldown(this); + this.location = this.origin.getLocation(); + this.state = State.LIFTING; + } else { + this.remove(); + return; + } + } else if (System.currentTimeMillis() - this.getStartTime() > this.chargeTime) { + final Location tempLoc = this.player.getEyeLocation().add(this.player.getEyeLocation().getDirection().normalize().multiply(1.2)); + tempLoc.add(0, 0.3, 0); + ParticleEffect.SMOKE_NORMAL.display(tempLoc, 4, 0.3, 0.1, 0.3, 0); + } + } else if (this.state == State.LIFTING) { + if (System.currentTimeMillis() - this.delay >= this.liftAnimationInterval) { + this.delay = System.currentTimeMillis(); + this.animateLift(); + } + } else if (this.state == State.GRABBED) { + if (this.player.isSneaking()) { + this.revert(); + final Location oldLoc = this.location.clone(); + this.location = this.player.getEyeLocation().add(this.player.getEyeLocation().getDirection().normalize().multiply(this.grabbedDistance)); + + // Check to make sure the new location is available to move to. + for (final Block block : this.getBlocks()) { + if (!ElementalAbility.isAir(block.getType()) && !this.isTransparent(block)) { + this.location = oldLoc; + break; + } + } + this.draw(); + return; + } else { + this.state = State.LIFTED; + return; + } + } else if (this.state == State.SHOT) { + if (System.currentTimeMillis() - this.delay >= this.shootAnimationInterval) { + this.delay = System.currentTimeMillis(); + if (GeneralMethods.isRegionProtectedFromBuild(this, this.location)) { + this.remove(); + return; + } + + this.revert(); + this.location.add(GeneralMethods.getDirection(this.location, this.destination).normalize().multiply(1)); + if (this.location.distanceSquared(this.destination) < 4) { + this.remove(); + return; + } + + // If an earthsmash runs into too many blocks we should remove it. + int badBlocksFound = 0; + for (final Block block : this.getBlocks()) { + if (!ElementalAbility.isAir(block.getType()) && (!this.isTransparent(block) || block.getType() == Material.WATER)) { + badBlocksFound++; + } + } + + if (badBlocksFound > this.maxBlocksToPassThrough) { + this.remove(); + return; + } + this.shootingCollisionDetection(); + this.draw(); + this.smashToSmashCollisionDetection(); + } + return; + } else if (this.state == State.FLYING) { + if (!this.player.isSneaking()) { + this.remove(); + return; + } else if (System.currentTimeMillis() - this.delay >= this.flightAnimationInterval) { + this.delay = System.currentTimeMillis(); + if (GeneralMethods.isRegionProtectedFromBuild(this, this.location)) { + this.remove(); + return; + } + this.revert(); + this.destination = this.player.getEyeLocation().clone().add(this.player.getEyeLocation().getDirection().normalize().multiply(this.shootRange)); + final Vector direction = GeneralMethods.getDirection(this.location, this.destination).normalize(); + + final List entities = GeneralMethods.getEntitiesAroundPoint(this.location.clone().add(0, 2, 0), this.flightDetectionRadius); + if (entities.size() == 0) { + this.remove(); + return; + } + for (final Entity entity : entities) { + if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { + continue; + } + GeneralMethods.setVelocity(this, entity, direction.clone().multiply(this.flightSpeed)); + } + + // These values tend to work well when dealing with a person aiming upward or downward. + if (direction.getY() < -0.35) { + this.location = this.player.getLocation().clone().add(0, -3.2, 0); + } else if (direction.getY() > 0.35) { + this.location = this.player.getLocation().clone().add(0, -1.7, 0); + } else { + this.location = this.player.getLocation().clone().add(0, -2.2, 0); + } + this.draw(); + } + if (System.currentTimeMillis() - this.flightStartTime > this.flightDuration) { + this.remove(); + return; + } + } + } + + /** + * Begins animating the EarthSmash from the ground. The lift animation + * consists of 3 steps, and each one has to design the shape in the ground + * that removes the Earthbendable material. We also need to make sure that + * there is a clear path for the EarthSmash to rise, and that there is + * enough Earthbendable material for it to be created. + */ + public void animateLift() { + if (this.animationCounter < 4) { + this.revert(); + this.location.add(0, 1, 0); + // Remove the blocks underneath the rising smash. + if (this.animationCounter == 0) { + // Check all of the blocks and make sure that they can be removed AND make sure there is enough dirt. + int totalBendableBlocks = 0; + for (int x = -1; x <= 1; x++) { + for (int y = -2; y <= -1; y++) { + for (int z = -1; z <= 1; z++) { + final Block block = this.location.clone().add(x, y, z).getBlock(); + if (GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { + this.remove(); + return; + } + if (this.isEarthbendable(block)) { + totalBendableBlocks++; + } + } + } + } + if (totalBendableBlocks < this.requiredBendableBlocks) { + this.remove(); + return; + } + // Make sure there is a clear path upward otherwise remove. + for (int y = 0; y <= 3; y++) { + final Block tempBlock = this.location.clone().add(0, y, 0).getBlock(); + if (!this.isTransparent(tempBlock) && !ElementalAbility.isAir(tempBlock.getType())) { + this.remove(); + return; + } + } + // Design what this EarthSmash looks like by using BlockRepresenters. + final Location tempLoc = this.location.clone().add(0, -2, 0); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + if ((Math.abs(x) + Math.abs(y) + Math.abs(z)) % 2 == 0) { + final Block block = tempLoc.clone().add(x, y, z).getBlock(); + this.currentBlocks.add(new BlockRepresenter(x, y, z, this.selectMaterialForRepresenter(block.getType()), block.getBlockData())); + } + } + } + } + + // Remove the design of the second level of removed dirt. + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + if ((Math.abs(x) + Math.abs(z)) % 2 == 1) { + final Block block = this.location.clone().add(x, -2, z).getBlock(); + if (this.isEarthbendable(block)) { + addTempAirBlock(block); + } + } + + // Remove the first level of dirt. + final Block block = this.location.clone().add(x, -1, z).getBlock(); + if (this.isEarthbendable(block)) { + addTempAirBlock(block); + } + } + } + + /* + * We needed to calculate all of the blocks based on the + * location being 1 above the initial bending block, however we + * want to animate it starting from the original bending block. + * We must readjust the location back to what it originally was. + */ + this.location.add(0, -1, 0); + + // Move any entities that are above the rock. + final List entities = GeneralMethods.getEntitiesAroundPoint(this.location, this.liftRange); + for (final Entity entity : entities) { + final org.bukkit.util.Vector velocity = entity.getVelocity(); + entity.setVelocity(velocity.add(new Vector(0, this.liftKnockup, 0))); + } + } + + this.location.getWorld().playEffect(this.location, Effect.GHAST_SHOOT, 0, 7); + this.draw(); + } else { + this.state = State.LIFTED; + } + this.animationCounter++; + } + + /** + * Redraws the blocks for this instance of EarthSmash. + */ + public void draw() { + if (this.currentBlocks.size() == 0) { + this.remove(); + return; + } + for (final BlockRepresenter blockRep : this.currentBlocks) { + final Block block = this.location.clone().add(blockRep.getX(), blockRep.getY(), blockRep.getZ()).getBlock(); + if (block.getType().equals(Material.SAND) || block.getType().equals(Material.GRAVEL)) { // Check if block can be affected by gravity. + + } + if (this.player != null && this.isTransparent(block)) { + this.affectedBlocks.add(new TempBlock(block, blockRep.getType())); + getPreventEarthbendingBlocks().add(block); + } + } + } + + public void revert() { + this.checkRemainingBlocks(); + for (int i = 0; i < this.affectedBlocks.size(); i++) { + final TempBlock tblock = this.affectedBlocks.get(i); + getPreventEarthbendingBlocks().remove(tblock.getBlock()); + tblock.revertBlock(); + this.affectedBlocks.remove(i); + i--; + } + } + + /** + * Checks to see which of the blocks are still attached to the EarthSmash, + * remember that blocks can be broken or used in other abilities so we need + * to double check and remove any that are not still attached. + * + * Also when we remove the blocks from instances, movedearth, or tempair we + * should do it on a delay because tempair takes a couple seconds before the + * block shows up in that map. + */ + public void checkRemainingBlocks() { + for (int i = 0; i < this.currentBlocks.size(); i++) { + final BlockRepresenter brep = this.currentBlocks.get(i); + final Block block = this.location.clone().add(brep.getX(), brep.getY(), brep.getZ()).getBlock(); + // Check for grass because sometimes the dirt turns into grass. + if (block.getType() != brep.getType() && (block.getType() != Material.GRASS) && (block.getType() != Material.COBBLESTONE)) { + this.currentBlocks.remove(i); + i--; + } + } + } + + @Override + public void remove() { + super.remove(); + this.state = State.REMOVED; + this.revert(); + } + + /** + * Gets the blocks surrounding the EarthSmash's loc. This method ignores the + * blocks that should be Air, and only returns the ones that are dirt. + */ + public List getBlocks() { + final List blocks = new ArrayList(); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + if ((Math.abs(x) + Math.abs(y) + Math.abs(z)) % 2 == 0) { // Give it the cool shape. + if (this.location != null) { + blocks.add(this.location.getWorld().getBlockAt(this.location.clone().add(x, y, z))); + } + } + } + } + } + return blocks; + } + + /** + * Gets the blocks surrounding the EarthSmash's loc. This method returns all + * the blocks surrounding the loc, including dirt and air. + */ + public List getBlocksIncludingInner() { + final List blocks = new ArrayList(); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + if (this.location != null) { + blocks.add(this.location.getWorld().getBlockAt(this.location.clone().add(x, y, z))); + } + } + } + } + return blocks; + } + + /** + * Switches the Sand Material and Gravel to SandStone and stone + * respectively, since gravel and sand cannot be bent due to gravity. + */ + public static Material selectMaterial(final Material mat) { + if (mat == Material.SAND) { + return Material.SANDSTONE; + } else if (mat == Material.GRAVEL) { + return Material.STONE; + } else { + return mat; + } + } + + public Material selectMaterialForRepresenter(final Material mat) { + final Material tempMat = selectMaterial(mat); + final Random rand = new Random(); + if (!isEarthbendable(tempMat, true, true, true) && !this.isMetalbendable(tempMat)) { + if (this.currentBlocks.size() < 1) { + return Material.DIRT; + } else { + return this.currentBlocks.get(rand.nextInt(this.currentBlocks.size())).getType(); + } + } + return tempMat; + } + + /** + * Determines if a player is trying to grab an EarthSmash. A player is + * trying to grab an EarthSmash if they are staring at it and holding shift. + */ + private EarthSmash aimingAtSmashCheck(final Player player, final State reqState) { + if (!this.allowGrab) { + return null; + } + + final List blocks = GeneralMethods.getBlocksAroundPoint(GeneralMethods.getTargetedLocation(player, this.grabRange, getTransparentMaterials()), 1); + for (final EarthSmash smash : getAbilities(EarthSmash.class)) { + if (reqState == null || smash.state == reqState) { + for (final Block block : blocks) { + if (block == null || smash.getLocation() == null) { + continue; + } + if (block.getLocation().getWorld() == smash.location.getWorld() && block.getLocation().distanceSquared(smash.location) <= Math.pow(this.grabDetectionRadius, 2)) { + return smash; + } + } + } + } + return null; + } + + /** + * This method handles any collision between an EarthSmash and the + * surrounding entities, the method only applies to earthsmashes that have + * already been shot. + */ + public void shootingCollisionDetection() { + final List entities = GeneralMethods.getEntitiesAroundPoint(this.location, this.hitRadius); + for (final Entity entity : entities) { + if (entity instanceof LivingEntity && entity != this.player && !this.affectedEntities.contains(entity)) { + if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { + continue; + } + this.affectedEntities.add(entity); + final double damage = this.currentBlocks.size() / 13.0 * this.damage; + DamageHandler.damageEntity(entity, damage, this); + final Vector travelVec = GeneralMethods.getDirection(this.location, entity.getLocation()); + GeneralMethods.setVelocity(this, entity, travelVec.setY(this.knockup).normalize().multiply(this.knockback)); + } + } + } + + /** + * EarthSmash to EarthSmash collision can only happen when one of the + * Smashes have been shot by a player. If we find out that one of them have + * collided then we want to return since a smash can only remove 1 at a + * time. + */ + public void smashToSmashCollisionDetection() { + for (final EarthSmash smash : getAbilities(EarthSmash.class)) { + if (smash.location != null && smash != this && smash.location.getWorld() == this.location.getWorld() && smash.location.distanceSquared(this.location) < Math.pow(this.flightDetectionRadius, 2)) { + smash.remove(); + this.remove(); + return; + } + } + } + + /** + * Determines whether or not a player is trying to fly ontop of an + * EarthSmash. A player is considered "flying" if they are standing ontop of + * the earthsmash and holding shift. + */ + private static EarthSmash flyingInSmashCheck(final Player player) { + for (final EarthSmash smash : getAbilities(EarthSmash.class)) { + if (!smash.allowFlight) { + continue; + } + // Check to see if the player is standing on top of the smash. + if (smash.state == State.LIFTED) { + if (smash.location.getWorld().equals(player.getWorld()) && smash.location.clone().add(0, 2, 0).distanceSquared(player.getLocation()) <= Math.pow(smash.flightDetectionRadius, 2)) { + return smash; + } + } + } + return null; + } + + /** + * A BlockRepresenter is used to keep track of each of the individual types + * of blocks that are attached to an EarthSmash. Without the representer + * then an EarthSmash can only be made up of 1 material at a time. For + * example, an ESmash that is entirely dirt, coalore, or sandstone. Using + * the representer will allow all the materials to be mixed together. + */ + public class BlockRepresenter { + private int x, y, z; + private Material type; + private BlockData data; + + public BlockRepresenter(final int x, final int y, final int z, final Material type, final BlockData data) { + this.x = x; + this.y = y; + this.z = z; + this.type = type; + this.data = data; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public int getZ() { + return this.z; + } + + public Material getType() { + return this.type; + } + + public BlockData getData() { + return this.data; + } + + public void setX(final int x) { + this.x = x; + } + + public void setY(final int y) { + this.y = y; + } + + public void setZ(final int z) { + this.z = z; + } + + public void setType(final Material type) { + this.type = type; + } + + public void setData(final BlockData data) { + this.data = data; + } + + @Override + public String toString() { + return this.x + ", " + this.y + ", " + this.z + ", " + this.type.toString(); + } + } + + public class Pair { + private F first; // first member of pair. + private S second; // second member of pair. + + public Pair(final F first, final S second) { + this.first = first; + this.second = second; + } + + public void setFirst(final F first) { + this.first = first; + } + + public void setSecond(final S second) { + this.second = second; + } + + public F getFirst() { + return this.first; + } + + public S getSecond() { + return this.second; + } + } + + @Override + public String getName() { + return "EarthSmash"; + } + + @Override + public Location getLocation() { + return this.location; + } + + @Override + public long getCooldown() { + return this.cooldown; + } + + @Override + public boolean isSneakAbility() { + return true; + } + + @Override + public boolean isHarmlessAbility() { + return false; + } + + @Override + public List getLocations() { + final ArrayList locations = new ArrayList<>(); + for (final TempBlock tblock : this.affectedBlocks) { + locations.add(tblock.getLocation()); + } + return locations; + } + + public boolean isAllowGrab() { + return this.allowGrab; + } + + public void setAllowGrab(final boolean allowGrab) { + this.allowGrab = allowGrab; + } + + public boolean isAllowFlight() { + return this.allowFlight; + } + + public void setAllowFlight(final boolean allowFlight) { + this.allowFlight = allowFlight; + } + + public int getAnimationCounter() { + return this.animationCounter; + } + + public void setAnimationCounter(final int animationCounter) { + this.animationCounter = animationCounter; + } + + public int getProgressCounter() { + return this.progressCounter; + } + + public void setProgressCounter(final int progressCounter) { + this.progressCounter = progressCounter; + } + + public int getRequiredBendableBlocks() { + return this.requiredBendableBlocks; + } + + public void setRequiredBendableBlocks(final int requiredBendableBlocks) { + this.requiredBendableBlocks = requiredBendableBlocks; + } + + public int getMaxBlocksToPassThrough() { + return this.maxBlocksToPassThrough; + } + + public void setMaxBlocksToPassThrough(final int maxBlocksToPassThrough) { + this.maxBlocksToPassThrough = maxBlocksToPassThrough; + } + + public long getDelay() { + return this.delay; + } + + public void setDelay(final long delay) { + this.delay = delay; + } + + public long getChargeTime() { + return this.chargeTime; + } + + public void setChargeTime(final long chargeTime) { + this.chargeTime = chargeTime; + } + + public long getDuration() { + return this.duration; + } + + public void setDuration(final long duration) { + this.duration = duration; + } + + public long getFlightDuration() { + return this.flightDuration; + } + + public void setFlightDuration(final long flightDuration) { + this.flightDuration = flightDuration; + } + + public long getFlightStartTime() { + return this.flightStartTime; + } + + public void setFlightStartTime(final long flightStartTime) { + this.flightStartTime = flightStartTime; + } + + public long getShootAnimationInterval() { + return this.shootAnimationInterval; + } + + public void setShootAnimationInterval(final long shootAnimationInterval) { + this.shootAnimationInterval = shootAnimationInterval; + } + + public long getFlightAnimationInterval() { + return this.flightAnimationInterval; + } + + public void setFlightAnimationInterval(final long flightAnimationInterval) { + this.flightAnimationInterval = flightAnimationInterval; + } + + public long getLiftAnimationInterval() { + return this.liftAnimationInterval; + } + + public void setLiftAnimationInterval(final long liftAnimationInterval) { + this.liftAnimationInterval = liftAnimationInterval; + } + + public double getGrabRange() { + return this.grabRange; + } + + public void setGrabRange(final double grabRange) { + this.grabRange = grabRange; + } + + public double getSelectRange() { + return this.selectRange; + } + + public void setSelectRange(final double selectRange) { + this.selectRange = selectRange; + } + + public double getShootRange() { + return this.shootRange; + } + + public void setShootRange(final double shootRange) { + this.shootRange = shootRange; + } + + public double getDamage() { + return this.damage; + } + + public void setDamage(final double damage) { + this.damage = damage; + } + + public double getKnockback() { + return this.knockback; + } + + public void setKnockback(final double knockback) { + this.knockback = knockback; + } + + public double getKnockup() { + return this.knockup; + } + + public void setKnockup(final double knockup) { + this.knockup = knockup; + } + + public double getFlightSpeed() { + return this.flightSpeed; + } + + public void setFlightSpeed(final double flightSpeed) { + this.flightSpeed = flightSpeed; + } + + public double getGrabbedDistance() { + return this.grabbedDistance; + } + + public void setGrabbedDistance(final double grabbedDistance) { + this.grabbedDistance = grabbedDistance; + } + + public double getGrabDetectionRadius() { + return this.grabDetectionRadius; + } + + public void setGrabDetectionRadius(final double grabDetectionRadius) { + this.grabDetectionRadius = grabDetectionRadius; + } + + public double getFlightDetectionRadius() { + return this.flightDetectionRadius; + } + + public void setFlightDetectionRadius(final double flightDetectionRadius) { + this.flightDetectionRadius = flightDetectionRadius; + } + + public State getState() { + return this.state; + } + + public void setState(final State state) { + this.state = state; + } + + public Block getOrigin() { + return this.origin; + } + + public void setOrigin(final Block origin) { + this.origin = origin; + } + + public Location getDestination() { + return this.destination; + } + + public void setDestination(final Location destination) { + this.destination = destination; + } + + public ArrayList getAffectedEntities() { + return this.affectedEntities; + } + + public ArrayList getCurrentBlocks() { + return this.currentBlocks; + } + + public ArrayList getAffectedBlocks() { + return this.affectedBlocks; + } + + public void setCooldown(final long cooldown) { + this.cooldown = cooldown; + } + + public void setLocation(final Location location) { + this.location = location; + } + +} diff --git a/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java b/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java index 12330e89..f821ec51 100644 --- a/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java +++ b/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java @@ -102,7 +102,7 @@ public class RaiseEarth extends EarthAbility { private boolean canInstantiate() { for (final Block block : this.affectedBlocks.keySet()) { - if (!this.isEarthbendable(block) || TempBlock.isTempBlock(block)) { + if (!this.isEarthbendable(block) || (TempBlock.isTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block))) { return false; } } diff --git a/src/com/projectkorra/projectkorra/earthbending/Ripple.java b/src/com/projectkorra/projectkorra/earthbending/Ripple.java index 25fc4bb2..74c33920 100644 --- a/src/com/projectkorra/projectkorra/earthbending/Ripple.java +++ b/src/com/projectkorra/projectkorra/earthbending/Ripple.java @@ -285,7 +285,7 @@ public class Ripple extends EarthAbility { final Vector vector = this.direction.clone(); vector.setY(.5); final double knock = this.bPlayer.isAvatarState() ? AvatarState.getValue(this.knockback) : this.knockback; - entity.setVelocity(vector.clone().normalize().multiply(knock)); + GeneralMethods.setVelocity(this, entity, vector.clone().normalize().multiply(knock)); AirAbility.breakBreathbendingHold(entity); } diff --git a/src/com/projectkorra/projectkorra/earthbending/combo/EarthPillars.java b/src/com/projectkorra/projectkorra/earthbending/combo/EarthPillars.java index 611c63f4..406fdbad 100644 --- a/src/com/projectkorra/projectkorra/earthbending/combo/EarthPillars.java +++ b/src/com/projectkorra/projectkorra/earthbending/combo/EarthPillars.java @@ -100,8 +100,7 @@ public class EarthPillars extends EarthAbility implements ComboAbility { if (lent instanceof Player && !((Player) lent).isOnline()) { continue; } - - lent.setVelocity(new Vector(0, this.knockup, 0)); + GeneralMethods.setVelocity(this, lent, new Vector(0, this.knockup, 0)); } if (this.damaging) { DamageHandler.damageEntity(lent, this.damage, this); diff --git a/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurge.java b/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurge.java index 8d969430..81ada408 100644 --- a/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurge.java +++ b/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurge.java @@ -236,7 +236,7 @@ public class LavaSurge extends LavaAbility { x = (this.random.nextBoolean()) ? -x : x; z = (this.random.nextBoolean()) ? -z : z; - fbs.setVelocity(this.direction.clone().add(new Vector(x, 0.2, z)).multiply(1.2)); + GeneralMethods.setVelocity(this, fbs, this.direction.clone().add(new Vector(x, 0.2, z)).multiply(1.2)); fbs.setDropItem(false); for (final Block b : this.fracture) { @@ -244,7 +244,7 @@ public class LavaSurge extends LavaAbility { final FallingBlock fb = GeneralMethods.spawnFallingBlock(b.getLocation().add(new Vector(0, 1, 0)), Material.MAGMA_BLOCK, Material.MAGMA_BLOCK.createBlockData()); ALL_FALLING_BLOCKS.add(fb); this.fallingBlocks.add(fb); - fb.setVelocity(this.direction.clone().add(new Vector(this.random.nextDouble() / 10, 0.1, this.random.nextDouble() / 10)).multiply(1.2)); + GeneralMethods.setVelocity(this, fb, this.direction.clone().add(new Vector(this.random.nextDouble() / 10, 0.1, this.random.nextDouble() / 10)).multiply(1.2)); fb.setDropItem(false); } } @@ -258,7 +258,7 @@ public class LavaSurge extends LavaAbility { if (e.getEntityId() != this.player.getEntityId()) { DamageHandler.damageEntity(e, this.impactDamage, this); e.setFireTicks(100); - GeneralMethods.setVelocity(e, this.direction.clone()); + GeneralMethods.setVelocity(this, e, this.direction.clone()); } } } diff --git a/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurgeWave.java b/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurgeWave.java index 082aef15..dc01e60b 100644 --- a/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurgeWave.java +++ b/src/com/projectkorra/projectkorra/earthbending/lava/LavaSurgeWave.java @@ -207,7 +207,7 @@ public class LavaSurgeWave extends LavaAbility { if (knockback) { final Vector dir = direction.clone(); dir.setY(dir.getY() * this.verticalPush); - entity.setVelocity(entity.getVelocity().clone().add(dir.clone().multiply(this.horizontalPush))); + GeneralMethods.setVelocity(this, entity, entity.getVelocity().clone().add(dir.clone().multiply(this.horizontalPush))); entity.setFallDistance(0); if (entity.getFireTicks() > 0) { diff --git a/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java b/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java index 3dde48e6..a06443fc 100644 --- a/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java +++ b/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java @@ -156,7 +156,7 @@ public class MetalClips extends MetalAbility { vector = GeneralMethods.getDirection(this.player.getLocation(), GeneralMethods.getTargetedLocation(this.player, this.range)); } - item.setVelocity(vector.normalize().add(new Vector(0, 0.1, 0).multiply(1.2))); + GeneralMethods.setVelocity(this, item, vector.normalize().add(new Vector(0, 0.1, 0).multiply(1.2))); this.trackedIngots.add(item); this.player.getInventory().removeItem(is); } @@ -228,7 +228,7 @@ public class MetalClips extends MetalAbility { dz = target.getZ() - location.getZ(); final Vector vector = new Vector(dx, dy, dz); vector.normalize(); - this.targetEntity.setVelocity(vector.multiply(this.metalClipsCount / 2D)); + GeneralMethods.setVelocity(this, this.targetEntity, vector.multiply(this.metalClipsCount / 2D)); this.remove(); } @@ -342,7 +342,7 @@ public class MetalClips extends MetalAbility { final Item iron = (Item) entity; if (Arrays.asList(METAL_ITEMS).contains(iron.getItemStack().getType())) { - iron.setVelocity(vector.normalize().multiply(this.magnetSpeed).add(new Vector(0, 0.2, 0))); + GeneralMethods.setVelocity(this, iron, vector.normalize().multiply(this.magnetSpeed).add(new Vector(0, 0.2, 0))); } } } @@ -367,7 +367,7 @@ public class MetalClips extends MetalAbility { final Vector vector = GeneralMethods.getDirection(this.targetEntity.getLocation(), this.player.getLocation()); if (distance > 0.5) { - this.targetEntity.setVelocity(vector.normalize().multiply(0.2)); + GeneralMethods.setVelocity(this, this.targetEntity, vector.normalize().multiply(0.2)); } } @@ -384,7 +384,7 @@ public class MetalClips extends MetalAbility { final Vector vector = GeneralMethods.getDirection(this.targetEntity.getLocation(), GeneralMethods.getTargetedLocation(this.player, 10)); if (distance > 1.2) { - this.targetEntity.setVelocity(vector.normalize().multiply(0.2)); + GeneralMethods.setVelocity(this, this.targetEntity, vector.normalize().multiply(0.2)); } } @@ -401,9 +401,9 @@ public class MetalClips extends MetalAbility { final Vector vector = GeneralMethods.getDirection(oldLocation, GeneralMethods.getTargetedLocation(this.player, 10)); if (distance > 1.2) { - this.targetEntity.setVelocity(vector.normalize().multiply(.5)); + GeneralMethods.setVelocity(this, this.targetEntity, vector.normalize().multiply(.5)); } else { - this.targetEntity.setVelocity(new Vector(0, 0, 0)); + GeneralMethods.setVelocity(this, this.targetEntity, new Vector(0, 0, 0)); } this.targetEntity.setFallDistance(0); diff --git a/src/com/projectkorra/projectkorra/event/AbilityVelocityAffectEntityEvent.java b/src/com/projectkorra/projectkorra/event/AbilityVelocityAffectEntityEvent.java new file mode 100644 index 00000000..e2cf2efd --- /dev/null +++ b/src/com/projectkorra/projectkorra/event/AbilityVelocityAffectEntityEvent.java @@ -0,0 +1,75 @@ +package com.projectkorra.projectkorra.event; + +import org.bukkit.entity.Entity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.util.Vector; + +import com.projectkorra.projectkorra.ability.Ability; + +/** + * Cancellable event called when an ability would push or alter the velocity of + * an entity. + * + * the entity can be changed, vector can be modified, and the ability that + * caused the change can be accessed. + * + * @author dNiym + * + */ + +public class AbilityVelocityAffectEntityEvent extends Event implements Cancellable { + + Entity affected; + Vector velocity; + Ability ability; + boolean cancelled = false; + + private static final HandlerList handlers = new HandlerList(); + + public AbilityVelocityAffectEntityEvent(Ability ability, Entity entity, Vector vector) { + this.affected = entity; + this.ability = ability; + this.velocity = vector; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public Entity getAffected() { + return affected; + } + + public void setAffected(Entity affected) { + this.affected = affected; + } + + public Vector getVelocity() { + return velocity; + } + + public void setVelocity(Vector velocity) { + this.velocity = velocity; + } + + public Ability getAbility() { + return ability; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/com/projectkorra/projectkorra/event/PlayerStanceChangeEvent.java b/src/com/projectkorra/projectkorra/event/PlayerStanceChangeEvent.java new file mode 100644 index 00000000..33e7e03e --- /dev/null +++ b/src/com/projectkorra/projectkorra/event/PlayerStanceChangeEvent.java @@ -0,0 +1,41 @@ +package com.projectkorra.projectkorra.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class PlayerStanceChangeEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + + private final Player player; + private final String oldStance; + private final String newStance; + + public PlayerStanceChangeEvent(final Player player, final String oldStance, final String newStance) { + this.player = player; + this.oldStance = oldStance; + this.newStance = newStance; + } + + public Player getPlayer() { + return this.player; + } + + public String getOldStance() { + return this.oldStance; + } + + public String getNewStance() { + return this.newStance; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } +} diff --git a/src/com/projectkorra/projectkorra/firebending/FireBlast.java b/src/com/projectkorra/projectkorra/firebending/FireBlast.java index c3ea453b..aad1d81f 100644 --- a/src/com/projectkorra/projectkorra/firebending/FireBlast.java +++ b/src/com/projectkorra/projectkorra/firebending/FireBlast.java @@ -110,14 +110,14 @@ public class FireBlast extends FireAbility { } private void applyModifiers(double damage, double range) { - int damageMod = 0; - int rangeMod = 0; + double damageMod = 0; + double rangeMod = 0; - damageMod = (int) (this.getDayFactor(damage) - damage); - rangeMod = (int) (this.getDayFactor(range) - range); + damageMod = this.getDayFactor(damage) - damage; + rangeMod = this.getDayFactor(range) - range; - damageMod = (int) (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getDamageFactor() * damage - damage) + damageMod : damageMod); - rangeMod = (int) (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getRangeFactor() * range - range) + rangeMod : rangeMod); + damageMod = bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getDamageFactor() * damage - damage) + damageMod : damageMod; + rangeMod = bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getRangeFactor() * range - range) + rangeMod : rangeMod; this.range += rangeMod; this.damage += damageMod; @@ -166,6 +166,10 @@ public class FireBlast extends FireAbility { } public boolean checkLocation(Block block) { + if (block.isLiquid()) { + this.remove(); + return false; + } if (!block.isPassable()) { if (block.getType() == Material.FURNACE && this.powerFurnace) { final Furnace furnace = (Furnace) block.getState(); @@ -199,9 +203,9 @@ public class FireBlast extends FireAbility { private void affect(final Entity entity) { if (entity.getUniqueId() != this.player.getUniqueId() && !GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) && !((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { if (this.bPlayer.isAvatarState()) { - GeneralMethods.setVelocity(entity, this.direction.clone().multiply(AvatarState.getValue(this.knockback))); + GeneralMethods.setVelocity(this, entity, this.direction.clone().multiply(AvatarState.getValue(this.knockback))); } else { - GeneralMethods.setVelocity(entity, this.direction.clone().multiply(this.knockback)); + GeneralMethods.setVelocity(this, entity, this.direction.clone().multiply(this.knockback)); } if (entity instanceof LivingEntity) { entity.setFireTicks((int) (this.fireTicks * 20)); diff --git a/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java b/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java index 8725a5dc..3a18c27f 100644 --- a/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java +++ b/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java @@ -89,18 +89,18 @@ public class FireBlastCharged extends FireAbility { private void applyModifiers() { long chargeTimeMod = 0; - int damageMod = 0; - int rangeMod = 0; + double damageMod = 0; + double rangeMod = 0; if (isDay(player.getWorld())) { - chargeTimeMod = (long) (this.chargeTime / getDayFactor()) - this.chargeTime; - damageMod = (int) (this.getDayFactor(this.maxDamage) - this.maxDamage); - rangeMod = (int) (this.getDayFactor(this.range) - this.range); + chargeTimeMod = (long) (this.chargeTime / getDayFactor() - this.chargeTime); + damageMod = this.getDayFactor(this.maxDamage) - this.maxDamage; + rangeMod = this.getDayFactor(this.range) - this.range; } chargeTimeMod = (long) (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (chargeTime / BlueFireAbility.getCooldownFactor() - chargeTime) + chargeTimeMod : chargeTimeMod); - damageMod = (int) (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getDamageFactor() * maxDamage - maxDamage) + damageMod : damageMod); - rangeMod = (int) (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getRangeFactor() * range - range) + rangeMod : rangeMod); + damageMod = (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getDamageFactor() * maxDamage - maxDamage) + damageMod : damageMod); + rangeMod = (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getRangeFactor() * range - range) + rangeMod : rangeMod); if (this.bPlayer.isAvatarState()) { this.chargeTime = getConfig().getLong("Abilities.Avatar.AvatarState.Fire.FireBlast.Charged.ChargeTime"); diff --git a/src/com/projectkorra/projectkorra/firebending/FireJet.java b/src/com/projectkorra/projectkorra/firebending/FireJet.java index 8c382942..ded60a23 100644 --- a/src/com/projectkorra/projectkorra/firebending/FireJet.java +++ b/src/com/projectkorra/projectkorra/firebending/FireJet.java @@ -10,6 +10,7 @@ import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.airbending.AirSpout; @@ -57,7 +58,7 @@ public class FireJet extends FireAbility { final Block block = player.getLocation().getBlock(); if (isIgnitable(block) || ElementalAbility.isAir(block.getType()) || block.getType() == Material.STONE_SLAB || block.getType() == Material.ACACIA_SLAB || block.getType() == Material.BIRCH_SLAB || block.getType() == Material.DARK_OAK_SLAB || block.getType() == Material.JUNGLE_SLAB || block.getType() == Material.OAK_SLAB || block.getType() == Material.SPRUCE_SLAB || isIlluminationTorch(block) || this.bPlayer.isAvatarState()) { - player.setVelocity(player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed)); + GeneralMethods.setVelocity(this, player, player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed)); if (!canFireGrief()) { if (ElementalAbility.isAir(block.getType())) { createTempFire(block.getLocation()); @@ -102,7 +103,7 @@ public class FireJet extends FireAbility { } final Vector velocity = this.player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed * timefactor); - this.player.setVelocity(velocity); + GeneralMethods.setVelocity(this, this.player, velocity); this.player.setFallDistance(0); } } diff --git a/src/com/projectkorra/projectkorra/firebending/WallOfFire.java b/src/com/projectkorra/projectkorra/firebending/WallOfFire.java index a45bb920..bf8b0267 100644 --- a/src/com/projectkorra/projectkorra/firebending/WallOfFire.java +++ b/src/com/projectkorra/projectkorra/firebending/WallOfFire.java @@ -73,16 +73,16 @@ public class WallOfFire extends FireAbility { this.origin = GeneralMethods.getTargetedLocation(player, this.range); - int widthMod = 0; - int heightMod = 0; + double widthMod = 0; + double heightMod = 0; long durationMod = 0; - int damageMod = 0; + double damageMod = 0; if (isDay(player.getWorld())) { - widthMod = (int) this.getDayFactor(this.width) - this.width; - heightMod = (int) this.getDayFactor(this.height) - this.height; + widthMod = this.getDayFactor(this.width) - this.width; + heightMod = this.getDayFactor(this.height) - this.height; durationMod = ((long) this.getDayFactor(this.duration) - this.duration); - damageMod = (int) (this.getDayFactor(this.damage) - this.damage); + damageMod = this.getDayFactor(this.damage) - this.damage; } widthMod = (int) (bPlayer.canUseSubElement(SubElement.BLUE_FIRE) ? (BlueFireAbility.getRangeFactor() * width - width) + widthMod : widthMod); @@ -121,7 +121,7 @@ public class WallOfFire extends FireAbility { } private void affect(final Entity entity) { - GeneralMethods.setVelocity(entity, new Vector(0, 0, 0)); + GeneralMethods.setVelocity(this, entity, new Vector(0, 0, 0)); if (entity instanceof LivingEntity) { final Block block = ((LivingEntity) entity).getEyeLocation().getBlock(); if (TempBlock.isTempBlock(block) && isIce(block)) { diff --git a/src/com/projectkorra/projectkorra/firebending/combo/FireComboStream.java b/src/com/projectkorra/projectkorra/firebending/combo/FireComboStream.java index de0a9917..628ae3fb 100644 --- a/src/com/projectkorra/projectkorra/firebending/combo/FireComboStream.java +++ b/src/com/projectkorra/projectkorra/firebending/combo/FireComboStream.java @@ -94,7 +94,15 @@ public class FireComboStream extends BukkitRunnable { } this.location.add(this.direction.normalize().multiply(this.speed)); - if (this.initialLocation.distanceSquared(this.location) > this.distance * this.distance) { + + try { + this.location.checkFinite(); + } catch (IllegalArgumentException e) { + this.remove(); + return; + } + + if (this.initialLocation.distanceSquared(this.location) > this.distance * this.distance || !Double.isFinite(this.collisionRadius)) { this.remove(); return; } else if (this.collides && this.checkCollisionCounter % this.checkCollisionDelay == 0) { @@ -136,7 +144,7 @@ public class FireComboStream extends BukkitRunnable { fireSpin.getAffectedEntities().add(entity); final double newKnockback = this.bPlayer.isAvatarState() ? this.knockback + 0.5 : this.knockback; DamageHandler.damageEntity(entity, this.damage, coreAbility); - entity.setVelocity(direction.normalize().multiply(newKnockback)); + GeneralMethods.setVelocity(coreAbility, entity, direction.normalize().multiply(newKnockback)); } } else if (coreAbility.getName().equalsIgnoreCase("JetBlaze")) { final JetBlaze jetBlaze = CoreAbility.getAbility(this.player, JetBlaze.class); diff --git a/src/com/projectkorra/projectkorra/object/Preset.java b/src/com/projectkorra/projectkorra/object/Preset.java index f57cf592..6817ba71 100644 --- a/src/com/projectkorra/projectkorra/object/Preset.java +++ b/src/com/projectkorra/projectkorra/object/Preset.java @@ -17,6 +17,7 @@ import org.bukkit.scheduler.BukkitRunnable; import com.projectkorra.projectkorra.BendingPlayer; import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ability.CoreAbility; +import com.projectkorra.projectkorra.board.BendingBoardManager; import com.projectkorra.projectkorra.configuration.ConfigManager; import com.projectkorra.projectkorra.storage.DBConnection; @@ -146,6 +147,7 @@ public class Preset { } } bPlayer.setAbilities(abilities); + BendingBoardManager.updateAllSlots(player); return boundAll; } @@ -256,6 +258,7 @@ public class Preset { } } bPlayer.setAbilities(abilities); + BendingBoardManager.updateAllSlots(player); return boundAll; } return false; diff --git a/src/com/projectkorra/projectkorra/storage/DBConnection.java b/src/com/projectkorra/projectkorra/storage/DBConnection.java index e1f32d1a..58c7e1c9 100644 --- a/src/com/projectkorra/projectkorra/storage/DBConnection.java +++ b/src/com/projectkorra/projectkorra/storage/DBConnection.java @@ -68,6 +68,11 @@ public class DBConnection { final String query = "CREATE TABLE `pk_cooldowns` (uuid VARCHAR(36) NOT NULL, cooldown_id INTEGER NOT NULL, value BIGINT, PRIMARY KEY (uuid, cooldown_id));"; sql.modifyQuery(query, false); } + if (!sql.tableExists("pk_board")) { + ProjectKorra.log.info("Creating pk_board table"); + final String query = "CREATE TABLE `pk_board` (uuid VARCHAR(36) NOT NULL, enabled BOOLEAN NOT NULL, PRIMARY KEY (uuid));"; + sql.modifyQuery(query, false); + } } else { sql = new SQLite(ProjectKorra.log, "Establishing SQLite Connection.", "projectkorra.db", ProjectKorra.plugin.getDataFolder().getAbsolutePath()); if (((SQLite) sql).open() == null) { @@ -112,6 +117,11 @@ public class DBConnection { final String query = "CREATE TABLE `pk_cooldowns` (uuid TEXT(36) NOT NULL, cooldown_id INTEGER NOT NULL, value BIGINT, PRIMARY KEY (uuid, cooldown_id));"; sql.modifyQuery(query, false); } + if (!sql.tableExists("pk_board")) { + ProjectKorra.log.info("Creating pk_board table"); + final String query = "CREATE TABLE `pk_board` (uuid TEXT(36) NOT NULL, enabled INTEGER NOT NULL, PRIMARY KEY (uuid));"; + sql.modifyQuery(query, false); + } } } diff --git a/src/com/projectkorra/projectkorra/util/BlockSource.java b/src/com/projectkorra/projectkorra/util/BlockSource.java index 5a56abbb..7c89bcf4 100644 --- a/src/com/projectkorra/projectkorra/util/BlockSource.java +++ b/src/com/projectkorra/projectkorra/util/BlockSource.java @@ -161,7 +161,7 @@ public class BlockSource { public static Block getSourceBlock(final Player player, final double range, final BlockSourceType sourceType, final ClickType clickType) { final BlockSourceInformation info = getValidBlockSourceInformation(player, range, sourceType, clickType); if (info != null) { - if (TempBlock.isTempBlock(info.getBlock()) && !WaterAbility.isBendableWaterTempBlock(info.getBlock())) { + if (TempBlock.isTempBlock(info.getBlock()) && !WaterAbility.isBendableWaterTempBlock(info.getBlock()) && !EarthAbility.isBendableEarthTempBlock(info.getBlock())) { return null; } return info.getBlock(); diff --git a/src/com/projectkorra/projectkorra/util/TempBlock.java b/src/com/projectkorra/projectkorra/util/TempBlock.java index f535d163..900d4b60 100644 --- a/src/com/projectkorra/projectkorra/util/TempBlock.java +++ b/src/com/projectkorra/projectkorra/util/TempBlock.java @@ -53,7 +53,7 @@ public class TempBlock { public TempBlock(final Block block, final BlockData newData, final long revertTime) { this.block = block; this.newData = newData; - this.setRevertTime(revertTime); + if (instances.containsKey(block)) { final TempBlock temp = instances.get(block); if (!newData.equals(temp.block.getBlockData())) { @@ -64,12 +64,15 @@ public class TempBlock { instances.put(block, temp); } else { this.state = block.getState(); + if (this.state instanceof Container || this.state.getType() == Material.JUKEBOX) { return; } instances.put(block, this); block.setBlockData(newData, GeneralMethods.isLightEmitting(newData.getMaterial())); } + + this.setRevertTime(revertTime); } public static TempBlock get(final Block block) { @@ -166,7 +169,7 @@ public class TempBlock { } public void setRevertTime(final long revertTime) { - if(revertTime <= 0) { + if(revertTime <= 0 || state instanceof Container) { return; } diff --git a/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java b/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java index 6ddbac66..883154b8 100644 --- a/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java +++ b/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java @@ -207,7 +207,7 @@ public class OctopusForm extends WaterAbility { } final double knock = this.bPlayer.isAvatarState() ? AvatarState.getValue(this.knockback) : this.knockback; - entity.setVelocity(GeneralMethods.getDirection(this.player.getLocation(), location).normalize().multiply(knock)); + GeneralMethods.setVelocity(this, entity, GeneralMethods.getDirection(this.player.getLocation(), location).normalize().multiply(knock)); if (entity instanceof LivingEntity) { DamageHandler.damageEntity(entity, this.damage, this); diff --git a/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java b/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java index 08f181a0..fdf5f571 100644 --- a/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java +++ b/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java @@ -377,7 +377,7 @@ public class SurgeWave extends WaterAbility { } final Vector dir = direction.clone(); dir.setY(dir.getY() * this.knockup); - GeneralMethods.setVelocity(entity, entity.getVelocity().clone().add(dir.clone().multiply(this.getNightFactor(this.knockback)))); + GeneralMethods.setVelocity(this, entity, entity.getVelocity().clone().add(dir.clone().multiply(this.getNightFactor(this.knockback)))); entity.setFallDistance(0); if (entity.getFireTicks() > 0) { diff --git a/src/com/projectkorra/projectkorra/waterbending/Torrent.java b/src/com/projectkorra/projectkorra/waterbending/Torrent.java index c93e3e83..c9d14e4f 100644 --- a/src/com/projectkorra/projectkorra/waterbending/Torrent.java +++ b/src/com/projectkorra/projectkorra/waterbending/Torrent.java @@ -591,7 +591,7 @@ public class Torrent extends WaterAbility { velocity.setZ(vec.getY()); } - GeneralMethods.setVelocity(entity, velocity); + GeneralMethods.setVelocity(this, entity, velocity); entity.setFallDistance(0); if (entity instanceof LivingEntity) { final double damageDealt = this.getNightFactor(this.deflectDamage); @@ -611,7 +611,7 @@ public class Torrent extends WaterAbility { direction.setY(this.knockup); } if (!this.freeze) { - entity.setVelocity(direction.multiply(this.knockback)); + GeneralMethods.setVelocity(this, entity, direction.multiply(this.knockback)); } if (entity instanceof LivingEntity && !this.hurtEntities.contains(entity)) { double damageDealt = this.getNightFactor(this.damage); diff --git a/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java b/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java index 664f7a50..e1c55e09 100644 --- a/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java +++ b/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java @@ -180,7 +180,7 @@ public class TorrentWave extends WaterAbility { final Vector direction = GeneralMethods.getDirection(this.origin, entity.getLocation()); direction.setY(0); direction.normalize(); - entity.setVelocity(entity.getVelocity().clone().add(direction.multiply(this.knockback))); + GeneralMethods.setVelocity(this, entity, entity.getVelocity().clone().add(direction.multiply(this.knockback))); } @Override diff --git a/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java b/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java index 2b067176..0a120065 100644 --- a/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java +++ b/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java @@ -283,7 +283,7 @@ public class WaterManipulation extends WaterAbility { } final Location location = this.player.getEyeLocation(); final Vector vector = location.getDirection(); - entity.setVelocity(vector.normalize().multiply(this.knockback)); + GeneralMethods.setVelocity(this, entity, vector.normalize().multiply(this.knockback)); if (this.bPlayer.isAvatarState()) { this.damage = getConfig().getDouble("Abilities.Avatar.AvatarState.Water.WaterManipulation.Damage"); @@ -364,7 +364,7 @@ public class WaterManipulation extends WaterAbility { AFFECTED_BLOCKS.put(block, block); } if (PhaseChange.getFrozenBlocksAsBlock().contains(block)) { - PhaseChange.getFrozenBlocksAsBlock().remove(block); + PhaseChange.thaw(block); } new TempBlock(block, Material.WATER); } else { diff --git a/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java b/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java index e997ce09..2f84bdfe 100644 --- a/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java +++ b/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java @@ -299,8 +299,7 @@ public class WaterSpoutWave extends WaterAbility { if (this.bPlayer.isAvatarState()) { currentSpeed = this.getNightFactor(this.speed); } - - this.player.setVelocity(this.player.getEyeLocation().getDirection().normalize().multiply(currentSpeed)); + GeneralMethods.setVelocity(this, this.player, this.player.getEyeLocation().getDirection().normalize().multiply(currentSpeed)); for (final Block block : GeneralMethods.getBlocksAroundPoint(this.player.getLocation().add(0, -1, 0), this.waveRadius)) { if (ElementalAbility.isAir(block.getType()) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { if (this.iceWave) { @@ -372,7 +371,7 @@ public class WaterSpoutWave extends WaterAbility { final BukkitRunnable br = new BukkitRunnable() { @Override public void run() { - WaterSpoutWave.this.createBlock(block, mat); + WaterSpoutWave.this.createBlock(block, block.getLocation().distance(player.getLocation()) >= 1.6 ? mat : Material.WATER); } }; br.runTaskLater(ProjectKorra.plugin, delay); diff --git a/src/com/projectkorra/projectkorra/waterbending/blood/Bloodbending.java b/src/com/projectkorra/projectkorra/waterbending/blood/Bloodbending.java index fc203eec..dcf503f2 100644 --- a/src/com/projectkorra/projectkorra/waterbending/blood/Bloodbending.java +++ b/src/com/projectkorra/projectkorra/waterbending/blood/Bloodbending.java @@ -153,7 +153,7 @@ public class Bloodbending extends BloodAbility { vector = GeneralMethods.getDirection(location, GeneralMethods.getTargetedLocation(this.player, location.distance(target))); } vector.normalize(); - entity.setVelocity(vector.multiply(this.knockback)); + GeneralMethods.setVelocity(this, entity, vector.multiply(this.knockback)); new HorizontalVelocityTracker(entity, this.player, 200, this); } this.remove(); @@ -220,7 +220,7 @@ public class Bloodbending extends BloodAbility { continue; } if (entity instanceof LivingEntity) { - entity.setVelocity(this.vector); + GeneralMethods.setVelocity(this, entity, this.vector); new TempPotionEffect((LivingEntity) entity, effect); entity.setFallDistance(0); if (entity instanceof Creature) { @@ -281,7 +281,7 @@ public class Bloodbending extends BloodAbility { this.vector = new Vector(0, 0, 0); } - this.target.setVelocity(this.vector); + GeneralMethods.setVelocity(this, this.target, this.vector); new TempPotionEffect((LivingEntity) this.target, effect); this.target.setFallDistance(0); diff --git a/src/com/projectkorra/projectkorra/waterbending/combo/IceWave.java b/src/com/projectkorra/projectkorra/waterbending/combo/IceWave.java index ef29923d..57066ca0 100644 --- a/src/com/projectkorra/projectkorra/waterbending/combo/IceWave.java +++ b/src/com/projectkorra/projectkorra/waterbending/combo/IceWave.java @@ -27,6 +27,10 @@ public class IceWave extends IceAbility implements ComboAbility { public IceWave(final Player player) { super(player); + if (!hasAbility(player, WaterSpoutWave.class)) { + return; + } + if (!this.bPlayer.canBendIgnoreBindsCooldowns(this)) { return; } diff --git a/src/com/projectkorra/projectkorra/waterbending/ice/IceSpikePillar.java b/src/com/projectkorra/projectkorra/waterbending/ice/IceSpikePillar.java index 55a497fc..13e11548 100644 --- a/src/com/projectkorra/projectkorra/waterbending/ice/IceSpikePillar.java +++ b/src/com/projectkorra/projectkorra/waterbending/ice/IceSpikePillar.java @@ -246,7 +246,7 @@ public class IceSpikePillar extends IceAbility { } private void affect(final LivingEntity entity) { - entity.setVelocity(this.thrownForce); + GeneralMethods.setVelocity(this, entity, this.thrownForce); DamageHandler.damageEntity(entity, this.damage, this); this.damaged.add(entity); diff --git a/src/com/projectkorra/projectkorra/waterbending/ice/PhaseChange.java b/src/com/projectkorra/projectkorra/waterbending/ice/PhaseChange.java index a406674b..2d1fc4fe 100644 --- a/src/com/projectkorra/projectkorra/waterbending/ice/PhaseChange.java +++ b/src/com/projectkorra/projectkorra/waterbending/ice/PhaseChange.java @@ -46,6 +46,7 @@ public class PhaseChange extends IceAbility { private final List active_types = new ArrayList<>(); private static Map PLAYER_BY_BLOCK = new HashMap<>(); + private static List BLOCKS = new ArrayList<>(); private final CopyOnWriteArrayList blocks = new CopyOnWriteArrayList<>(); private final Random r = new Random(); @@ -99,10 +100,12 @@ public class PhaseChange extends IceAbility { tb.revertBlock(); this.blocks.remove(tb); PLAYER_BY_BLOCK.remove(tb); + BLOCKS.remove(tb.getBlock()); } else if (tb.getLocation().distanceSquared(this.player.getLocation()) > (this.controlRadius * this.controlRadius)) { tb.revertBlock(); this.blocks.remove(tb); PLAYER_BY_BLOCK.remove(tb); + BLOCKS.remove(tb.getBlock()); } } } @@ -129,10 +132,12 @@ public class PhaseChange extends IceAbility { tb.revertBlock(); this.blocks.remove(tb); PLAYER_BY_BLOCK.remove(tb); + BLOCKS.remove(tb.getBlock()); } else if (tb.getLocation().distanceSquared(this.player.getLocation()) > (this.controlRadius * this.controlRadius)) { tb.revertBlock(); this.blocks.remove(tb); PLAYER_BY_BLOCK.remove(tb); + BLOCKS.remove(tb.getBlock()); } } } @@ -301,6 +306,7 @@ public class PhaseChange extends IceAbility { } this.blocks.add(tb); PLAYER_BY_BLOCK.put(tb, this.player); + BLOCKS.add(tb.getBlock()); playIcebendingSound(b.getLocation()); } @@ -382,7 +388,8 @@ public class PhaseChange extends IceAbility { new TempBlock(b, Material.AIR.createBlockData(), 120 * 1000L); } else { tb.revertBlock(); - new TempBlock(b, Material.SNOW.createBlockData(d -> ((Snow) d).setLayers(snow.getLayers() - 1)), 120 * 1000L); + snow.setLayers(snow.getLayers() - 1); + new TempBlock(b, snow, 120 * 1000L); } } } @@ -407,7 +414,7 @@ public class PhaseChange extends IceAbility { new TempBlock(b, Material.AIR.createBlockData(), 120 * 1000L); } else { snow.setLayers(snow.getLayers() - 1); - new TempBlock(b, Material.SNOW.createBlockData(d -> ((Snow) d).setLayers(snow.getLayers() - 1)), 120 * 1000L); + new TempBlock(b, snow, 120 * 1000L); } } @@ -432,6 +439,7 @@ public class PhaseChange extends IceAbility { return false; } PLAYER_BY_BLOCK.remove(tb); + BLOCKS.remove(tb.getBlock()); if (pc.getFrozenBlocks() != null) { pc.getFrozenBlocks().remove(tb); tb.revertBlock(); @@ -460,18 +468,14 @@ public class PhaseChange extends IceAbility { } public static List getFrozenBlocksAsBlock() { - final List list = new ArrayList<>(); - for (final TempBlock tb : PLAYER_BY_BLOCK.keySet()) { - final Block b = tb.getBlock(); - list.add(b); - } - return list; + return BLOCKS; } public void revertFrozenBlocks() { if (this.active_types.contains(PhaseChangeType.FREEZE)) { for (final TempBlock tb : this.blocks) { PLAYER_BY_BLOCK.remove(tb); + BLOCKS.remove(tb.getBlock()); tb.revertBlock(); } this.blocks.clear(); diff --git a/src/com/projectkorra/projectkorra/waterbending/multiabilities/WaterArmsWhip.java b/src/com/projectkorra/projectkorra/waterbending/multiabilities/WaterArmsWhip.java index 850ce95e..202a8022 100644 --- a/src/com/projectkorra/projectkorra/waterbending/multiabilities/WaterArmsWhip.java +++ b/src/com/projectkorra/projectkorra/waterbending/multiabilities/WaterArmsWhip.java @@ -114,7 +114,7 @@ public class WaterArmsWhip extends WaterAbility { waw.grabbed = false; if (waw.grabbedEntity != null) { GRABBED_ENTITIES.remove(waw.grabbedEntity); - waw.grabbedEntity.setVelocity(waw.grabbedEntity.getVelocity().multiply(2.5)); + GeneralMethods.setVelocity(this, waw.grabbedEntity, waw.grabbedEntity.getVelocity().multiply(2.5)); } return; } @@ -300,7 +300,7 @@ public class WaterArmsWhip extends WaterAbility { continue; } final Vector vector = endOfArm.toVector().subtract(entity.getLocation().toVector()); - entity.setVelocity(vector.multiply(this.pullMultiplier)); + GeneralMethods.setVelocity(this, entity, vector.multiply(this.pullMultiplier)); } break; case PUNCH: @@ -310,7 +310,7 @@ public class WaterArmsWhip extends WaterAbility { } final Vector vector = entity.getLocation().toVector().subtract(endOfArm.toVector()); - entity.setVelocity(vector.multiply(0.15)); + GeneralMethods.setVelocity(this, entity, vector.multiply(0.15)); if (entity instanceof LivingEntity) { if (entity.getEntityId() != this.player.getEntityId()) { this.hasDamaged = true; @@ -373,9 +373,9 @@ public class WaterArmsWhip extends WaterAbility { final Vector vector = new Vector(dx, dy, dz); if (distance > 0.5) { - this.grabbedEntity.setVelocity(vector.normalize().multiply(.65)); + GeneralMethods.setVelocity(this, this.grabbedEntity, vector.normalize().multiply(.65)); } else { - this.grabbedEntity.setVelocity(new Vector(0, 0, 0)); + GeneralMethods.setVelocity(this, this.grabbedEntity, new Vector(0, 0, 0)); } this.grabbedEntity.setFallDistance(0); @@ -392,7 +392,7 @@ public class WaterArmsWhip extends WaterAbility { } final Vector vector = this.player.getLocation().toVector().subtract(location.toVector()); - this.player.setVelocity(vector.multiply(-0.25)); + GeneralMethods.setVelocity(this, this.player, vector.multiply(-0.25)); this.player.setFallDistance(0); } } diff --git a/src/com/projectkorra/projectkorra/waterbending/passive/FastSwim.java b/src/com/projectkorra/projectkorra/waterbending/passive/FastSwim.java index 71a1f1fa..95ad6240 100644 --- a/src/com/projectkorra/projectkorra/waterbending/passive/FastSwim.java +++ b/src/com/projectkorra/projectkorra/waterbending/passive/FastSwim.java @@ -3,6 +3,7 @@ package com.projectkorra.projectkorra.waterbending.passive; import org.bukkit.Location; import org.bukkit.entity.Player; +import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.PassiveAbility; import com.projectkorra.projectkorra.ability.WaterAbility; @@ -57,7 +58,7 @@ public class FastSwim extends WaterAbility implements PassiveAbility { if (this.bPlayer.getBoundAbility() == null || (this.bPlayer.getBoundAbility() != null && !this.bPlayer.getBoundAbility().isSneakAbility())) { if (this.player.isSneaking()) { if (isWater(this.player.getLocation().getBlock()) && !this.bPlayer.isOnCooldown(this)) { - this.player.setVelocity(this.player.getEyeLocation().getDirection().clone().normalize().multiply(this.swimSpeed)); + GeneralMethods.setVelocity(this, this.player, this.player.getEyeLocation().getDirection().clone().normalize().multiply(this.swimSpeed)); } } else { this.bPlayer.addCooldown(this); diff --git a/src/plugin.yml b/src/plugin.yml index 6d1df07b..b19e7033 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -43,6 +43,7 @@ permissions: default: true description: Grants access to most abilities and basic commands. children: + bending.command.board: true bending.command.bind: true bending.command.display: true bending.command.toggle: true