/* * This file is part of MyPet * * Copyright © 2011-2016 Keyle * MyPet is licensed under the GNU Lesser General Public License. * * MyPet is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MyPet is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.Keyle.MyPet.repository.types; import com.google.common.base.Optional; import de.Keyle.MyPet.MyPetApi; import de.Keyle.MyPet.api.MyPetVersion; import de.Keyle.MyPet.api.entity.MyPet; import de.Keyle.MyPet.api.entity.MyPetType; import de.Keyle.MyPet.api.entity.StoredMyPet; import de.Keyle.MyPet.api.player.MyPetPlayer; import de.Keyle.MyPet.api.repository.Repository; import de.Keyle.MyPet.api.repository.RepositoryCallback; import de.Keyle.MyPet.api.repository.RepositoryInitException; import de.Keyle.MyPet.api.skill.skilltree.SkillTreeMobType; import de.Keyle.MyPet.api.util.service.types.RepositoryMyPetConverterService; import de.Keyle.MyPet.entity.InactiveMyPet; import de.Keyle.MyPet.util.player.MyPetPlayerImpl; import de.keyle.knbt.TagStream; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.sql.*; import java.util.*; public class SqLiteRepository implements Repository { private Connection connection; private int version = 1; @Override public void disable() { saveData(); try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } @Override public void save() { saveData(); } @Override public void init() throws RepositoryInitException { try { File dbFile = new File(MyPetApi.getPlugin().getDataFolder().getPath() + File.separator + "pets.db"); Class.forName("org.sqlite.JDBC"); connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath()); PreparedStatement statement = connection.prepareStatement("SELECT name FROM sqlite_master WHERE type='table' AND name='info';"); ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { resultSet.close(); statement = connection.prepareStatement("SELECT * FROM info;"); resultSet = statement.executeQuery(); updateStructure(resultSet); updateInfo(); } else { initStructure(); } resultSet.close(); } catch (Exception e) { e.printStackTrace(); throw new RepositoryInitException(e); } } private void updateStructure(ResultSet resultSet) { try { int oldVersion = resultSet.getInt("version"); if (oldVersion < version) { MyPetApi.getLogger().info("[SQLite] Updating database from v" + oldVersion + " to v" + version + "."); switch (oldVersion) { case 1: //updateToV2(); } } } catch (SQLException e) { e.printStackTrace(); } } private void initStructure() { try { Statement create = connection.createStatement(); create.executeUpdate("CREATE TABLE pets (" + "uuid VARCHAR(36) NOT NULL PRIMARY KEY, " + "owner_uuid VARCHAR(36) NOT NULL , " + "exp DOUBLE, " + "health DOUBLE, " + "respawn_time INTEGER, " + "name VARCHAR(1024), " + "type VARCHAR(20), " + "last_used BIGINT, " + "hunger INTEGER, " + "world_group VARCHAR(255), " + "wants_to_spawn BOOLEAN, " + "skilltree VARCHAR(255), " + "skills BLOB, " + "info BLOB, " + "last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP" + ")"); createTimestampTrigger("pets", "last_update", "uuid"); create.executeUpdate("CREATE TABLE players (" + "internal_uuid VARCHAR(36) NOT NULL PRIMARY KEY, " + "mojang_uuid VARCHAR(36) UNIQUE, " + "name VARCHAR(16) UNIQUE, " + "auto_respawn BOOLEAN, " + "auto_respawn_min INTEGER , " + "capture_mode BOOLEAN, " + "health_bar INTEGER, " + "pet_idle_volume FLOAT, " + "resource_pack BOOLEAN NULL DEFAULT NULL, " + "extended_info BLOB, " + "multi_world VARCHAR(2000), " + "last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP" + ")"); createTimestampTrigger("players", "last_update", "internal_uuid"); create.executeUpdate("CREATE TABLE info (" + "version INTEGER UNIQUE, " + "mypet_version VARCHAR(20), " + "mypet_build VARCHAR(20), " + "last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP" + ")"); createTimestampTrigger("info", "last_update", "version"); PreparedStatement insert = connection.prepareStatement("INSERT INTO info (version, mypet_version, mypet_build) VALUES (?,?,?);"); insert.setInt(1, version); insert.setString(2, MyPetVersion.getVersion()); insert.setString(3, MyPetVersion.getBuild()); insert.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } private void createTimestampTrigger(String table, String column, String id) { try { Statement create = connection.createStatement(); create.execute("CREATE TRIGGER [update_time_trigger_" + table + "] " + "AFTER UPDATE ON " + table + " FOR EACH ROW " + "WHEN NEW." + column + " < OLD." + column + " " + "BEGIN " + " UPDATE " + table + " SET " + column + "=CURRENT_TIMESTAMP " + " WHERE NEW." + id + "=OLD." + id + ";" + "END;"); } catch (SQLException e) { e.printStackTrace(); } } @Override public void cleanup(final long timestamp, final RepositoryCallback<Integer> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("DELETE FROM pets WHERE last_used<?;"); statement.setLong(1, timestamp); int result = statement.executeUpdate(); //MyPetLogger.write("DELETE pet: " + result); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), result); } } catch (SQLException e) { e.printStackTrace(); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), 0); } } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } @Override public void countMyPets(final RepositoryCallback<Integer> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT COUNT(uuid) FROM pets;"); ResultSet resultSet = statement.executeQuery(); resultSet.next(); callback.setValue(resultSet.getInt(1)); callback.runTask(MyPetApi.getPlugin()); } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } @Override public void countMyPets(final MyPetType type, final RepositoryCallback<Integer> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT COUNT(uuid) FROM pets WHERE type=?;"); statement.setString(1, type.name()); ResultSet resultSet = statement.executeQuery(); resultSet.next(); callback.setValue(resultSet.getInt(1)); callback.runTask(MyPetApi.getPlugin()); } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } public void saveData() { updateInfo(); savePets(); savePlayers(); } private void updateInfo() { try { PreparedStatement update = connection.prepareStatement("UPDATE info SET version=?, mypet_version=?, mypet_build=?;"); update.setInt(1, version); update.setString(2, MyPetVersion.getVersion()); update.setString(3, MyPetVersion.getBuild()); update.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } private void savePets() { for (MyPet myPet : MyPetApi.getMyPetManager().getAllActiveMyPets()) { try { PreparedStatement statement = connection.prepareStatement("UPDATE pets SET " + "owner_uuid=?, " + "exp=?, " + "health=?, " + "respawn_time=?, " + "name=?, " + "type=?, " + "last_used=?, " + "hunger=?, " + "world_group=?, " + "wants_to_spawn=?, " + "skilltree=?, " + "skills=?, " + "info=? " + "WHERE uuid=?;"); statement.setString(1, myPet.getOwner().getInternalUUID().toString()); statement.setDouble(2, myPet.getExp()); statement.setDouble(3, myPet.getHealth()); statement.setInt(4, myPet.getRespawnTime()); statement.setBytes(5, myPet.getPetName().getBytes(StandardCharsets.UTF_8)); statement.setString(6, myPet.getPetType().name()); statement.setLong(7, myPet.getLastUsed()); statement.setDouble(8, myPet.getSaturation()); statement.setString(9, myPet.getWorldGroup()); statement.setBoolean(10, myPet.wantsToRespawn()); statement.setString(11, myPet.getSkilltree() != null ? myPet.getSkilltree().getName() : null); statement.setBytes(12, TagStream.writeTag(myPet.getSkillInfo(), true)); statement.setBytes(13, TagStream.writeTag(myPet.getInfo(), true)); statement.setString(14, myPet.getUUID().toString()); int result = statement.executeUpdate(); //MyPetLogger.write("UPDATE pet: " + result); } catch (SQLException | IOException e) { e.printStackTrace(); } } } @SuppressWarnings("unchecked") private void savePlayers() { for (MyPetPlayer player : MyPetApi.getPlayerManager().getMyPetPlayers()) { try { PreparedStatement statement = connection.prepareStatement( "UPDATE players SET " + "mojang_uuid=?, " + "name=?, " + "auto_respawn=?, " + "auto_respawn_min=?, " + "capture_mode=?, " + "health_bar=?, " + "pet_idle_volume=?, " + "resource_pack=?, " + "extended_info=?, " + "multi_world=? " + "WHERE internal_uuid=?;"); statement.setString(1, player.getMojangUUID() != null ? player.getMojangUUID().toString() : null); statement.setString(2, player.getName()); statement.setBoolean(3, player.hasAutoRespawnEnabled()); statement.setInt(4, player.getAutoRespawnMin()); statement.setBoolean(5, player.isCaptureHelperActive()); statement.setBoolean(6, player.isHealthBarActive()); statement.setFloat(7, player.getPetLivingSoundVolume()); statement.setBoolean(8, false); statement.setBytes(9, TagStream.writeTag(player.getExtendedInfo(), true)); JSONObject multiWorldObject = new JSONObject(); for (String worldGroupName : player.getMyPetsForWorldGroups().keySet()) { multiWorldObject.put(worldGroupName, player.getMyPetsForWorldGroups().get(worldGroupName).toString()); } statement.setString(10, multiWorldObject.toJSONString()); statement.setString(11, player.getInternalUUID().toString()); int result = statement.executeUpdate(); //MyPetLogger.write("UPDATE player: " + result); } catch (SQLException | IOException e) { e.printStackTrace(); } } } // Pets ------------------------------------------------------------------------------------------------------------ private List<StoredMyPet> resultSetToMyPet(MyPetPlayer owner, ResultSet resultSet, boolean next) { List<StoredMyPet> pets = new ArrayList<>(); try { while (!next || resultSet.next()) { next = true; InactiveMyPet pet = new InactiveMyPet(owner); pet.setUUID(UUID.fromString(resultSet.getString("uuid"))); pet.setExp(resultSet.getDouble("exp")); pet.setHealth(resultSet.getDouble("health")); pet.setRespawnTime(resultSet.getInt("respawn_time")); pet.setPetName(new String(resultSet.getBytes("name"), StandardCharsets.UTF_8)); pet.setPetType(MyPetType.valueOf(resultSet.getString("type"))); pet.setLastUsed(resultSet.getLong("last_used")); pet.setHungerValue(resultSet.getDouble("hunger")); pet.setWorldGroup(resultSet.getString("world_group")); pet.wantsToRespawn = resultSet.getBoolean("wants_to_spawn"); String skillTreeName = resultSet.getString("skilltree"); if (skillTreeName != null) { if (SkillTreeMobType.byPetType(pet.getPetType()) != null) { SkillTreeMobType mobType = SkillTreeMobType.byPetType(pet.getPetType()); if (mobType.hasSkillTree(skillTreeName)) { pet.setSkilltree(mobType.getSkillTree(skillTreeName)); } } } pet.setSkills(TagStream.readTag(resultSet.getBytes("skills"), true)); pet.setInfo(TagStream.readTag(resultSet.getBytes("info"), true)); Optional<RepositoryMyPetConverterService> converter = MyPetApi.getServiceManager().getService(RepositoryMyPetConverterService.class); if (converter.isPresent()) { converter.get().convert(pet); } pets.add(pet); } } catch (SQLException | IOException e) { e.printStackTrace(); } return pets; } @Override public List<StoredMyPet> getAllMyPets() { try { List<MyPetPlayer> playerList = getAllMyPetPlayers(); Map<UUID, MyPetPlayer> owners = new HashMap<>(); for (MyPetPlayer player : playerList) { owners.put(player.getInternalUUID(), player); } Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT * FROM pets;"); List<StoredMyPet> pets = new ArrayList<>(); while (resultSet.next()) { if (!owners.containsKey(UUID.fromString(resultSet.getString("owner_uuid")))) { continue; } MyPetPlayer owner = owners.get(UUID.fromString(resultSet.getString("owner_uuid"))); InactiveMyPet pet = new InactiveMyPet(owner); pet.setUUID(UUID.fromString(resultSet.getString("uuid"))); pet.setExp(resultSet.getDouble("exp")); pet.setHealth(resultSet.getDouble("health")); pet.setRespawnTime(resultSet.getInt("respawn_time")); pet.setPetName(resultSet.getString("name")); pet.setPetType(MyPetType.valueOf(resultSet.getString("type"))); pet.setLastUsed(resultSet.getLong("last_used")); pet.setHungerValue(resultSet.getInt("hunger")); pet.setWorldGroup(resultSet.getString("world_group")); pet.wantsToRespawn = resultSet.getBoolean("wants_to_spawn"); String skillTreeName = resultSet.getString("skilltree"); if (skillTreeName != null) { if (SkillTreeMobType.byPetType(pet.getPetType()) != null) { SkillTreeMobType mobType = SkillTreeMobType.byPetType(pet.getPetType()); if (mobType.hasSkillTree(skillTreeName)) { pet.setSkilltree(mobType.getSkillTree(skillTreeName)); } } } pet.setSkills(TagStream.readTag(resultSet.getBytes("skills"), true)); pet.setInfo(TagStream.readTag(resultSet.getBytes("info"), true)); pets.add(pet); } return pets; } catch (SQLException | IOException e) { e.printStackTrace(); } return new ArrayList<>(); } @Override public void hasMyPets(final MyPetPlayer myPetPlayer, final RepositoryCallback<Boolean> callback) { if (callback != null) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT COUNT(uuid) FROM pets WHERE owner_uuid=?;"); statement.setString(1, myPetPlayer.getInternalUUID().toString()); ResultSet resultSet = statement.executeQuery(); resultSet.next(); //MyPetLogger.write("HAS pet: " + (resultSet.getInt(1) > 0)); callback.runTask(MyPetApi.getPlugin(), resultSet.getInt(1) > 0); } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } } @Override public void getMyPets(final MyPetPlayer owner, final RepositoryCallback<List<StoredMyPet>> callback) { if (callback != null) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT * FROM pets WHERE owner_uuid=?;"); statement.setString(1, owner.getInternalUUID().toString()); ResultSet resultSet = statement.executeQuery(); List<StoredMyPet> pets = resultSetToMyPet(owner, resultSet, true); //MyPetLogger.write("LOAD pets: " + pets); callback.runTask(MyPetApi.getPlugin(), pets); } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } } @Override public void getMyPet(final UUID uuid, final RepositoryCallback<StoredMyPet> callback) { if (callback != null) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT * FROM pets WHERE uuid=?;"); statement.setString(1, uuid.toString()); ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { MyPetPlayer owner = MyPetApi.getPlayerManager().getMyPetPlayer(UUID.fromString(resultSet.getString("owner_uuid"))); if (owner != null) { List<StoredMyPet> pets = resultSetToMyPet(owner, resultSet, false); if (pets.size() > 0) { //MyPetLogger.write("LOAD pet: " + pets.get(0)); callback.runTask(MyPetApi.getPlugin(), pets.get(0)); } } } } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } } @Override public void removeMyPet(final UUID uuid, final RepositoryCallback<Boolean> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("DELETE FROM pets WHERE uuid=?;"); statement.setString(1, uuid.toString()); int result = statement.executeUpdate(); //MyPetLogger.write("DELETE pet: " + result); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), result > 0); } } catch (SQLException e) { e.printStackTrace(); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), false); } } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } @Override public void removeMyPet(final StoredMyPet storedMyPet, final RepositoryCallback<Boolean> callback) { removeMyPet(storedMyPet.getUUID(), callback); } @Override public void addMyPet(final StoredMyPet storedMyPet, final RepositoryCallback<Boolean> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement( "INSERT INTO pets (uuid, " + "owner_uuid, " + "exp, " + "health, " + "respawn_time, " + "name, " + "type, " + "last_used, " + "hunger, " + "world_group, " + "wants_to_spawn, " + "skilltree, " + "skills, " + "info) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); statement.setString(1, storedMyPet.getUUID().toString()); statement.setString(2, storedMyPet.getOwner().getInternalUUID().toString()); statement.setDouble(3, storedMyPet.getExp()); statement.setDouble(4, storedMyPet.getHealth()); statement.setInt(5, storedMyPet.getRespawnTime()); statement.setString(6, storedMyPet.getPetName()); statement.setString(7, storedMyPet.getPetType().name()); statement.setLong(8, storedMyPet.getLastUsed()); statement.setDouble(9, storedMyPet.getSaturation()); statement.setString(10, storedMyPet.getWorldGroup()); statement.setBoolean(11, storedMyPet.wantsToRespawn()); statement.setString(12, storedMyPet.getSkilltree() != null ? storedMyPet.getSkilltree().getName() : null); try { statement.setBytes(13, TagStream.writeTag(storedMyPet.getSkillInfo(), true)); statement.setBytes(14, TagStream.writeTag(storedMyPet.getInfo(), true)); } catch (IOException e) { e.printStackTrace(); } boolean result = statement.executeUpdate() > 0; //MyPetLogger.write("INSERT pet: " + result); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), result); } } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } public boolean addMyPets(List<StoredMyPet> pets) { try { PreparedStatement statement = connection.prepareStatement( "INSERT INTO pets (uuid, " + "owner_uuid, " + "exp, " + "health, " + "respawn_time, " + "name, " + "type, " + "last_used, " + "hunger, " + "world_group, " + "wants_to_spawn, " + "skilltree, " + "skills, " + "info) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); int i = 0; for (StoredMyPet storedMyPet : pets) { statement.setString(1, storedMyPet.getUUID().toString()); statement.setString(2, storedMyPet.getOwner().getInternalUUID().toString()); statement.setDouble(3, storedMyPet.getExp()); statement.setDouble(4, storedMyPet.getHealth()); statement.setInt(5, storedMyPet.getRespawnTime()); statement.setString(6, storedMyPet.getPetName()); statement.setString(7, storedMyPet.getPetType().name()); statement.setLong(8, storedMyPet.getLastUsed()); statement.setDouble(9, storedMyPet.getSaturation()); statement.setString(10, storedMyPet.getWorldGroup()); statement.setBoolean(11, storedMyPet.wantsToRespawn()); statement.setString(12, storedMyPet.getSkilltree() != null ? storedMyPet.getSkilltree().getName() : null); try { statement.setBytes(13, TagStream.writeTag(storedMyPet.getSkillInfo(), true)); } catch (IOException e) { e.printStackTrace(); } try { statement.setBytes(14, TagStream.writeTag(storedMyPet.getInfo(), true)); } catch (IOException e) { e.printStackTrace(); } statement.addBatch(); if (++i % 500 == 0 && i != pets.size()) { statement.executeBatch(); } } statement.executeBatch(); return true; } catch (SQLException e) { e.printStackTrace(); } return false; } @Override public void updateMyPet(final StoredMyPet storedMyPet, final RepositoryCallback<Boolean> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("UPDATE pets SET " + "owner_uuid=?, " + "exp=?, " + "health=?, " + "respawn_time=?, " + "name=?, " + "type=?, " + "last_used=?, " + "hunger=?, " + "world_group=?, " + "wants_to_spawn=?, " + "skilltree=?, " + "skills=?, " + "info=? " + "WHERE uuid=?;"); statement.setString(1, storedMyPet.getOwner().getInternalUUID().toString()); statement.setDouble(2, storedMyPet.getExp()); statement.setDouble(3, storedMyPet.getHealth()); statement.setInt(4, storedMyPet.getRespawnTime()); statement.setBytes(5, storedMyPet.getPetName().getBytes(StandardCharsets.UTF_8)); statement.setString(6, storedMyPet.getPetType().name()); statement.setLong(7, storedMyPet.getLastUsed()); statement.setDouble(8, storedMyPet.getSaturation()); statement.setString(9, storedMyPet.getWorldGroup()); statement.setBoolean(10, storedMyPet.wantsToRespawn()); statement.setString(11, storedMyPet.getSkilltree() != null ? storedMyPet.getSkilltree().getName() : null); statement.setBytes(12, TagStream.writeTag(storedMyPet.getSkillInfo(), true)); statement.setBytes(13, TagStream.writeTag(storedMyPet.getInfo(), true)); statement.setString(14, storedMyPet.getUUID().toString()); int result = statement.executeUpdate(); //MyPetLogger.write("UPDATE pet: " + result); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), result > 0); } } catch (SQLException | IOException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } // Players --------------------------------------------------------------------------------------------------------- private MyPetPlayer resultSetToMyPetPlayer(ResultSet resultSet) { try { if (resultSet.next()) { MyPetPlayerImpl petPlayer; UUID internalUUID = UUID.fromString(resultSet.getString("internal_uuid")); String playerName = resultSet.getString("name"); UUID mojangUUID = resultSet.getString("mojang_uuid") != null ? UUID.fromString(resultSet.getString("mojang_uuid")) : null; if (mojangUUID != null) { petPlayer = new MyPetPlayerImpl(internalUUID, mojangUUID); petPlayer.setLastKnownName(playerName); } else if (playerName != null) { petPlayer = new MyPetPlayerImpl(internalUUID, playerName); } else { MyPetApi.getLogger().warning("Player with no UUID or name found!"); return null; } petPlayer.setAutoRespawnEnabled(resultSet.getBoolean("auto_respawn")); petPlayer.setAutoRespawnMin(resultSet.getInt("auto_respawn_min")); petPlayer.setCaptureHelperActive(resultSet.getBoolean("capture_mode")); petPlayer.setHealthBarActive(resultSet.getBoolean("health_bar")); petPlayer.setPetLivingSoundVolume(resultSet.getFloat("pet_idle_volume")); petPlayer.setExtendedInfo(TagStream.readTag(resultSet.getBytes("extended_info"), true)); JSONParser parser = new JSONParser(); try { JSONObject jsonObject = (JSONObject) parser.parse(resultSet.getString("multi_world")); for (Object o : jsonObject.keySet()) { String petUUID = jsonObject.get(o.toString()).toString(); petPlayer.setMyPetForWorldGroup(o.toString(), UUID.fromString(petUUID)); } } catch (ParseException e) { e.printStackTrace(); } return petPlayer; } } catch (SQLException | IOException e) { e.printStackTrace(); } return null; } @Override public List<MyPetPlayer> getAllMyPetPlayers() { try { Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT * FROM players;"); List<MyPetPlayer> players = new ArrayList<>(); MyPetPlayer player; while (true) { player = resultSetToMyPetPlayer(resultSet); if (player == null) { break; } players.add(player); } return players; } catch (SQLException e) { e.printStackTrace(); } return new ArrayList<>(); } @Override public void isMyPetPlayer(final Player player, final RepositoryCallback<Boolean> callback) { if (callback != null) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT COUNT(internal_uuid) FROM players WHERE mojang_uuid=? OR name=?;"); statement.setString(1, player.getUniqueId().toString()); statement.setString(2, player.getName()); ResultSet resultSet = statement.executeQuery(); resultSet.next(); //MyPetLogger.write("IS player: " + (resultSet.getInt(1) > 0)); callback.runTask(MyPetApi.getPlugin(), resultSet.getInt(1) > 0); } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } } public void getMyPetPlayer(final UUID uuid, final RepositoryCallback<MyPetPlayer> callback) { if (callback != null) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT * FROM players WHERE internal_uuid=?;"); statement.setString(1, uuid.toString()); ResultSet resultSet = statement.executeQuery(); MyPetPlayer player = resultSetToMyPetPlayer(resultSet); if (player != null) { //MyPetLogger.write("LOAD player: " + player); callback.runTask(MyPetApi.getPlugin(), player); } } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } } @Override public void getMyPetPlayer(final Player player, final RepositoryCallback<MyPetPlayer> callback) { if (callback != null) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("SELECT * FROM players WHERE mojang_uuid=? OR name=?;"); statement.setString(1, player.getUniqueId().toString()); statement.setString(2, player.getName()); ResultSet resultSet = statement.executeQuery(); MyPetPlayer player = resultSetToMyPetPlayer(resultSet); if (player != null) { //MyPetLogger.write("LOAD player: " + player); callback.runTask(MyPetApi.getPlugin(), player); } } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } } @Override public void updateMyPetPlayer(final MyPetPlayer player, final RepositoryCallback<Boolean> callback) { new BukkitRunnable() { @Override public void run() { boolean result = updatePlayer(player); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), result); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } @SuppressWarnings("unchecked") public boolean updatePlayer(final MyPetPlayer player) { try { PreparedStatement statement = connection.prepareStatement( "UPDATE players SET " + "mojang_uuid=?, " + "name=?, " + "auto_respawn=?, " + "auto_respawn_min=?, " + "capture_mode=?, " + "health_bar=?, " + "pet_idle_volume=?, " + "resource_pack=?, " + "extended_info=?, " + "multi_world=? " + "WHERE internal_uuid=?;"); statement.setString(1, player.getMojangUUID() != null ? player.getMojangUUID().toString() : null); statement.setString(2, player.getName()); statement.setBoolean(3, player.hasAutoRespawnEnabled()); statement.setInt(4, player.getAutoRespawnMin()); statement.setBoolean(5, player.isCaptureHelperActive()); statement.setBoolean(6, player.isHealthBarActive()); statement.setFloat(7, player.getPetLivingSoundVolume()); statement.setBoolean(8, false); statement.setBytes(9, TagStream.writeTag(player.getExtendedInfo(), true)); JSONObject multiWorldObject = new JSONObject(); for (String worldGroupName : player.getMyPetsForWorldGroups().keySet()) { multiWorldObject.put(worldGroupName, player.getMyPetsForWorldGroups().get(worldGroupName).toString()); } statement.setString(10, multiWorldObject.toJSONString()); statement.setString(11, player.getInternalUUID().toString()); int result = statement.executeUpdate(); //MyPetLogger.write("UPDATE player: " + result); return result > 0; } catch (SQLException | IOException e) { e.printStackTrace(); } return false; } @Override public void addMyPetPlayer(final MyPetPlayer player, final RepositoryCallback<Boolean> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement( "INSERT INTO players (" + "internal_uuid, " + "mojang_uuid, " + "name, " + "auto_respawn, " + "auto_respawn_min, " + "capture_mode, " + "health_bar, " + "pet_idle_volume, " + "resource_pack, " + "extended_info, " + "multi_world) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); statement.setString(1, player.getInternalUUID().toString()); statement.setString(2, player.getMojangUUID() != null ? player.getMojangUUID().toString() : null); statement.setString(3, player.getName()); statement.setBoolean(4, player.hasAutoRespawnEnabled()); statement.setInt(5, player.getAutoRespawnMin()); statement.setBoolean(6, player.isCaptureHelperActive()); statement.setBoolean(7, player.isHealthBarActive()); statement.setFloat(8, player.getPetLivingSoundVolume()); statement.setBoolean(9, false); try { statement.setBytes(10, TagStream.writeTag(player.getExtendedInfo(), true)); } catch (IOException e) { e.printStackTrace(); } JSONObject multiWorldObject = new JSONObject(); for (String worldGroupName : player.getMyPetsForWorldGroups().keySet()) { multiWorldObject.put(worldGroupName, player.getMyPetsForWorldGroups().get(worldGroupName).toString()); } statement.setString(11, multiWorldObject.toJSONString()); boolean result = statement.executeUpdate() > 0; //MyPetLogger.write("INSERT player: " + result); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), result); } } catch (SQLException e) { e.printStackTrace(); } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } @SuppressWarnings("unchecked") public boolean addMyPetPlayers(List<MyPetPlayer> players) { try { PreparedStatement statement = connection.prepareStatement( "INSERT INTO players (" + "internal_uuid, " + "mojang_uuid, " + "name, " + "auto_respawn, " + "auto_respawn_min, " + "capture_mode, " + "health_bar, " + "pet_idle_volume, " + "resource_pack, " + "extended_info, " + "multi_world) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); int i = 0; HashSet<String> playerNames = new HashSet<>(); for (MyPetPlayer player : players) { String playerName = player.getName(); if (playerNames.contains(playerName)) { MyPetApi.getLogger().info("Found duplicate Player: " + player.toString()); continue; } playerNames.add(playerName); statement.setString(1, player.getInternalUUID().toString()); statement.setString(2, player.getMojangUUID() != null ? player.getMojangUUID().toString() : null); statement.setString(3, playerName); statement.setBoolean(4, player.hasAutoRespawnEnabled()); statement.setInt(5, player.getAutoRespawnMin()); statement.setBoolean(6, player.isCaptureHelperActive()); statement.setBoolean(7, player.isHealthBarActive()); statement.setFloat(8, player.getPetLivingSoundVolume()); statement.setBoolean(9, false); statement.setBytes(10, TagStream.writeTag(player.getExtendedInfo(), true)); JSONObject multiWorldObject = new JSONObject(); for (String worldGroupName : player.getMyPetsForWorldGroups().keySet()) { multiWorldObject.put(worldGroupName, player.getMyPetsForWorldGroups().get(worldGroupName).toString()); } statement.setString(11, multiWorldObject.toJSONString()); statement.addBatch(); if (++i % 500 == 0 && i != players.size()) { statement.executeBatch(); } } statement.executeBatch(); return true; } catch (SQLException | IOException e) { e.printStackTrace(); } return false; } @Override public void removeMyPetPlayer(final MyPetPlayer player, final RepositoryCallback<Boolean> callback) { new BukkitRunnable() { @Override public void run() { try { PreparedStatement statement = connection.prepareStatement("DELETE FROM players WHERE internal_uuid=?;"); statement.setString(1, player.getInternalUUID().toString()); int result = statement.executeUpdate(); //MyPetLogger.write("DELETE player: " + result); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), result > 0); } } catch (SQLException e) { e.printStackTrace(); if (callback != null) { callback.runTask(MyPetApi.getPlugin(), false); } } } }.runTaskAsynchronously(MyPetApi.getPlugin()); } }