diff --git a/pom.xml b/pom.xml
index eace9821..413e2dae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,18 @@
commons-lang3
3.8.1
+
+
+ com.zaxxer
+ HikariCP
+ 3.4.1
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.18
+
me.markeh
@@ -244,4 +256,4 @@
${project.build.directory}
UTF-8
-
\ No newline at end of file
+
diff --git a/src/com/projectkorra/projectkorra/BendingManager.java b/src/com/projectkorra/projectkorra/BendingManager.java
index e173b0f2..62e8b3ac 100644
--- a/src/com/projectkorra/projectkorra/BendingManager.java
+++ b/src/com/projectkorra/projectkorra/BendingManager.java
@@ -1,18 +1,12 @@
package com.projectkorra.projectkorra;
-import java.util.HashMap;
-import java.util.UUID;
-
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.World;
-import org.bukkit.entity.Player;
-
+import co.aikar.timings.lib.MCTiming;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.configuration.configs.properties.FirePropertiesConfig;
import com.projectkorra.projectkorra.configuration.configs.properties.WaterPropertiesConfig;
+import com.projectkorra.projectkorra.cooldown.CooldownManager;
import com.projectkorra.projectkorra.earthbending.metal.MetalClips;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.util.ActionBar;
@@ -20,8 +14,13 @@ import com.projectkorra.projectkorra.util.RevertChecker;
import com.projectkorra.projectkorra.util.TempArmor;
import com.projectkorra.projectkorra.util.TempPotionEffect;
import com.projectkorra.projectkorra.waterbending.blood.Bloodbending;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
-import co.aikar.timings.lib.MCTiming;
+import java.util.HashMap;
+import java.util.UUID;
public class BendingManager implements Runnable {
@@ -51,6 +50,10 @@ public class BendingManager implements Runnable {
return instance;
}
+ /**
+ * @deprecated handled by {@link CooldownManager}.
+ */
+ @Deprecated
public void handleCooldowns() {
for (final UUID uuid : BendingPlayer.getPlayers().keySet()) {
final BendingPlayer bPlayer = BendingPlayer.getPlayers().get(uuid);
diff --git a/src/com/projectkorra/projectkorra/BendingPlayer.java b/src/com/projectkorra/projectkorra/BendingPlayer.java
index 66dd92cb..95a3351f 100644
--- a/src/com/projectkorra/projectkorra/BendingPlayer.java
+++ b/src/com/projectkorra/projectkorra/BendingPlayer.java
@@ -1,23 +1,5 @@
package com.projectkorra.projectkorra;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Stream;
-
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-import org.bukkit.Bukkit;
-import org.bukkit.GameMode;
-import org.bukkit.Location;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.entity.Player;
-
import com.projectkorra.projectkorra.Element.SubElement;
import com.projectkorra.projectkorra.ability.Ability;
import com.projectkorra.projectkorra.ability.AvatarAbility;
@@ -35,11 +17,31 @@ import com.projectkorra.projectkorra.storage.DBConnection;
import com.projectkorra.projectkorra.util.Cooldown;
import com.projectkorra.projectkorra.util.DBCooldownManager;
import com.projectkorra.projectkorra.waterbending.blood.Bloodbending;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.entity.Player;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
/**
* Class that presents a player and stores all bending information about the
* player.
+ *
+ * @deprecated use {@link com.projectkorra.projectkorra.player.BendingPlayer}.
*/
+@Deprecated
@SuppressWarnings("rawtypes")
public class BendingPlayer {
diff --git a/src/com/projectkorra/projectkorra/GeneralMethods.java b/src/com/projectkorra/projectkorra/GeneralMethods.java
index ee20c206..bc3f8f16 100644
--- a/src/com/projectkorra/projectkorra/GeneralMethods.java
+++ b/src/com/projectkorra/projectkorra/GeneralMethods.java
@@ -1,59 +1,8 @@
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.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-
-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.plugin.Plugin;
-import org.bukkit.plugin.PluginManager;
-import org.bukkit.plugin.java.JavaPlugin;
-import org.bukkit.scheduler.BukkitRunnable;
-import org.bukkit.util.Vector;
-
+import br.net.fabiozumbi12.RedProtect.Bukkit.API.RedProtectAPI;
+import br.net.fabiozumbi12.RedProtect.Bukkit.RedProtect;
+import br.net.fabiozumbi12.RedProtect.Bukkit.Region;
import com.bekvon.bukkit.residence.Residence;
import com.bekvon.bukkit.residence.api.ResidenceInterface;
import com.bekvon.bukkit.residence.protection.ClaimedResidence;
@@ -102,6 +51,7 @@ import com.projectkorra.projectkorra.configuration.configs.properties.ChatProper
import com.projectkorra.projectkorra.configuration.configs.properties.GeneralPropertiesConfig;
import com.projectkorra.projectkorra.earthbending.EarthBlast;
import com.projectkorra.projectkorra.earthbending.passive.EarthPassive;
+import com.projectkorra.projectkorra.element.ElementManager;
import com.projectkorra.projectkorra.event.BendingPlayerCreationEvent;
import com.projectkorra.projectkorra.event.BendingReloadEvent;
import com.projectkorra.projectkorra.event.PlayerBindChangeEvent;
@@ -109,6 +59,7 @@ 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.player.BendingPlayerManager;
import com.projectkorra.projectkorra.storage.DBConnection;
import com.projectkorra.projectkorra.util.ActionBar;
import com.projectkorra.projectkorra.util.BlockCacheElement;
@@ -131,10 +82,6 @@ import com.songoda.kingdoms.constants.land.Land;
import com.songoda.kingdoms.constants.land.SimpleChunkLocation;
import com.songoda.kingdoms.constants.player.KingdomPlayer;
import com.songoda.kingdoms.manager.game.GameManagement;
-
-import 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;
@@ -146,6 +93,60 @@ 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;
+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 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.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("rawtypes")
public class GeneralMethods {
@@ -323,7 +324,10 @@ public class GeneralMethods {
* @param uuid The UUID of the player
* @param player The player name
* @throws SQLException
+ *
+ * @deprecated use {@link BendingPlayerManager} and {@link ElementManager}.
*/
+ @Deprecated
public static void createBendingPlayer(final UUID uuid, final String player) {
new BukkitRunnable() {
@@ -335,6 +339,7 @@ public class GeneralMethods {
}.runTaskAsynchronously(ProjectKorra.plugin);
}
+ @Deprecated
private static void createBendingPlayerAsynchronously(final UUID uuid, final String player) {
ResultSet rs = DBConnection.sql.readQuery("SELECT * FROM pk_players WHERE uuid = '" + uuid.toString() + "'");
try {
@@ -725,17 +730,17 @@ public class GeneralMethods {
*/
public static Entity getClosestEntity(Location center, double radius) {
Entity found = null;
- double distance = radius * radius;
+ Double distance = null;
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(center, radius)) {
- double check = center.distance(entity.getLocation());
+ double check = center.distanceSquared(entity.getLocation());
- if (check < distance) {
+ if (distance == null || check < distance) {
found = entity;
distance = check;
}
}
-
+
return found;
}
@@ -747,12 +752,12 @@ public class GeneralMethods {
*/
public static LivingEntity getClosestLivingEntity(Location center, double radius) {
LivingEntity le = null;
- double distance = radius * radius;
+ Double distance = null;
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(center, radius)) {
- double check = center.distance(entity.getLocation());
+ double check = center.distanceSquared(entity.getLocation());
- if (entity instanceof LivingEntity && check < distance) {
+ if (entity instanceof LivingEntity && (distance == null || check < distance)) {
le = (LivingEntity) entity;
distance = check;
}
@@ -962,6 +967,16 @@ public class GeneralMethods {
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");
@@ -1031,8 +1046,8 @@ public class GeneralMethods {
public static Entity getTargetedEntity(final Player player, final double range) {
return getTargetedEntity(player, range, new ArrayList());
}
-
- public static Location getTargetedLocation(final Player player, final double range, final boolean ignoreTempBlocks, final Material... nonOpaque2) {
+
+ 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();
@@ -1052,6 +1067,11 @@ public class GeneralMethods {
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();
@@ -1068,12 +1088,16 @@ public class GeneralMethods {
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, Material.AIR);
+ return getTargetedLocation(player, range, false);
}
public static Block getTopBlock(final Location loc, final int range) {
diff --git a/src/com/projectkorra/projectkorra/ProjectKorra.java b/src/com/projectkorra/projectkorra/ProjectKorra.java
index 67fc14f0..ba301678 100644
--- a/src/com/projectkorra/projectkorra/ProjectKorra.java
+++ b/src/com/projectkorra/projectkorra/ProjectKorra.java
@@ -1,17 +1,7 @@
package com.projectkorra.projectkorra;
-import java.lang.reflect.Method;
-import java.util.Base64;
-import java.util.HashMap;
-import java.util.logging.Logger;
-
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.Statistic;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.java.JavaPlugin;
-import org.bukkit.scheduler.BukkitTask;
-
+import co.aikar.timings.lib.MCTiming;
+import co.aikar.timings.lib.TimingManager;
import com.bekvon.bukkit.residence.protection.FlagPermissions;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.util.CollisionInitializer;
@@ -28,6 +18,7 @@ import com.projectkorra.projectkorra.earthbending.util.EarthbendingManager;
import com.projectkorra.projectkorra.firebending.util.FirebendingManager;
import com.projectkorra.projectkorra.hooks.PlaceholderAPIHook;
import com.projectkorra.projectkorra.hooks.WorldGuardFlag;
+import com.projectkorra.projectkorra.module.ModuleManager;
import com.projectkorra.projectkorra.object.Preset;
import com.projectkorra.projectkorra.storage.DBConnection;
import com.projectkorra.projectkorra.util.Metrics;
@@ -36,9 +27,17 @@ import com.projectkorra.projectkorra.util.StatisticsManager;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.Updater;
import com.projectkorra.projectkorra.waterbending.util.WaterbendingManager;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Statistic;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitTask;
-import co.aikar.timings.lib.MCTiming;
-import co.aikar.timings.lib.TimingManager;
+import java.lang.reflect.Method;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.logging.Logger;
public class ProjectKorra extends JavaPlugin {
@@ -89,6 +88,7 @@ public class ProjectKorra extends JavaPlugin {
}
Manager.startup();
+ ModuleManager.startup();
this.getServer().getPluginManager().registerEvents(new PKListener(this), this);
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new BendingManager(), 0, 1);
diff --git a/src/com/projectkorra/projectkorra/ability/AbilityManager.java b/src/com/projectkorra/projectkorra/ability/AbilityManager.java
new file mode 100644
index 00000000..4e43601c
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/ability/AbilityManager.java
@@ -0,0 +1,129 @@
+package com.projectkorra.projectkorra.ability;
+
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.util.MultiAbilityManager;
+import com.projectkorra.projectkorra.firebending.FireBlast;
+import com.projectkorra.projectkorra.module.DatabaseModule;
+import com.projectkorra.projectkorra.module.ModuleManager;
+import com.projectkorra.projectkorra.player.BendingPlayer;
+import com.projectkorra.projectkorra.player.BendingPlayerLoadedEvent;
+import com.projectkorra.projectkorra.player.BendingPlayerManager;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import java.sql.SQLException;
+
+public class AbilityManager extends DatabaseModule {
+
+ private final BendingPlayerManager bendingPlayerManager;
+
+ private AbilityManager() {
+ super("Ability", new AbilityRepository());
+
+ this.bendingPlayerManager = ModuleManager.getModule(BendingPlayerManager.class);
+
+ runAsync(() -> {
+ try {
+ getRepository().createTables();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ runSync(() -> {
+ log("Created database tables.");
+ });
+ });
+
+ registerAbilities();
+ }
+
+ private void registerAbilities() {
+ registerAbility(FireBlast.class);
+ }
+
+ private void registerAbility(Class extends Ability> abilityClass) {
+ // TODO
+ }
+
+ @EventHandler
+ public void onBendingPlayerLoaded(BendingPlayerLoadedEvent event) {
+ BendingPlayer bendingPlayer = event.getBendingPlayer();
+
+ runAsync(() -> {
+ try {
+ String[] abilities = getRepository().selectPlayerAbilities(bendingPlayer.getId());
+
+ bendingPlayer.setAbilities(abilities);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public boolean bindAbility(Player player, String abilityName, int slot) {
+ PlayerBindAbilityEvent playerBindAbilityEvent = new PlayerBindAbilityEvent(player, abilityName);
+ getPlugin().getServer().getPluginManager().callEvent(playerBindAbilityEvent);
+
+ if (playerBindAbilityEvent.isCancelled()) {
+ String cancelMessage = playerBindAbilityEvent.getCancelMessage();
+
+ if (cancelMessage != null) {
+ GeneralMethods.sendBrandingMessage(player, cancelMessage);
+ }
+
+ return false;
+ }
+
+ BendingPlayer bendingPlayer = this.bendingPlayerManager.getBendingPlayer(player);
+
+ bendingPlayer.setAbility(slot, abilityName);
+
+ runAsync(() -> {
+ try {
+ getRepository().insertPlayerAbility(bendingPlayer.getId(), abilityName, slot);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+
+ return true;
+ }
+
+ public boolean unbindAbility(Player player, int slot) {
+ BendingPlayer bendingPlayer = this.bendingPlayerManager.getBendingPlayer(player);
+
+ String abilityName = bendingPlayer.getAbility(slot);
+
+ if (abilityName == null) {
+ player.sendMessage("No ability bound");
+ return false;
+ }
+
+ bendingPlayer.setAbility(slot, null);
+
+ runAsync(() -> {
+ try {
+ getRepository().deletePlayerAbility(bendingPlayer.getId(), abilityName);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+
+ return true;
+ }
+
+ public void clearBinds(Player player) {
+ BendingPlayer bendingPlayer = this.bendingPlayerManager.getBendingPlayer(player);
+
+ bendingPlayer.setAbilities(new String[9]);
+
+ runAsync(() -> {
+ try {
+ getRepository().deletePlayerAbilities(bendingPlayer.getId());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/ability/AbilityRepository.java b/src/com/projectkorra/projectkorra/ability/AbilityRepository.java
new file mode 100644
index 00000000..ad4ca5b2
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/ability/AbilityRepository.java
@@ -0,0 +1,100 @@
+package com.projectkorra.projectkorra.ability;
+
+import com.projectkorra.projectkorra.database.DatabaseQuery;
+import com.projectkorra.projectkorra.database.DatabaseRepository;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class AbilityRepository extends DatabaseRepository {
+
+ private static final DatabaseQuery CREATE_TABLE_PLAYER_ABILITIES = DatabaseQuery.newBuilder()
+ .mysql("CREATE TABLE IF NOT EXISTS pk_player_abilities (player_id INTEGER REFERENCES pk_bending_players (player_id), ability_name VARCHAR(50) NOT NULL, slot TINYINT NOT NULL, PRIMARY KEY (player_id, ability_name), INDEX player_index (player_id), INDEX ability_index (ability_name));")
+ .sqlite("CREATE TABLE IF NOT EXISTS pk_player_abilities (player_id INTEGER REFERENCES pk_bending_players (player_id), ability_name VARCHAR(50) NOT NULL, slot TINYINT NOT NULL, PRIMARY KEY (player_id, ability_name)); CREATE INDEX player_index ON pk_player_abilities (player_id); CREATE INDEX ability_index ON pk_player_abilities (ability_name);")
+ .build();
+
+ private static final DatabaseQuery SELECT_PLAYER_ABILITIES = DatabaseQuery.newBuilder()
+ .query("SELECT ability_name, slot FROM pk_player_abilities WHERE player_id = ?;")
+ .build();
+
+ private static final DatabaseQuery INSERT_PLAYER_ABILITY = DatabaseQuery.newBuilder()
+ .query("INSERT INTO pk_player_abilities VALUES (?, ?, ?);")
+ .build();
+
+ private static final DatabaseQuery DELETE_PLAYER_ABILITIES = DatabaseQuery.newBuilder()
+ .query("DELETE FROM pk_player_abilities WHERE player_id = ?")
+ .build();
+
+ private static final DatabaseQuery DELETE_PLAYER_ABILITY = DatabaseQuery.newBuilder()
+ .query("DELETE FROM pk_player_abilities WHERE player_id = ? AND ability_name = ?;")
+ .build();
+
+ protected void createTables() throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(CREATE_TABLE_PLAYER_ABILITIES.getQuery())) {
+ statement.executeUpdate();
+ }
+ }
+
+ protected String[] selectPlayerAbilities(int playerId) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(SELECT_PLAYER_ABILITIES.getQuery())) {
+ statement.setInt(1, playerId);
+
+ String[] abilities = new String[9];
+
+ try (ResultSet rs = statement.executeQuery()) {
+ while (rs.next()) {
+ String abilityName = rs.getString("ability_name");
+ int slot = rs.getInt("slot");
+
+ if (slot < 0 || slot >= abilities.length) {
+ // TODO Log illegal slot
+ continue;
+ }
+
+ abilities[slot] = abilityName;
+ }
+
+ return abilities;
+ }
+ }
+ }
+
+ protected void insertPlayerAbility(int playerId, String abilityName, int slot) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(INSERT_PLAYER_ABILITY.getQuery())) {
+ statement.setInt(1, playerId);
+ statement.setString(2, abilityName);
+ statement.setInt(3, slot);
+
+ statement.executeUpdate();
+ }
+ }
+
+ protected void deletePlayerAbilities(int playerId) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(DELETE_PLAYER_ABILITIES.getQuery())) {
+ statement.setInt(1, playerId);
+
+ statement.executeUpdate();
+ }
+ }
+
+ protected void deletePlayerAbility(int playerId, String abilityName) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(DELETE_PLAYER_ABILITY.getQuery())) {
+ statement.setInt(1, playerId);
+ statement.setString(2, abilityName);
+
+ statement.executeUpdate();
+ }
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/ability/EarthAbility.java b/src/com/projectkorra/projectkorra/ability/EarthAbility.java
index d0aae2fc..1617ebaf 100644
--- a/src/com/projectkorra/projectkorra/ability/EarthAbility.java
+++ b/src/com/projectkorra/projectkorra/ability/EarthAbility.java
@@ -563,10 +563,10 @@ public abstract class EarthAbility extends ElementalAbi
if (block.equals(sourceblock)) {
info.getState().update(true, false);
if (RaiseEarth.blockInAllAffectedBlocks(sourceblock)) {
- EarthAbility.revertBlock(sourceblock);
+ RaiseEarth.revertAffectedBlock(sourceblock);
}
if (RaiseEarth.blockInAllAffectedBlocks(block)) {
- EarthAbility.revertBlock(block);
+ RaiseEarth.revertAffectedBlock(block);
}
MOVED_EARTH.remove(block);
return true;
@@ -595,10 +595,10 @@ public abstract class EarthAbility extends ElementalAbi
}
if (RaiseEarth.blockInAllAffectedBlocks(sourceblock)) {
- EarthAbility.revertBlock(sourceblock);
+ RaiseEarth.revertAffectedBlock(sourceblock);
}
if (RaiseEarth.blockInAllAffectedBlocks(block)) {
- EarthAbility.revertBlock(block);
+ RaiseEarth.revertAffectedBlock(block);
}
MOVED_EARTH.remove(block);
}
diff --git a/src/com/projectkorra/projectkorra/ability/PlayerBindAbilityEvent.java b/src/com/projectkorra/projectkorra/ability/PlayerBindAbilityEvent.java
new file mode 100644
index 00000000..0317ee46
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/ability/PlayerBindAbilityEvent.java
@@ -0,0 +1,61 @@
+package com.projectkorra.projectkorra.ability;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+
+public class PlayerBindAbilityEvent extends PlayerEvent implements Cancellable
+{
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final String abilityName;
+
+ private boolean cancelled;
+ private String cancelMessage;
+
+ public PlayerBindAbilityEvent(Player player, String abilityName)
+ {
+ super(player);
+
+ this.abilityName = abilityName;
+ }
+
+ public String getAbilityName()
+ {
+ return this.abilityName;
+ }
+
+ @Override
+ public boolean isCancelled()
+ {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancelled)
+ {
+ this.cancelled = cancelled;
+ }
+
+ public String getCancelMessage()
+ {
+ return this.cancelMessage;
+ }
+
+ public void setCancelMessage(String cancelMessage)
+ {
+ this.cancelMessage = cancelMessage;
+ }
+
+ @Override
+ public HandlerList getHandlers()
+ {
+ return HANDLER_LIST;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java b/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java
index 1317c01c..38943ff7 100644
--- a/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java
+++ b/src/com/projectkorra/projectkorra/ability/util/MultiAbilityManager.java
@@ -6,9 +6,12 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import com.projectkorra.projectkorra.ability.PlayerBindAbilityEvent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
import org.bukkit.scheduler.BukkitRunnable;
import com.projectkorra.projectkorra.BendingPlayer;
@@ -17,7 +20,7 @@ import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.event.PlayerBindChangeEvent;
-public class MultiAbilityManager {
+public class MultiAbilityManager implements Listener {
public static Map playerAbilities = new ConcurrentHashMap<>();
public static Map playerSlot = new ConcurrentHashMap<>();
@@ -34,6 +37,19 @@ public class MultiAbilityManager {
waterArms.add(new MultiAbilityInfoSub("Spear", Element.ICE));
multiAbilityList.add(new MultiAbilityInfo("WaterArms", waterArms));
manage();
+
+ // TODO Properly set this up as a Module
+ ProjectKorra.plugin.getServer().getPluginManager().registerEvents(this, ProjectKorra.plugin);
+ }
+
+ @EventHandler
+ public void onPlayerBindAbility(PlayerBindAbilityEvent event)
+ {
+ if (playerAbilities.containsKey(event.getPlayer()))
+ {
+ event.setCancelled(true);
+ event.setCancelMessage(ChatColor.RED + "You can't edit your binds right now!");
+ }
}
/**
diff --git a/src/com/projectkorra/projectkorra/airbending/AirBlast.java b/src/com/projectkorra/projectkorra/airbending/AirBlast.java
index 1b1c0650..13ff8fca 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirBlast.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirBlast.java
@@ -213,72 +213,72 @@ public class AirBlast extends AirAbility {
}
private void affect(final Entity entity) {
- final boolean isUser = entity.getUniqueId() == this.player.getUniqueId();
-
- if (!isUser || this.isFromOtherOrigin) {
- this.pushFactor = this.pushFactorForOthers;
- final Vector velocity = entity.getVelocity();
- final double max = this.speed / this.speedFactor;
- double factor = this.pushFactor;
-
- final Vector push = this.direction.clone();
- if (Math.abs(push.getY()) > max && !isUser) {
- if (push.getY() < 0) {
- push.setY(-max);
- } else {
- push.setY(max);
- }
- }
- if (this.location.getWorld().equals(this.origin.getWorld())) {
- factor *= 1 - this.location.distance(this.origin) / (2 * this.range);
- }
-
- if (isUser && GeneralMethods.isSolid(this.player.getLocation().add(0, -.5, 0).getBlock())) {
- factor *= .5;
- }
-
- final double comp = velocity.dot(push.clone().normalize());
- if (comp > factor) {
- velocity.multiply(.5);
- velocity.add(push.clone().normalize().multiply(velocity.clone().dot(push.clone().normalize())));
- } else if (comp + factor * .5 > factor) {
- velocity.add(push.clone().multiply(factor - comp));
- } else {
- velocity.add(push.clone().multiply(factor * .5));
- }
-
- if (entity instanceof Player) {
- if (Commands.invincible.contains(((Player) entity).getName())) {
- return;
- }
- }
-
- if (Double.isNaN(velocity.length())) {
+ if (entity instanceof Player) {
+ if (Commands.invincible.contains(((Player) entity).getName())) {
return;
}
+ }
+
+ final boolean isUser = entity.getUniqueId() == this.player.getUniqueId();
+ double knockback = this.pushFactorForOthers;
- GeneralMethods.setVelocity(entity, velocity);
- if (this.source != null) {
- new HorizontalVelocityTracker(entity, this.player, 200l, this.source);
+ if (isUser) {
+ if (isFromOtherOrigin) {
+ knockback = this.pushFactor;
} else {
- new HorizontalVelocityTracker(entity, this.player, 200l, this);
- }
-
- if (entity.getFireTicks() > 0) {
- entity.getWorld().playEffect(entity.getLocation(), Effect.EXTINGUISH, 0);
- }
-
- entity.setFireTicks(0);
- breakBreathbendingHold(entity);
-
- if (this.source != null && (this.damage > 0 && entity instanceof LivingEntity && !entity.equals(this.player) && !this.affectedEntities.contains(entity))) {
- DamageHandler.damageEntity(entity, this.damage, this.source);
- this.affectedEntities.add(entity);
- } else if (this.source == null && (this.damage > 0 && entity instanceof LivingEntity && !entity.equals(this.player) && !this.affectedEntities.contains(entity))) {
- DamageHandler.damageEntity(entity, this.damage, this);
- this.affectedEntities.add(entity);
+ return;
}
}
+
+ final double max = this.speed / this.speedFactor;
+
+ final Vector push = this.direction.clone();
+ if (Math.abs(push.getY()) > max && !isUser) {
+ if (push.getY() < 0) {
+ push.setY(-max);
+ } else {
+ push.setY(max);
+ }
+ }
+
+ if (this.location.getWorld().equals(this.origin.getWorld())) {
+ knockback *= 1 - this.location.distance(this.origin) / (2 * this.range);
+ }
+
+ if (GeneralMethods.isSolid(entity.getLocation().add(0, -0.5, 0).getBlock()) && source == null) {
+ knockback *= 0.85;
+ }
+
+ push.normalize().multiply(knockback);
+
+ if (Math.abs(entity.getVelocity().dot(push)) > knockback && entity.getVelocity().angle(push) > Math.PI / 3) {
+ push.normalize().add(entity.getVelocity()).multiply(knockback);
+ }
+
+ GeneralMethods.setVelocity(entity, push);
+
+ if (this.source != null) {
+ new HorizontalVelocityTracker(entity, this.player, 200l, this.source);
+ } else {
+ new HorizontalVelocityTracker(entity, this.player, 200l, this);
+ }
+
+ if (this.damage > 0 && entity instanceof LivingEntity && !entity.equals(this.player) && !this.affectedEntities.contains(entity)) {
+ if (this.source != null) {
+ DamageHandler.damageEntity(entity, this.damage, this.source);
+ } else {
+ DamageHandler.damageEntity(entity, this.damage, this);
+ }
+
+ this.affectedEntities.add(entity);
+ }
+
+ if (entity.getFireTicks() > 0) {
+ entity.getWorld().playEffect(entity.getLocation(), Effect.EXTINGUISH, 0);
+ }
+
+ entity.setFireTicks(0);
+ breakBreathbendingHold(entity);
}
@Override
diff --git a/src/com/projectkorra/projectkorra/airbending/AirBurst.java b/src/com/projectkorra/projectkorra/airbending/AirBurst.java
index 6ea1c3ff..31832346 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirBurst.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirBurst.java
@@ -325,10 +325,6 @@ public class AirBurst extends AirAbility {
return this.blasts;
}
- public ArrayList getAffectedEntities() {
- return this.affectedEntities;
- }
-
@Override
public Class getConfigType() {
return AirBurstConfig.class;
diff --git a/src/com/projectkorra/projectkorra/airbending/AirSuction.java b/src/com/projectkorra/projectkorra/airbending/AirSuction.java
index 175715f4..1a1d40f1 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirSuction.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirSuction.java
@@ -44,6 +44,8 @@ public class AirSuction extends AirAbility {
private double radius;
@Attribute(Attribute.KNOCKBACK)
private double pushFactor;
+ @Attribute(Attribute.KNOCKBACK + "Others")
+ private double pushFactorForOthers;
private Random random;
private Location location;
private Location origin;
@@ -78,7 +80,8 @@ public class AirSuction extends AirAbility {
this.speed = config.Speed;
this.range = config.Range;
this.radius = config.Radius;
- this.pushFactor = config.PushFactor;
+ this.pushFactor = config.PushFactor_Self;
+ this.pushFactorForOthers = config.PushFactor_Others;
this.cooldown = config.Cooldown;
this.random = new Random();
this.origin = this.getTargetLocation();
@@ -203,10 +206,15 @@ public class AirSuction extends AirAbility {
if ((entity.getEntityId() == this.player.getEntityId()) && !this.canAffectSelf) {
continue;
}
- final Vector velocity = entity.getVelocity();
+
+ double knockback = this.pushFactor;
+
+ if (entity.getEntityId() != player.getEntityId()) {
+ knockback = this.pushFactorForOthers;
+ }
+
final double max = this.speed;
final Vector push = this.direction.clone();
- double factor = this.pushFactor;
if (Math.abs(push.getY()) > max) {
if (push.getY() < 0) {
@@ -217,20 +225,16 @@ public class AirSuction extends AirAbility {
}
if (this.location.getWorld().equals(this.origin.getWorld())) {
- factor *= 1 - this.location.distance(this.origin) / (2 * this.range);
+ knockback *= 1 - this.location.distance(this.origin) / (2 * this.range);
+ }
+
+ push.normalize().multiply(knockback);
+
+ if (Math.abs(entity.getVelocity().dot(push)) > knockback) {
+ push.normalize().add(entity.getVelocity()).multiply(knockback);
}
- final double comp = velocity.dot(push.clone().normalize());
- if (comp > factor) {
- velocity.multiply(.5);
- velocity.add(push.clone().normalize().multiply(velocity.clone().dot(push.clone().normalize())));
- } else if (comp + factor * .5 > factor) {
- velocity.add(push.clone().multiply(factor - comp));
- } else {
- velocity.add(push.clone().multiply(factor * .5));
- }
-
- GeneralMethods.setVelocity(entity, velocity);
+ GeneralMethods.setVelocity(entity, push.normalize().multiply(knockback));
new HorizontalVelocityTracker(entity, this.player, 200l, this);
entity.setFallDistance(0);
diff --git a/src/com/projectkorra/projectkorra/airbending/AirSwipe.java b/src/com/projectkorra/projectkorra/airbending/AirSwipe.java
index eabf8215..c10a88fb 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirSwipe.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirSwipe.java
@@ -78,7 +78,7 @@ public class AirSwipe extends AirAbility {
}
this.charging = charging;
- this.origin = player.getEyeLocation();
+ this.origin = GeneralMethods.getMainHandLocation(player);
this.particles = config.AnimationParticleAmount;
this.arc = config.Arc;
this.arcIncrement = config.StepSize;
diff --git a/src/com/projectkorra/projectkorra/airbending/Suffocate.java b/src/com/projectkorra/projectkorra/airbending/Suffocate.java
index 776b4fcf..04cdbe6e 100644
--- a/src/com/projectkorra/projectkorra/airbending/Suffocate.java
+++ b/src/com/projectkorra/projectkorra/airbending/Suffocate.java
@@ -143,7 +143,6 @@ public class Suffocate extends AirAbility {
}
}
- this.bPlayer.addCooldown(this);
this.start();
}
@@ -172,7 +171,7 @@ public class Suffocate extends AirAbility {
if (this.player.getWorld().equals(this.targets.get(0).getWorld())) {
dist = this.player.getEyeLocation().distance(this.targets.get(0).getEyeLocation());
}
- final Location targetLoc = this.player.getEyeLocation().clone().add(this.player.getEyeLocation().getDirection().normalize().multiply(dist));
+ final Location targetLoc = GeneralMethods.getTargetedLocation(player, dist, false, getTransparentMaterials());
final List ents = GeneralMethods.getEntitiesAroundPoint(targetLoc, this.constantAimRadius);
for (int i = 0; i < this.targets.size(); i++) {
@@ -337,6 +336,7 @@ public class Suffocate extends AirAbility {
@Override
public void remove() {
super.remove();
+ this.bPlayer.addCooldown(this);
for (int i = 0; i < this.tasks.size(); i++) {
this.tasks.get(i).cancel();
this.tasks.remove(i);
diff --git a/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java b/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java
index b287ee0a..29f9e70d 100644
--- a/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java
+++ b/src/com/projectkorra/projectkorra/airbending/combo/AirSweep.java
@@ -3,6 +3,7 @@ package com.projectkorra.projectkorra.airbending.combo;
import java.util.ArrayList;
import java.util.List;
+import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
@@ -133,22 +134,23 @@ public class AirSweep extends AirAbility implements ComboAbility
if (this.origin == null) {
this.direction = this.player.getEyeLocation().getDirection().normalize();
- this.origin = this.player.getLocation().add(this.direction.clone().multiply(10));
+ this.origin = GeneralMethods.getMainHandLocation(player).add(this.direction.clone().multiply(10));
}
if (this.progressCounter < 8) {
return;
}
if (this.destination == null) {
- this.destination = this.player.getLocation().add(this.player.getEyeLocation().getDirection().normalize().multiply(10));
+ this.destination = GeneralMethods.getMainHandLocation(player).add(GeneralMethods.getMainHandLocation(player).getDirection().normalize().multiply(10));
final Vector origToDest = GeneralMethods.getDirection(this.origin, this.destination);
+ final Location hand = GeneralMethods.getMainHandLocation(player);
for (double i = 0; i < 30; i++) {
final Location endLoc = this.origin.clone().add(origToDest.clone().multiply(i / 30));
- if (GeneralMethods.locationEqualsIgnoreDirection(this.player.getLocation(), endLoc)) {
+ if (GeneralMethods.locationEqualsIgnoreDirection(hand, endLoc)) {
continue;
}
- final Vector vec = GeneralMethods.getDirection(this.player.getLocation(), endLoc);
+ final Vector vec = GeneralMethods.getDirection(hand, endLoc);
- final FireComboStream fs = new FireComboStream(this.player, this, vec, this.player.getLocation(), this.range, this.speed);
+ final FireComboStream fs = new FireComboStream(this.player, this, vec, hand, this.range, this.speed);
fs.setDensity(1);
fs.setSpread(0F);
fs.setUseNewParticles(true);
@@ -193,17 +195,17 @@ public class AirSweep extends AirAbility implements ComboAbility
this.remove();
return;
}
- if (!entity.equals(this.player) && !this.affectedEntities.contains(entity) && !(entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) {
- this.affectedEntities.add(entity);
+ if (!entity.equals(this.player) && !(entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) {
if (this.knockback != 0) {
- final Vector force = fstream.getDirection();
- entity.setVelocity(force.multiply(this.knockback));
+ final Vector force = fstream.getLocation().getDirection();
+ GeneralMethods.setVelocity(entity, force.clone().multiply(this.knockback));
+ new HorizontalVelocityTracker(entity, this.player, 200l, this);
+ entity.setFallDistance(0);
}
- if (this.damage != 0) {
- if (entity instanceof LivingEntity) {
- if (fstream.getAbility().getName().equalsIgnoreCase("AirSweep")) {
- DamageHandler.damageEntity(entity, this.damage, this);
- } else {
+ if(!this.affectedEntities.contains(entity)) {
+ this.affectedEntities.add(entity);
+ if (this.damage != 0) {
+ if (entity instanceof LivingEntity) {
DamageHandler.damageEntity(entity, this.damage, this);
}
}
diff --git a/src/com/projectkorra/projectkorra/command/PresetCommand.java b/src/com/projectkorra/projectkorra/command/PresetCommand.java
index 9eac68ea..9da29fbf 100644
--- a/src/com/projectkorra/projectkorra/command/PresetCommand.java
+++ b/src/com/projectkorra/projectkorra/command/PresetCommand.java
@@ -78,41 +78,45 @@ public class PresetCommand extends PKCommand {
bPlayer = BendingPlayer.getBendingPlayer(player);
}
- // bending preset list.
- if (args.size() == 1) {
- if (Arrays.asList(listaliases).contains(args.get(0)) && this.hasPermission(sender, "list")) {
- boolean firstMessage = true;
-
- final List presets = Preset.presets.get(player.getUniqueId());
- final List presetNames = new ArrayList();
-
- if (presets == null || presets.isEmpty()) {
- GeneralMethods.sendBrandingMessage(sender, ChatColor.RED + this.noPresets);
- return;
- }
-
- for (final Preset preset : presets) {
- presetNames.add(preset.getName());
- }
-
- for (final String s : this.getPage(presetNames, ChatColor.GOLD + "Presets: ", 1, false)) {
- if (firstMessage) {
- GeneralMethods.sendBrandingMessage(sender, s);
- firstMessage = false;
- } else {
- sender.sendMessage(ChatColor.YELLOW + s);
- }
- }
-
- return;
+ int page = 1;
+ String name = null;
+ if (args.size() == 1 && !Arrays.asList(listaliases).contains(args.get(0))){
+ this.help(sender, false);
+ } else if (args.size() >= 2) {
+ if (Arrays.asList(listaliases).contains(args.get(0))) {
+ page = Integer.parseInt(args.get(1));
} else {
- this.help(sender, false);
- return;
+ name = args.get(1);
}
}
- final String name = args.get(1);
- if (Arrays.asList(deletealiases).contains(args.get(0)) && this.hasPermission(sender, "delete")) { // bending preset delete name.
+ // bending preset list.
+ if (Arrays.asList(listaliases).contains(args.get(0)) && this.hasPermission(sender, "list")) {
+ boolean firstMessage = true;
+
+ final List presets = Preset.presets.get(player.getUniqueId());
+ final List presetNames = new ArrayList();
+
+ if (presets == null || presets.isEmpty()) {
+ GeneralMethods.sendBrandingMessage(sender, ChatColor.RED + this.noPresets);
+ return;
+ }
+
+ for (final Preset preset : presets) {
+ presetNames.add(preset.getName());
+ }
+
+ for (final String s : this.getPage(presetNames, ChatColor.GOLD + "Presets: ", page, false)) {
+ if (firstMessage) {
+ GeneralMethods.sendBrandingMessage(sender, s);
+ firstMessage = false;
+ } else {
+ sender.sendMessage(ChatColor.YELLOW + s);
+ }
+ }
+
+ return;
+ } else if (Arrays.asList(deletealiases).contains(args.get(0)) && this.hasPermission(sender, "delete")) { // bending preset delete name.
if (!Preset.presetExists(player, name)) {
GeneralMethods.sendBrandingMessage(sender, ChatColor.RED + this.noPresetName);
return;
diff --git a/src/com/projectkorra/projectkorra/configuration/ConfigManager.java b/src/com/projectkorra/projectkorra/configuration/ConfigManager.java
index 95deda30..dd9d00ce 100644
--- a/src/com/projectkorra/projectkorra/configuration/ConfigManager.java
+++ b/src/com/projectkorra/projectkorra/configuration/ConfigManager.java
@@ -91,4 +91,4 @@ public class ConfigManager {
return null;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBlastConfig.java b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBlastConfig.java
index a0e33e7b..c00109c6 100644
--- a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBlastConfig.java
+++ b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBlastConfig.java
@@ -7,8 +7,8 @@ public class AirBlastConfig extends AbilityConfig {
public final long Cooldown = 500;
public final int AnimationParticleAmount = 5;
public final int SelectionParticleAmount = 5;
- public final double PushFactor_Self = 2.5;
- public final double PushFactor_Others = 2.5;
+ public final double PushFactor_Self = 2.0;
+ public final double PushFactor_Others = 1.6;
public final double Speed = 25;
public final double Range = 20;
public final double SelectionRange = 10;
@@ -35,4 +35,4 @@ public class AirBlastConfig extends AbilityConfig {
return new String[] { "Abilities", "Air" };
}
-}
\ No newline at end of file
+}
diff --git a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBurstConfig.java b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBurstConfig.java
index 500ff7d8..49bc727d 100644
--- a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBurstConfig.java
+++ b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirBurstConfig.java
@@ -7,7 +7,7 @@ public class AirBurstConfig extends AbilityConfig {
public final long Cooldown = 0;
public final long ChargeTime = 1750;
public final double FallHeightThreshold = 15;
- public final double PushFactor = 2.0;
+ public final double PushFactor = 2.8;
public final double Damage = 0;
public final double AnglePhi = 10;
public final double AngleTheta = 10;
@@ -31,4 +31,4 @@ public class AirBurstConfig extends AbilityConfig {
return new String[] { "Abilities", "Air" };
}
-}
\ No newline at end of file
+}
diff --git a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirSuctionConfig.java b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirSuctionConfig.java
index 1a0851f7..94f8c7ab 100644
--- a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirSuctionConfig.java
+++ b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/AirSuctionConfig.java
@@ -7,7 +7,8 @@ public class AirSuctionConfig extends AbilityConfig {
public final long Cooldown = 500;
public final int AnimationParticleAmount = 5;
public final int SelectionParticleAmount = 5;
- public final double PushFactor = 2.5;
+ public final double PushFactor_Self = 2.0;
+ public final double PushFactor_Others = 1.3;
public final double Speed = 25;
public final double Range = 20;
public final double SelectionRange = 10;
@@ -29,4 +30,4 @@ public class AirSuctionConfig extends AbilityConfig {
return new String[] { "Abilities", "Air" };
}
-}
\ No newline at end of file
+}
diff --git a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/SuffocateConfig.java b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/SuffocateConfig.java
index 54fdca02..96aca238 100644
--- a/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/SuffocateConfig.java
+++ b/src/com/projectkorra/projectkorra/configuration/configs/abilities/air/SuffocateConfig.java
@@ -4,7 +4,7 @@ import com.projectkorra.projectkorra.configuration.configs.abilities.AbilityConf
public class SuffocateConfig extends AbilityConfig {
- public final long Cooldown = 0;
+ public final long Cooldown = 6500;
public final boolean RequireConstantAim = true;
public final double ConstantAimRadius = 3;
public final boolean CanSuffocateUndead = false;
@@ -42,4 +42,4 @@ public class SuffocateConfig extends AbilityConfig {
return new String[] { "Abilities", "Air" };
}
-}
\ No newline at end of file
+}
diff --git a/src/com/projectkorra/projectkorra/cooldown/CooldownManager.java b/src/com/projectkorra/projectkorra/cooldown/CooldownManager.java
new file mode 100644
index 00000000..bbd93822
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/cooldown/CooldownManager.java
@@ -0,0 +1,193 @@
+package com.projectkorra.projectkorra.cooldown;
+
+import com.projectkorra.projectkorra.event.PlayerCooldownChangeEvent;
+import com.projectkorra.projectkorra.module.DatabaseModule;
+import com.projectkorra.projectkorra.module.ModuleManager;
+import com.projectkorra.projectkorra.player.BendingPlayer;
+import com.projectkorra.projectkorra.player.BendingPlayerLoadedEvent;
+import com.projectkorra.projectkorra.player.BendingPlayerManager;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+import java.sql.SQLException;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.UUID;
+import java.util.function.Function;
+
+public class CooldownManager extends DatabaseModule {
+
+ private final BendingPlayerManager bendingPlayerManager;
+
+ private final Map> cooldownMap = new HashMap<>();
+ private final Map> cooldownQueue = new HashMap<>();
+
+ private final Function> queueFunction = uuid -> new PriorityQueue<>(Comparator.comparing(cooldown -> cooldown.ExpireTime));
+
+ private CooldownManager() {
+ super("Cooldown", new CooldownRepository());
+
+ this.bendingPlayerManager = ModuleManager.getModule(BendingPlayerManager.class);
+
+ runAsync(() -> {
+ try {
+ getRepository().createTables();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+
+ runTimer(() -> {
+ this.cooldownQueue.forEach((uuid, cooldowns) -> {
+ long currentTime = System.currentTimeMillis();
+
+ while (!cooldowns.isEmpty()) {
+ Cooldown cooldown = cooldowns.peek();
+
+ if (currentTime < cooldown.ExpireTime) {
+ break;
+ }
+
+ this.cooldownMap.get(uuid).remove(cooldown.AbilityName);
+ cooldowns.poll();
+
+ if (cooldown.Permanent) {
+ int playerId = this.bendingPlayerManager.getBendingPlayer(uuid).getId();
+
+ runAsync(() -> {
+ try {
+ getRepository().deleteCooldown(playerId, cooldown.AbilityName);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+ }
+ });
+
+ this.cooldownMap.values().removeIf(Map::isEmpty);
+ this.cooldownQueue.values().removeIf(PriorityQueue::isEmpty);
+ }, 1, 1);
+ }
+
+ @EventHandler
+ public void onBendingPlayerLoaded(BendingPlayerLoadedEvent event) {
+ Player player = event.getPlayer();
+ BendingPlayer bendingPlayer = event.getBendingPlayer();
+
+ runAsync(() -> {
+ try {
+ Map cooldowns = getRepository().selectCooldowns(bendingPlayer.getId());
+
+ this.cooldownMap.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).putAll(cooldowns);
+ this.cooldownQueue.computeIfAbsent(player.getUniqueId(), queueFunction).addAll(cooldowns.values());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ @EventHandler
+ public void onQuit(PlayerQuitEvent event) {
+ this.cooldownMap.remove(event.getPlayer().getUniqueId());
+ this.cooldownQueue.remove(event.getPlayer().getUniqueId());
+ }
+
+ public void addCooldown(Player player, String abilityName, long duration, boolean permanent) {
+ if (duration <= 0) {
+ return;
+ }
+
+ PlayerCooldownChangeEvent event = new PlayerCooldownChangeEvent(player, abilityName, duration, PlayerCooldownChangeEvent.Result.ADDED);
+ getPlugin().getServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return;
+ }
+
+ long expireTime = System.currentTimeMillis() + duration;
+ Cooldown cooldown = new Cooldown(abilityName, expireTime, permanent);
+
+ this.cooldownMap.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).put(abilityName, cooldown);
+ this.cooldownQueue.computeIfAbsent(player.getUniqueId(), queueFunction).add(cooldown);
+
+ if (permanent) {
+ int playerId = this.bendingPlayerManager.getBendingPlayer(player).getId();
+
+ runAsync(() -> {
+ try {
+ getRepository().insertCooldown(playerId, abilityName, expireTime);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+ }
+
+ public long getCooldown(Player player, String abilityName) {
+ Map cooldowns = this.cooldownMap.get(player.getUniqueId());
+
+ if (cooldowns != null && cooldowns.containsKey(abilityName)) {
+ return cooldowns.get(abilityName).ExpireTime;
+ }
+
+ return -1L;
+ }
+
+ public boolean isOnCooldown(Player player, String abilityName) {
+ Map cooldowns = this.cooldownMap.get(player.getUniqueId());
+
+ return cooldowns != null && cooldowns.containsKey(abilityName);
+ }
+
+ public void removeCooldown(Player player, String abilityName) {
+ UUID uuid = player.getUniqueId();
+ Map cooldowns = this.cooldownMap.get(player.getUniqueId());
+
+ if (cooldowns == null) {
+ return;
+ }
+
+ Cooldown cooldown = cooldowns.remove(abilityName);
+
+ if (cooldown == null) {
+ return;
+ }
+
+ if (this.cooldownQueue.containsKey(uuid)) {
+ this.cooldownQueue.get(uuid).remove(cooldown);
+ }
+
+ if (cooldown.Permanent) {
+ int playerId = this.bendingPlayerManager.getBendingPlayer(player).getId();
+
+ runAsync(() -> {
+ try {
+ getRepository().deleteCooldown(playerId, cooldown.AbilityName);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+ }
+
+ public static class Cooldown {
+
+ final String AbilityName;
+ final long ExpireTime;
+ final boolean Permanent;
+
+ public Cooldown(String abilityName, long expireTime) {
+ this(abilityName, expireTime, false);
+ }
+
+ public Cooldown(String abilityName, long expireTime, boolean permanent) {
+ AbilityName = abilityName;
+ ExpireTime = expireTime;
+ Permanent = permanent;
+ }
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/cooldown/CooldownRepository.java b/src/com/projectkorra/projectkorra/cooldown/CooldownRepository.java
new file mode 100644
index 00000000..859237da
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/cooldown/CooldownRepository.java
@@ -0,0 +1,82 @@
+package com.projectkorra.projectkorra.cooldown;
+
+import com.projectkorra.projectkorra.database.DatabaseQuery;
+import com.projectkorra.projectkorra.database.DatabaseRepository;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class CooldownRepository extends DatabaseRepository {
+
+ private static final DatabaseQuery CREATE_TABLE_COOLDOWNS = DatabaseQuery.newBuilder()
+ .query("CREATE TABLE IF NOT EXISTS pk_cooldowns (player_id INTEGER REFERENCES pk_bending_players (player_id), ability_name VARCHAR(100) NOT NULL, expire_time BIGINT NOT NULL, PRIMARY KEY (player_id, ability_name));")
+ .build();
+
+ private static final DatabaseQuery SELECT_COOLDOWNS = DatabaseQuery.newBuilder()
+ .query("SELECT * FROM pk_cooldowns WHERE player_id = ?")
+ .build();
+
+ private static final DatabaseQuery INSERT_COOLDOWN = DatabaseQuery.newBuilder()
+ .query("INSERT INTO pk_cooldowns VALUES (?, ?, ?);")
+ .build();
+
+ private static final DatabaseQuery DELETE_COOLDOWN = DatabaseQuery.newBuilder()
+ .query("DELETE FROM pk_cooldowns WHERE player_id = ? AND ability_name = ?;")
+ .build();
+
+ protected void createTables() throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(CREATE_TABLE_COOLDOWNS.getQuery())) {
+ statement.executeUpdate();
+ }
+ }
+
+ protected Map selectCooldowns(int playerId) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(SELECT_COOLDOWNS.getQuery())) {
+ statement.setInt(1, playerId);
+
+ Map cooldowns = new HashMap<>();
+
+ try (ResultSet rs = statement.executeQuery()) {
+ while (rs.next()) {
+ String abilityName = rs.getString("ability_name");
+ long expireTime = rs.getLong("expire_time");
+
+ cooldowns.put(abilityName, new CooldownManager.Cooldown(abilityName, expireTime, true));
+ }
+
+ return cooldowns;
+ }
+ }
+ }
+
+ protected void insertCooldown(int playerId, String abilityName, long expireTime) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(INSERT_COOLDOWN.getQuery())) {
+ statement.setInt(1, playerId);
+ statement.setString(2, abilityName);
+ statement.setLong(3, expireTime);
+
+ statement.executeUpdate();
+ }
+ }
+
+ protected void deleteCooldown(int playerId, String abilityName) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(DELETE_COOLDOWN.getQuery())) {
+ statement.setInt(1, playerId);
+ statement.setString(2, abilityName);
+
+ statement.executeUpdate();
+ }
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/database/DatabaseConfig.java b/src/com/projectkorra/projectkorra/database/DatabaseConfig.java
new file mode 100644
index 00000000..c7c781e8
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/database/DatabaseConfig.java
@@ -0,0 +1,26 @@
+package com.projectkorra.projectkorra.database;
+
+import com.projectkorra.projectkorra.configuration.Config;
+
+public class DatabaseConfig implements Config {
+
+ public final DatabaseManager.Engine Engine = DatabaseManager.Engine.SQLITE;
+
+ public final String SQLite_File = "projectkorra.sql";
+
+ public final String MySQL_IP = "localhost";
+ public final String MySQL_Port = "3306";
+ public final String MySQL_DatabaseName = "projectkorra";
+ public final String MySQL_Username = "root";
+ public final String MySQL_Password = "password";
+
+ @Override
+ public String getName() {
+ return "Database";
+ }
+
+ @Override
+ public String[] getParents() {
+ return new String[0];
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/database/DatabaseManager.java b/src/com/projectkorra/projectkorra/database/DatabaseManager.java
new file mode 100644
index 00000000..78748b8c
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/database/DatabaseManager.java
@@ -0,0 +1,52 @@
+package com.projectkorra.projectkorra.database;
+
+import com.projectkorra.projectkorra.configuration.ConfigManager;
+import com.projectkorra.projectkorra.database.engine.MySQLDatabase;
+import com.projectkorra.projectkorra.database.engine.SQLDatabase;
+import com.projectkorra.projectkorra.database.engine.SQLiteDatabase;
+import com.projectkorra.projectkorra.module.Module;
+
+import java.util.logging.Level;
+
+public class DatabaseManager extends Module {
+
+ private final DatabaseConfig config;
+ private final SQLDatabase database;
+
+ private DatabaseManager() {
+ super("Database");
+
+ this.config = ConfigManager.getConfig(DatabaseConfig.class);
+
+ switch (this.config.Engine) {
+ case MYSQL:
+ this.database = new MySQLDatabase(this.config);
+ break;
+ case SQLITE:
+ this.database = new SQLiteDatabase(this, this.config);
+ break;
+ default:
+ log(Level.SEVERE, "Unknown database engine.");
+ this.database = null;
+ break;
+ }
+ }
+
+ public DatabaseConfig getConfig() {
+ return this.config;
+ }
+
+ public SQLDatabase getDatabase() {
+ return this.database;
+ }
+
+ @Override
+ public void onDisable() {
+ this.database.close();
+ }
+
+ public enum Engine {
+ MYSQL,
+ SQLITE;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/database/DatabaseQuery.java b/src/com/projectkorra/projectkorra/database/DatabaseQuery.java
new file mode 100644
index 00000000..9eb6f970
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/database/DatabaseQuery.java
@@ -0,0 +1,55 @@
+package com.projectkorra.projectkorra.database;
+
+import com.projectkorra.projectkorra.module.ModuleManager;
+
+public class DatabaseQuery {
+
+ private final String mysql;
+ private final String sqlite;
+
+ private DatabaseQuery(String mysql, String sqlite) {
+ this.mysql = mysql;
+ this.sqlite = sqlite;
+ }
+
+ public String getQuery() {
+ switch (ModuleManager.getModule(DatabaseManager.class).getConfig().Engine) {
+ case MYSQL:
+ return this.mysql;
+ case SQLITE:
+ return this.sqlite;
+ }
+
+ return null;
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+
+ private String mysql;
+ private String sqlite;
+
+ public Builder mysql(String mysql) {
+ this.mysql = mysql;
+ return this;
+ }
+
+ public Builder sqlite(String sqlite) {
+ this.sqlite = sqlite;
+ return this;
+ }
+
+ public Builder query(String query) {
+ this.mysql = query;
+ this.sqlite = query;
+ return this;
+ }
+
+ public DatabaseQuery build() {
+ return new DatabaseQuery(this.mysql, this.sqlite);
+ }
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/database/DatabaseRepository.java b/src/com/projectkorra/projectkorra/database/DatabaseRepository.java
new file mode 100644
index 00000000..83a9859c
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/database/DatabaseRepository.java
@@ -0,0 +1,17 @@
+package com.projectkorra.projectkorra.database;
+
+import com.projectkorra.projectkorra.database.engine.SQLDatabase;
+import com.projectkorra.projectkorra.module.ModuleManager;
+
+public abstract class DatabaseRepository {
+
+ private final DatabaseManager databaseManager;
+
+ public DatabaseRepository() {
+ this.databaseManager = ModuleManager.getModule(DatabaseManager.class);
+ }
+
+ protected SQLDatabase getDatabase() {
+ return this.databaseManager.getDatabase();
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/database/engine/MySQLDatabase.java b/src/com/projectkorra/projectkorra/database/engine/MySQLDatabase.java
new file mode 100644
index 00000000..da2f07c7
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/database/engine/MySQLDatabase.java
@@ -0,0 +1,42 @@
+package com.projectkorra.projectkorra.database.engine;
+
+import com.projectkorra.projectkorra.database.DatabaseConfig;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+public class MySQLDatabase implements SQLDatabase {
+
+ private final HikariDataSource hikari;
+
+ public MySQLDatabase(DatabaseConfig databaseConfig) {
+ HikariConfig hikariConfig = new HikariConfig();
+
+ hikariConfig.setJdbcUrl("jdbc:mysql://" + databaseConfig.MySQL_IP + ":" + databaseConfig.MySQL_Port + "/" + databaseConfig.MySQL_DatabaseName);
+ hikariConfig.setDriverClassName("com.mysql.jdbc.Driver");
+ hikariConfig.setUsername(databaseConfig.MySQL_Username);
+ hikariConfig.setPassword(databaseConfig.MySQL_Password);
+ hikariConfig.setMinimumIdle(1);
+ hikariConfig.setMaximumPoolSize(10);
+ hikariConfig.setConnectionTimeout(10000);
+
+ this.hikari = new HikariDataSource(hikariConfig);
+ }
+
+ @Override
+ public Connection getConnection() {
+ try (Connection connection = this.hikari.getConnection()) {
+ return connection;
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public void close() {
+ this.hikari.close();
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/database/engine/SQLDatabase.java b/src/com/projectkorra/projectkorra/database/engine/SQLDatabase.java
new file mode 100644
index 00000000..117dbb02
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/database/engine/SQLDatabase.java
@@ -0,0 +1,10 @@
+package com.projectkorra.projectkorra.database.engine;
+
+import java.sql.Connection;
+
+public interface SQLDatabase {
+
+ Connection getConnection();
+
+ void close();
+}
diff --git a/src/com/projectkorra/projectkorra/database/engine/SQLiteDatabase.java b/src/com/projectkorra/projectkorra/database/engine/SQLiteDatabase.java
new file mode 100644
index 00000000..c86f9c5b
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/database/engine/SQLiteDatabase.java
@@ -0,0 +1,64 @@
+package com.projectkorra.projectkorra.database.engine;
+
+import com.projectkorra.projectkorra.database.DatabaseConfig;
+import com.projectkorra.projectkorra.database.DatabaseManager;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+public class SQLiteDatabase implements SQLDatabase {
+
+ private final File databaseFile;
+ private Connection connection;
+
+ public SQLiteDatabase(DatabaseManager databaseManager, DatabaseConfig databaseConfig) {
+ this.databaseFile = new File(databaseManager.getPlugin().getDataFolder(), databaseConfig.SQLite_File);
+
+ if (!this.databaseFile.getParentFile().exists()) {
+ this.databaseFile.getParentFile().mkdirs();
+ }
+
+ if (!this.databaseFile.exists()) {
+ try {
+ this.databaseFile.createNewFile();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ open();
+ }
+
+ public void open() {
+ try {
+ this.connection = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getAbsolutePath());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public Connection getConnection() {
+ try {
+ if (this.connection == null || this.connection.isClosed()) {
+ open();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ return this.connection;
+ }
+
+ @Override
+ public void close() {
+ try {
+ this.connection.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/earthbending/Catapult.java b/src/com/projectkorra/projectkorra/earthbending/Catapult.java
index 044add6b..9e624c4b 100644
--- a/src/com/projectkorra/projectkorra/earthbending/Catapult.java
+++ b/src/com/projectkorra/projectkorra/earthbending/Catapult.java
@@ -11,6 +11,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
+import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.EarthAbility;
import com.projectkorra.projectkorra.attribute.Attribute;
@@ -70,6 +71,9 @@ public class Catapult extends EarthAbility {
private void moveEarth(final Vector apply, final Vector direction) {
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.origin, 2)) {
if (entity.getEntityId() != this.player.getEntityId()) {
+ if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) {
+ continue;
+ }
entity.setVelocity(apply);
}
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/Collapse.java b/src/com/projectkorra/projectkorra/earthbending/Collapse.java
index 42db5e40..a2e879ed 100644
--- a/src/com/projectkorra/projectkorra/earthbending/Collapse.java
+++ b/src/com/projectkorra/projectkorra/earthbending/Collapse.java
@@ -99,7 +99,7 @@ public class Collapse extends EarthAbility {
thisBlock = this.block.getWorld().getBlockAt(this.location.clone().add(this.direction.clone().multiply(-i)));
this.affectedBlocks.put(thisBlock, thisBlock);
if (RaiseEarth.blockInAllAffectedBlocks(thisBlock)) {
- EarthAbility.revertBlock(thisBlock);
+ RaiseEarth.revertAffectedBlock(thisBlock);
}
}
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java b/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java
index 43c32723..16e3cb9d 100644
--- a/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java
+++ b/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@@ -376,8 +377,12 @@ public class EarthBlast extends EarthAbility {
this.firstDestination = this.location.clone();
if (this.destination.getY() - this.location.getY() > 2) {
this.firstDestination.setY(this.destination.getY() - 1);
- } else {
+ } else if (this.location.getY() > player.getEyeLocation().getY() && this.location.getBlock().getRelative(BlockFace.UP).isPassable()) {
+ this.firstDestination.subtract(0, 2, 0);
+ } else if (this.location.getBlock().getRelative(BlockFace.UP).isPassable() && this.location.getBlock().getRelative(BlockFace.UP, 2).isPassable()) {
this.firstDestination.add(0, 2, 0);
+ } else {
+ this.firstDestination.add(GeneralMethods.getDirection(this.location, this.destination).normalize().setY(0));
}
if (this.destination.distanceSquared(this.location) <= 1) {
diff --git a/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java b/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java
index d5433629..e89a2ed7 100644
--- a/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java
+++ b/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java
@@ -2,7 +2,6 @@ package com.projectkorra.projectkorra.earthbending;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location;
@@ -15,11 +14,10 @@ import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.configuration.configs.abilities.earth.RaiseEarthConfig;
import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType;
+import com.projectkorra.projectkorra.util.TempBlock;
public class RaiseEarth extends EarthAbility {
- private static final Map ALL_AFFECTED_BLOCKS = new ConcurrentHashMap<>();
-
private int distance;
@Attribute(Attribute.HEIGHT)
private int height;
@@ -104,7 +102,7 @@ public class RaiseEarth extends EarthAbility {
private boolean canInstantiate() {
for (final Block block : this.affectedBlocks.keySet()) {
- if (!this.isEarthbendable(block) || ALL_AFFECTED_BLOCKS.containsKey(block)) {
+ if (!this.isEarthbendable(block) || TempBlock.isTempBlock(block)) {
return false;
}
}
@@ -143,11 +141,15 @@ public class RaiseEarth extends EarthAbility {
}
public static boolean blockInAllAffectedBlocks(final Block block) {
- return ALL_AFFECTED_BLOCKS.containsKey(block);
+ for (RaiseEarth raiseEarth : getAbilities(RaiseEarth.class)) {
+ if (raiseEarth.affectedBlocks.contains(block)) {
+ return true;
+ }
+ }
+ return false;
}
public static void revertAffectedBlock(final Block block) {
- ALL_AFFECTED_BLOCKS.remove(block);
for (final RaiseEarth raiseEarth : getAbilities(RaiseEarth.class)) {
raiseEarth.affectedBlocks.remove(block);
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java b/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java
index e2e5eab4..f65e30c8 100644
--- a/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java
+++ b/src/com/projectkorra/projectkorra/earthbending/metal/MetalClips.java
@@ -18,6 +18,7 @@ import org.bukkit.entity.Zombie;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
+import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.MetalAbility;
@@ -166,7 +167,7 @@ public class MetalClips extends MetalAbility {
return;
} else if (this.metalClipsCount == 3 && !this.canUse4Clips) {
return;
- } else if (this.targetEntity != null && GeneralMethods.isRegionProtectedFromBuild(this, this.targetEntity.getLocation())) {
+ } else if (this.targetEntity != null && (GeneralMethods.isRegionProtectedFromBuild(this, this.targetEntity.getLocation()) || ((targetEntity instanceof Player) && Commands.invincible.contains(((Player) targetEntity).getName())))) {
return;
}
diff --git a/src/com/projectkorra/projectkorra/element/Element.java b/src/com/projectkorra/projectkorra/element/Element.java
new file mode 100644
index 00000000..01d05579
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/element/Element.java
@@ -0,0 +1,38 @@
+package com.projectkorra.projectkorra.element;
+
+import org.bukkit.ChatColor;
+
+public class Element {
+
+ private final int elementId;
+ private final String elementName;
+ private final String displayName;
+ private final ChatColor color;
+
+ public Element(int elementId, String elementName, String displayName, ChatColor color) {
+ this.elementId = elementId;
+ this.elementName = elementName;
+ this.displayName = displayName;
+ this.color = color;
+ }
+
+ public int getId() {
+ return this.elementId;
+ }
+
+ public String getName() {
+ return this.elementName;
+ }
+
+ public String getDisplayName() {
+ return this.displayName;
+ }
+
+ public ChatColor getColor() {
+ return this.color;
+ }
+
+ public String getColoredName() {
+ return this.color + this.displayName;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/element/ElementManager.java b/src/com/projectkorra/projectkorra/element/ElementManager.java
new file mode 100644
index 00000000..7d638d80
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/element/ElementManager.java
@@ -0,0 +1,271 @@
+package com.projectkorra.projectkorra.element;
+
+import com.google.common.base.Preconditions;
+import com.projectkorra.projectkorra.module.DatabaseModule;
+import com.projectkorra.projectkorra.module.ModuleManager;
+import com.projectkorra.projectkorra.player.BendingPlayer;
+import com.projectkorra.projectkorra.player.BendingPlayerLoadedEvent;
+import com.projectkorra.projectkorra.player.BendingPlayerManager;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class ElementManager extends DatabaseModule {
+
+ private static final String WATER = "water", EARTH = "earth", FIRE = "fire", AIR = "air", CHI = "chi", AVATAR = "avatar";
+ private static final String BLOOD = "blood", HEALING = "healing", ICE = "ice", PLANT = "plant";
+ private static final String LAVA = "lava", METAL = "metal", SAND = "sand";
+ private static final String COMBUSTION = "combustion", LIGHTNING = "lightning";
+ private static final String FLIGHT = "flight", SPIRITUAL = "spiritual";
+
+ private final BendingPlayerManager bendingPlayerManager;
+
+ private final Map elements = new HashMap<>();
+ private final Map names = new HashMap<>();
+
+ private final String nameRegex = "[a-zA-Z]+";
+
+ private Element water, earth, fire, air, chi, avatar;
+ private SubElement blood, healing, ice, plant;
+ private SubElement lava, metal, sand;
+ private SubElement combustion, lightning;
+ private SubElement flight, spiritual;
+
+ private ElementManager() {
+ super("Element", new ElementRepository());
+
+ this.bendingPlayerManager = ModuleManager.getModule(BendingPlayerManager.class);
+
+ runAsync(() -> {
+ try {
+ getRepository().createTables();
+
+ // Waterbending
+ this.water = addElement(WATER, "Water", ChatColor.AQUA);
+ this.blood = addSubElement(BLOOD, "Blood", ChatColor.DARK_AQUA, this.water);
+ this.healing = addSubElement(HEALING, "Healing", ChatColor.DARK_AQUA, this.water);
+ this.ice = addSubElement(ICE, "Ice", ChatColor.DARK_AQUA, this.water);
+ this.plant = addSubElement(PLANT, "Plant", ChatColor.DARK_AQUA, this.water);
+
+ // Earthbending
+ this.earth = addElement(EARTH, "Earth", ChatColor.AQUA);
+ this.lava = addSubElement(LAVA, "Lava", ChatColor.DARK_GREEN, this.earth);
+ this.metal = addSubElement(METAL, "Metal", ChatColor.DARK_GREEN, this.earth);
+ this.sand = addSubElement(SAND, "Sand", ChatColor.DARK_GREEN, this.earth);
+
+ // Firebending
+ this.fire = addElement(FIRE, "Fire", ChatColor.RED);
+ this.combustion = addSubElement(COMBUSTION, "Combustion", ChatColor.DARK_RED, this.fire);
+ this.lightning = addSubElement(LIGHTNING, "Lightning", ChatColor.DARK_RED, this.fire);
+
+ // Airbending
+ this.air = addElement(AIR, "Air", ChatColor.GRAY);
+ this.flight = addSubElement(FLIGHT, "Flight", ChatColor.DARK_GRAY, this.air);
+ this.spiritual = addSubElement(SPIRITUAL, "Spiritual", ChatColor.DARK_GRAY, this.air);
+
+ // Chiblocking
+ this.chi = addElement(CHI, "Chi", ChatColor.GOLD);
+
+ // Avatar
+ this.avatar = addElement(AVATAR, "Avatar", ChatColor.DARK_PURPLE);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ runSync(() -> {
+ log("Populated element database tables.");
+ });
+ });
+ }
+
+ @EventHandler
+ public void onBendingPlayerLoaded(BendingPlayerLoadedEvent event) {
+ BendingPlayer bendingPlayer = event.getBendingPlayer();
+
+ runAsync(() -> {
+ try {
+ List elements = getRepository().selectPlayerElements(bendingPlayer.getId()).stream().map(this.elements::get).collect(Collectors.toList());
+
+ elements.forEach(bendingPlayer::addElement);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public boolean addElement(Player player, Element element) {
+ BendingPlayer bendingPlayer = this.bendingPlayerManager.getBendingPlayer(player);
+
+ if (!bendingPlayer.addElement(element)) {
+ return false;
+ }
+
+ runAsync(() -> {
+ try {
+ getRepository().insertPlayerElement(bendingPlayer.getId(), element.getId());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+
+ return true;
+ }
+
+ public void setElement(Player player, Element element) {
+ BendingPlayer bendingPlayer = this.bendingPlayerManager.getBendingPlayer(player);
+
+ bendingPlayer.clearElements();
+ bendingPlayer.addElement(element);
+
+ runAsync(() -> {
+ try {
+ getRepository().deletePlayerElements(bendingPlayer.getId());
+ getRepository().insertPlayerElement(bendingPlayer.getId(), element.getId());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public boolean removeElement(Player player, Element element) {
+ BendingPlayer bendingPlayer = this.bendingPlayerManager.getBendingPlayer(player);
+
+ if (!bendingPlayer.removeElement(element)) {
+ return false;
+ }
+
+ runAsync(() -> {
+ try {
+ getRepository().deletePlayerElement(bendingPlayer.getId(), element.getId());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+
+ return true;
+ }
+
+ public void clearElements(Player player) {
+ BendingPlayer bendingPlayer = this.bendingPlayerManager.getBendingPlayer(player);
+
+ bendingPlayer.clearElements();
+
+ runAsync(() -> {
+ try {
+ getRepository().deletePlayerElements(bendingPlayer.getId());
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ private Element addElement(String elementName, String displayName, ChatColor color) {
+ int elementId = registerElement(elementName);
+
+ Element element = new Element(elementId, elementName, displayName, color);
+
+ this.elements.put(elementId, element);
+ this.names.put(elementName, element);
+
+ return element;
+ }
+
+ private SubElement addSubElement(String elementName, String displayName, ChatColor color, Element parent) {
+ int elementId = registerElement(elementName);
+
+ SubElement element = new SubElement(elementId, elementName, displayName, color, parent);
+
+ this.elements.put(elementId, element);
+ this.names.put(elementName, element);
+
+ return element;
+ }
+
+ private int registerElement(String elementName) {
+ Preconditions.checkNotNull(elementName, "Element name cannot be null");
+
+ Preconditions.checkArgument(Pattern.matches(this.nameRegex, elementName), "Element name must only contain letters and spaces");
+
+ try {
+ return getRepository().selectElemenetId(elementName);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return -1;
+ }
+ }
+
+ public Element getWater() {
+ return this.water;
+ }
+
+ public SubElement getBlood() {
+ return this.blood;
+ }
+
+ public SubElement getHealing() {
+ return this.healing;
+ }
+
+ public SubElement getIce() {
+ return this.ice;
+ }
+
+ public SubElement getPlant() {
+ return this.plant;
+ }
+
+ public Element getEarth() {
+ return this.earth;
+ }
+
+ public SubElement getLava() {
+ return this.lava;
+ }
+
+ public SubElement getMetal() {
+ return this.metal;
+ }
+
+ public SubElement getSand() {
+ return this.sand;
+ }
+
+ public Element getFire() {
+ return this.fire;
+ }
+
+ public SubElement getCombustion() {
+ return this.combustion;
+ }
+
+ public SubElement getLightning() {
+ return this.lightning;
+ }
+
+ public Element getAir() {
+ return this.air;
+ }
+
+ public SubElement getFlight() {
+ return this.flight;
+ }
+
+ public SubElement getSpiritual() {
+ return this.spiritual;
+ }
+
+ public Element getChi() {
+ return this.chi;
+ }
+
+ public Element getAvatar() {
+ return this.avatar;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/element/ElementRepository.java b/src/com/projectkorra/projectkorra/element/ElementRepository.java
new file mode 100644
index 00000000..2d35f9a1
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/element/ElementRepository.java
@@ -0,0 +1,136 @@
+package com.projectkorra.projectkorra.element;
+
+import com.projectkorra.projectkorra.database.DatabaseQuery;
+import com.projectkorra.projectkorra.database.DatabaseRepository;
+
+import java.sql.*;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ElementRepository extends DatabaseRepository {
+
+ private static final DatabaseQuery CREATE_TABLE_ELEMENTS = DatabaseQuery.newBuilder()
+ .mysql("CREATE TABLE IF NOT EXISTS pk_elements (element_id INTEGER PRIMARY KEY AUTO_INCREMENT, element_name VARCHAR(50) NOT NULL, UNIQUE INDEX name_index (element_name));")
+ .sqlite("CREATE TABLE IF NOT EXISTS pk_elements (element_id INTEGER PRIMARY KEY AUTOINCREMENT, element_name VARCHAR(50) NOT NULL); CREATE UNIQUE INDEX name_index ON pk_elements (element_name);")
+ .build();
+
+ private static final DatabaseQuery CREATE_TABLE_PLAYER_ELEMENTS = DatabaseQuery.newBuilder()
+ .mysql("CREATE TABLE IF NOT EXISTS pk_player_elements (player_id INTEGER REFERENCES pk_bending_players (player_id), element_id INTEGER REFERENCES pk_elements (element_id), PRIMARY KEY (player_id, element_id), INDEX player_index (player_id), INDEX element_index (element_id));")
+ .sqlite("CREATE TABLE IF NOT EXISTS pk_player_elements (player_id INTEGER REFERENCES pk_bending_players (player_id), element_id INTEGER REFERENCES pk_elements (element_id), PRIMARY KEY (player_id, element_id)); CREATE INDEX player_index ON pk_player_elements (player_id); CREATE INDEX element_index ON pk_player_elements (element_id);")
+ .build();
+
+ private static final DatabaseQuery SELECT_ELEMENT_ID = DatabaseQuery.newBuilder()
+ .query("SELECT element_id FROM pk_elements WHERE element_name = ?;")
+ .build();
+
+ private static final DatabaseQuery INSERT_ELEMENT_ID = DatabaseQuery.newBuilder()
+ .query("INSERT INTO pk_elements (element_name) VALUES (?);")
+ .build();
+
+ private static final DatabaseQuery SELECT_PLAYER_ELEMENTS = DatabaseQuery.newBuilder()
+ .query("SELECT element_id FROM pk_player_elements WHERE player_id = ?;")
+ .build();
+
+ private static final DatabaseQuery INSERT_PLAYER_ELEMENT = DatabaseQuery.newBuilder()
+ .query("INSERT INTO pk_player_elements VALUES (?, ?);")
+ .build();
+
+ private static final DatabaseQuery DELETE_PLAYER_ELEMENTS = DatabaseQuery.newBuilder()
+ .query("DELETE FROM pk_player_elements WHERE player_id = ?;")
+ .build();
+
+ private static final DatabaseQuery DELETE_PLAYER_ELEMENT = DatabaseQuery.newBuilder()
+ .query("DELETE FROM pk_player_elements WHERE player_id = ? AND element_id = ?;")
+ .build();
+
+ protected void createTables() throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement elements = connection.prepareStatement(CREATE_TABLE_ELEMENTS.getQuery()); PreparedStatement playerElements = connection.prepareStatement(CREATE_TABLE_PLAYER_ELEMENTS.getQuery())) {
+ elements.executeUpdate();
+ playerElements.executeUpdate();
+ }
+ }
+
+ protected int selectElemenetId(String elementName) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(SELECT_ELEMENT_ID.getQuery())) {
+ statement.setString(1, elementName);
+
+ try (ResultSet rs = statement.executeQuery()) {
+ if (!rs.next()) {
+ return insertElementId(elementName);
+ }
+
+ return rs.getInt("element_id");
+ }
+ }
+ }
+
+ private int insertElementId(String elementName) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(INSERT_ELEMENT_ID.getQuery(), Statement.RETURN_GENERATED_KEYS)) {
+ statement.setString(1, elementName);
+
+ statement.executeUpdate();
+
+ try (ResultSet rs = statement.getGeneratedKeys()) {
+ rs.next();
+
+ return rs.getInt(1);
+ }
+ }
+ }
+
+ protected Set selectPlayerElements(int playerId) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(SELECT_PLAYER_ELEMENTS.getQuery())) {
+ statement.setInt(1, playerId);
+
+ Set elements = new HashSet<>();
+
+ try (ResultSet rs = statement.executeQuery()) {
+ while (rs.next()) {
+ elements.add(rs.getInt("element_id"));
+ }
+
+ return elements;
+ }
+ }
+ }
+
+ protected void insertPlayerElement(int playerId, int elementId) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(INSERT_PLAYER_ELEMENT.getQuery())) {
+ statement.setInt(1, playerId);
+ statement.setInt(2, elementId);
+
+ statement.executeUpdate();
+ }
+ }
+
+ protected void deletePlayerElements(int playerId) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(DELETE_PLAYER_ELEMENTS.getQuery())) {
+ statement.setInt(1, playerId);
+
+ statement.executeUpdate();
+ }
+ }
+
+ protected void deletePlayerElement(int playerId, int elementId) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(DELETE_PLAYER_ELEMENT.getQuery())) {
+ statement.setInt(1, playerId);
+ statement.setInt(2, elementId);
+
+ statement.executeUpdate();
+ }
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/element/SubElement.java b/src/com/projectkorra/projectkorra/element/SubElement.java
new file mode 100644
index 00000000..6854740a
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/element/SubElement.java
@@ -0,0 +1,18 @@
+package com.projectkorra.projectkorra.element;
+
+import org.bukkit.ChatColor;
+
+public class SubElement extends Element {
+
+ private final Element parent;
+
+ public SubElement(int elementId, String elementName, String displayName, ChatColor color, Element parent) {
+ super(elementId, elementName, displayName, color);
+
+ this.parent = parent;
+ }
+
+ public Element getParent() {
+ return this.parent;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java b/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java
index 3fa43402..1b61e7a7 100644
--- a/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java
+++ b/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java
@@ -217,7 +217,7 @@ public class FireBlastCharged extends FireAbility {
}
boolean exploded = false;
- for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.location, 2 * this.collisionRadius)) {
+ for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.location, this.collisionRadius)) {
if (entity.getEntityId() == this.player.getEntityId() || GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation())) {
continue;
}
@@ -311,7 +311,9 @@ public class FireBlastCharged extends FireAbility {
@Override
public void remove() {
super.remove();
- this.bPlayer.addCooldown(this);
+ if (this.charged) {
+ this.bPlayer.addCooldown(this);
+ }
}
@Override
diff --git a/src/com/projectkorra/projectkorra/firebending/FireJet.java b/src/com/projectkorra/projectkorra/firebending/FireJet.java
index 6e9d235a..3fe40aad 100644
--- a/src/com/projectkorra/projectkorra/firebending/FireJet.java
+++ b/src/com/projectkorra/projectkorra/firebending/FireJet.java
@@ -74,10 +74,8 @@ public class FireJet extends FireAbility {
this.time = System.currentTimeMillis();
this.start();
-
+
this.previousGlidingState = player.isGliding();
-
- this.bPlayer.addCooldown(this);
}
}
@@ -122,6 +120,7 @@ public class FireJet extends FireAbility {
}
this.flightHandler.removeInstance(this.player, this.getName());
this.player.setFallDistance(0);
+ this.bPlayer.addCooldown(this);
}
@Override
diff --git a/src/com/projectkorra/projectkorra/firebending/WallOfFire.java b/src/com/projectkorra/projectkorra/firebending/WallOfFire.java
index a8695d29..16a62b81 100644
--- a/src/com/projectkorra/projectkorra/firebending/WallOfFire.java
+++ b/src/com/projectkorra/projectkorra/firebending/WallOfFire.java
@@ -103,7 +103,6 @@ public class WallOfFire extends FireAbility {
this.initializeBlocks();
this.start();
- this.bPlayer.addCooldown(this);
}
private void affect(final Entity entity) {
@@ -211,6 +210,12 @@ public class WallOfFire extends FireAbility {
}
}
+ @Override
+ public void remove() {
+ super.remove();
+ this.bPlayer.addCooldown(this);
+ }
+
@Override
public String getName() {
return "WallOfFire";
diff --git a/src/com/projectkorra/projectkorra/firebending/combo/JetBlast.java b/src/com/projectkorra/projectkorra/firebending/combo/JetBlast.java
index a4421df1..5e044148 100644
--- a/src/com/projectkorra/projectkorra/firebending/combo/JetBlast.java
+++ b/src/com/projectkorra/projectkorra/firebending/combo/JetBlast.java
@@ -81,7 +81,6 @@ public class JetBlast extends FireAbility implements ComboAbilit
return;
}
- this.bPlayer.addCooldown("JetBlast", this.cooldown);
this.firstTime = false;
final float spread = 0F;
ParticleEffect.EXPLOSION_LARGE.display(this.player.getLocation(), 1, spread, spread, spread, 0);
@@ -108,6 +107,7 @@ public class JetBlast extends FireAbility implements ComboAbilit
task.remove();
}
super.remove();
+ this.bPlayer.addCooldown("JetBlast", this.cooldown);
}
@Override
diff --git a/src/com/projectkorra/projectkorra/firebending/combo/JetBlaze.java b/src/com/projectkorra/projectkorra/firebending/combo/JetBlaze.java
index 2063e3c3..bb4dd4a7 100644
--- a/src/com/projectkorra/projectkorra/firebending/combo/JetBlaze.java
+++ b/src/com/projectkorra/projectkorra/firebending/combo/JetBlaze.java
@@ -90,7 +90,6 @@ public class JetBlaze extends FireAbility implements ComboAbilit
this.remove();
return;
}
- this.bPlayer.addCooldown("JetBlaze", this.cooldown);
this.firstTime = false;
} else if (System.currentTimeMillis() - this.time > this.duration) {
this.remove();
@@ -105,7 +104,7 @@ public class JetBlaze extends FireAbility implements ComboAbilit
fs.setDensity(8);
fs.setSpread(1.0F);
fs.setUseNewParticles(true);
- fs.setCollisionRadius(3);
+ fs.setCollisionRadius(2);
fs.setParticleEffect(ParticleEffect.SMOKE_LARGE);
fs.setDamage(this.damage);
fs.setFireTicks(this.fireTicks);
@@ -123,6 +122,7 @@ public class JetBlaze extends FireAbility implements ComboAbilit
task.remove();
}
super.remove();
+ this.bPlayer.addCooldown("JetBlaze", this.cooldown);
}
@Override
diff --git a/src/com/projectkorra/projectkorra/firebending/lightning/Lightning.java b/src/com/projectkorra/projectkorra/firebending/lightning/Lightning.java
index 5eb0801e..31b84960 100644
--- a/src/com/projectkorra/projectkorra/firebending/lightning/Lightning.java
+++ b/src/com/projectkorra/projectkorra/firebending/lightning/Lightning.java
@@ -3,6 +3,8 @@ package com.projectkorra.projectkorra.firebending.lightning;
import java.util.ArrayList;
import java.util.List;
+import com.projectkorra.projectkorra.ability.CoreAbility;
+import com.projectkorra.projectkorra.firebending.FireJet;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
@@ -181,6 +183,9 @@ public class Lightning extends LightningAbility {
} else if (!this.bPlayer.canBendIgnoreCooldowns(this)) {
this.remove();
return;
+ } else if (CoreAbility.hasAbility(player, FireJet.class)){
+ this.removeWithTasks();
+ return;
}
this.locations.clear();
diff --git a/src/com/projectkorra/projectkorra/module/DatabaseModule.java b/src/com/projectkorra/projectkorra/module/DatabaseModule.java
new file mode 100644
index 00000000..743f7b0b
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/module/DatabaseModule.java
@@ -0,0 +1,18 @@
+package com.projectkorra.projectkorra.module;
+
+import com.projectkorra.projectkorra.database.DatabaseRepository;
+
+public abstract class DatabaseModule extends Module {
+
+ private final T repository;
+
+ protected DatabaseModule(String name, T repository) {
+ super(name);
+
+ this.repository = repository;
+ }
+
+ protected T getRepository() {
+ return this.repository;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/module/Module.java b/src/com/projectkorra/projectkorra/module/Module.java
new file mode 100644
index 00000000..f68e0f0a
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/module/Module.java
@@ -0,0 +1,88 @@
+package com.projectkorra.projectkorra.module;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.projectkorra.projectkorra.ProjectKorra;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.logging.Level;
+
+public abstract class Module implements Listener {
+
+ private static final String LOG_FORMAT = "(%s) %s";
+
+ private final String name;
+ private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+
+ protected Module(String name) {
+ this.name = name;
+ }
+
+ protected final void enable() {
+ long startTime = System.currentTimeMillis();
+ log("Enabling...");
+
+ getPlugin().getServer().getPluginManager().registerEvents(this, getPlugin());
+ onEnable();
+
+ long finishTime = System.currentTimeMillis();
+ log(String.format("Enabled! [%sms]", finishTime - startTime));
+ }
+
+ public void onEnable() {
+
+ }
+
+ protected final void disable() {
+ long startTime = System.currentTimeMillis();
+ log("Disabling...");
+
+ HandlerList.unregisterAll(this);
+ onDisable();
+
+ long finishTime = System.currentTimeMillis();
+ log(String.format("Disabled! [%sms]", finishTime - startTime));
+ }
+
+ public void onDisable() {
+
+ }
+
+ protected final void runSync(Runnable runnable) {
+ getPlugin().getServer().getScheduler().runTask(getPlugin(), runnable);
+ }
+
+ protected final void runAsync(Runnable runnable) {
+ getPlugin().getServer().getScheduler().runTaskAsynchronously(getPlugin(), runnable);
+ }
+
+ protected final void runTimer(Runnable runnable, long delay, long period) {
+ getPlugin().getServer().getScheduler().runTaskTimer(getPlugin(), runnable, delay, period);
+ }
+
+ protected final void runAsyncTimer(Runnable runnable, long delay, long period) {
+ getPlugin().getServer().getScheduler().runTaskTimerAsynchronously(getPlugin(), runnable, delay, period);
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ protected Gson getGson() {
+ return this.gson;
+ }
+
+ public final void log(String message) {
+ log(Level.INFO, message);
+ }
+
+ public final void log(Level level, String message) {
+ getPlugin().getLogger().log(level, String.format(LOG_FORMAT, getName(), message));
+ }
+
+ public ProjectKorra getPlugin() {
+ return JavaPlugin.getPlugin(ProjectKorra.class);
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/module/ModuleManager.java b/src/com/projectkorra/projectkorra/module/ModuleManager.java
new file mode 100644
index 00000000..20418125
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/module/ModuleManager.java
@@ -0,0 +1,82 @@
+package com.projectkorra.projectkorra.module;
+
+import com.google.common.base.Preconditions;
+import com.projectkorra.projectkorra.ability.AbilityManager;
+import com.projectkorra.projectkorra.cooldown.CooldownManager;
+import com.projectkorra.projectkorra.database.DatabaseManager;
+import com.projectkorra.projectkorra.element.ElementManager;
+import com.projectkorra.projectkorra.player.BendingPlayerManager;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ModuleManager {
+
+ private static final Map, Module> MODULES = new HashMap<>();
+
+ /**
+ * Registers a new {@link Module} instance.
+ *
+ * @param moduleClass {@link Class} of the {@link Module} to be registered
+ * @throws NullPointerException if moduleClass is null
+ * @throws IllegalArgumentException if moduleClass has already been registered
+ */
+ public static void registerModule(Class extends Module> moduleClass) {
+ Preconditions.checkNotNull(moduleClass, "moduleClass cannot be null");
+ Preconditions.checkArgument(!MODULES.containsKey(moduleClass), "moduleClass has already been registered");
+
+ try {
+ Constructor extends Module> constructor = moduleClass.getDeclaredConstructor();
+ boolean accessible = constructor.isAccessible();
+ constructor.setAccessible(true);
+
+ Module module = constructor.newInstance();
+
+ MODULES.put(moduleClass, module);
+ module.enable();
+
+ constructor.setAccessible(accessible);
+ } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns a registered {@link Module} by its {@link Class}.
+ *
+ * @param moduleClass {@link Class} of the registered {@link Module}
+ * @return instance of the {@link Module} class
+ * @throws NullPointerException if moduleClass is null
+ * @throws IllegalArgumentException if moduleClass has not been registered
+ */
+ public static T getModule(Class moduleClass) {
+ Preconditions.checkNotNull(moduleClass, "moduleClass cannot be null");
+ Preconditions.checkArgument(MODULES.containsKey(moduleClass), "moduleClass has not been registered");
+
+ return moduleClass.cast(MODULES.get(moduleClass));
+ }
+
+ /**
+ * Register all our core {@link Module}s onEnable.
+ */
+ public static void startup() {
+ registerModule(DatabaseManager.class);
+ registerModule(BendingPlayerManager.class);
+ registerModule(ElementManager.class);
+ registerModule(AbilityManager.class);
+ registerModule(CooldownManager.class);
+ }
+
+ /**
+ * Disable all our core {@link Module}s onDisable.
+ */
+ public static void shutdown() {
+ registerModule(CooldownManager.class);
+ registerModule(AbilityManager.class);
+ registerModule(ElementManager.class);
+ getModule(BendingPlayerManager.class).disable();
+ getModule(DatabaseManager.class).disable();
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/player/BendingPlayer.java b/src/com/projectkorra/projectkorra/player/BendingPlayer.java
new file mode 100644
index 00000000..67dae2a0
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/player/BendingPlayer.java
@@ -0,0 +1,267 @@
+package com.projectkorra.projectkorra.player;
+
+import com.projectkorra.projectkorra.ability.Ability;
+import com.projectkorra.projectkorra.ability.AbilityManager;
+import com.projectkorra.projectkorra.ability.ChiAbility;
+import com.projectkorra.projectkorra.ability.CoreAbility;
+import com.projectkorra.projectkorra.ability.util.PassiveManager;
+import com.projectkorra.projectkorra.cooldown.CooldownManager;
+import com.projectkorra.projectkorra.element.Element;
+import com.projectkorra.projectkorra.element.ElementManager;
+import com.projectkorra.projectkorra.module.ModuleManager;
+import org.bukkit.entity.Player;
+
+import java.util.*;
+
+public class BendingPlayer {
+
+ private final BendingPlayerManager manager;
+ private final ElementManager elementManager;
+ private final AbilityManager abilityManager;
+ private final CooldownManager cooldownManager;
+
+ private final int playerId;
+ private final UUID uuid;
+ private final Player player;
+ private final String playerName;
+ private final long firstLogin;
+
+ private final Set elements;
+ private final Set toggledElements;
+ private final String[] abilities;
+
+ private ChiAbility stance;
+ private boolean bendingRemoved;
+ private boolean toggled;
+ private boolean tremorSense;
+ private boolean illumination;
+ private boolean chiBlocked;
+ private long slowTime;
+
+ public BendingPlayer(int playerId, UUID uuid, String playerName, long firstLogin) {
+ this.manager = ModuleManager.getModule(BendingPlayerManager.class);
+ this.elementManager = ModuleManager.getModule(ElementManager.class);
+ this.abilityManager = ModuleManager.getModule(AbilityManager.class);
+ this.cooldownManager = ModuleManager.getModule(CooldownManager.class);
+
+ this.playerId = playerId;
+ this.uuid = uuid;
+ this.player = manager.getPlugin().getServer().getPlayer(uuid);
+ this.playerName = playerName;
+ this.firstLogin = firstLogin;
+
+ this.elements = new HashSet<>();
+ this.toggledElements = new HashSet<>();
+ this.abilities = new String[9];
+ }
+
+ public Set getElements() {
+ return new HashSet<>(this.elements);
+ }
+
+ public boolean addElement(Element element) {
+ return this.elements.add(element);
+ }
+
+ public boolean removeElement(Element element) {
+ return this.elements.remove(element);
+ }
+
+ public void clearElements() {
+ this.elements.clear();
+ }
+
+ public boolean hasElement(Element element) {
+ if (element.equals(this.elementManager.getAvatar())) {
+ return this.player.hasPermission("bending.avatar");
+ }
+
+ return this.elements.contains(element);
+ }
+
+ public boolean canBloodbend() {
+ return this.elements.contains(this.elementManager.getBlood());
+ }
+
+ public boolean canUseHealing() {
+ return this.elements.contains(this.elementManager.getHealing());
+ }
+
+ public boolean canIcebend() {
+ return this.elements.contains(this.elementManager.getIce());
+ }
+
+ public boolean canPlantbend() {
+ return this.elements.contains(this.elementManager.getPlant());
+ }
+
+ public boolean canLavabend() {
+ return this.elements.contains(this.elementManager.getLava());
+ }
+
+ public boolean canMetalbend() {
+ return this.elements.contains(this.elementManager.getMetal());
+ }
+
+ public boolean canSandbend() {
+ return this.elements.contains(this.elementManager.getSand());
+ }
+
+ public boolean canCombustionbend() {
+ return this.elements.contains(this.elementManager.getCombustion());
+ }
+
+ public boolean canUseLightning() {
+ return this.elements.contains(this.elementManager.getLightning());
+ }
+
+ public boolean canUseFlight() {
+ return this.elements.contains(this.elementManager.getFlight());
+ }
+
+ public boolean canUseSpiritual() {
+ return this.elements.contains(this.elementManager.getSpiritual());
+ }
+
+ public boolean isElementToggled(Element element) {
+ return this.toggledElements.contains(element);
+ }
+
+ public void toggleElement(Element element) {
+ if (this.toggledElements.contains(element)) {
+ this.toggledElements.remove(element);
+ } else {
+ this.toggledElements.add(element);
+ }
+ }
+
+ public CoreAbility getBoundAbility() {
+ return CoreAbility.getAbility(getBoundAbilityName());
+ }
+
+ public String getBoundAbilityName() {
+ int slot = this.player.getInventory().getHeldItemSlot();
+ return this.abilities[slot];
+ }
+
+ public String getAbility(int slot) {
+ return this.abilities[slot];
+ }
+
+ public List getAbilities() {
+ return Arrays.asList(this.abilities);
+ }
+
+ public void setAbilities(String[] abilities) {
+ System.arraycopy(abilities, 0, this.abilities, 0, 9);
+ }
+
+ public void setAbility(int slot, String abilityName) {
+ this.abilities[slot] = abilityName;
+ }
+
+ public void addCooldown(Ability ability) {
+ addCooldown(ability, ability.getCooldown());
+ }
+
+ public void addCooldown(Ability ability, long duration) {
+ addCooldown(ability.getName(), duration);
+ }
+
+ public void addCooldown(Ability ability, long duration, boolean permanent) {
+ addCooldown(ability.getName(), duration, permanent);
+ }
+
+ public void addCooldown(String abilityName, long duration) {
+ addCooldown(abilityName, duration, false);
+ }
+
+ public void addCooldown(String abilityName, long duration, boolean permanent) {
+ this.cooldownManager.addCooldown(this.player, abilityName, duration, permanent);
+ }
+
+ public boolean isOnCooldown(Ability ability) {
+ return isOnCooldown(ability.getName());
+ }
+
+ public boolean isOnCooldown(String abilityName) {
+ return this.cooldownManager.isOnCooldown(this.player, abilityName);
+ }
+
+ public void removeCooldown(Ability ability) {
+ removeCoolldown(ability.getName());
+ }
+
+ public void removeCoolldown(String abilityName) {
+ this.cooldownManager.removeCooldown(this.player, abilityName);
+ }
+
+ public ChiAbility getStance() {
+ return this.stance;
+ }
+
+ public void setStance(ChiAbility stance) {
+ this.stance = stance;
+ }
+
+ public boolean isBendingRemoved() {
+ return this.bendingRemoved;
+ }
+
+ protected void setBendingRemoved(boolean bendingRemoved) {
+ this.bendingRemoved = bendingRemoved;
+ }
+
+ public boolean isToggled() {
+ return this.toggled;
+ }
+
+ public void toggleBending() {
+ this.toggled = !this.toggled;
+ PassiveManager.registerPassives(this.player); // TODO redo this passive system
+ }
+
+ public boolean isTremorSensing() {
+ return this.tremorSense;
+ }
+
+ public void toggleTremorSense() {
+ this.tremorSense = !this.tremorSense;
+ }
+
+ public boolean isIlluminating() {
+ return this.illumination;
+ }
+
+ public void toggleIllumination() {
+ this.illumination = !this.illumination;
+ }
+
+ public boolean isChiBlocked() {
+ return this.chiBlocked;
+ }
+
+ public void blockChi() {
+ this.chiBlocked = true;
+ }
+
+ public void unblockChi() {
+ this.chiBlocked = false;
+ }
+
+ public boolean canBeSlowed() {
+ return System.currentTimeMillis() > this.slowTime;
+ }
+
+ public void slow(long cooldown) {
+ this.slowTime = System.currentTimeMillis() + cooldown;
+ }
+
+ public int getId() {
+ return this.playerId;
+ }
+
+ public long getFirstLogin() {
+ return this.firstLogin;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/player/BendingPlayerLoadedEvent.java b/src/com/projectkorra/projectkorra/player/BendingPlayerLoadedEvent.java
new file mode 100644
index 00000000..85e8deeb
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/player/BendingPlayerLoadedEvent.java
@@ -0,0 +1,31 @@
+package com.projectkorra.projectkorra.player;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+
+public class BendingPlayerLoadedEvent extends PlayerEvent {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final BendingPlayer bendingPlayer;
+
+ public BendingPlayerLoadedEvent(Player player, BendingPlayer bendingPlayer) {
+ super(player);
+
+ this.bendingPlayer = bendingPlayer;
+ }
+
+ public BendingPlayer getBendingPlayer() {
+ return this.bendingPlayer;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/player/BendingPlayerManager.java b/src/com/projectkorra/projectkorra/player/BendingPlayerManager.java
new file mode 100644
index 00000000..321dc062
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/player/BendingPlayerManager.java
@@ -0,0 +1,119 @@
+package com.projectkorra.projectkorra.player;
+
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.event.PlayerCooldownChangeEvent;
+import com.projectkorra.projectkorra.module.DatabaseModule;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.player.PlayerLoginEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+import java.sql.SQLException;
+import java.util.*;
+
+public class BendingPlayerManager extends DatabaseModule {
+
+ private final Map players = new HashMap<>();
+
+ private final Set disconnected = new HashSet<>();
+ private final long databaseSyncInterval = 20 * 30;
+
+ private BendingPlayerManager() {
+ super("Bending Player", new BendingPlayerRepository());
+
+ runAsync(() -> {
+ try {
+ getRepository().createTables();
+
+ for (Player player : getPlugin().getServer().getOnlinePlayers()) {
+ loadBendingPlayer(player);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+
+ runTimer(() -> {
+ this.disconnected.forEach(this.players::remove);
+ this.disconnected.clear();
+ }, this.databaseSyncInterval, this.databaseSyncInterval);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onLogin(PlayerLoginEvent event) {
+ if (this.disconnected.remove(event.getPlayer().getUniqueId())) {
+ return;
+ }
+
+ runAsync(() -> {
+ loadBendingPlayer(event.getPlayer());
+ });
+ }
+
+ @EventHandler
+ public void onQuit(PlayerQuitEvent event) {
+ this.disconnected.add(event.getPlayer().getUniqueId());
+ }
+
+ @EventHandler
+ public void onCooldownChange(PlayerCooldownChangeEvent event) {
+ Player player = event.getPlayer();
+ BendingPlayer bendingPlayer = this.players.get(player.getUniqueId());
+
+ String ability = bendingPlayer.getBoundAbilityName();
+
+ if (ability != null && ability.equals(event.getAbility())) {
+ GeneralMethods.displayMovePreview(player);
+ }
+ }
+
+ public void removeBending(Player player) {
+ BendingPlayer bendingPlayer = this.players.get(player.getUniqueId());
+
+ bendingPlayer.setBendingRemoved(true);
+
+ updateBendingRemoved(bendingPlayer);
+ }
+
+ public void returnBending(Player player) {
+ BendingPlayer bendingPlayer = this.players.get(player.getUniqueId());
+
+ bendingPlayer.setBendingRemoved(false);
+
+ updateBendingRemoved(bendingPlayer);
+ }
+
+ private void updateBendingRemoved(BendingPlayer bendingPlayer) {
+ runAsync(() -> {
+ try {
+ getRepository().updateBendingRemoved(bendingPlayer);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ private void loadBendingPlayer(Player player) {
+ try {
+ BendingPlayer bendingPlayer = getRepository().selectPlayer(player);
+
+ runSync(() -> {
+ this.players.put(player.getUniqueId(), bendingPlayer);
+
+ BendingPlayerLoadedEvent bendingPlayerLoadedEvent = new BendingPlayerLoadedEvent(player, bendingPlayer);
+ getPlugin().getServer().getPluginManager().callEvent(bendingPlayerLoadedEvent);
+ });
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public BendingPlayer getBendingPlayer(Player player) {
+ return getBendingPlayer(player.getUniqueId());
+ }
+
+ public BendingPlayer getBendingPlayer(UUID uuid) {
+ return this.players.get(uuid);
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/player/BendingPlayerRepository.java b/src/com/projectkorra/projectkorra/player/BendingPlayerRepository.java
new file mode 100644
index 00000000..e59ac602
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/player/BendingPlayerRepository.java
@@ -0,0 +1,118 @@
+package com.projectkorra.projectkorra.player;
+
+import com.projectkorra.projectkorra.database.DatabaseQuery;
+import com.projectkorra.projectkorra.database.DatabaseRepository;
+import org.bukkit.entity.Player;
+
+import java.nio.ByteBuffer;
+import java.sql.*;
+import java.util.UUID;
+
+public class BendingPlayerRepository extends DatabaseRepository {
+
+ private static final DatabaseQuery CREATE_TABLE_BENDING_PLAYERS = DatabaseQuery.newBuilder()
+ .mysql("CREATE TABLE IF NOT EXISTS pk_bending_players (player_id INTEGER PRIMARY KEY AUTO_INCREMENT, uuid BINARY(16) NOT NULL, player_name VARCHAR(16) NOT NULL, first_login BIGINT NOT NULL, bending_removed BOOLEAN, INDEX uuid_index (uuid));")
+ .sqlite("CREATE TABLE IF NOT EXISTS pk_bending_players (player_id INTEGER PRIMARY KEY AUTOINCREMENT, uuid BINARY(16) NOT NULL, player_name VARCHAR(16) NOT NULL, first_login BIGINT NOT NULL, bending_removed BOOLEAN); CREATE INDEX uuid_index ON pk_bending_players (uuid);")
+ .build();
+
+ private static final DatabaseQuery SELECT_BENDING_PLAYER = DatabaseQuery.newBuilder()
+ .query("SELECT player_id, player_name, first_login, bending_removed FROM pk_bending_players WHERE uuid = ?;")
+ .build();
+
+ private static final DatabaseQuery INSERT_BENDING_PLAYER = DatabaseQuery.newBuilder()
+ .query("INSERT INTO pk_bending_players (uuid, player_name, first_login) VALUES (?, ?, ?);")
+ .build();
+
+ private static final DatabaseQuery UPDATE_PLAYER_NAME = DatabaseQuery.newBuilder()
+ .query("UPDATE pk_bending_players SET player_name = ? WHERE player_id = ?;")
+ .build();
+
+ private static final DatabaseQuery UPDATE_BENDING_REMOVED = DatabaseQuery.newBuilder()
+ .query("UPDATE pk_bending_players SET bending_removed = ? WHERE player_id = ?;")
+ .build();
+
+ protected void createTables() throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(CREATE_TABLE_BENDING_PLAYERS.getQuery())) {
+ statement.executeUpdate();
+ }
+ }
+
+ protected BendingPlayer selectPlayer(Player player) throws SQLException {
+ UUID uuid = player.getUniqueId();
+ byte[] binaryUUID = ByteBuffer.allocate(16).putLong(uuid.getMostSignificantBits()).putLong(uuid.getLeastSignificantBits()).array();
+
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(SELECT_BENDING_PLAYER.getQuery())) {
+ statement.setBytes(1, binaryUUID);
+
+ try (ResultSet rs = statement.executeQuery()) {
+ if (!rs.next()) {
+ return insertPlayer(player.getUniqueId(), player.getName());
+ }
+
+ int playerId = rs.getInt("player_id");
+ String playerName = rs.getString("player_name");
+ long firstLogin = rs.getLong("first_login");
+ boolean bendingRemoved = rs.getBoolean("bending_removed");
+
+ if (!player.getName().equals(playerName)) {
+ updatePlayerName(playerId, player.getName());
+ }
+
+ BendingPlayer bendingPlayer = new BendingPlayer(playerId, uuid, playerName, firstLogin);
+
+ bendingPlayer.setBendingRemoved(bendingRemoved);
+
+ return bendingPlayer;
+ }
+ }
+ }
+
+ private BendingPlayer insertPlayer(UUID uuid, String playerName) throws SQLException {
+ byte[] binaryUUID = ByteBuffer.allocate(16).putLong(uuid.getMostSignificantBits()).putLong(uuid.getLeastSignificantBits()).array();
+
+ Connection connection = getDatabase().getConnection();
+ long firstLogin = System.currentTimeMillis();
+
+ try (PreparedStatement statement = connection.prepareStatement(INSERT_BENDING_PLAYER.getQuery(), Statement.RETURN_GENERATED_KEYS)) {
+ statement.setBytes(1, binaryUUID);
+ statement.setString(2, playerName);
+ statement.setLong(3, firstLogin);
+
+ statement.executeUpdate();
+
+ try (ResultSet rs = statement.getGeneratedKeys()) {
+ rs.next();
+
+ int playerId = rs.getInt(1);
+
+ return new BendingPlayer(playerId, uuid, playerName, firstLogin);
+ }
+ }
+ }
+
+ protected void updatePlayerName(int playerId, String playerName) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(UPDATE_PLAYER_NAME.getQuery())) {
+ statement.setInt(1, playerId);
+ statement.setString(2, playerName);
+
+ statement.executeUpdate();
+ }
+ }
+
+ protected void updateBendingRemoved(BendingPlayer bendingPlayer) throws SQLException {
+ Connection connection = getDatabase().getConnection();
+
+ try (PreparedStatement statement = connection.prepareStatement(UPDATE_BENDING_REMOVED.getQuery())) {
+ statement.setInt(1, bendingPlayer.getId());
+ statement.setBoolean(2, bendingPlayer.isBendingRemoved());
+
+ statement.executeUpdate();
+ }
+ }
+}
diff --git a/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java b/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java
index b451f74a..7db0060e 100644
--- a/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java
+++ b/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java
@@ -256,12 +256,11 @@ public class SurgeWall extends WaterAbility {
}
final ArrayList blocks = new ArrayList();
- final Location targetLoc = GeneralMethods.getTargetedLocation(this.player, (int) this.range, Material.WATER, Material.ICE);
+ final Location targetLoc = GeneralMethods.getTargetedLocation(this.player, (int) this.range, false, false, Material.WATER, Material.ICE);
this.location = targetLoc.clone();
final Vector eyeDir = this.player.getEyeLocation().getDirection();
Vector vector;
Block block;
-
for (double i = 0; i <= this.getNightFactor(this.radius); i += 0.5) {
for (double angle = 0; angle < 360; angle += 10) {
vector = GeneralMethods.getOrthogonalVector(eyeDir.clone(), angle, i);
diff --git a/src/com/projectkorra/projectkorra/waterbending/util/WaterReturn.java b/src/com/projectkorra/projectkorra/waterbending/util/WaterReturn.java
index 52dd2c28..15543946 100644
--- a/src/com/projectkorra/projectkorra/waterbending/util/WaterReturn.java
+++ b/src/com/projectkorra/projectkorra/waterbending/util/WaterReturn.java
@@ -116,8 +116,8 @@ public class WaterReturn extends WaterAbility {
private void fillBottle() {
final PlayerInventory inventory = this.player.getInventory();
- if (inventory.contains(Material.GLASS_BOTTLE)) {
- final int index = inventory.first(Material.GLASS_BOTTLE);
+ final int index = inventory.first(Material.GLASS_BOTTLE);
+ if (index >= 0) {
final ItemStack item = inventory.getItem(index);
final ItemStack water = waterBottleItem();
@@ -148,27 +148,15 @@ public class WaterReturn extends WaterAbility {
return false;
}
- public static boolean hasWaterBottle(final Player player) {
- if (hasAbility(player, WaterReturn.class) || isBending(player)) {
- return false;
- }
- final PlayerInventory inventory = player.getInventory();
- if (inventory.contains(Material.POTION)) {
- final ItemStack item = inventory.getItem(inventory.first(Material.POTION));
- final PotionMeta meta = (PotionMeta) item.getItemMeta();
- return meta.getBasePotionData().getType() == PotionType.WATER;
- }
- return false;
- }
-
- public static void emptyWaterBottle(final Player player) {
- final PlayerInventory inventory = player.getInventory();
+ public static int firstWaterBottle(final PlayerInventory inventory) {
int index = inventory.first(Material.POTION);
// Check that the first one found is actually a WATER bottle. We aren't implementing potion bending just yet.
- if (index != -1 && !((PotionMeta) inventory.getItem(index).getItemMeta()).getBasePotionData().getType().equals(PotionType.WATER)) {
- for (int i = 0; i < inventory.getSize(); i++) {
- if (inventory.getItem(i).getType() == Material.POTION) {
+ if (index != -1) {
+ int aux = index;
+ index = -1;
+ for (int i = aux; i < inventory.getSize(); i++) {
+ if (inventory.getItem(i) != null && inventory.getItem(i).getType() == Material.POTION && inventory.getItem(i).hasItemMeta()) {
final PotionMeta meta = (PotionMeta) inventory.getItem(i).getItemMeta();
if (meta.getBasePotionData().getType().equals(PotionType.WATER)) {
index = i;
@@ -178,6 +166,22 @@ public class WaterReturn extends WaterAbility {
}
}
+ return index;
+ }
+
+ public static boolean hasWaterBottle(final Player player) {
+ if (hasAbility(player, WaterReturn.class) || isBending(player)) {
+ return false;
+ }
+ final PlayerInventory inventory = player.getInventory();
+
+ return WaterReturn.firstWaterBottle(inventory) >= 0;
+ }
+
+ public static void emptyWaterBottle(final Player player) {
+ final PlayerInventory inventory = player.getInventory();
+ int index = WaterReturn.firstWaterBottle(inventory);
+
if (index != -1) {
final ItemStack item = inventory.getItem(index);
if (item.getAmount() == 1) {