diff --git a/pom.xml b/pom.xml index 7e1be5a..13e6590 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 net.tylermurphy KenshinsHideAndSeek - 1.5.0 + 1.5.1 Hide and Seek Plugin UTF-8 diff --git a/src/main/java/net/tylermurphy/hideAndSeek/Main.java b/src/main/java/net/tylermurphy/hideAndSeek/Main.java index 1248551..69619f1 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/Main.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/Main.java @@ -62,7 +62,6 @@ public class Main extends JavaPlugin implements Listener { public Main() { super(); onConstructed(); - board = new Board(); database = new Database(); } @@ -70,7 +69,6 @@ public class Main extends JavaPlugin implements Listener { protected Main(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) { super(loader, description, dataFolder, file); onConstructed(); - board = new Board(); database = new Database(); } @@ -89,7 +87,6 @@ public class Main extends JavaPlugin implements Listener { Config.loadConfig(); Localization.loadLocalization(); Items.loadItems(); - } public void onEnable() { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/About.java b/src/main/java/net/tylermurphy/hideAndSeek/command/About.java index bda6016..e36ee84 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/About.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/About.java @@ -26,7 +26,7 @@ public class About implements ICommand { public void execute(Player sender, String[] args) { sender.sendMessage( - String.format("%s%sHide and Seek %s(%s1.5.0%s)\n", ChatColor.AQUA, ChatColor.BOLD, ChatColor.GRAY,ChatColor.WHITE,ChatColor.GRAY) + + String.format("%s%sHide and Seek %s(%s1.5.1%s)\n", ChatColor.AQUA, ChatColor.BOLD, ChatColor.GRAY,ChatColor.WHITE,ChatColor.GRAY) + String.format("%sAuthor: %s[KenshinEto]\n", ChatColor.GRAY, ChatColor.WHITE) + String.format("%sHelp Command: %s/hs %shelp", ChatColor.GRAY, ChatColor.AQUA, ChatColor.WHITE) ); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java index 4aeac68..123432d 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java @@ -89,7 +89,8 @@ public class Config { lobbyItemStartAdmin, leaveOnEnd, mapSaveEnabled, - allowNaturalCauses; + allowNaturalCauses, + saveInventory; public static int minPlayers, @@ -267,6 +268,7 @@ public class Config { leaveOnEnd = config.getBoolean("leaveOnEnd"); placeholderError = config.getString("placeholder.incorrect"); placeholderNoData = config.getString("placeholder.noData"); + saveInventory = config.getBoolean("saveInventory"); try { countdownDisplay = CountdownDisplay.valueOf(config.getString("hideCountdownDisplay")); } catch (IllegalArgumentException e) { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java b/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java index 0489b5d..8afc4ba 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java @@ -39,6 +39,7 @@ public class Database { private final GameDataTable playerInfo; private final NameDataTable nameInfo; + private final InventoryTable inventoryInfo; private final DatabaseConnection connection; public Database(){ @@ -53,6 +54,8 @@ public class Database { nameInfo = new NameDataTable(this); + inventoryInfo = new InventoryTable(this); + LegacyTable legacyTable = new LegacyTable(this); if(legacyTable.exists()){ if(legacyTable.copyData()){ @@ -69,6 +72,8 @@ public class Database { public NameDataTable getNameData() { return nameInfo; } + public InventoryTable getInventoryData() { return inventoryInfo; } + protected Connection connect() { Connection conn = null; try { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java b/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java index ce392a9..929356e 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java @@ -23,6 +23,7 @@ import net.tylermurphy.hideAndSeek.Main; import net.tylermurphy.hideAndSeek.database.util.PlayerInfo; import net.tylermurphy.hideAndSeek.game.Board; import net.tylermurphy.hideAndSeek.game.util.WinType; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.sql.*; @@ -91,7 +92,7 @@ public class GameDataTable { } @Nullable - public PlayerInfo getInfoRanking(String order, int place) { + public PlayerInfo getInfoRanking(@NotNull String order, int place) { String sql = "SELECT * FROM hs_data ORDER BY "+order+" DESC LIMIT 1 OFFSET ?;"; try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { statement.setInt(1, place-1); @@ -154,7 +155,7 @@ public class GameDataTable { } @Nullable - public Integer getRanking(String order, UUID uuid) { + public Integer getRanking(@NotNull String order, @NotNull UUID uuid) { String sql = "SELECT count(*) AS total FROM hs_data WHERE "+order+" >= (SELECT "+order+" FROM hs_data WHERE uuid = ?) AND "+order+" > 0;"; try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { statement.setBytes(1, database.encodeUUID(uuid)); @@ -170,7 +171,16 @@ public class GameDataTable { return null; } - public void addWins(Board board, List uuids, List winners, Map hider_kills, Map hider_deaths, Map seeker_kills, Map seeker_deaths, WinType type) { + public void addWins( + @NotNull Board board, + @NotNull List uuids, + @NotNull List winners, + @NotNull Map hider_kills, + @NotNull Map hider_deaths, + @NotNull Map seeker_kills, + @NotNull Map seeker_deaths, + @NotNull WinType type + ) { for(UUID uuid : uuids) { PlayerInfo info = getInfo(uuid); if(info == null){ @@ -190,7 +200,7 @@ public class GameDataTable { } } - protected boolean updateInfo(byte[] uuid, int hider_wins, int seeker_wins, int hider_games, int seeker_games, int hider_kills, int seeker_kills, int hider_deaths, int seeker_deaths){ + protected boolean updateInfo(@NotNull byte[] uuid, int hider_wins, int seeker_wins, int hider_games, int seeker_games, int hider_kills, int seeker_kills, int hider_deaths, int seeker_deaths){ boolean success; String sql = "INSERT OR REPLACE INTO hs_data (uuid, hider_wins, seeker_wins, hider_games, seeker_games, hider_kills, seeker_kills, hider_deaths, seeker_deaths) VALUES (?,?,?,?,?,?,?,?,?)"; try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { @@ -211,7 +221,7 @@ public class GameDataTable { e.printStackTrace(); success = false; } finally { - CACHE.remove(uuid); + CACHE.remove(database.decodeUUID(uuid)); } return success; } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/InventoryTable.java b/src/main/java/net/tylermurphy/hideAndSeek/database/InventoryTable.java new file mode 100644 index 0000000..814ea5e --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/InventoryTable.java @@ -0,0 +1,106 @@ +package net.tylermurphy.hideAndSeek.database; + +import net.tylermurphy.hideAndSeek.Main; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.io.BukkitObjectInputStream; +import org.bukkit.util.io.BukkitObjectOutputStream; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.sql.*; +import java.util.UUID; + +public class InventoryTable { + + private final Database database; + + protected InventoryTable(Database database) { + + String sql = "CREATE TABLE IF NOT EXISTS hs_inventory (\n" + + " uuid BINARY(16) NOT NULL,\n" + + " inventory TEXT NOT NULL,\n" + + " PRIMARY KEY (uuid)\n" + + ");"; + + try(Connection connection = database.connect(); Statement statement = connection.createStatement()) { + statement.executeUpdate(sql); + } catch (SQLException e) { + Main.getInstance().getLogger().severe("SQL Error: " + e.getMessage()); + e.printStackTrace(); + } + + this.database = database; + } + + @Nullable + public ItemStack[] getInventory(@NotNull UUID uuid) { + String sql = "SELECT * FROM hs_inventory WHERE uuid = ?;"; + try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setBytes(1, database.encodeUUID(uuid)); + ResultSet rs = statement.executeQuery(); + if (rs.next()) { + String data = rs.getString("inventory"); + if(data == null) return null; + return itemStackArrayFromBase64(data); + } + rs.close(); + } catch (SQLException e) { + Main.getInstance().getLogger().severe("SQL Error: " + e.getMessage()); + e.printStackTrace(); + } catch (IOException e) { + Main.getInstance().getLogger().severe("IO Error: " + e.getMessage()); + e.printStackTrace(); + } + return null; + } + + public boolean saveInventory(@NotNull UUID uuid, @NotNull ItemStack[] itemArray) { + String sql = "INSERT OR REPLACE INTO hs_inventory (uuid, inventory) VALUES (?,?)"; + String data = itemStackArrayToBase64(itemArray); + try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setBytes(1, database.encodeUUID(uuid)); + statement.setString(2, data); + statement.execute(); + statement.close(); + return true; + } catch (SQLException e) { + Main.getInstance().getLogger().severe("SQL Error: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + private String itemStackArrayToBase64(ItemStack[] itemArray) throws IllegalStateException { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + + dataOutput.writeObject(itemArray); + + dataOutput.close(); + + return Base64Coder.encodeLines(outputStream.toByteArray()); + } catch (Exception e) { + throw new IllegalStateException("Error whilst saving items, Please contact the developer", e); + } + } + + private ItemStack[] itemStackArrayFromBase64(String data) throws IOException { + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + + ItemStack[] itemArray = (ItemStack[]) dataInput.readObject(); + + dataInput.close(); + return itemArray; + } catch (ClassNotFoundException e) { + throw new IOException("Error whilst loading items, Please contact the developer", e); + } + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java b/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java index e5ac4bb..dd32507 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java @@ -22,6 +22,7 @@ package net.tylermurphy.hideAndSeek.database; import net.tylermurphy.hideAndSeek.Main; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.management.BufferPoolMXBean; @@ -51,7 +52,7 @@ public class NameDataTable { } @Nullable - public String getName(UUID uuid) { + public String getName(@NotNull UUID uuid) { String sql = "SELECT * FROM hs_names WHERE uuid = ?;"; try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { statement.setBytes(1, database.encodeUUID(uuid)); @@ -73,7 +74,7 @@ public class NameDataTable { } @Nullable - public UUID getUUID(String name) { + public UUID getUUID(@NotNull String name) { String sql = "SELECT * FROM hs_names WHERE name = ?;"; try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { statement.setString(1, name); @@ -94,7 +95,7 @@ public class NameDataTable { return null; } - public boolean update(UUID uuid, String name){ + public boolean update(@NotNull UUID uuid, @NotNull String name){ String sql = "INSERT OR REPLACE INTO hs_names (uuid, name) VALUES (?,?)"; try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { statement.setBytes(1, database.encodeUUID(uuid)); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java index 78c5e01..87fa4a2 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java @@ -33,6 +33,7 @@ import net.tylermurphy.hideAndSeek.world.WorldLoader; import org.bukkit.*; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.io.File; import java.util.*; @@ -169,6 +170,10 @@ public class Game { public void join(Player player) { if (status != Status.STARTING && status != Status.PLAYING) { + if(saveInventory) { + ItemStack[] data = player.getInventory().getContents(); + Main.getInstance().getDatabase().getInventoryData().saveInventory(player.getUniqueId(), data); + } PlayerLoader.joinPlayer(player); board.addHider(player); board.createLobbyBoard(player); @@ -185,6 +190,10 @@ public class Game { public void leave(Player player) { PlayerLoader.unloadPlayer(player); + if(saveInventory) { + ItemStack[] data = Main.getInstance().getDatabase().getInventoryData().getInventory(player.getUniqueId()); + player.getInventory().setContents(data); + } if (announceMessagesToNonPlayers) Bukkit.broadcastMessage(messagePrefix + message("GAME_LEAVE").addPlayer(player)); else broadcastMessage(messagePrefix + message("GAME_LEAVE").addPlayer(player)); if (board.isHider(player) && status != Status.ENDING && status != Status.STANDBY) { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java index af59c21..bd2a965 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java @@ -19,6 +19,7 @@ package net.tylermurphy.hideAndSeek.game; +import com.cryptomorin.xseries.XItemStack; import com.cryptomorin.xseries.messages.Titles; import net.md_5.bungee.api.ChatColor; import net.tylermurphy.hideAndSeek.Main; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java index 7ac4f85..5233d2e 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java @@ -2,6 +2,7 @@ package net.tylermurphy.hideAndSeek.game.listener; import net.tylermurphy.hideAndSeek.Main; import net.tylermurphy.hideAndSeek.configuration.Items; +import net.tylermurphy.hideAndSeek.game.PlayerLoader; import net.tylermurphy.hideAndSeek.game.util.Status; import org.bukkit.Bukkit; import org.bukkit.GameMode; @@ -59,16 +60,18 @@ public class JoinLeaveHandler implements Listener { } private void handleLeave(Player player) { + if(!Main.getInstance().getBoard().contains(player)) return; + PlayerLoader.unloadPlayer(player); Main.getInstance().getBoard().remove(player); + if(saveInventory) { + ItemStack[] data = Main.getInstance().getDatabase().getInventoryData().getInventory(player.getUniqueId()); + player.getInventory().setContents(data); + } if (Main.getInstance().getGame().getStatus() == Status.STANDBY) { Main.getInstance().getBoard().reloadLobbyBoards(); } else { Main.getInstance().getBoard().reloadGameBoards(); } - for(PotionEffect effect : player.getActivePotionEffects()) { - player.removePotionEffect(effect.getType()); - } - removeItems(player); } private void removeItems(Player player) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6153c46..d782edb 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -94,6 +94,12 @@ leaveServer: hub # default: true mapSaveEnabled: true +# By default, the plugin clears your inventory when joining the game. This is something it will always do. But you don't get what you used to have +# in your inventory back after you leave the game. You can allow the plugin to save a players inventory before joining the lobby, and give it back +# after leaving the game. +# default: false +saveInventory: false + # How you want to store game data. If you are running a single server, sqlite is fine, as no setup is necessary. # But if you want the data to go across multiple servers, you can switch it to mysql. # WARNING: Data is not saved across databases. You have to migrate the data yourself! diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c4224dc..8cd75ee 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: KenshinsHideAndSeek main: net.tylermurphy.hideAndSeek.Main -version: 1.5.0 +version: 1.5.1 author: KenshinEto load: STARTUP api-version: 1.13