TF-ProjectKorra/src/com/projectkorra/projectkorra/GeneralMethods.java
Christopher Martin 75c4f41be5
1.9.2 (#1153)
## Additions
* Adds support for Minecraft 1.17!
* Adds vanished player support to the `/pk who <Player>` command.
  * Should work with most common vanishing plugins, tested using Essentials vanish.
  * Affects `/pk who` and `/pk who <Player>`.
* Adds new `"Abilities.Earth.EarthSmash.Lift.Knockup"` configuration option to control the velocity applied to players standing where an EarthSmash is created.
* Adds new `"Abilities.Earth.EarthSmash.Lift.Range"` configuration option to control the range in which entities need to be standing in relation to where an EarthSmash is created to get the Knockup applied.

## Fixes
* Fixes players sometimes "falling through" their EarthSmash if they try to create it underneath themselves.
  * Reduces the overall push so it feels more natural.
  * Expands the push radius so it can affect entities within one block of the location.
* Fixes IceWave activating sometimes when PhaseChange wasn't clicked.
* Fixes IceWave users getting stuck on their ice midair.
* Fixes the display command showing hidden combos and passives
* Fixes an error caused by adding attribute modifiers to abilities sometimes.
* Fixes an error preventing the plugin from working on Minecraft 1.17.
  * ClassDefNotFoundError resulting from EntityHuman being moved during the 1.17 Minecraft update. We no longer rely on NMS for this area as a proper API has been introduced. As such, GeneralMethods and EarthArmor have been updated to reflect these changes.
2021-06-15 09:49:50 -07:00

2504 lines
90 KiB
Java

package com.projectkorra.projectkorra;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import com.bekvon.bukkit.residence.Residence;
import com.bekvon.bukkit.residence.api.ResidenceInterface;
import com.bekvon.bukkit.residence.protection.ClaimedResidence;
import com.bekvon.bukkit.residence.protection.ResidencePermissions;
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.object.TownyPermission.ActionType;
import com.palmergames.bukkit.towny.utils.PlayerCacheUtil;
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 org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Levelled;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MainHand;
import org.bukkit.plugin.Plugin;
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;
import com.projectkorra.projectkorra.ability.AddonAbility;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.EarthAbility;
import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.ability.PassiveAbility;
import com.projectkorra.projectkorra.ability.WaterAbility;
import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.ability.util.CollisionInitializer;
import com.projectkorra.projectkorra.ability.util.CollisionManager;
import com.projectkorra.projectkorra.ability.util.ComboManager;
import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation;
import com.projectkorra.projectkorra.ability.util.MultiAbilityManager;
import com.projectkorra.projectkorra.ability.util.PassiveManager;
import com.projectkorra.projectkorra.airbending.AirBlast;
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;
import com.projectkorra.projectkorra.firebending.FireBlast;
import com.projectkorra.projectkorra.firebending.FireShield;
import com.projectkorra.projectkorra.firebending.combustion.Combustion;
import com.projectkorra.projectkorra.object.Preset;
import com.projectkorra.projectkorra.storage.DBConnection;
import com.projectkorra.projectkorra.util.ActionBar;
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.TempArmor;
import com.projectkorra.projectkorra.util.TempArmorStand;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.waterbending.WaterManipulation;
import com.projectkorra.projectkorra.waterbending.WaterSpout;
import br.net.fabiozumbi12.RedProtect.Bukkit.RedProtect;
import br.net.fabiozumbi12.RedProtect.Bukkit.Region;
import br.net.fabiozumbi12.RedProtect.Bukkit.API.RedProtectAPI;
import me.markeh.factionsframework.entities.FPlayer;
import me.markeh.factionsframework.entities.FPlayers;
import me.markeh.factionsframework.entities.Faction;
import me.markeh.factionsframework.entities.Factions;
import me.markeh.factionsframework.enums.Rel;
import me.ryanhamshire.GriefPrevention.Claim;
import me.ryanhamshire.GriefPrevention.GriefPrevention;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
public class GeneralMethods {
// Represents PlayerName, previously checked blocks, and whether they were true or false
private static final Map<String, Map<Block, BlockCacheElement>> BLOCK_CACHE = new ConcurrentHashMap<>();
private static final ArrayList<Ability> INVINCIBLE = new ArrayList<>();
private static ProjectKorra plugin;
public GeneralMethods(final ProjectKorra plugin) {
GeneralMethods.plugin = plugin;
}
/**
* Checks to see if an AbilityExists. Uses method
* {@link CoreAbility#getAbility(String)} to check if it exists.
*
* @param string Ability Name
* @return true if ability exists
*/
public static boolean abilityExists(final String string) {
return CoreAbility.getAbility(string) != null;
}
/**
* Binds a Ability to the hotbar slot that the player is on.
*
* @param player The player to bind to
* @param ability The ability name to Bind
* @see #bindAbility(Player, String, int)
*/
public static void bindAbility(final Player player, final String ability) {
final int slot = player.getInventory().getHeldItemSlot() + 1;
bindAbility(player, ability, slot);
}
/**
* Binds a Ability to a specific hotbar slot.
*
* @param player The player to bind to
* @param ability
* @param slot
* @see #bindAbility(Player, String)
*/
public static void bindAbility(final Player player, final String ability, final int slot) {
if (MultiAbilityManager.playerAbilities.containsKey(player)) {
GeneralMethods.sendBrandingMessage(player, ChatColor.RED + "You can't edit your binds right now!");
return;
}
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player.getName());
final CoreAbility coreAbil = CoreAbility.getAbility(ability);
if (bPlayer == null) {
return;
}
bPlayer.getAbilities().put(slot, ability);
if (coreAbil != null) {
GeneralMethods.sendBrandingMessage(player, coreAbil.getElement().getColor() + ConfigManager.languageConfig.get().getString("Commands.Bind.SuccessfullyBound").replace("{ability}", ability).replace("{slot}", String.valueOf(slot)));
}
saveAbility(bPlayer, slot, ability);
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
* <p>
* Cycles through a list of ability names to check if any instances of the
* abilities exist at a specific location. If an instance of the ability is
* found then it will be removed, with the exception FireShield, and
* AirShield.
*/
@Deprecated
public static boolean blockAbilities(final Player player, final List<String> abilitiesToBlock, final Location loc, final double radius) {
boolean hasBlocked = false;
for (final String ability : abilitiesToBlock) {
if (ability.equalsIgnoreCase("FireBlast")) {
hasBlocked = FireBlast.annihilateBlasts(loc, radius, player) || hasBlocked;
} else if (ability.equalsIgnoreCase("EarthBlast")) {
hasBlocked = EarthBlast.annihilateBlasts(loc, radius, player) || hasBlocked;
} else if (ability.equalsIgnoreCase("WaterManipulation")) {
hasBlocked = WaterManipulation.annihilateBlasts(loc, radius, player) || hasBlocked;
} else if (ability.equalsIgnoreCase("AirSwipe")) {
hasBlocked = AirSwipe.removeSwipesAroundPoint(loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("AirBlast")) {
hasBlocked = AirBlast.removeAirBlastsAroundPoint(loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("AirSuction")) {
hasBlocked = AirSuction.removeAirSuctionsAroundPoint(loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("Combustion")) {
hasBlocked = Combustion.removeAroundPoint(loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("FireShield")) {
hasBlocked = FireShield.isWithinShield(loc) || hasBlocked;
} else if (ability.equalsIgnoreCase("AirShield")) {
hasBlocked = AirShield.isWithinShield(loc) || hasBlocked;
} else if (ability.equalsIgnoreCase("WaterSpout")) {
hasBlocked = WaterSpout.removeSpouts(loc, radius, player) || hasBlocked;
} else if (ability.equalsIgnoreCase("AirSpout")) {
hasBlocked = AirSpout.removeSpouts(loc, radius, player) || hasBlocked;
} else if (ability.equalsIgnoreCase("Twister")) {
// hasBlocked = AirCombo.removeAroundPoint(player, "Twister", loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("AirStream")) {
// hasBlocked = AirCombo.removeAroundPoint(player, "AirStream", loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("AirSweep")) {
// hasBlocked = AirCombo.removeAroundPoint(player, "AirSweep", loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("FireKick")) {
// hasBlocked = FireCombo.removeAroundPoint(player, "FireKick", loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("FireSpin")) {
// hasBlocked = FireCombo.removeAroundPoint(player, "FireSpin", loc, radius) || hasBlocked;
} else if (ability.equalsIgnoreCase("FireWheel")) {
// hasBlocked = FireCombo.removeAroundPoint(player, "FireWheel", loc, radius) || hasBlocked;
}
}
return hasBlocked;
}
/**
* Breaks a block and sets it to {@link Material#AIR AIR}.
*
* @param block The block to break
*/
public static void breakBlock(final Block block) {
block.breakNaturally(new ItemStack(Material.AIR));
}
public static boolean canView(final Player player, final String ability) {
return player.hasPermission("bending.ability." + ability);
}
/**
* Checks if there is a diagonal wall in front of the location in the given
* direction, in any 2 dimensions and all 3
*
* @param location spot to check
* @param direction which way to check
* @return true if diagonal wall is found
*/
public static boolean checkDiagonalWall(final Location location, final Vector direction) {
final boolean[] xyzsolid = { false, false, false };
for (int i = 0; i < 3; i++) {
double value;
if (i == 0) {
value = direction.getX();
} else if (i == 1) {
value = direction.getY();
} else {
value = direction.getZ();
}
final BlockFace face = GeneralMethods.getBlockFaceFromValue(i, value);
if (face == null) {
continue;
}
xyzsolid[i] = location.getBlock().getRelative(face).getType().isSolid();
}
final boolean a = xyzsolid[0] && xyzsolid[2];
final boolean b = xyzsolid[0] && xyzsolid[1];
final boolean c = xyzsolid[1] && xyzsolid[2];
return (a || b || c || (a && b));
}
public static int compareArmor(Material first, Material second) {
return getArmorTier(first) - getArmorTier(second);
}
/**
* Creates a {@link BendingPlayer} with the data from the database. This
* runs when a player logs in.
*
* @param uuid The UUID of the player
* @param player The player name
* @throws SQLException
*/
public static void createBendingPlayer(final UUID uuid, final String player) {
new BukkitRunnable() {
@Override
public void run() {
createBendingPlayerAsynchronously(uuid, player);
}
}.runTaskAsynchronously(ProjectKorra.plugin);
}
private static void createBendingPlayerAsynchronously(final UUID uuid, final String player) {
final ResultSet rs2 = DBConnection.sql.readQuery("SELECT * FROM pk_players WHERE uuid = '" + uuid.toString() + "'");
try {
if (!rs2.next()) { // Data doesn't exist, we want a completely new player.
DBConnection.sql.modifyQuery("INSERT INTO pk_players (uuid, player, slot1, slot2, slot3, slot4, slot5, slot6, slot7, slot8, slot9) VALUES ('" + uuid.toString() + "', '" + player + "', 'null', 'null', 'null', 'null', 'null', 'null', 'null', 'null', 'null')");
new BukkitRunnable() {
@Override
public void run() {
new BendingPlayer(uuid, player, new ArrayList<Element>(), new ArrayList<SubElement>(), new HashMap<Integer, String>(), false);
ProjectKorra.log.info("Created new BendingPlayer for " + player);
}
}.runTask(ProjectKorra.plugin);
} else {
// The player has at least played before.
final String player2 = rs2.getString("player");
if (!player.equalsIgnoreCase(player2)) {
DBConnection.sql.modifyQuery("UPDATE pk_players SET player = '" + player + "' WHERE uuid = '" + uuid.toString() + "'");
// They have changed names.
ProjectKorra.log.info("Updating Player Name for " + player);
}
final String subelement = rs2.getString("subelement");
final String element = rs2.getString("element");
final String permaremoved = rs2.getString("permaremoved");
boolean p = false;
final ArrayList<Element> elements = new ArrayList<Element>();
if (element != null && !element.equals("NULL")) {
final boolean hasAddon = element.contains(";");
final String[] split = element.split(";");
if (split[0] != null) { // Player has an element.
if (split[0].contains("a")) {
elements.add(Element.AIR);
}
if (split[0].contains("w")) {
elements.add(Element.WATER);
}
if (split[0].contains("e")) {
elements.add(Element.EARTH);
}
if (split[0].contains("f")) {
elements.add(Element.FIRE);
}
if (split[0].contains("c")) {
elements.add(Element.CHI);
}
if (hasAddon) {
/*
* Because plugins which depend on ProjectKorra
* would be loaded after ProjectKorra, addon
* elements would = null. To work around this, we
* keep trying to load in the elements from the
* database until it successfully loads everything
* in, or it times out.
*/
final CopyOnWriteArrayList<String> addonClone = new CopyOnWriteArrayList<String>(Arrays.asList(split[split.length - 1].split(",")));
final long startTime = System.currentTimeMillis();
final long timeoutLength = 30000; // How long until it should time out attempting to load addons in.
new BukkitRunnable() {
@Override
public void run() {
if (addonClone.isEmpty()) {
ProjectKorra.log.info("Successfully loaded in all addon elements!");
this.cancel();
} else if (System.currentTimeMillis() - startTime > timeoutLength) {
ProjectKorra.log.severe("ProjectKorra has timed out after attempting to load in the following addon elements: " + addonClone.toString());
ProjectKorra.log.severe("These elements have taken too long to load in, resulting in users having lost these element.");
this.cancel();
} else {
ProjectKorra.log.info("Attempting to load in the following addon elements... " + addonClone.toString());
for (final String addon : addonClone) {
if (Element.getElement(addon) != null) {
elements.add(Element.getElement(addon));
addonClone.remove(addon);
}
}
}
}
}.runTaskTimer(ProjectKorra.plugin, 0, 20);
}
}
}
final ArrayList<SubElement> subelements = new ArrayList<SubElement>();
boolean shouldSave = false;
if (subelement != null && !subelement.equals("NULL")) {
final boolean hasAddon = subelement.contains(";");
final String[] split = subelement.split(";");
if (subelement.equals("-")) {
final Player playero = Bukkit.getPlayer(uuid);
for (final SubElement sub : Element.getAllSubElements()) {
if ((playero != null && playero.hasPermission("bending." + sub.getParentElement().getName().toLowerCase() + "." + sub.getName().toLowerCase() + sub.getType().getBending())) && elements.contains(sub.getParentElement())) {
subelements.add(sub);
shouldSave = true && playero != null;
}
}
} else if (split[0] != null) {
if (split[0].contains("m")) {
subelements.add(Element.METAL);
}
if (split[0].contains("v")) {
subelements.add(Element.LAVA);
}
if (split[0].contains("s")) {
subelements.add(Element.SAND);
}
if (split[0].contains("c")) {
subelements.add(Element.COMBUSTION);
}
if (split[0].contains("l")) {
subelements.add(Element.LIGHTNING);
}
if (split[0].contains("t")) {
subelements.add(Element.SPIRITUAL);
}
if (split[0].contains("f")) {
subelements.add(Element.FLIGHT);
}
if (split[0].contains("i")) {
subelements.add(Element.ICE);
}
if (split[0].contains("h")) {
subelements.add(Element.HEALING);
}
if (split[0].contains("b")) {
subelements.add(Element.BLOOD);
}
if (split[0].contains("p")) {
subelements.add(Element.PLANT);
}
if (split[0].contains("r")) {
subelements.add(Element.BLUE_FIRE);
}
if (hasAddon) {
final CopyOnWriteArrayList<String> addonClone = new CopyOnWriteArrayList<String>(Arrays.asList(split[split.length - 1].split(",")));
final long startTime = System.currentTimeMillis();
final long timeoutLength = 30000; // How long until it should time out attempting to load addons in.
new BukkitRunnable() {
@Override
public void run() {
if (addonClone.isEmpty()) {
ProjectKorra.log.info("Successfully loaded in all addon subelements!");
this.cancel();
} else if (System.currentTimeMillis() - startTime > timeoutLength) {
ProjectKorra.log.severe("ProjectKorra has timed out after attempting to load in the following addon subelements: " + addonClone.toString());
ProjectKorra.log.severe("These subelements have taken too long to load in, resulting in users having lost these subelement.");
this.cancel();
} else {
ProjectKorra.log.info("Attempting to load in the following addon subelements... " + addonClone.toString());
for (final String addon : addonClone) {
if (Element.getElement(addon) != null && Element.getElement(addon) instanceof SubElement) {
subelements.add((SubElement) Element.getElement(addon));
addonClone.remove(addon);
}
}
}
}
}.runTaskTimer(ProjectKorra.plugin, 0, 20);
}
}
}
final HashMap<Integer, String> abilities = new HashMap<Integer, String>();
final ConcurrentHashMap<Integer, String> abilitiesClone = new ConcurrentHashMap<Integer, String>(abilities);
for (int i = 1; i <= 9; i++) {
final String ability = rs2.getString("slot" + i);
abilitiesClone.put(i, ability);
}
final long startTime = System.currentTimeMillis();
final long timeoutLength = 30000; // How long until it should time out attempting to load addons in.
new BukkitRunnable() {
@Override
public void run() {
if (abilitiesClone.isEmpty()) {
// All abilities loaded.
this.cancel();
} else if (System.currentTimeMillis() - startTime > timeoutLength) {
ProjectKorra.log.severe("ProjectKorra has timed out after attempting to load in the following external abilities: " + abilitiesClone.values().toString());
ProjectKorra.log.severe("These abilities have taken too long to load in, resulting in users having lost them if bound.");
this.cancel();
} else {
for (final int slot : abilitiesClone.keySet()) {
final String ability = abilitiesClone.get(slot);
if (ability.equalsIgnoreCase("null")) {
abilitiesClone.remove(slot);
continue;
} else if (CoreAbility.getAbility(ability) != null && CoreAbility.getAbility(ability).isEnabled()) {
abilities.put(slot, ability);
abilitiesClone.remove(slot);
continue;
}
}
}
}
}.runTaskTimer(ProjectKorra.plugin, 0, 20);
p = (permaremoved != null && (permaremoved.equals("true")));
final boolean boolean_p = p;
final boolean shouldSave_ = shouldSave;
new BukkitRunnable() {
@Override
public void run() {
new BendingPlayer(uuid, player, elements, subelements, abilities, boolean_p);
if (shouldSave_) {
saveSubElements(BendingPlayer.getBendingPlayer(player));
}
}
}.runTask(ProjectKorra.plugin);
}
} catch (final SQLException ex) {
ex.printStackTrace();
}
}
/**
* Deserializes the configuration file "bendingPlayers.yml" of the old
* BendingPlugin and creates a converted.yml ready for conversion.
*
* @throws IOException If the "bendingPlayers.yml" file is not found
*/
public static void deserializeFile() {
final File readFile = new File(".", "bendingPlayers.yml");
final File writeFile = new File(".", "converted.yml");
if (readFile.exists()) {
try (DataInputStream input = new DataInputStream(new FileInputStream(readFile)); BufferedReader reader = new BufferedReader(new InputStreamReader(input));
DataOutputStream output = new DataOutputStream(new FileOutputStream(writeFile)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output))) {
String line;
while ((line = reader.readLine()) != null) {
if (!line.trim().contains("==: BendingPlayer")) {
writer.write(line + "\n");
}
}
} catch (final IOException e) {
e.printStackTrace();
}
}
}
@Deprecated
public static void displayColoredParticle(final Location loc, ParticleEffect type, final String hexVal, final float xOffset, final float yOffset, final float zOffset) {
int r = 0;
int g = 0;
int b = 0;
if (hexVal.length() <= 6) {
r = Integer.valueOf(hexVal.substring(0, 2), 16).intValue();
g = Integer.valueOf(hexVal.substring(2, 4), 16).intValue();
b = Integer.valueOf(hexVal.substring(4, 6), 16).intValue();
} else if (hexVal.length() <= 7 && hexVal.substring(0, 1).equals("#")) {
r = Integer.valueOf(hexVal.substring(1, 3), 16).intValue();
g = Integer.valueOf(hexVal.substring(3, 5), 16).intValue();
b = Integer.valueOf(hexVal.substring(5, 7), 16).intValue();
}
float red = r / 255.0F;
final float green = g / 255.0F;
final float blue = b / 255.0F;
if (red <= 0) {
red = 1 / 255.0F;
}
loc.setX(loc.getX() + (Math.random() * 2 - 1) * xOffset);
loc.setY(loc.getY() + (Math.random() * 2 - 1) * yOffset);
loc.setZ(loc.getZ() + (Math.random() * 2 - 1) * zOffset);
if (type != ParticleEffect.RED_DUST && type != ParticleEffect.REDSTONE && type != ParticleEffect.SPELL_MOB && type != ParticleEffect.MOB_SPELL && type != ParticleEffect.SPELL_MOB_AMBIENT && type != ParticleEffect.MOB_SPELL_AMBIENT) {
type = ParticleEffect.RED_DUST;
}
type.display(loc, 0, red, green, blue);
}
@Deprecated
public static void displayColoredParticle(final Location loc, final String hexVal) {
displayColoredParticle(loc, ParticleEffect.RED_DUST, hexVal, 0, 0, 0);
}
@Deprecated
public static void displayColoredParticle(final Location loc, final String hexVal, final float xOffset, final float yOffset, final float zOffset) {
displayColoredParticle(loc, ParticleEffect.RED_DUST, hexVal, xOffset, yOffset, zOffset);
}
public static void displayColoredParticle(String hexVal, final Location loc, final int amount, final double offsetX, final double offsetY, final double offsetZ) {
int r = 0;
int g = 0;
int b = 0;
if (hexVal.startsWith("#")) {
hexVal = hexVal.substring(1);
}
if (hexVal.length() <= 6) {
r = Integer.valueOf(hexVal.substring(0, 2), 16).intValue();
g = Integer.valueOf(hexVal.substring(2, 4), 16).intValue();
b = Integer.valueOf(hexVal.substring(4, 6), 16).intValue();
}
new ColoredParticle(Color.fromRGB(r, g, b), 1F).display(loc, amount, offsetX, offsetY, offsetZ);
}
public static void displayColoredParticle(final String hexVal, final Location loc) {
displayColoredParticle(hexVal, loc, 1, 0, 0, 0);
}
/**
* Drops a {@code Collection<ItemStack>} of items on a specified block.
*
* @param block The block to drop items on.
* @param items The items to drop.
*/
public static void dropItems(final Block block, final Collection<ItemStack> items) {
for (final ItemStack item : items) {
if(item.getType() != Material.AIR) {
block.getWorld().dropItem(block.getLocation(), item);
}
}
}
public static void displayMovePreview(final Player player) {
displayMovePreview(player, player.getInventory().getHeldItemSlot() + 1);
}
public static void displayMovePreview(final Player player, final int slot) {
if (!ConfigManager.defaultConfig.get().getBoolean("Properties.BendingPreview")) {
return;
}
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
if (bPlayer == null) {
return;
}
String displayedMessage = bPlayer.getAbilities().get(slot);
final CoreAbility ability = CoreAbility.getAbility(displayedMessage);
if (ability != null && bPlayer != null) {
displayedMessage = ability.getMovePreview(player);
} else if (displayedMessage == null || displayedMessage.isEmpty() || displayedMessage.equals("")) {
displayedMessage = "";
}
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) {
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) {
player.setAbsorptionAmount(hearts);
}
public static int getArmorTier(Material mat) {
switch (mat) {
case NETHERITE_HELMET:
case NETHERITE_CHESTPLATE:
case NETHERITE_LEGGINGS:
case NETHERITE_BOOTS:
return 7;
case DIAMOND_HELMET:
case DIAMOND_CHESTPLATE:
case DIAMOND_LEGGINGS:
case DIAMOND_BOOTS:
return 6;
case TURTLE_HELMET:
return 5;
case IRON_HELMET:
case IRON_CHESTPLATE:
case IRON_LEGGINGS:
case IRON_BOOTS:
return 4;
case CHAINMAIL_HELMET:
case CHAINMAIL_CHESTPLATE:
case CHAINMAIL_LEGGINGS:
case CHAINMAIL_BOOTS:
return 3;
case GOLDEN_HELMET:
case GOLDEN_CHESTPLATE:
case GOLDEN_LEGGINGS:
case GOLDEN_BOOTS:
return 2;
case LEATHER_HELMET:
case LEATHER_CHESTPLATE:
case LEATHER_LEGGINGS:
case LEATHER_BOOTS:
return 1;
default:
return 0;
}
}
public static int getArmorIndex(Material mat) {
switch (mat) {
case NETHERITE_HELMET:
case DIAMOND_HELMET:
case TURTLE_HELMET:
case IRON_HELMET:
case CHAINMAIL_HELMET:
case GOLDEN_HELMET:
case LEATHER_HELMET:
return 3;
case NETHERITE_CHESTPLATE:
case DIAMOND_CHESTPLATE:
case IRON_CHESTPLATE:
case CHAINMAIL_CHESTPLATE:
case GOLDEN_CHESTPLATE:
case LEATHER_CHESTPLATE:
return 2;
case NETHERITE_LEGGINGS:
case DIAMOND_LEGGINGS:
case IRON_LEGGINGS:
case CHAINMAIL_LEGGINGS:
case GOLDEN_LEGGINGS:
case LEATHER_LEGGINGS:
return 1;
case NETHERITE_BOOTS:
case DIAMOND_BOOTS:
case IRON_BOOTS:
case CHAINMAIL_BOOTS:
case GOLDEN_BOOTS:
case LEATHER_BOOTS:
return 0;
default:
return -1;
}
}
/**
* This gets the BlockFace in the specified dimension of a certain value
*
* @param xyz 0 for x, 1 for y, 2 for z
* @param value vector value for which direction to check
* @return BlockFace for block in specified dimension and value
*/
public static BlockFace getBlockFaceFromValue(final int xyz, final double value) {
switch (xyz) {
case 0:
if (value > 0) {
return BlockFace.EAST;
} else if (value < 0) {
return BlockFace.WEST;
} else {
return BlockFace.SELF;
}
case 1:
if (value > 0) {
return BlockFace.UP;
} else if (value < 0) {
return BlockFace.DOWN;
} else {
return BlockFace.SELF;
}
case 2:
if (value > 0) {
return BlockFace.SOUTH;
} else if (value < 0) {
return BlockFace.NORTH;
} else {
return BlockFace.SELF;
}
default:
return null;
}
}
public static List<Block> getBlocksAlongLine(final Location ploc, final Location tloc, final World w) {
final List<Block> blocks = new ArrayList<Block>();
// Next we will name each coordinate
final int x1 = ploc.getBlockX();
final int y1 = ploc.getBlockY();
final int z1 = ploc.getBlockZ();
final int x2 = tloc.getBlockX();
final int y2 = tloc.getBlockY();
final int z2 = tloc.getBlockZ();
// Then we create the following integers
int xMin, yMin, zMin;
int xMax, yMax, zMax;
int x, y, z;
// Now we need to make sure xMin is always lower then xMax
if (x1 > x2) { // If x1 is a higher number then x2
xMin = x2;
xMax = x1;
} else {
xMin = x1;
xMax = x2;
}
// Same with Y
if (y1 > y2) {
yMin = y2;
yMax = y1;
} else {
yMin = y1;
yMax = y2;
}
// And Z
if (z1 > z2) {
zMin = z2;
zMax = z1;
} else {
zMin = z1;
zMax = z2;
}
// Now it's time for the loop
for (x = xMin; x <= xMax; x++) {
for (y = yMin; y <= yMax; y++) {
for (z = zMin; z <= zMax; z++) {
final Block b = new Location(w, x, y, z).getBlock();
blocks.add(b);
}
}
}
// And last but not least, we return with the list
return blocks;
}
/**
* Gets a {@code List<Blocks>} within the specified radius around the
* specified location.
*
* @param location The base location
* @param radius The block radius from location to include within the list
* of blocks
* @return The list of Blocks
*/
public static List<Block> getBlocksAroundPoint(final Location location, final double radius) {
final List<Block> blocks = new ArrayList<Block>();
final int xorg = location.getBlockX();
final int yorg = location.getBlockY();
final int zorg = location.getBlockZ();
final int r = (int) radius * 4;
for (int x = xorg - r; x <= xorg + r; x++) {
for (int y = yorg - r; y <= yorg + r; y++) {
for (int z = zorg - r; z <= zorg + r; z++) {
final Block block = location.getWorld().getBlockAt(x, y, z);
if (block.getLocation().distanceSquared(location) <= radius * radius) {
blocks.add(block);
}
}
}
}
return blocks;
}
public static BlockFace getCardinalDirection(final Vector vector) {
final BlockFace[] faces = { BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST, BlockFace.WEST, BlockFace.NORTH_WEST };
Vector n, ne, e, se, s, sw, w, nw;
w = new Vector(-1, 0, 0);
n = new Vector(0, 0, -1);
s = n.clone().multiply(-1);
e = w.clone().multiply(-1);
ne = n.clone().add(e.clone()).normalize();
se = s.clone().add(e.clone()).normalize();
nw = n.clone().add(w.clone()).normalize();
sw = s.clone().add(w.clone()).normalize();
final Vector[] vectors = { n, ne, e, se, s, sw, w, nw };
double comp = 0;
int besti = 0;
for (int i = 0; i < vectors.length; i++) {
final double dot = vector.dot(vectors[i]);
if (dot > comp) {
comp = dot;
besti = i;
}
}
return faces[besti];
}
public static List<Location> getCircle(final Location loc, final int radius, final int height, final boolean hollow, final boolean sphere, final int plusY) {
final List<Location> circleblocks = new ArrayList<Location>();
final int cx = loc.getBlockX();
final int cy = loc.getBlockY();
final int cz = loc.getBlockZ();
for (int x = cx - radius; x <= cx + radius; x++) {
for (int z = cz - radius; z <= cz + radius; z++) {
for (int y = (sphere ? cy - radius : cy); y < (sphere ? cy + radius : cy + height); y++) {
final double dist = (cx - x) * (cx - x) + (cz - z) * (cz - z) + (sphere ? (cy - y) * (cy - y) : 0);
if (dist < radius * radius && !(hollow && dist < (radius - 1) * (radius - 1))) {
final Location l = new Location(loc.getWorld(), x, y + plusY, z);
circleblocks.add(l);
}
}
}
}
return circleblocks;
}
/**
* Gets the closest entity within the specified radius around a point
* @param center point to check around
* @param radius distance from center to check within
* @return null if not found
*/
public static Entity getClosestEntity(Location center, double radius) {
Entity found = null;
Double distance = null;
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(center, radius)) {
double check = center.distanceSquared(entity.getLocation());
if (distance == null || check < distance) {
found = entity;
distance = check;
}
}
return found;
}
/**
* Gets the closest LivingEntity within the specified radius around a point
* @param center point to check around
* @param radius distance from center to check within
* @return null if not found
*/
public static LivingEntity getClosestLivingEntity(Location center, double radius) {
LivingEntity le = null;
Double distance = null;
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(center, radius)) {
double check = center.distanceSquared(entity.getLocation());
if (entity instanceof LivingEntity && (distance == null || check < distance)) {
le = (LivingEntity) entity;
distance = check;
}
}
return le;
}
public static String getCurrentDate() {
final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
final Date date = new Date();
return dateFormat.format(date);
}
public static Vector getDirection(final Location location, final Location destination) {
double x1, y1, z1;
double x0, y0, z0;
x1 = destination.getX();
y1 = destination.getY();
z1 = destination.getZ();
x0 = location.getX();
y0 = location.getY();
z0 = location.getZ();
return new Vector(x1 - x0, y1 - y0, z1 - z0);
}
public static double getDistanceFromLine(final Vector line, final Location pointonline, final Location point) {
final Vector AP = new Vector();
double Ax, Ay, Az;
Ax = pointonline.getX();
Ay = pointonline.getY();
Az = pointonline.getZ();
double Px, Py, Pz;
Px = point.getX();
Py = point.getY();
Pz = point.getZ();
AP.setX(Px - Ax);
AP.setY(Py - Ay);
AP.setZ(Pz - Az);
return (AP.crossProduct(line).length()) / (line.length());
}
/**
* Gets a {@code Collection<ItemStack>} of item drops from a single block.
*
* @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
* @return The item drops fromt the specified block
*/
public static Collection<ItemStack> getDrops(final Block block, final Material type, final BlockData data) {
final BlockState tempstate = block.getState();
block.setType(type);
block.setBlockData(data);
final Collection<ItemStack> item = block.getDrops();
tempstate.update(true);
return item;
}
/**
* Gets a {@code List<Entity>} of entities around a specified radius from
* the specified area
*
* @param location The base location
* @param radius The radius of blocks to look for entities from the location
* @return A list of entities around a point
*/
public static List<Entity> getEntitiesAroundPoint(final Location location, final double radius) {
return new ArrayList<>(location.getWorld().getNearbyEntities(location, radius, radius, radius, entity -> !(entity.isDead() || (entity instanceof Player && ((Player) entity).getGameMode().equals(GameMode.SPECTATOR)))));
}
public static long getGlobalCooldown() {
return ConfigManager.defaultConfig.get().getLong("Properties.GlobalCooldown");
}
/**
*
* @param one One location being tested
* @param two Another location being tested
* @return The horizontal distance between two locations
*/
public static double getHorizontalDistance(final Location one, final Location two) {
final double x = one.getX() - two.getX();
final double z = one.getZ() - two.getZ();
return Math.sqrt((x * x) + (z * z));
}
public static int getIntCardinalDirection(final Vector vector) {
final BlockFace face = getCardinalDirection(vector);
switch (face) {
case SOUTH:
return 7;
case SOUTH_WEST:
return 6;
case WEST:
return 3;
case NORTH_WEST:
return 0;
case NORTH:
return 1;
case NORTH_EAST:
return 2;
case EAST:
return 5;
case SOUTH_EAST:
return 8;
default:
return 4;
}
}
public static Plugin getItems() {
if (hasItems()) {
return Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraItems");
}
return null;
}
/**
* Returns the last ability used by a player. Also checks if a combo was
* used.
*
* @param player The player to check
* @return name of last ability used
*/
public static String getLastUsedAbility(final Player player, final boolean checkCombos) {
final List<AbilityInformation> lastUsedAbility = ComboManager.getRecentlyUsedAbilities(player, 1);
if (!lastUsedAbility.isEmpty()) {
if (ComboManager.checkForValidCombo(player) != null && checkCombos) {
return ComboManager.checkForValidCombo(player).getName();
} else {
return lastUsedAbility.get(0).getAbilityName();
}
}
return null;
}
/**
* Gets a location with a specified distance away from the left side of a
* location.
*
* @param location The origin location
* @param distance The distance to the left
* @return the location of the distance to the left
*/
public static Location getLeftSide(final Location location, final double distance) {
final float angle = location.getYaw() / 60;
return location.clone().add(new Vector(Math.cos(angle), 0, Math.sin(angle)).normalize().multiply(distance));
}
public static int getMaxPresets(final Player player) {
final int max = ConfigManager.getConfig().getInt("Properties.MaxPresets");
if (player.isOp()) {
return max;
}
for (int i = max; i > 0; i--) {
if (player.hasPermission("bending.command.preset.create." + i)) {
return i;
}
}
return 0;
}
public static Vector getOrthogonalVector(final Vector axis, final double degrees, final double length) {
Vector ortho = new Vector(axis.getY(), -axis.getX(), 0);
ortho = ortho.normalize();
ortho = ortho.multiply(length);
return rotateVectorAroundVector(axis, ortho, degrees);
}
public static Collection<Player> getPlayersAroundPoint(final Location location, final double distance) {
final Collection<Player> players = new HashSet<Player>();
for (final Player player : Bukkit.getOnlinePlayers()) {
if (player.getLocation().getWorld().equals(location.getWorld())) {
if (player.getLocation().distanceSquared(location) <= distance * distance) {
players.add(player);
}
}
}
return players;
}
public static Location getPointOnLine(final Location origin, final Location target, final double distance) {
return origin.clone().add(getDirection(origin, target).normalize().multiply(distance));
}
/**
* Returns a location with a specified distance away from the right side of
* a location.
*
* @param location The origin location
* @param distance The distance to the right
* @return the location of the distance to the right
*/
public static Location getRightSide(final Location location, final double distance) {
final float angle = location.getYaw() / 60;
return location.clone().subtract(new Vector(Math.cos(angle), 0, Math.sin(angle)).normalize().multiply(distance));
}
public static Location getMainHandLocation(final Player player) {
Location loc;
if (player.getMainHand() == MainHand.LEFT) {
loc = GeneralMethods.getLeftSide(player.getLocation(), .55).add(0, 1.2, 0);
} else {
loc = GeneralMethods.getRightSide(player.getLocation(), .55).add(0, 1.2, 0);
}
return loc;
}
public static Plugin getProbending() {
if (hasProbending()) {
return Bukkit.getServer().getPluginManager().getPlugin("Probending");
}
return null;
}
public static Plugin getRPG() {
if (hasRPG()) {
return Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraRPG");
}
return null;
}
public static Plugin getSpirits() {
if (hasSpirits()) {
return Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraSpirits");
}
return null;
}
public static BlockData getLavaData(final int level) {
return Material.LAVA.createBlockData(d -> ((Levelled) d).setLevel((level < 0 || level > ((Levelled) d).getMaximumLevel()) ? 0 : level));
}
public static BlockData getWaterData(final int level) {
return Material.WATER.createBlockData(d -> ((Levelled) d).setLevel((level < 0 || level > ((Levelled) d).getMaximumLevel()) ? 0 : level));
}
public static Entity getTargetedEntity(final Player player, final double range, final List<Entity> avoid) {
double longestr = range + 1;
Entity target = null;
final Location origin = player.getEyeLocation();
final Vector direction = player.getEyeLocation().getDirection().normalize();
for (final Entity entity : getEntitiesAroundPoint(origin, range)) {
if (entity instanceof Player) {
if (((Player) entity).isDead() || ((Player) entity).getGameMode().equals(GameMode.SPECTATOR)) {
continue;
}
}
if (avoid.contains(entity)) {
continue;
}
if (entity.getWorld().equals(origin.getWorld())) {
if (entity.getLocation().distanceSquared(origin) < longestr * longestr && getDistanceFromLine(direction, origin, entity.getLocation()) < 2 && (entity instanceof LivingEntity) && entity.getEntityId() != player.getEntityId() && entity.getLocation().distanceSquared(origin.clone().add(direction)) < entity.getLocation().distanceSquared(origin.clone().add(direction.clone().multiply(-1)))) {
target = entity;
longestr = entity.getLocation().distance(origin);
}
}
}
if (target != null) {
if (GeneralMethods.isObstructed(origin, target.getLocation())) {
target = null;
}
}
return target;
}
public static Entity getTargetedEntity(final Player player, final double range) {
return getTargetedEntity(player, range, new ArrayList<Entity>());
}
public static Location getTargetedLocation(final Player player, final double range, final boolean ignoreTempBlocks, final boolean checkDiagonals, final Material... nonOpaque2) {
final Location origin = player.getEyeLocation();
final Vector direction = origin.getDirection();
final HashSet<Material> trans = new HashSet<Material>();
trans.add(Material.AIR);
trans.add(Material.CAVE_AIR);
trans.add(Material.VOID_AIR);
if (nonOpaque2 != null) {
for (final Material material : nonOpaque2) {
trans.add(material);
}
}
final Location location = origin.clone();
final Vector vec = direction.normalize().multiply(0.2);
for (double i = 0; i < range; i += 0.2) {
location.add(vec);
if (checkDiagonals && checkDiagonalWall(location, vec)) {
location.subtract(vec);
break;
}
final Block block = location.getBlock();
if (trans.contains(block.getType())) {
continue;
} else if (ignoreTempBlocks && (TempBlock.isTempBlock(block) && !WaterAbility.isBendableWaterTempBlock(block) && !EarthAbility.isBendableEarthTempBlock(block))) {
continue;
} else {
location.subtract(vec);
break;
}
}
return location;
}
public static Location getTargetedLocation(final Player player, final double range, final boolean ignoreTempBlocks, final Material... nonOpaque2) {
return getTargetedLocation(player, range, ignoreTempBlocks, true, nonOpaque2);
}
public static Location getTargetedLocation(final Player player, final double range, final Material... nonOpaque2) {
return getTargetedLocation(player, range, false, nonOpaque2);
}
public static Location getTargetedLocation(final Player player, final int range) {
return getTargetedLocation(player, range, false);
}
public static Block getTopBlock(final Location loc, final int range) {
return getTopBlock(loc, range, range);
}
/**
* Returns the top block based around loc. PositiveY is the maximum amount
* of distance it will check upward. Similarly, negativeY is for downward.
*/
public static Block getTopBlock(final Location loc, final int positiveY, final int negativeY) {
Block blockHolder = loc.getBlock();
int y = 0;
// Only one of these while statements will go
while (!ElementalAbility.isAir(blockHolder.getType()) && Math.abs(y) < Math.abs(positiveY)) {
y++;
final Block tempBlock = loc.clone().add(0, y, 0).getBlock();
if (ElementalAbility.isAir(tempBlock.getType())) {
return blockHolder;
}
blockHolder = tempBlock;
}
while (ElementalAbility.isAir(blockHolder.getType()) && Math.abs(y) < Math.abs(negativeY)) {
y--;
blockHolder = loc.clone().add(0, y, 0).getBlock();
if (!ElementalAbility.isAir(blockHolder.getType())) {
return blockHolder;
}
}
return blockHolder;
}
public static Block getBottomBlock(final Location loc, final int positiveY, final int negativeY) {
Block blockHolder = loc.getBlock();
int y = 0;
// Only one of these while statements will go
while (!ElementalAbility.isAir(blockHolder.getType()) && Math.abs(y) < Math.abs(negativeY)) {
y--;
final Block tempblock = loc.clone().add(0, y, 0).getBlock();
if (ElementalAbility.isAir(tempblock.getType())) {
return blockHolder;
}
blockHolder = tempblock;
}
while (!ElementalAbility.isAir(blockHolder.getType()) && Math.abs(y) < Math.abs(positiveY)) {
y++;
blockHolder = loc.clone().add(0, y, 0).getBlock();
if (ElementalAbility.isAir(blockHolder.getType())) {
return blockHolder;
}
}
return blockHolder;
}
public static ArrayList<Element> getElementsWithNoWeaponBending() {
final ArrayList<Element> elements = new ArrayList<Element>();
if (!plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) {
elements.add(Element.AIR);
}
if (!plugin.getConfig().getBoolean("Properties.Water.CanBendWithWeapons")) {
elements.add(Element.WATER);
}
if (!plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) {
elements.add(Element.EARTH);
}
if (!plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) {
elements.add(Element.FIRE);
}
if (!plugin.getConfig().getBoolean("Properties.Chi.CanBendWithWeapons")) {
elements.add(Element.CHI);
}
return elements;
}
public static boolean hasItems() {
return Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraItems") != null;
}
public static boolean hasProbending() {
return Bukkit.getServer().getPluginManager().getPlugin("Probending") != null;
}
public static boolean hasRPG() {
return Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraRPG") != null;
}
public static boolean hasSpirits() {
return Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraSpirits") != null;
}
public static boolean isArmor(Material mat) {
switch (mat) {
case NETHERITE_HELMET:
case NETHERITE_CHESTPLATE:
case NETHERITE_LEGGINGS:
case NETHERITE_BOOTS:
case DIAMOND_HELMET:
case DIAMOND_CHESTPLATE:
case DIAMOND_LEGGINGS:
case DIAMOND_BOOTS:
case TURTLE_HELMET:
case IRON_HELMET:
case IRON_CHESTPLATE:
case IRON_LEGGINGS:
case IRON_BOOTS:
case CHAINMAIL_HELMET:
case CHAINMAIL_CHESTPLATE:
case CHAINMAIL_LEGGINGS:
case CHAINMAIL_BOOTS:
case GOLDEN_HELMET:
case GOLDEN_CHESTPLATE:
case GOLDEN_LEGGINGS:
case GOLDEN_BOOTS:
case LEATHER_HELMET:
case LEATHER_CHESTPLATE:
case LEATHER_LEGGINGS:
case LEATHER_BOOTS:
return true;
default:
return false;
}
}
public static boolean isAdjacentToThreeOrMoreSources(final Block block) {
return isAdjacentToThreeOrMoreSources(block, false);
}
public static boolean isAdjacentToThreeOrMoreSources(final Block block, final boolean lava) {
if (block == null || (TempBlock.isTempBlock(block) && (!lava && !WaterAbility.isBendableWaterTempBlock(block)))) {
return false;
}
int sources = 0;
final BlockFace[] faces = { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH };
for (final BlockFace face : faces) {
final Block blocki = block.getRelative(face);
if (lava) {
if (!(blocki.getType() == Material.LAVA && EarthPassive.canPhysicsChange(blocki))) {
continue;
}
} else {
if (!((ElementalAbility.isWater(blocki) || ElementalAbility.isIce(blocki)) && WaterManipulation.canPhysicsChange(blocki))) {
continue;
}
}
//At this point it should either be water or lava
if (blocki.getBlockData() instanceof Levelled) {
final Levelled level = (Levelled) blocki.getBlockData();
if (level.getLevel() == 0) {
sources++;
}
} else { //ice
sources++;
}
}
return sources >= 2;
}
public static boolean isImportEnabled() {
return ConfigManager.defaultConfig.get().getBoolean("Properties.ImportEnabled");
}
public static boolean isInteractable(final Block block) {
return isInteractable(block.getType());
}
public static boolean isInteractable(final Material material) {
return material.isInteractable();
}
public static boolean isObstructed(final Location location1, final Location location2) {
final Vector loc1 = location1.toVector();
final Vector loc2 = location2.toVector();
final Vector direction = loc2.subtract(loc1);
direction.normalize();
Location loc;
double max = 0;
if (location1.getWorld().equals(location2.getWorld())) {
max = location1.distance(location2);
}
for (double i = 0; i <= max; i++) {
loc = location1.clone().add(direction.clone().multiply(i));
final Material type = loc.getBlock().getType();
if (type != Material.AIR && !(ElementalAbility.getTransparentMaterialSet().contains(type) || ElementalAbility.isWater(loc.getBlock()))) {
return true;
}
}
return false;
}
/**
* isRegionProtectedFromBuild is one of the most server intensive methods in
* the plugin. It uses a blockCache that keeps track of recent blocks that
* may have already been checked. Abilities like TremorSense call this
* ability 5 times per tick even though it only needs to check a single
* block, instead of doing all 5 of those checks this method will now look
* in the map first.
*/
public static boolean isRegionProtectedFromBuild(final Player player, final String ability, final Location loc) {
if (!BLOCK_CACHE.containsKey(player.getName())) {
BLOCK_CACHE.put(player.getName(), new ConcurrentHashMap<Block, BlockCacheElement>());
}
final Map<Block, BlockCacheElement> blockMap = BLOCK_CACHE.get(player.getName());
final Block block = loc.getBlock();
if (blockMap.containsKey(block)) {
final BlockCacheElement elem = blockMap.get(block);
// both abilities must be equal to each other to use the cache
if ((ability == null && elem.getAbility() == null) || (ability != null && elem.getAbility() != null && elem.getAbility().equals(ability))) {
return elem.isAllowed();
}
}
final boolean value = isRegionProtectedFromBuildPostCache(player, ability, loc);
blockMap.put(block, new BlockCacheElement(player, block, ability, value, System.currentTimeMillis()));
return value;
}
public static boolean isRegionProtectedFromBuild(final Ability ability, final Location loc) {
return isRegionProtectedFromBuild(ability.getPlayer(), ability.getName(), loc);
}
public static boolean isRegionProtectedFromBuild(final Player player, final Location loc) {
return isRegionProtectedFromBuild(player, null, loc);
}
public static boolean isRegionProtectedFromBuildPostCache(final Player player, final String ability, final Location loc) {
final boolean allowHarmless = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.AllowHarmlessAbilities");
final boolean respectWorldGuard = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectWorldGuard");
//final boolean respectPreciousStones = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectPreciousStones");
final boolean respectFactions = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectFactions");
final boolean respectTowny = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectTowny");
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.Respect");
final boolean respectRedProtect = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectRedProtect");
boolean isIgnite = false;
boolean isExplosive = false;
boolean isHarmless = false;
final CoreAbility coreAbil = CoreAbility.getAbility(ability);
if (coreAbil != null) {
isIgnite = coreAbil.isIgniteAbility();
isExplosive = coreAbil.isExplosiveAbility();
isHarmless = coreAbil.isHarmlessAbility();
}
if (ability == null && allowHarmless) {
return false;
}
if (isHarmless && allowHarmless) {
return false;
}
final PluginManager pm = Bukkit.getPluginManager();
final Plugin wgp = pm.getPlugin("WorldGuard");
//final Plugin psp = pm.getPlugin("PreciousStones");
final Plugin facsfw = pm.getPlugin("FactionsFramework");
final Plugin twnp = pm.getPlugin("Towny");
final Plugin gpp = pm.getPlugin("GriefPrevention");
final Plugin lwc = pm.getPlugin("LWC");
final Plugin residence = pm.getPlugin("Residence");
final Plugin kingdoms = pm.getPlugin("Kingdoms");
final Plugin redprotect = pm.getPlugin("RedProtect");
for (final Location location : new Location[] { loc, player.getLocation() }) {
final World world = location.getWorld();
if (lwc != null && respectLWC) {
final LWCPlugin lwcp = (LWCPlugin) lwc;
final LWC lwc2 = lwcp.getLWC();
final Protection protection = lwc2.getProtectionCache().getProtection(location.getBlock());
if (protection != null) {
if (!lwc2.canAccessProtection(player, protection)) {
return true;
}
}
}
if (wgp != null && respectWorldGuard && !player.hasPermission("worldguard.region.bypass." + world.getName())) {
final WorldGuard wg = WorldGuard.getInstance();
if (!player.isOnline()) {
return true;
}
if (isIgnite) {
if (!player.hasPermission("worldguard.override.lighter")) {
if (wg.getPlatform().getGlobalStateManager().get(BukkitAdapter.adapt(world)).blockLighter) {
return true;
}
}
}
if (isExplosive) {
if (wg.getPlatform().getGlobalStateManager().get(BukkitAdapter.adapt(location.getWorld())).blockTNTExplosions) {
return true;
}
final StateFlag.State tntflag = wg.getPlatform().getRegionContainer().createQuery().queryState(BukkitAdapter.adapt(location), WorldGuardPlugin.inst().wrapPlayer(player), Flags.TNT);
if (tntflag != null && tntflag.equals(StateFlag.State.DENY)) {
return true;
}
}
final StateFlag bendingflag = (StateFlag) WorldGuard.getInstance().getFlagRegistry().get("bending");
if (bendingflag != null) {
final StateFlag.State bendingflagstate = wg.getPlatform().getRegionContainer().createQuery().queryState(BukkitAdapter.adapt(location), WorldGuardPlugin.inst().wrapPlayer(player), bendingflag);
if (bendingflagstate == null && !wg.getPlatform().getRegionContainer().createQuery().testState(BukkitAdapter.adapt(location), WorldGuardPlugin.inst().wrapPlayer(player), Flags.BUILD)) {
return true;
}
if (bendingflagstate != null && bendingflagstate.equals(StateFlag.State.DENY)) {
return true;
}
} else {
if (!wg.getPlatform().getRegionContainer().createQuery().testState(BukkitAdapter.adapt(location), WorldGuardPlugin.inst().wrapPlayer(player), Flags.BUILD)) {
return true;
}
}
}
if (facsfw != null && respectFactions) {
final FPlayer fPlayer = FPlayers.getBySender(player);
final Faction faction = Factions.getFactionAt(location);
final Rel relation = fPlayer.getRelationTo(faction);
if (!(faction.isNone() || fPlayer.getFaction().equals(faction) || relation == Rel.ALLY)) {
return true;
}
}
if (twnp != null && respectTowny) {
if (!PlayerCacheUtil.getCachePermission(player, location, Material.DIRT, ActionType.BUILD)) {
return true;
}
}
if (gpp != null && respectGriefPrevention) {
Material type = player.getWorld().getBlockAt(location).getType();
if (type == null) {
type = Material.AIR;
}
final String reason = GriefPrevention.instance.allowBuild(player, location); // WORKING with WorldGuard 6.0 BETA 4.
final Claim claim = GriefPrevention.instance.dataStore.getClaimAt(loc, true, null);
if (reason != null && claim != null) {
return true;
}
}
if (residence != null && respectResidence) {
final ResidenceInterface res = Residence.getInstance().getResidenceManagerAPI();
final ClaimedResidence claim = res.getByLoc(location);
if (claim != null) {
final ResidencePermissions perms = claim.getPermissions();
if (!perms.hasApplicableFlag(player.getName(), ConfigManager.getConfig().getString("Properties.RegionProtection.Residence.Flag"))) {
return true;
}
}
}
if (kingdoms != null && respectKingdoms) {
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) {
final RedProtectAPI api = RedProtect.get().getAPI();
final Region region = api.getRegion(location);
if (!(region != null && region.canBuild(player))) {
return true;
}
}
}
return false;
}
public static boolean isSameArmor(Material a, Material b) {
int ai = getArmorIndex(a), bi = getArmorIndex(b);
if (ai == -1 || bi == -1) {
return false;
}
return ai == bi;
}
public static boolean isSolid(final Block block) {
return isSolid(block.getType());
}
public static boolean isSolid(final Material material) {
return material.isSolid();
}
public static boolean isTransparent(final Block block) {
return isTransparent(block.getType());
}
public static boolean isTransparent(final Material material) {
return !material.isOccluding() && !material.isSolid();
}
/** Checks if an entity is Undead **/
public static boolean isUndead(final Entity entity) {
if (entity == null) {
return false;
}
switch (entity.getType()) {
case SKELETON:
case STRAY:
case WITHER_SKELETON:
case WITHER:
case ZOMBIE:
case HUSK:
case ZOMBIE_VILLAGER:
case ZOMBIFIED_PIGLIN:
case ZOGLIN:
case DROWNED:
case ZOMBIE_HORSE:
case SKELETON_HORSE:
case PHANTOM:
return true;
default:
return false;
}
}
public static boolean isWeapon(final Material mat) {
switch(mat) {
case BOW:
case CROSSBOW:
case DIAMOND_AXE:
case DIAMOND_HOE:
case DIAMOND_PICKAXE:
case DIAMOND_SHOVEL:
case DIAMOND_SWORD:
case GOLDEN_AXE:
case GOLDEN_HOE:
case GOLDEN_PICKAXE:
case GOLDEN_SHOVEL:
case GOLDEN_SWORD:
case IRON_AXE:
case IRON_HOE:
case IRON_PICKAXE:
case IRON_SHOVEL:
case IRON_SWORD:
case NETHERITE_AXE:
case NETHERITE_HOE:
case NETHERITE_PICKAXE:
case NETHERITE_SHOVEL:
case NETHERITE_SWORD:
case STONE_AXE:
case STONE_HOE:
case STONE_PICKAXE:
case STONE_SHOVEL:
case STONE_SWORD:
case TRIDENT:
case WOODEN_AXE:
case WOODEN_HOE:
case WOODEN_PICKAXE:
case WOODEN_SHOVEL:
case WOODEN_SWORD:
return true;
default:
return false;
}
}
public static void loadBendingPlayer(final BendingPlayer pl) {
final Player player = Bukkit.getPlayer(pl.getUUID());
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
if (bPlayer == null) {
return;
}
if (PKListener.getToggledOut().contains(player.getUniqueId())) {
bPlayer.toggleBending();
player.sendMessage(ChatColor.YELLOW + "Reminder, you toggled your bending before signing off. Enable it again with /bending toggle.");
}
Preset.loadPresets(player);
Element element = null;
String prefix = "";
final boolean chatEnabled = ConfigManager.languageConfig.get().getBoolean("Chat.Enable");
prefix = ChatColor.WHITE + ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Chat.Prefixes.Nonbender")) + " ";
if (player.hasPermission("bending.avatar") || (bPlayer.hasElement(Element.AIR) && bPlayer.hasElement(Element.EARTH) && bPlayer.hasElement(Element.FIRE) && bPlayer.hasElement(Element.WATER))) {
prefix = Element.AVATAR.getPrefix();
} else if (bPlayer.getElements().size() > 0) {
element = bPlayer.getElements().get(0);
prefix = element.getPrefix();
}
if (chatEnabled) {
player.setDisplayName(player.getName());
player.setDisplayName(prefix + ChatColor.RESET + player.getDisplayName());
}
// Handle the AirSpout/WaterSpout login glitches.
if (player.getGameMode() != GameMode.CREATIVE) {
final HashMap<Integer, String> bound = bPlayer.getAbilities();
for (final String str : bound.values()) {
if (str.equalsIgnoreCase("AirSpout") || str.equalsIgnoreCase("WaterSpout") || str.equalsIgnoreCase("SandSpout")) {
final Player fplayer = player;
new BukkitRunnable() {
@Override
public void run() {
fplayer.setFlying(false);
fplayer.setAllowFlight(false);
}
}.runTaskLater(ProjectKorra.plugin, 2);
break;
}
}
}
Bukkit.getServer().getPluginManager().callEvent(new BendingPlayerCreationEvent(bPlayer));
}
public static void reloadPlugin(final CommandSender sender) {
ProjectKorra.log.info("Reloading ProjectKorra and configuration");
final BendingReloadEvent event = new BendingReloadEvent(sender);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
sender.sendMessage(ChatColor.RED + "Reload event cancelled");
return;
}
if (DBConnection.isOpen()) {
DBConnection.sql.close();
}
GeneralMethods.stopBending();
ConfigManager.defaultConfig.reload();
ConfigManager.languageConfig.reload();
ConfigManager.presetConfig.reload();
Preset.loadExternalPresets();
new MultiAbilityManager();
new ComboManager();
// Stop the previous collision detection task before creating new manager.
ProjectKorra.collisionManager.stopCollisionDetection();
ProjectKorra.collisionManager = new CollisionManager();
ProjectKorra.collisionInitializer = new CollisionInitializer(ProjectKorra.collisionManager);
CoreAbility.registerAbilities();
reloadAddonPlugins();
ProjectKorra.collisionInitializer.initializeDefaultCollisions(); // must be called after abilities have been registered.
ProjectKorra.collisionManager.startCollisionDetection();
DBConnection.init();
if (!DBConnection.isOpen()) {
ProjectKorra.log.severe("Unable to enable ProjectKorra due to the database not being open");
stopPlugin();
}
for (final Player player : Bukkit.getOnlinePlayers()) {
Preset.unloadPreset(player);
GeneralMethods.createBendingPlayer(player.getUniqueId(), player.getName());
PassiveManager.registerPassives(player);
}
BendingBoardManager.reload();
plugin.updater.checkUpdate();
ProjectKorra.log.info("Reload complete");
}
public static void reloadAddonPlugins() {
for (int i = CoreAbility.getAddonPlugins().size() - 1; i > -1; i--) {
final String entry = CoreAbility.getAddonPlugins().get(i);
final String[] split = entry.split("::");
if (Bukkit.getServer().getPluginManager().isPluginEnabled(split[0])) {
CoreAbility.registerPluginAbilities((JavaPlugin) Bukkit.getServer().getPluginManager().getPlugin(split[0]), split[1]);
} else {
CoreAbility.getAddonPlugins().remove(i);
}
}
}
public static void removeBlock(final Block block) {
if (isAdjacentToThreeOrMoreSources(block, false)) {
block.setType(Material.WATER);
if (block.getBlockData() instanceof Levelled) {
((Levelled) block.getBlockData()).setLevel(1);
}
} else {
block.setType(Material.AIR);
}
}
public static void removeUnusableAbilities(final String player) {
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
if (bPlayer == null) {
return;
}
// Remove all active instances of abilities that will become unusable.
// We need to do this prior to filtering binds in case the player has a MultiAbility running.
for (final CoreAbility coreAbility : CoreAbility.getAbilities()) {
final CoreAbility playerAbility = CoreAbility.getAbility(bPlayer.getPlayer(), coreAbility.getClass());
if (playerAbility != null) {
if (playerAbility instanceof PassiveAbility && PassiveManager.hasPassive(bPlayer.getPlayer(), playerAbility)) {
// The player will be able to keep using the given PassiveAbility.
continue;
} else if (bPlayer.canBend(playerAbility)) {
// The player will still be able to use this given Ability, do not end it.
continue;
}
playerAbility.remove();
}
}
// Remove all bound abilities that will become unusable.
final HashMap<Integer, String> slots = bPlayer.getAbilities();
final HashMap<Integer, String> finalAbilities = new HashMap<Integer, String>();
for (final int i : slots.keySet()) {
if (bPlayer.canBind(CoreAbility.getAbility(slots.get(i)))) {
// The player will still be able to use this given Ability, do not remove it from their binds.
finalAbilities.put(i, slots.get(i));
}
}
bPlayer.setAbilities(finalAbilities);
}
public static Vector rotateVectorAroundVector(final Vector axis, final Vector rotator, final double degrees) {
final double angle = Math.toRadians(degrees);
Vector rotation = axis.clone();
final Vector rotate = rotator.clone();
rotation = rotation.normalize();
final Vector thirdaxis = rotation.crossProduct(rotate).normalize().multiply(rotate.length());
return rotate.multiply(Math.cos(angle)).add(thirdaxis.multiply(Math.sin(angle)));
}
/**
* Rotates a vector around the Y plane.
*/
public static Vector rotateXZ(final Vector vec, final double theta) {
final Vector vec2 = vec.clone();
final double x = vec2.getX();
final double z = vec2.getZ();
vec2.setX(x * Math.cos(Math.toRadians(theta)) - z * Math.sin(Math.toRadians(theta)));
vec2.setZ(x * Math.sin(Math.toRadians(theta)) + z * Math.cos(Math.toRadians(theta)));
return vec2;
}
public static void runDebug() {
final File debugFile = new File(plugin.getDataFolder(), "debug.txt");
if (debugFile.exists()) {
debugFile.delete(); // We're starting brand new.
}
writeToDebug("ProjectKorra Debug: Paste this on http://pastie.org and put it in your bug report thread.");
writeToDebug("====================");
writeToDebug("");
writeToDebug("");
writeToDebug("Date Created: " + getCurrentDate());
writeToDebug("Java Version: " + Runtime.class.getPackage().getImplementationVersion());
writeToDebug("Bukkit Version: " + Bukkit.getServer().getVersion());
writeToDebug("");
writeToDebug("ProjectKorra (Core) Information");
writeToDebug("====================");
writeToDebug("Version: " + plugin.getDescription().getVersion());
writeToDebug("Author: " + plugin.getDescription().getAuthors());
final List<String> officialSidePlugins = new ArrayList<String>();
if (hasRPG()) {
officialSidePlugins.add("ProjectKorra RPG v" + getRPG().getDescription().getVersion());
}
if (hasItems()) {
officialSidePlugins.add("ProjectKorra Items v" + getItems().getDescription().getVersion());
}
if (hasSpirits()) {
officialSidePlugins.add("ProjectKorra Spirits v" + getSpirits().getDescription().getVersion());
}
if (hasProbending()) {
officialSidePlugins.add("Probending v" + getProbending().getDescription().getVersion());
}
if (!officialSidePlugins.isEmpty()) {
writeToDebug("");
writeToDebug("ProjectKorra (Side Plugin) Information");
writeToDebug("====================");
for (final String line : officialSidePlugins) {
writeToDebug(line);
}
}
writeToDebug("");
writeToDebug("Supported Plugins");
writeToDebug("====================");
final boolean respectWorldGuard = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectWorldGuard");
final boolean respectPreciousStones = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectPreciousStones");
final boolean respectFactions = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectFactions");
final boolean respectTowny = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RespectTowny");
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.Respect");
final boolean respectRedProtect = ConfigManager.defaultConfig.get().getBoolean("Properties.RegionProtection.RedProtect");
final PluginManager pm = Bukkit.getPluginManager();
final Plugin wgp = pm.getPlugin("WorldGuard");
final Plugin psp = pm.getPlugin("PreciousStones");
final Plugin fcp = pm.getPlugin("FactionsFramework");
final Plugin twnp = pm.getPlugin("Towny");
final Plugin gpp = pm.getPlugin("GriefPrevention");
final Plugin lwc = pm.getPlugin("LWC");
final Plugin residence = pm.getPlugin("Residence");
final Plugin kingdoms = pm.getPlugin("Kingdoms");
final Plugin redprotect = pm.getPlugin("RedProtect");
if (wgp != null && respectWorldGuard) {
writeToDebug("WorldGuard v" + wgp.getDescription().getVersion());
}
if (psp != null && respectPreciousStones) {
writeToDebug("PreciousStones v" + psp.getDescription().getVersion());
}
if (fcp != null && respectFactions) {
writeToDebug("FactionsFramework v" + fcp.getDescription().getVersion());
}
if (twnp != null && respectTowny) {
writeToDebug("Towny v" + twnp.getDescription().getVersion());
}
if (gpp != null && respectGriefPrevention) {
writeToDebug("GriefPrevention v" + gpp.getDescription().getVersion());
}
if (lwc != null && respectLWC) {
writeToDebug("LWC v" + lwc.getDescription().getVersion());
}
if (residence != null && respectResidence) {
writeToDebug("Residence v" + residence.getDescription().getVersion());
}
if (kingdoms != null && respectKingdoms) {
writeToDebug("Kingdoms v" + kingdoms.getDescription().getVersion());
}
if (redprotect != null && respectRedProtect) {
writeToDebug("RedProtect v" + redprotect.getDescription().getVersion());
}
writeToDebug("");
writeToDebug("Plugins Hooking Into ProjectKorra (Core)");
writeToDebug("====================");
final String[] pkPlugins = new String[] { "projectkorrarpg", "projectkorraitems", "projectkorraspirits", "probending" };
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (plugin.getDescription().getDepend() != null && plugin.getDescription().getDepend().contains("ProjectKorra") && !Arrays.asList(pkPlugins).contains(plugin.getName().toLowerCase())) {
writeToDebug(plugin.getDescription().getName() + " v" + plugin.getDescription().getVersion());
}
}
writeToDebug("");
writeToDebug("Ability Information");
writeToDebug("====================");
final ArrayList<String> stockAbils = new ArrayList<String>();
final ArrayList<String> unofficialAbils = new ArrayList<String>();
for (final CoreAbility ability : CoreAbility.getAbilities()) {
if (ability.getClass().getPackage().getName().startsWith("com.projectkorra")) {
stockAbils.add(ability.getName());
} else {
unofficialAbils.add(ability.getName());
}
}
if (!stockAbils.isEmpty()) {
Collections.sort(stockAbils);
for (final String ability : stockAbils) {
writeToDebug(ability + " - STOCK");
}
}
if (!unofficialAbils.isEmpty()) {
Collections.sort(unofficialAbils);
for (final String ability : unofficialAbils) {
writeToDebug(ability + " - UNOFFICAL");
}
}
writeToDebug("");
writeToDebug("Collection Sizes");
writeToDebug("====================");
final ClassLoader loader = ProjectKorra.class.getClassLoader();
try {
for (final ClassPath.ClassInfo info : ClassPath.from(loader).getTopLevelClasses()) {
if (info.getName().startsWith("com.projectkorra.") && !info.getName().contains("hooks")) {
try {
final Class<?> clazz = info.load();
for (final Field field : clazz.getDeclaredFields()) {
final String simpleName = clazz.getSimpleName();
field.setAccessible(true);
try {
final Object obj = field.get(null);
if (obj instanceof Collection) {
writeToDebug(simpleName + ": " + field.getName() + " size=" + ((Collection<?>) obj).size());
} else if (obj instanceof Map) {
writeToDebug(simpleName + ": " + field.getName() + " size=" + ((Map<?, ?>) obj).size());
}
} catch (final Exception e) {
}
}
} catch (Exception e) {
continue;
}
}
}
} catch (final IOException e) {
e.printStackTrace();
}
writeToDebug("");
writeToDebug("CoreAbility Debugger");
writeToDebug("====================");
for (final String line : CoreAbility.getDebugString().split("\\n")) {
writeToDebug(line);
}
}
public static void saveAbility(final BendingPlayer bPlayer, final int slot, final String ability) {
if (bPlayer == null) {
return;
}
final String uuid = bPlayer.getUUIDString();
final PlayerBindChangeEvent event = new PlayerBindChangeEvent(Bukkit.getPlayer(UUID.fromString(uuid)), ability, slot, false);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
// Temp code to block modifications of binds, Should be replaced when bind event is added.
if (MultiAbilityManager.playerAbilities.containsKey(Bukkit.getPlayer(bPlayer.getUUID()))) {
return;
}
final HashMap<Integer, String> abilities = bPlayer.getAbilities();
DBConnection.sql.modifyQuery("UPDATE pk_players SET slot" + slot + " = '" + (abilities.get(slot) == null ? null : abilities.get(slot)) + "' WHERE uuid = '" + uuid + "'");
}
public static void saveElements(final BendingPlayer bPlayer) {
if (bPlayer == null) {
return;
}
final String uuid = bPlayer.getUUIDString();
final StringBuilder elements = new StringBuilder();
if (bPlayer.hasElement(Element.AIR)) {
elements.append("a");
}
if (bPlayer.hasElement(Element.WATER)) {
elements.append("w");
}
if (bPlayer.hasElement(Element.EARTH)) {
elements.append("e");
}
if (bPlayer.hasElement(Element.FIRE)) {
elements.append("f");
}
if (bPlayer.hasElement(Element.CHI)) {
elements.append("c");
}
boolean hasAddon = false;
for (final Element element : bPlayer.getElements()) {
if (Arrays.asList(Element.getAddonElements()).contains(element)) {
if (!hasAddon) {
hasAddon = true;
elements.append(";");
}
elements.append(element.getName() + ",");
}
}
if (elements.length() == 0) {
elements.append("NULL");
}
DBConnection.sql.modifyQuery("UPDATE pk_players SET element = '" + elements.toString() + "' WHERE uuid = '" + uuid + "'");
}
public static void saveSubElements(final BendingPlayer bPlayer) {
if (bPlayer == null) {
return;
}
final String uuid = bPlayer.getUUIDString();
final StringBuilder subs = new StringBuilder();
if (bPlayer.hasSubElement(Element.METAL)) {
subs.append("m");
}
if (bPlayer.hasSubElement(Element.LAVA)) {
subs.append("v");
}
if (bPlayer.hasSubElement(Element.SAND)) {
subs.append("s");
}
if (bPlayer.hasSubElement(Element.COMBUSTION)) {
subs.append("c");
}
if (bPlayer.hasSubElement(Element.LIGHTNING)) {
subs.append("l");
}
if (bPlayer.hasSubElement(Element.SPIRITUAL)) {
subs.append("t");
}
if (bPlayer.hasSubElement(Element.FLIGHT)) {
subs.append("f");
}
if (bPlayer.hasSubElement(Element.ICE)) {
subs.append("i");
}
if (bPlayer.hasSubElement(Element.HEALING)) {
subs.append("h");
}
if (bPlayer.hasSubElement(Element.BLOOD)) {
subs.append("b");
}
if (bPlayer.hasSubElement(Element.PLANT)) {
subs.append("p");
}
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
subs.append("r");
}
boolean hasAddon = false;
for (final Element element : bPlayer.getSubElements()) {
if (Arrays.asList(Element.getAddonSubElements()).contains(element)) {
if (!hasAddon) {
hasAddon = true;
subs.append(";");
}
subs.append(element.getName() + ",");
}
}
if (subs.length() == 0) {
subs.append("NULL");
}
DBConnection.sql.modifyQuery("UPDATE pk_players SET subelement = '" + subs.toString() + "' WHERE uuid = '" + uuid + "'");
}
public static void savePermaRemoved(final BendingPlayer bPlayer) {
if (bPlayer == null) {
return;
}
final String uuid = bPlayer.getUUIDString();
final boolean permaRemoved = bPlayer.isPermaRemoved();
DBConnection.sql.modifyQuery("UPDATE pk_players SET permaremoved = '" + (permaRemoved ? "true" : "false") + "' WHERE uuid = '" + uuid + "'");
}
public static FallingBlock spawnFallingBlock(final Location loc, final Material type) {
return spawnFallingBlock(loc, type, type.createBlockData());
}
public static FallingBlock spawnFallingBlock(final Location loc, final Material type, final BlockData data) {
return loc.getWorld().spawnFallingBlock(loc, data);
}
public static boolean playerHeadIsInBlock(final Player player, final Block block) {
return playerHeadIsInBlock(player, block, false);
}
public static boolean playerHeadIsInBlock(final Player player, final Block block, final boolean exact) {
double checkDistance;
if (exact) {
checkDistance = 0.5;
} else {
checkDistance = 0.75;
}
return (player.getEyeLocation().getBlockY() == block.getLocation().getBlockY() && (Math.abs(player.getEyeLocation().getX() - block.getLocation().add(0.5, 0.0, 0.5).getX()) < checkDistance) && (Math.abs(player.getEyeLocation().getZ() - block.getLocation().add(0.5, 0.0, 0.5).getZ()) < checkDistance));
}
public static boolean playerFeetIsInBlock(final Player player, final Block block) {
return playerFeetIsInBlock(player, block, false);
}
public static boolean playerFeetIsInBlock(final Player player, final Block block, final boolean exact) {
double checkDistance;
if (exact) {
checkDistance = 0.5;
} else {
checkDistance = 0.75;
}
return (player.getLocation().getBlockY() == block.getLocation().getBlockY() && (Math.abs(player.getLocation().getX() - block.getLocation().add(0.5, 0.0, 0.5).getX()) < checkDistance) && (Math.abs(player.getLocation().getZ() - block.getLocation().add(0.5, 0.0, 0.5).getZ()) < checkDistance));
}
public static void sendBrandingMessage(final CommandSender sender, final String message) {
ChatColor color;
try {
color = ChatColor.valueOf(ConfigManager.languageConfig.get().getString("Chat.Branding.Color").toUpperCase());
} catch (final IllegalArgumentException exception) {
color = ChatColor.GOLD;
}
final String prefix = ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Chat.Branding.ChatPrefix.Prefix")) + color + "ProjectKorra" + ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Chat.Branding.ChatPrefix.Suffix"));
if (!(sender instanceof Player)) {
sender.sendMessage(prefix + message);
} else {
final TextComponent prefixComponent = new TextComponent(prefix);
prefixComponent.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "http://projectkorra.com/"));
prefixComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(color + "Bending brought to you by ProjectKorra!\n" + color + "Click for more info.").create()));
/*
* The commented code below does not work due to an issue with
* Spigot. In the mean time, we'll have to use this incredibly
* 'hacky' method to force the color on the new line.
*/
String lastColor = "";
String newMessage = "";
for (int i = 0; i < message.split("").length; i++) {
final String c = message.split("")[i];
if (c.equalsIgnoreCase("§")) {
lastColor = "§" + message.split("")[i + 1];
newMessage = newMessage + c;
} else if (c.equalsIgnoreCase(" ")) { // Add color every word
newMessage = newMessage + " " + lastColor;
} else {
newMessage = newMessage + c;
}
}
final TextComponent messageComponent = new TextComponent(newMessage);
((Player) sender).spigot().sendMessage(new TextComponent(prefixComponent, messageComponent));
/*
* boolean prefixSent = false; for (String msg :
* message.split("\n")) { if (!prefixSent) { TextComponent
* messageComponent = new TextComponent(msg); ((Player)
* sender).spigot().sendMessage(new TextComponent(prefixComponent,
* messageComponent)); prefixSent = true; } else {
* sender.sendMessage(msg); } }
*/
}
}
public static void startCacheCleaner(final double period) {
new BukkitRunnable() {
@Override
public void run() {
for (final Map<Block, BlockCacheElement> map : BLOCK_CACHE.values()) {
for (final Block key : map.keySet()) {
final BlockCacheElement value = map.get(key);
if (System.currentTimeMillis() - value.getTime() > period) {
map.remove(key);
}
}
}
}
}.runTaskTimer(ProjectKorra.plugin, 0, (long) (period / 20));
}
public static void stopBending() {
for (final CoreAbility ability : CoreAbility.getAbilities()) {
if (ability instanceof AddonAbility) {
((AddonAbility) ability).stop();
}
}
CoreAbility.removeAll();
EarthAbility.stopBending();
WaterAbility.stopBending();
FireAbility.stopBending();
TempBlock.removeAll();
TempArmor.revertAll();
TempArmorStand.removeAll();
MovementHandler.resetAll();
MultiAbilityManager.removeAll();
if (!INVINCIBLE.isEmpty()) {
INVINCIBLE.clear();
}
}
public static void stopPlugin() {
plugin.getServer().getPluginManager().disablePlugin(plugin);
}
public static void writeToDebug(final String message) {
try {
final File dataFolder = plugin.getDataFolder();
if (!dataFolder.exists()) {
dataFolder.mkdir();
}
final File saveTo = new File(plugin.getDataFolder(), "debug.txt");
if (saveTo.exists()) {
saveTo.delete();
}
saveTo.createNewFile();
final FileWriter fw = new FileWriter(saveTo, true);
final PrintWriter pw = new PrintWriter(fw);
pw.println(message);
pw.flush();
pw.close();
} catch (final IOException e) {
e.printStackTrace();
}
}
public static boolean locationEqualsIgnoreDirection(final Location loc1, final Location loc2) {
return loc1.getWorld().equals(loc2.getWorld()) && loc1.getX() == loc2.getX() && loc1.getY() == loc2.getY() && loc1.getZ() == loc2.getZ();
}
public static boolean isLightEmitting(final Material material) {
switch (material) {
case GLOWSTONE:
case TORCH:
case SEA_LANTERN:
case BEACON:
case REDSTONE_LAMP:
case REDSTONE_TORCH:
case MAGMA_BLOCK:
case LAVA:
case JACK_O_LANTERN:
case CRYING_OBSIDIAN:
case SHROOMLIGHT:
case CAMPFIRE:
case SOUL_CAMPFIRE:
case SOUL_TORCH:
case LANTERN:
case SOUL_LANTERN:
case CONDUIT:
case RESPAWN_ANCHOR:
case BROWN_MUSHROOM:
case BREWING_STAND:
case ENDER_CHEST:
case END_PORTAL_FRAME:
case END_ROD:
return true;
default:
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);
}
}