TF-ProjectKorra/src/com/projectkorra/projectkorra/waterbending/Torrent.java
Christopher Martin 8d7f116c49
Include outstanding PR's and fix outstanding issues (#1069)
This PR moves over some outstanding PR's to the proper branch and resolves some extra issues. Thanks @xNuminousx!

## Additions
* Adds Surge interactions with Lava
    * Surge Wave and Surge Wall will both cause Lava to turn into TempBlock Cobblestone / Obsidian
    * Enabled via the new `Abilities.Water.Surge.Wave.SolidifyLava.Enabled` and `Abilities.Water.Surge.Wall.SolidifyLava.Enabled` config options. They both default to `true`
    * Duration of the created TempBlocks is set via the new `Abilities.Water.Surge.Wave.SolidifyLava.Duration` and `Abilities.Water.Surge.Wall.SolidifyLava.Duration` config options. They both default to `36000`

## Fixes
* Fixes DensityShift turning non-full blocks into Sand causing the player to get stuck in the ground. Now it will still prevent fall damage on non-full earthbendable blocks but will not turn them to Sand.
* Fixes EarthDome and potentially other combos from not respecting their `Enabled` config option
* Fixes players with usernames the same as ability names getting incorrect cooldowns applied. Resolves #1068 

## Misc. Changes
* Changes Water abilities that require sources to deactivate if their source is destroyed after selection occurs but before the ability starts
* Changes AirSuction origin selection to remove if the player gets too far away
* Changes AirSwipe streams to be independent of one another (i.e. one hitting a wall won't cause them all to stop)
* Reduces the default collision radius of AirSwipe and prevents entities from getting hit through corners
* Bumps the Spigot API version to 1.16
2020-07-19 16:37:50 -07:00

985 lines
28 KiB
Java

package com.projectkorra.projectkorra.waterbending;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
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.AirAbility;
import com.projectkorra.projectkorra.ability.WaterAbility;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
import com.projectkorra.projectkorra.waterbending.util.WaterReturn;
public class Torrent extends WaterAbility {
private static final double CLEANUP_RANGE = 50;
private static final Map<TempBlock, Pair<Player, Integer>> FROZEN_BLOCKS = new ConcurrentHashMap<>();
private boolean sourceSelected;
private boolean settingUp;
private boolean forming;
private boolean formed;
private boolean launch;
private boolean launching;
private boolean freeze;
private boolean revert;
private int layer;
private int maxLayer;
private int maxHits;
private int hits = 1;
private long time;
private long interval;
@Attribute(Attribute.COOLDOWN)
private long cooldown;
private long revertTime;
private double startAngle;
private double angle;
@Attribute(Attribute.RADIUS)
private double radius;
@Attribute(Attribute.KNOCKBACK)
private double knockback;
@Attribute(Attribute.KNOCKUP)
private double knockup;
@Attribute(Attribute.DAMAGE)
private double damage;
@Attribute("Successive" + Attribute.DAMAGE)
private double successiveDamage;
@Attribute("Deflect" + Attribute.DAMAGE)
private double deflectDamage;
@Attribute(Attribute.RANGE)
private double range;
@Attribute(Attribute.SELECT_RANGE)
private double selectRange;
private Block sourceBlock;
private TempBlock source;
private Location location;
private ArrayList<TempBlock> blocks;
private ArrayList<TempBlock> launchedBlocks;
private ArrayList<Entity> hurtEntities;
public Torrent(final Player player) {
super(player);
this.layer = 0;
this.startAngle = 0;
this.maxLayer = getConfig().getInt("Abilities.Water.Torrent.MaxLayer");
this.knockback = getConfig().getDouble("Abilities.Water.Torrent.Knockback");
this.angle = getConfig().getDouble("Abilities.Water.Torrent.Angle");
this.radius = getConfig().getDouble("Abilities.Water.Torrent.Radius");
this.knockup = getConfig().getDouble("Abilities.Water.Torrent.Knockup");
this.interval = getConfig().getLong("Abilities.Water.Torrent.Interval");
this.damage = getConfig().getDouble("Abilities.Water.Torrent.InitialDamage");
this.successiveDamage = getConfig().getDouble("Abilities.Water.Torrent.SuccessiveDamage");
this.maxHits = getConfig().getInt("Abilities.Water.Torrent.MaxHits");
this.deflectDamage = getConfig().getDouble("Abilities.Water.Torrent.DeflectDamage");
this.range = getConfig().getDouble("Abilities.Water.Torrent.Range");
this.selectRange = getConfig().getDouble("Abilities.Water.Torrent.SelectRange");
this.cooldown = getConfig().getLong("Abilities.Water.Torrent.Cooldown");
this.revert = getConfig().getBoolean("Abilities.Water.Torrent.Revert");
this.revertTime = getConfig().getLong("Abilities.Water.Torrent.RevertTime");
this.blocks = new ArrayList<>();
this.launchedBlocks = new ArrayList<>();
this.hurtEntities = new ArrayList<>();
final Torrent oldTorrent = getAbility(player, Torrent.class);
if (oldTorrent != null) {
if (!oldTorrent.sourceSelected) {
oldTorrent.use();
this.bPlayer.addCooldown("Torrent", oldTorrent.cooldown);
return;
} else {
oldTorrent.remove();
}
}
if (this.bPlayer.isOnCooldown("Torrent")) {
return;
}
if (this.bPlayer.isAvatarState()) {
this.knockback = getConfig().getDouble("Abilities.Avatar.AvatarState.Water.Torrent.Push");
this.damage = getConfig().getDouble("Abilities.Avatar.AvatarState.Water.Torrent.InitialDamage");
this.successiveDamage = getConfig().getDouble("Abilities.Avatar.AvatarState.Water.Torrent.SuccessiveDamage");
this.maxHits = getConfig().getInt("Abilities.Avatar.AvatarState.Water.Torrent.MaxHits");
}
this.time = System.currentTimeMillis();
this.sourceBlock = BlockSource.getWaterSourceBlock(player, this.selectRange, ClickType.LEFT_CLICK, true, true, this.bPlayer.canPlantbend());
if (this.sourceBlock != null && !GeneralMethods.isRegionProtectedFromBuild(this, this.sourceBlock.getLocation())) {
this.sourceSelected = true;
this.start();
}
}
private void freeze() {
if (this.layer == 0) {
return;
} else if (!this.bPlayer.canBendIgnoreBindsCooldowns(getAbility("PhaseChange"))) {
return;
}
final List<Block> ice = GeneralMethods.getBlocksAroundPoint(this.location, this.layer);
final List<Entity> trapped = GeneralMethods.getEntitiesAroundPoint(this.location, this.layer);
ICE_SETTING: for (final Block block : ice) {
if (isTransparent(this.player, block) && block.getType() != Material.ICE) {
for (final Entity entity : trapped) {
if (entity instanceof Player) {
if (Commands.invincible.contains(((Player) entity).getName())) {
return;
}
if (!getConfig().getBoolean("Properties.Water.FreezePlayerHead") && GeneralMethods.playerHeadIsInBlock((Player) entity, block)) {
continue ICE_SETTING;
}
if (!getConfig().getBoolean("Properties.Water.FreezePlayerFeet") && GeneralMethods.playerFeetIsInBlock((Player) entity, block)) {
continue ICE_SETTING;
}
}
}
final TempBlock tblock = new TempBlock(block, Material.ICE);
FROZEN_BLOCKS.put(tblock, Pair.of(this.player, this.getId()));
if (this.revert) {
tblock.setRevertTime(this.revertTime + (new Random().nextInt((500 + 500) + 1) - 500));
}
playIcebendingSound(block.getLocation());
}
}
}
@Override
public void progress() {
if (!this.bPlayer.canBendIgnoreCooldowns(this)) {
this.remove();
return;
} else if (!isWaterbendable(this.sourceBlock) && !this.settingUp && !this.forming && !this.formed && !this.launching) {
this.remove();
return;
}
if (System.currentTimeMillis() > this.time + this.interval) {
this.time = System.currentTimeMillis();
if (this.sourceSelected) {
if (this.sourceBlock.getLocation().getWorld() != this.player.getWorld()) {
this.remove();
return;
}
if (this.sourceBlock.getLocation().distanceSquared(this.player.getLocation()) > this.selectRange * this.selectRange) {
return;
}
if (this.player.isSneaking()) {
this.sourceSelected = false;
this.settingUp = true;
if (TempBlock.isTempBlock(this.sourceBlock)) {
final TempBlock origin = TempBlock.get(this.sourceBlock);
if (FROZEN_BLOCKS.containsKey(origin)) {
massThaw(origin);
} else if (isBendableWaterTempBlock(origin)) {
origin.revertBlock();
}
}
if (isPlant(this.sourceBlock) || isSnow(this.sourceBlock)) {
new PlantRegrowth(this.player, this.sourceBlock);
this.sourceBlock.setType(Material.AIR);
} else if (!GeneralMethods.isAdjacentToThreeOrMoreSources(this.sourceBlock)) {
this.sourceBlock.setType(Material.AIR);
}
this.source = new TempBlock(this.sourceBlock, Material.WATER);
this.location = this.sourceBlock.getLocation();
} else {
playFocusWaterEffect(this.sourceBlock);
return;
}
}
if (this.settingUp) {
if (!this.player.isSneaking()) {
this.location = this.source.getLocation();
this.remove();
return;
}
final Location eyeLoc = this.player.getEyeLocation();
final double startAngle = this.player.getEyeLocation().getDirection().angle(new Vector(1, 0, 0));
final double dx = this.radius * Math.cos(startAngle);
final double dy = 0;
final double dz = this.radius * Math.sin(startAngle);
final Location setup = eyeLoc.clone().add(dx, dy, dz);
if (!this.location.getWorld().equals(this.player.getWorld())) {
this.remove();
return;
} else if (this.location.distanceSquared(setup) > this.range * this.range) {
this.remove();
return;
}
if (this.location.getBlockY() > setup.getBlockY()) {
final Vector direction = new Vector(0, -1, 0);
this.location = this.location.clone().add(direction);
} else if (this.location.getBlockY() < setup.getBlockY()) {
final Vector direction = new Vector(0, 1, 0);
this.location = this.location.clone().add(direction);
} else {
final Vector direction = GeneralMethods.getDirection(this.location, setup).normalize();
this.location = this.location.clone().add(direction);
}
if (this.location.distanceSquared(setup) <= 1) {
this.settingUp = false;
this.source.revertBlock();
this.source = null;
this.forming = true;
} else if (!this.location.getBlock().equals(this.source.getLocation().getBlock())) {
this.source.revertBlock();
this.source = null;
final Block block = this.location.getBlock();
if (!isTransparent(this.player, block)) {
this.remove();
return;
}
this.source = new TempBlock(this.location.getBlock(), Material.WATER);
}
}
if (this.forming && !this.player.isSneaking()) {
this.location = this.player.getEyeLocation().add(this.radius, 0, 0);
this.remove();
return;
}
if (this.forming || this.formed) {
if ((new Random()).nextInt(4) == 0) {
playWaterbendingSound(this.location);
}
for (double theta = this.startAngle; theta < this.angle + this.startAngle; theta += 20) {
final Location loc = this.player.getEyeLocation();
final double phi = Math.toRadians(theta);
final double dx = Math.cos(phi) * this.radius;
final double dy = 0;
final double dz = Math.sin(phi) * this.radius;
loc.add(dx, dy, dz);
if (isWater(loc.getBlock()) && GeneralMethods.isAdjacentToThreeOrMoreSources(loc.getBlock())) {
ParticleEffect.WATER_BUBBLE.display(loc.getBlock().getLocation().clone().add(.5, .5, .5), 5, Math.random(), Math.random(), Math.random(), 0);
}
loc.subtract(dx, dy, dz);
}
if (this.angle < 220) {
this.angle += 20;
} else {
this.forming = false;
this.formed = true;
}
this.formRing();
if (this.blocks.isEmpty()) {
this.remove();
return;
}
}
if (this.formed && !this.player.isSneaking() && !this.launch) {
new TorrentWave(this.player, this.radius);
this.remove();
return;
}
if (this.launch && this.formed) {
this.launching = true;
this.launch = false;
this.formed = false;
if (!this.launch()) {
this.returnWater(this.location);
this.remove();
return;
}
}
if (this.launching) {
if (!this.player.isSneaking()) {
this.remove();
return;
}
if (!this.launch()) {
this.remove();
return;
}
}
}
}
private boolean launch() {
if (this.launchedBlocks.isEmpty() && this.blocks.isEmpty()) {
return false;
}
if (this.launchedBlocks.isEmpty()) {
this.clearRing();
final Location loc = this.player.getEyeLocation();
final ArrayList<Block> doneBlocks = new ArrayList<Block>();
for (double theta = this.startAngle; theta < this.angle + this.startAngle; theta += 20) {
final double phi = Math.toRadians(theta);
final double dx = Math.cos(phi) * this.radius;
final double dy = 0;
final double dz = Math.sin(phi) * this.radius;
final Location blockloc = loc.clone().add(dx, dy, dz);
if (Math.abs(theta - this.startAngle) < 10) {
this.location = blockloc.clone();
}
final Block block = blockloc.getBlock();
if (!doneBlocks.contains(block) && !GeneralMethods.isRegionProtectedFromBuild(this, blockloc)) {
if (isTransparent(this.player, block)) {
this.launchedBlocks.add(new TempBlock(block, Material.WATER));
doneBlocks.add(block);
} else if (!isTransparent(this.player, block)) {
break;
}
}
}
if (this.launchedBlocks.isEmpty()) {
return false;
} else {
return true;
}
}
final Entity target = GeneralMethods.getTargetedEntity(this.player, this.range, this.hurtEntities);
Location targetLoc = this.player.getTargetBlock(getTransparentMaterialSet(), (int) this.range).getLocation();
if (target != null) {
targetLoc = target.getLocation();
}
final ArrayList<TempBlock> newBlocks = new ArrayList<TempBlock>();
final List<Entity> entities = GeneralMethods.getEntitiesAroundPoint(this.player.getLocation(), this.range + 5);
final List<Entity> affectedEntities = new ArrayList<Entity>();
final Block realBlock = this.launchedBlocks.get(0).getBlock();
final Vector dir = GeneralMethods.getDirection(this.location, targetLoc).normalize();
if (target != null) {
targetLoc = this.location.clone().add(dir.clone().multiply(10));
}
if (this.layer == 0) {
this.location = this.location.clone().add(dir);
}
final Block locBlock = this.location.getBlock();
if (this.location.distanceSquared(this.player.getLocation()) > this.range * this.range || GeneralMethods.isRegionProtectedFromBuild(this, this.location)) {
if (this.layer < this.maxLayer) {
if (this.freeze || this.layer < 1) {
this.layer++;
}
}
if (this.launchedBlocks.size() == 1) {
this.remove();
return false;
}
} else if (!isTransparent(this.player, locBlock)) {
if (this.layer < this.maxLayer) {
if (this.layer == 0) {
this.hurtEntities.clear();
}
if (this.freeze || this.layer < 1) {
this.layer++;
}
}
if (this.freeze) {
this.freeze();
} else if (this.launchedBlocks.size() == 1) {
this.location = realBlock.getLocation();
this.remove();
return false;
}
} else {
if (locBlock.equals(realBlock) && this.layer == 0) {
return true;
}
if (locBlock.getLocation().distanceSquared(targetLoc) > 1) {
if (isWater(locBlock)) {
ParticleEffect.WATER_BUBBLE.display(locBlock.getLocation().clone().add(.5, .5, .5), 5, Math.random(), Math.random(), Math.random(), 0);
}
newBlocks.add(new TempBlock(locBlock, Material.WATER));
} else {
if (this.layer < this.maxLayer) {
if (this.layer == 0) {
this.hurtEntities.clear();
}
if (this.freeze || this.layer < 1) {
this.layer++;
}
}
if (this.freeze) {
this.freeze();
}
}
}
for (int i = 0; i < this.launchedBlocks.size(); i++) {
final TempBlock block = this.launchedBlocks.get(i);
if (i == this.launchedBlocks.size() - 1) {
block.revertBlock();
} else {
newBlocks.add(block);
for (final Entity entity : entities) {
if (entity.getWorld() != block.getBlock().getWorld()) {
continue;
}
if (entity.getLocation().distanceSquared(block.getLocation()) <= 1.5 * 1.5 && !affectedEntities.contains(entity)) {
if (i == 0) {
this.affect(entity, dir);
} else {
this.affect(entity, GeneralMethods.getDirection(block.getLocation(), this.launchedBlocks.get(i - 1).getLocation()).normalize());
}
affectedEntities.add(entity);
}
}
}
}
this.launchedBlocks.clear();
this.launchedBlocks.addAll(newBlocks);
if (this.launchedBlocks.isEmpty()) {
return false;
}
return true;
}
private void formRing() {
this.clearRing();
this.startAngle += 30;
final Location loc = this.player.getEyeLocation();
final ArrayList<Block> doneBlocks = new ArrayList<Block>();
final ArrayList<Entity> affectedEntities = new ArrayList<Entity>();
final List<Entity> entities = GeneralMethods.getEntitiesAroundPoint(loc, this.radius + 2);
for (double theta = this.startAngle; theta < this.angle + this.startAngle; theta += 20) {
final double phi = Math.toRadians(theta);
final double dx = Math.cos(phi) * this.radius;
final double dy = 0;
final double dz = Math.sin(phi) * this.radius;
final Location blockLoc = loc.clone().add(dx, dy, dz);
final Block block = blockLoc.getBlock();
if (!doneBlocks.contains(block)) {
if (isTransparent(this.player, block)) {
this.blocks.add(new TempBlock(block, Material.WATER));
doneBlocks.add(block);
for (final Entity entity : entities) {
if (entity.getWorld() != blockLoc.getWorld()) {
continue;
}
if (!affectedEntities.contains(entity) && entity.getLocation().distanceSquared(blockLoc) <= 1.5 * 1.5) {
this.deflect(entity);
}
}
}
}
}
}
private void clearRing() {
for (final TempBlock block : this.blocks) {
block.revertBlock();
}
this.blocks.clear();
}
@Override
public void remove() {
super.remove();
this.clearRing();
for (final TempBlock block : this.launchedBlocks) {
block.revertBlock();
}
this.launchedBlocks.clear();
if (this.source != null) {
this.source.revertBlock();
}
if (this.location != null) {
this.returnWater(this.location);
}
}
private void returnWater(final Location location) {
new WaterReturn(this.player, location.getBlock());
}
public static void create(final Player player) {
if (hasAbility(player, Torrent.class)) {
return;
}
if (WaterReturn.hasWaterBottle(player)) {
final Location eyeLoc = player.getEyeLocation();
final Block block = eyeLoc.add(eyeLoc.getDirection().normalize()).getBlock();
if (isTransparent(player, block) && isTransparent(player, eyeLoc.getBlock())) {
if (block.getType() != Material.WATER) {
block.setType(Material.WATER);
block.setBlockData(GeneralMethods.getWaterData(0));
}
final Torrent tor = new Torrent(player);
if (tor.sourceSelected || tor.settingUp) {
WaterReturn.emptyWaterBottle(player);
}
block.setType(Material.AIR);
}
}
}
private void use() {
this.launch = true;
if (this.launching) {
this.freeze = true;
}
}
private void deflect(final Entity entity) {
if (entity.getEntityId() == this.player.getEntityId()) {
return;
}
if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) {
return;
}
double x, z, vx, vz, mag;
double angle = 50;
angle = Math.toRadians(angle);
x = entity.getLocation().getX() - this.player.getLocation().getX();
z = entity.getLocation().getZ() - this.player.getLocation().getZ();
mag = Math.sqrt(x * x + z * z);
vx = (x * Math.cos(angle) - z * Math.sin(angle)) / mag;
vz = (x * Math.sin(angle) + z * Math.cos(angle)) / mag;
final Vector vec = new Vector(vx, 0, vz).normalize().multiply(this.knockback);
final Vector velocity = entity.getVelocity();
if (this.bPlayer.isAvatarState()) {
velocity.setX(AvatarState.getValue(vec.getX()));
velocity.setZ(AvatarState.getValue(vec.getZ()));
} else {
velocity.setX(vec.getX());
velocity.setZ(vec.getY());
}
GeneralMethods.setVelocity(entity, velocity);
entity.setFallDistance(0);
if (entity instanceof LivingEntity) {
final double damageDealt = this.getNightFactor(this.deflectDamage);
DamageHandler.damageEntity(entity, damageDealt, this);
AirAbility.breakBreathbendingHold(entity);
}
}
private void affect(final Entity entity, final Vector direction) {
if (entity.getEntityId() == this.player.getEntityId()) {
return;
}
if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || (entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) {
return;
}
if (direction.getY() > this.knockup) {
direction.setY(this.knockup);
}
if (!this.freeze) {
entity.setVelocity(direction.multiply(this.knockback));
}
if (entity instanceof LivingEntity && !this.hurtEntities.contains(entity)) {
double damageDealt = this.getNightFactor(this.damage);
if (this.hits > 1 && this.hits <= this.maxHits) {
damageDealt = this.getNightFactor(this.successiveDamage);
}
if (this.hits == this.maxHits) {
this.hits = this.maxHits + 1;
} else {
this.hits += 1;
}
DamageHandler.damageEntity(entity, damageDealt, this);
AirAbility.breakBreathbendingHold(entity);
this.hurtEntities.add(entity);
((LivingEntity) entity).setNoDamageTicks(0);
}
}
public static void progressAllCleanup() {
for (final TempBlock block : FROZEN_BLOCKS.keySet()) {
final Player player = FROZEN_BLOCKS.get(block).getLeft();
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
if (bPlayer == null) {
FROZEN_BLOCKS.remove(block);
continue;
} else if (block.getBlock().getType() != Material.ICE) {
FROZEN_BLOCKS.remove(block);
continue;
} else if (!player.isOnline()) {
thaw(block);
continue;
} else if (block.getBlock().getWorld() != player.getWorld()) {
thaw(block);
continue;
} else if (block.getLocation().distanceSquared(player.getLocation()) > CLEANUP_RANGE * CLEANUP_RANGE || !bPlayer.canBendIgnoreBindsCooldowns(getAbility("Torrent"))) {
thaw(block);
}
}
}
public static void thaw(final Block block) {
if (TempBlock.isTempBlock(block)) {
final TempBlock tblock = TempBlock.get(block);
if (FROZEN_BLOCKS.containsKey(tblock)) {
thaw(tblock);
}
}
}
public static void thaw(final TempBlock block) {
block.revertBlock();
FROZEN_BLOCKS.remove(block);
}
/**
* Thaws the entire mass of ice created by a torrent that the given block is
* part of
*
* @param origin part of the ice mass created by a torrent
*/
public static void massThaw(final TempBlock origin) {
if (FROZEN_BLOCKS.containsKey(origin)) {
final Player creator = FROZEN_BLOCKS.get(origin).getLeft();
final int id = FROZEN_BLOCKS.get(origin).getRight();
for (final TempBlock tb : FROZEN_BLOCKS.keySet()) {
if (tb.equals(origin)) {
continue;
}
final Player check = FROZEN_BLOCKS.get(tb).getLeft();
final int id2 = FROZEN_BLOCKS.get(tb).getRight();
if (creator.equals(check) && id == id2) {
thaw(tb);
}
}
thaw(origin);
}
}
public static boolean canThaw(final Block block) {
if (TempBlock.isTempBlock(block)) {
final TempBlock tblock = TempBlock.get(block);
return !FROZEN_BLOCKS.containsKey(tblock);
}
return true;
}
public static void removeCleanup() {
for (final TempBlock block : FROZEN_BLOCKS.keySet()) {
thaw(block);
}
}
public static boolean wasBrokenFor(final Player player, final Block block) {
final Torrent torrent = getAbility(player, Torrent.class);
if (torrent != null) {
if (torrent.sourceBlock == null) {
return false;
}
if (torrent.sourceBlock.equals(block)) {
return true;
}
}
return false;
}
@Override
public String getName() {
return "Torrent";
}
@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 boolean isCollidable() {
return this.forming || this.formed || this.launch || this.launching;
}
@Override
public boolean allowBreakPlants() {
return false;
}
@Override
public List<Location> getLocations() {
final ArrayList<Location> locations = new ArrayList<>();
for (final TempBlock tblock : this.blocks) {
locations.add(tblock.getLocation());
}
for (final TempBlock tblock : this.launchedBlocks) {
locations.add(tblock.getLocation());
}
return locations;
}
public boolean isSourceSelected() {
return this.sourceSelected;
}
public void setSourceSelected(final boolean sourceSelected) {
this.sourceSelected = sourceSelected;
}
public boolean isSettingUp() {
return this.settingUp;
}
public void setSettingUp(final boolean settingUp) {
this.settingUp = settingUp;
}
public boolean isForming() {
return this.forming;
}
public void setForming(final boolean forming) {
this.forming = forming;
}
public boolean isFormed() {
return this.formed;
}
public void setFormed(final boolean formed) {
this.formed = formed;
}
public boolean isLaunch() {
return this.launch;
}
public void setLaunch(final boolean launch) {
this.launch = launch;
}
public boolean isLaunching() {
return this.launching;
}
public void setLaunching(final boolean launching) {
this.launching = launching;
}
public boolean isFreeze() {
return this.freeze;
}
public void setFreeze(final boolean freeze) {
this.freeze = freeze;
}
public int getLayer() {
return this.layer;
}
public void setLayer(final int layer) {
this.layer = layer;
}
public int getMaxLayer() {
return this.maxLayer;
}
public void setMaxLayer(final int maxLayer) {
this.maxLayer = maxLayer;
}
public long getTime() {
return this.time;
}
public void setTime(final long time) {
this.time = time;
}
public long getInterval() {
return this.interval;
}
public void setInterval(final long interval) {
this.interval = interval;
}
public double getStartAngle() {
return this.startAngle;
}
public void setStartAngle(final double startAngle) {
this.startAngle = startAngle;
}
public double getAngle() {
return this.angle;
}
public void setAngle(final double angle) {
this.angle = angle;
}
public double getRadius() {
return this.radius;
}
public void setRadius(final double radius) {
this.radius = radius;
}
public double getPush() {
return this.knockback;
}
public void setPush(final double push) {
this.knockback = push;
}
public double getMaxUpwardForce() {
return this.knockup;
}
public void setMaxUpwardForce(final double maxUpwardForce) {
this.knockup = maxUpwardForce;
}
public double getDamage() {
return this.damage;
}
public void setDamage(final double damage) {
this.damage = damage;
}
public double getDeflectDamage() {
return this.deflectDamage;
}
public void setDeflectDamage(final double deflectDamage) {
this.deflectDamage = deflectDamage;
}
public double getRange() {
return this.range;
}
public void setRange(final double range) {
this.range = range;
}
public double getSelectRange() {
return this.selectRange;
}
public void setSelectRange(final double selectRange) {
this.selectRange = selectRange;
}
public Block getSourceBlock() {
return this.sourceBlock;
}
public void setSourceBlock(final Block sourceBlock) {
this.sourceBlock = sourceBlock;
}
public TempBlock getSource() {
return this.source;
}
public void setSource(final TempBlock source) {
this.source = source;
}
public ArrayList<TempBlock> getBlocks() {
return this.blocks;
}
public void setBlocks(final ArrayList<TempBlock> blocks) {
this.blocks = blocks;
}
public static double getCleanupRange() {
return CLEANUP_RANGE;
}
public static Map<TempBlock, Player> getFrozenBlocks() {
final Map<TempBlock, Player> blocks = new HashMap<>();
for (final TempBlock tb : FROZEN_BLOCKS.keySet()) {
blocks.put(tb, FROZEN_BLOCKS.get(tb).getLeft());
}
return blocks;
}
public ArrayList<TempBlock> getLaunchedBlocks() {
return this.launchedBlocks;
}
public ArrayList<Entity> getHurtEntities() {
return this.hurtEntities;
}
public void setCooldown(final long cooldown) {
this.cooldown = cooldown;
}
public void setLocation(final Location location) {
this.location = location;
}
}