diff --git a/pom.xml b/pom.xml index be2b865..f834f6d 100644 --- a/pom.xml +++ b/pom.xml @@ -60,13 +60,6 @@ - - - mysql - mysql-connector-java - 8.0.33 - - com.sk89q.worldedit @@ -100,6 +93,12 @@ 1.18.30 provided + + + org.yaml + snakeyaml + 2.0 + diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadChatController.java b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadChatController.java index a545a0f..d1320e1 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadChatController.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadChatController.java @@ -9,13 +9,13 @@ import java.util.List; -import static org.modularsoft.PlayerHeadHunt.HeadQuery.foundHeadsAlreadyCount; - public class HeadChatController { private final PlayerHeadHuntMain plugin; + private final HeadQuery headQuery; - public HeadChatController(PlayerHeadHuntMain plugin) { + public HeadChatController(PlayerHeadHuntMain plugin, HeadQuery headQuery) { this.plugin = plugin; + this.headQuery = headQuery; } public void headFoundResponse(Player player, boolean hasAlreadyBeenFound, int headCount, int x, int y, int z) { @@ -28,7 +28,8 @@ public void headFoundResponse(Player player, boolean hasAlreadyBeenFound, int he player.playSound(player.getLocation(), plugin.config().getHeadFoundSound(), 1, 1); } - int otherPlayerFoundHead = foundHeadsAlreadyCount(plugin, x, y, z) - 1; + // Get the number of other players who have found this head + int otherPlayerFoundHead = Math.max(0, headQuery.foundHeadsAlreadyCount(x, y, z) - 1); String otherPlayersHaveFoundSuffix; if (otherPlayerFoundHead == 0) { @@ -39,18 +40,18 @@ public void headFoundResponse(Player player, boolean hasAlreadyBeenFound, int he } } else if (otherPlayerFoundHead == 1) { otherPlayersHaveFoundSuffix = plugin.config().getLangHeadNotFirstFinderSingle() - .replace("%OTHERPLAYERSFOUNDHEAD%", "" + otherPlayerFoundHead); + .replace("%OTHERPLAYERSFOUNDHEAD%", String.valueOf(otherPlayerFoundHead)); } else { otherPlayersHaveFoundSuffix = plugin.config().getLangHeadNotFirstFinderMultiple() - .replace("%OTHERPLAYERSFOUNDHEAD%", "" + otherPlayerFoundHead); + .replace("%OTHERPLAYERSFOUNDHEAD%", String.valueOf(otherPlayerFoundHead)); } + // Replace placeholders in the message String message = baseMessage - .replace("%FOUNDHEADS%", "" + headCount) - .replace("%NUMBEROFHEADS%", "" + plugin.config().getTotalHeads()) + .replace("%FOUNDHEADS%", String.valueOf(headCount)) + .replace("%NUMBEROFHEADS%", String.valueOf(plugin.config().getTotalHeads())) .replace("%ALREADYFOUNDHEADS%", otherPlayersHaveFoundSuffix); - // Play sound for a Player Head that is found. player.sendMessage(message); } @@ -100,9 +101,9 @@ public void newPlayerJoinsTheHunt(Player player) { } public void playersOwnHeadCountResponse(Player player) { - // Players wants to see their own head count + // Use the instance of HeadQuery to call the method player.sendMessage(plugin.config().getLangHeadCount() - .replace("%FOUNDHEADS%", "" + HeadQuery.foundHeadsCount(plugin, player)) + .replace("%FOUNDHEADS%", "" + headQuery.foundHeadsCount(player)) .replace("%NUMBEROFHEADS%", "" + plugin.config().getTotalHeads())); } diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadQuery.java b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadQuery.java index af057aa..56b1c0f 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadQuery.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadQuery.java @@ -2,217 +2,177 @@ import lombok.Getter; import org.bukkit.entity.Player; +import org.modularsoft.PlayerHeadHunt.helpers.YamlFileManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class HeadQuery { + private final YamlFileManager yamlFileManager; + + public HeadQuery(YamlFileManager yamlFileManager) { + this.yamlFileManager = yamlFileManager; + } + public record HeadHunter(@Getter String name, @Getter int headsCollected) { } - /** - * @param plugin The PlayerHeadHunt main plugin - * @param player The player to check - * @return Returns the number of heads found by the player - */ - public static int foundHeadsCount(PlayerHeadHuntMain plugin, Player player) { - String playerUUID = "" + player.getUniqueId(); - - try { - // Check how many heads the player has collected. - PreparedStatement foundHeadsCount = plugin.getConnection().prepareStatement( - "SELECT headsCollected AS 'heads' FROM playerdata WHERE uuid=?"); - foundHeadsCount.setString(1, playerUUID); - ResultSet results = foundHeadsCount.executeQuery(); - - if (results.next()) return results.getInt("heads"); - } catch (SQLException e) { - e.printStackTrace(); - player.sendMessage(plugin.config().getLangDatabaseConnectionError()); + public int foundHeadsCount(Player player) { + String playerUUID = player.getUniqueId().toString(); + Map data = yamlFileManager.getData(); + Map playerData = (Map) data.get(playerUUID); + + if (playerData == null) { + return 0; // No data for the player, so no heads collected + } + + List> headsCollected = (List>) playerData.get("headsCollected"); + if (headsCollected == null) { + return 0; // No heads collected yet } - return 0; + + return headsCollected.size(); // Return the count of collected heads } - /** - * @param plugin The PlayerHeadHunt main plugin - * @param xCord The x int to check - * @param yCord The y int to check - * @param zCord The z int to check - * @return Returns the number of other players who have found this head already - */ - public static int foundHeadsAlreadyCount(PlayerHeadHuntMain plugin, int xCord, int yCord, int zCord) { - try { - // Check how many heads the player has collected. - PreparedStatement foundHeadsCount = plugin.getConnection().prepareStatement( - "SELECT COUNT(*) AS total_heads FROM heads WHERE headcordx=? AND headcordy=? AND headcordz=?;"); - foundHeadsCount.setInt(1, xCord); - foundHeadsCount.setInt(2, yCord); - foundHeadsCount.setInt(3, zCord); - ResultSet results = foundHeadsCount.executeQuery(); - - if (results.next()) return results.getInt("total_heads"); - } catch (SQLException e) { - e.printStackTrace(); + public int foundHeadsAlreadyCount(int xCord, int yCord, int zCord) { + Map data = yamlFileManager.getData(); + Object headsObject = data.get("heads"); + + // Ensure the "heads" object is a list + if (!(headsObject instanceof List)) { + return 0; // Return 0 if the data is not a list } - return 0; + + List heads = (List) headsObject; + + // Filter and count matching heads + return (int) heads.stream() + .filter(head -> head instanceof Map) + .map(head -> (Map) head) + .filter(head -> + head.get("x") instanceof Integer && head.get("y") instanceof Integer && head.get("z") instanceof Integer && + head.get("x").equals(xCord) && head.get("y").equals(yCord) && head.get("z").equals(zCord) + ) + .count(); } - /** - * Clears the number of heads found by the player to 0 - * @param plugin The PlayerHeadHunt main plugin - * @param player The player to reset - * @return Returns true if the clear was successful. - */ - public static boolean clearHeads(PlayerHeadHuntMain plugin, Player player) { - String playerUUID = "" + player.getUniqueId(); - - // - // Database Query - // Check how many heads the player has collected. - // - try { - PreparedStatement clearHeadsStatement = plugin.getConnection().prepareStatement( - "DELETE FROM heads WHERE playerid=(SELECT id FROM playerdata WHERE uuid=?)"); - clearHeadsStatement.setString(1, playerUUID); - clearHeadsStatement.executeUpdate(); - - PreparedStatement resetHeadCountStatement = plugin.getConnection().prepareStatement( - "UPDATE playerdata SET headsCollected = 0 WHERE uuid = ?"); - resetHeadCountStatement.setString(1, playerUUID); - resetHeadCountStatement.executeUpdate(); - return true; - } catch (SQLException e) { - e.printStackTrace(); - player.sendMessage(plugin.config().getLangDatabaseConnectionError()); + public boolean clearHeads(Player player) { + String playerUUID = player.getUniqueId().toString(); + Map data = yamlFileManager.getData(); + Map playerData = (Map) data.get(playerUUID); + + if (playerData == null) { + return false; // No data for the player } - return false; + // Clear the contents of the headsCollected list + List> headsCollected = (List>) playerData.get("headsCollected"); + if (headsCollected != null) { + headsCollected.clear(); + } + + // Reset the headsCollectedCount to 0 + playerData.put("headsCollectedCount", 0); + + yamlFileManager.save(); + return true; } - /** - * Checks if the player has found a head in the specified position before - * @param plugin The PlayerHeadHunt main plugin - * @param player The player who found the head - * @param x X position of the head - * @param y Y position of the head - * @param z Z position of the head - * @return True if the head has already been found - */ - public static boolean hasAlreadyCollectedHead(PlayerHeadHuntMain plugin, Player player, int x, int y, int z) { + public boolean hasAlreadyCollectedHead(Player player, int x, int y, int z) { String playerUUID = player.getUniqueId().toString(); + Map data = yamlFileManager.getData(); + Map playerData = (Map) data.get(playerUUID); - try { - // Check if the player has already found that Player Head before. - PreparedStatement hasAlreadyFoundHeadStatement = plugin.getConnection().prepareStatement( - "SELECT e.* FROM heads e JOIN playerdata p ON e.playerid = p.id WHERE p.uuid = ? AND headcordx=? AND headcordy=? AND headcordz=?"); - hasAlreadyFoundHeadStatement.setString(1, playerUUID); - hasAlreadyFoundHeadStatement.setString(2, "" + x); - hasAlreadyFoundHeadStatement.setString(3, "" + y); - hasAlreadyFoundHeadStatement.setString(4, "" + z); - ResultSet results = hasAlreadyFoundHeadStatement.executeQuery(); - - // Return's true if we already found the head. - return results.next(); - } catch (SQLException e) { - e.printStackTrace(); - player.sendMessage(plugin.config().getLangDatabaseConnectionError()); + if (playerData == null) { + return false; // Player has no data, so they haven't collected any heads } - return false; + + List> headsCollected = (List>) playerData.get("headsCollected"); + if (headsCollected == null) { + return false; // No heads collected yet + } + + // Check if the head coordinates already exist in the list + return headsCollected.stream().anyMatch(head -> + head.get("x") == x && head.get("y") == y && head.get("z") == z); } - /** - * Ties the location of the head (x, y, z) to the player so that we know in - * the future that this head has been found - * @param plugin The PlayerHeadHunt main plugin - * @param player The player who found the head - * @param x X position of the head - * @param y Y position of the head - * @param z Z position of the head - */ - public static void insertCollectedHead(PlayerHeadHuntMain plugin, Player player, int x, int y, int z) { + public void insertCollectedHead(Player player, int x, int y, int z) { String playerUUID = player.getUniqueId().toString(); + Map data = yamlFileManager.getData(); + Map playerData = (Map) data.get(playerUUID); + + if (playerData == null) { + playerData = new HashMap<>(); + playerData.put("headsCollected", new ArrayList>()); + playerData.put("headsCollectedCount", 0); + data.put(playerUUID, playerData); + } - try { - // Insert Player Head - PreparedStatement insertCollectedHeadStatement = plugin.getConnection().prepareStatement( - "INSERT INTO heads (playerid, headcordx, headcordy, headcordz) " + - "VALUES ((SELECT id FROM playerdata WHERE uuid=?), ?, ?, ?)"); - insertCollectedHeadStatement.setString(1, playerUUID); - insertCollectedHeadStatement.setString(2, String.valueOf(x)); - insertCollectedHeadStatement.setString(3, String.valueOf(y)); - insertCollectedHeadStatement.setString(4, String.valueOf(z)); - insertCollectedHeadStatement.executeUpdate(); - - PreparedStatement updatePlayersHeadsCollectedStatement = plugin.getConnection().prepareStatement( - "UPDATE playerdata SET headsCollected = headsCollected + 1 WHERE uuid = ?"); - updatePlayersHeadsCollectedStatement.setString(1, "" + player.getUniqueId()); - updatePlayersHeadsCollectedStatement.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - player.sendMessage(plugin.config().getLangDatabaseConnectionError()); + List> headsCollected = (List>) playerData.get("headsCollected"); + if (headsCollected == null) { + headsCollected = new ArrayList<>(); + playerData.put("headsCollected", headsCollected); } + + // Add the new head coordinates to the list + Map newHead = new HashMap<>(); + newHead.put("x", x); + newHead.put("y", y); + newHead.put("z", z); + headsCollected.add(newHead); + + // Increment the count of collected heads + int currentCount = (int) playerData.getOrDefault("headsCollectedCount", 0); + playerData.put("headsCollectedCount", currentCount + 1); + + yamlFileManager.save(); } - /** - * @param plugin The PlayerHeadHunt main plugin - * @param player The player who joined - * @return Returns true if the player specified was indeed a new player. - */ - public static boolean addNewHunter(PlayerHeadHuntMain plugin, Player player) { + public boolean addNewHunter(Player player) { String playerUUID = player.getUniqueId().toString(); String username = player.getName(); + Map data = yamlFileManager.getData(); - try { - // Check if a player has been added into the database already. - PreparedStatement findstatement = plugin.getConnection().prepareStatement( - "SELECT * FROM playerdata WHERE uuid=?"); - findstatement.setString(1, playerUUID); - ResultSet results = findstatement.executeQuery(); - - // The player already exists - if (results.next()) - return false; - - PreparedStatement insertstatement = plugin.getConnection().prepareStatement( - "INSERT INTO playerdata (uuid, username) VALUES (?, ?)"); - insertstatement.setString(1, playerUUID); - insertstatement.setString(2, username); - insertstatement.executeUpdate(); - return true; - } catch (SQLException e) { - e.printStackTrace(); - player.sendMessage(plugin.config().getLangDatabaseConnectionError()); + if (data.containsKey(playerUUID)) { + return false; } - return false; + + // Use a mutable map to store player data + Map newPlayerData = new HashMap<>(); + newPlayerData.put("username", username); + newPlayerData.put("headsCollected", new ArrayList>()); // Initialize an empty list for collected heads + newPlayerData.put("headsCollectedCount", 0); // Optional: Track the count separately for efficiency + data.put(playerUUID, newPlayerData); + + yamlFileManager.save(); + return true; } - /** - * @param plugin The PlayerHeadHunt main plugin - * @param player The player who issued the command - * @return Returns a list of the Best Hunters. idx 0 is the best player and so on... - */ - public static List getBestHunters(PlayerHeadHuntMain plugin, Player player, int topHunters) { + public List getBestHunters(int topHunters) { + Map data = yamlFileManager.getData(); List bestHunters = new ArrayList<>(); - try { - // Check if a player has been added into the database already. - PreparedStatement getHeadHuntersStatement = plugin.getConnection().prepareStatement( - "SELECT username, headsCollected, id FROM playerdata ORDER BY headsCollected DESC LIMIT ?"); - getHeadHuntersStatement.setInt(1, topHunters); - ResultSet results = getHeadHuntersStatement.executeQuery(); - - // The player already exists - while (results.next()) { - String name = results.getString("username"); - int headsCollected = results.getInt("headsCollected"); - bestHunters.add(new HeadHunter(name, headsCollected)); + data.forEach((key, value) -> { + if (value instanceof Map) { + Map playerData = (Map) value; + + String username = (String) playerData.get("username"); + Object headsCollectedObj = playerData.get("headsCollected"); + + // Validate that headsCollected is a list + if (username != null && headsCollectedObj instanceof List) { + int headsCollectedCount = ((List) headsCollectedObj).size(); + bestHunters.add(new HeadHunter(username, headsCollectedCount)); + } } - } catch (SQLException e) { - e.printStackTrace(); - player.sendMessage(plugin.config().getLangDatabaseConnectionError()); - } - return bestHunters; + }); + + // Sort hunters by the number of heads collected in descending order + bestHunters.sort((a, b) -> Integer.compare(b.headsCollected(), a.headsCollected())); + + // Return the top hunters + return bestHunters.subList(0, Math.min(topHunters, bestHunters.size())); } -} +} \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadScoreboardController.java b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadScoreboardController.java index 9b6e3fa..9ba3d2f 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadScoreboardController.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadScoreboardController.java @@ -33,4 +33,11 @@ public void reloadScoreboard(Player player, int headsFound) { player.setScoreboard(board); } + + public void updateLeaderboard(int totalHeads) { + for (Player player : Bukkit.getOnlinePlayers()) { + int headsFound = plugin.getHeadQuery().foundHeadsCount(player); // Get the player's collected heads + reloadScoreboard(player, headsFound); // Reload the scoreboard with the updated total + } + } } diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadWorldController.java b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadWorldController.java index ac130bd..11f1a1c 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/HeadWorldController.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/HeadWorldController.java @@ -21,28 +21,22 @@ import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import org.modularsoft.PlayerHeadHunt.helpers.YamlFileManager; -import java.util.Objects; -import java.util.Random; -import java.util.UUID; +import java.io.File; +import java.util.*; -/** - * This class controls any functionality that requires access to the world. - */ public class HeadWorldController { private final PlayerHeadHuntMain plugin; + private final YamlFileManager yamlFileManager; + private final HeadQuery headQuery; - public HeadWorldController(PlayerHeadHuntMain plugin) { + public HeadWorldController(PlayerHeadHuntMain plugin, HeadQuery headQuery) { this.plugin = plugin; + this.yamlFileManager = new YamlFileManager(new File(plugin.getDataFolder(), "player-data.yml")); + this.headQuery = headQuery; } - /** - * Using the lower region and upper region areas in the config file, count the - * number of heads in the region (technically it counts the number of player heads) - * and update the "totalHeads" field in the config to reflect the answer. - * - * Note: Heads that have disappeared temporarily will not show up in this count. - */ public void countHeadsInRegion() { String headBlock = plugin.config().getHeadBlock().toLowerCase(); BlockVector3 upperRegion = plugin.config().getUpperRegion(); @@ -53,21 +47,49 @@ public void countHeadsInRegion() { Mask mask = new BlockTypeMask(world, BlockTypes.get(headBlock)); try (EditSession editSession = WorldEdit.getInstance().newEditSession(world)) { - int countedblocks = editSession.countBlocks(selection, mask); - plugin.getServer().getConsoleSender().sendMessage("There are " + countedblocks + " total heads in the region"); + int countedBlocks = editSession.countBlocks(selection, mask); + plugin.getServer().getConsoleSender().sendMessage("There are " + countedBlocks + " total heads in the region"); - // Put total amount into config file. - plugin.config().setTotalHeads(countedblocks); + // Update the HEAD.HEADTOTAL in the plugin config + plugin.config().setTotalHeads(countedBlocks); plugin.config().save(); } } public void playerCollectedHead(Player player, Block block, int x, int y, int z) { - HeadQuery.insertCollectedHead(plugin, player, x, y, z); + String playerUUID = player.getUniqueId().toString(); + Map data = yamlFileManager.getData(); + Map playerData = (Map) data.get(playerUUID); + + if (playerData == null) { + playerData = new HashMap<>(); + playerData.put("headsCollected", new ArrayList>()); + data.put(playerUUID, playerData); + } + + List> collectedHeads = (List>) playerData.get("headsCollected"); + if (collectedHeads == null) { + collectedHeads = new ArrayList<>(); + playerData.put("headsCollected", collectedHeads); + } + + boolean alreadyCollected = collectedHeads.stream().anyMatch(head -> + head.get("x") == x && head.get("y") == y && head.get("z") == z); + + if (alreadyCollected) { + player.sendMessage(plugin.config().getLangHeadAlreadyFound()); + return; + } + + collectedHeads.add(Map.of("x", x, "y", y, "z", z)); + yamlFileManager.save(); + + // Increment the player's head count + plugin.getHeadQuery().insertCollectedHead(player, x, y, z); + Material blockType = block.getType(); BlockData blockData = block.getBlockData(); - // Break and set the block to be replaced later int headRespawnTimer = plugin.config().getHeadRespawnTimer(); breakBlock(x, y, z); @@ -77,7 +99,6 @@ public void run() { replaceHeadBlock(blockType, blockData, x, y, z); } }.runTaskLater(plugin, headRespawnTimer); - } private void breakBlock(int x, int y, int z) { @@ -105,4 +126,46 @@ private String getRandomHead() { int skins = plugin.config().getHeadSkins().size(); return plugin.config().getHeadSkins().get(random.nextInt(0, skins)); } -} + + public Location findNearestUnclaimedHead(Player player) { + Location playerLocation = player.getLocation(); + Map data = yamlFileManager.getData(); + Object headsObject = data.get("heads"); + + if (!(headsObject instanceof List heads)) { + plugin.getServer().getConsoleSender().sendMessage("§cNo heads data found in the YAML file."); + return null; // No heads available + } + + Location nearestHead = null; + double nearestDistance = Double.MAX_VALUE; + + for (Object headObj : heads) { + if (headObj instanceof Map head) { + int x = (int) head.get("x"); + int y = (int) head.get("y"); + int z = (int) head.get("z"); + + if (!headQuery.hasAlreadyCollectedHead(player, x, y, z)) { + Location headLocation = new Location(player.getWorld(), x, y, z); + double distance = playerLocation.distance(headLocation); + + plugin.getServer().getConsoleSender().sendMessage("§aFound unclaimed head at: " + x + ", " + y + ", " + z + " (Distance: " + distance + ")"); + + if (distance < nearestDistance) { + nearestDistance = distance; + nearestHead = headLocation; + } + } else { + plugin.getServer().getConsoleSender().sendMessage("§eHead at " + x + ", " + y + ", " + z + " already collected by the player."); + } + } + } + + if (nearestHead == null) { + plugin.getServer().getConsoleSender().sendMessage("§cNo unclaimed heads found for the player."); + } + + return nearestHead; + } +} \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/PlayerHeadHuntMain.java b/src/main/java/org/modularsoft/PlayerHeadHunt/PlayerHeadHuntMain.java index b95faf7..f8e9afd 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/PlayerHeadHuntMain.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/PlayerHeadHuntMain.java @@ -1,61 +1,60 @@ package org.modularsoft.PlayerHeadHunt; -import org.modularsoft.PlayerHeadHunt.commands.clearheads; -import org.modularsoft.PlayerHeadHunt.commands.heads; -import org.modularsoft.PlayerHeadHunt.commands.countheads; -import org.modularsoft.PlayerHeadHunt.commands.leaderboard; +import lombok.Getter; +import org.modularsoft.PlayerHeadHunt.commands.*; import org.modularsoft.PlayerHeadHunt.events.HeadFindEvent; import org.modularsoft.PlayerHeadHunt.events.HeadHatOnHead; import org.modularsoft.PlayerHeadHunt.events.HeadHunterOnJoin; -import com.mysql.cj.jdbc.MysqlDataSource; import org.bukkit.ChatColor; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import org.modularsoft.PlayerHeadHunt.helpers.YamlFileManager; -import java.sql.Connection; -import java.sql.SQLException; +import java.io.File; import java.util.Objects; public class PlayerHeadHuntMain extends JavaPlugin { private PluginConfig config; - private Connection connection; private ConsoleCommandSender console; + private HeadWorldController headWorldController; public PluginConfig config() { return config; } + @Getter + private HeadQuery headQuery; + @Override public void onEnable() { // Generate configuration file - // plugin.saveDefaultConfig(); + saveDefaultConfig(); config = new PluginConfig(this); console = getServer().getConsoleSender(); - HeadChatController headChatController = new HeadChatController(this); - HeadWorldController headWorldController = new HeadWorldController(this); + YamlFileManager yamlFileManager = new YamlFileManager(new File(getDataFolder(), "player-data.yml")); + headQuery = new HeadQuery(yamlFileManager); + + HeadChatController headChatController = new HeadChatController(this, headQuery); + HeadWorldController headWorldController = new HeadWorldController(this, headQuery); HeadHatController headHatController = new HeadHatController(this); HeadScoreboardController headScoreboardController = new HeadScoreboardController(this); - // Connect to the database - establishConnection(); - // Do an initial calculation of the number of heads. This can be // manually recalculated with the relevant command. headWorldController.countHeadsInRegion(); // Plugin Event Register PluginManager pluginmanager = getServer().getPluginManager(); - pluginmanager.registerEvents(new HeadFindEvent(this, headWorldController, headChatController, headHatController, headScoreboardController), this); - pluginmanager.registerEvents(new HeadHunterOnJoin(this, headChatController, headScoreboardController), this); + pluginmanager.registerEvents(new HeadFindEvent(this, headWorldController, headChatController, headHatController, headScoreboardController, headQuery), this); + pluginmanager.registerEvents(new HeadHunterOnJoin(this, headChatController, headScoreboardController, headQuery, headWorldController), this); pluginmanager.registerEvents(new HeadHatOnHead(), this); // Command Registry Objects.requireNonNull(getCommand("heads")).setExecutor(new heads(this, headChatController)); - Objects.requireNonNull(getCommand("clearheads")).setExecutor(new clearheads(this, headChatController, headHatController, headScoreboardController)); - Objects.requireNonNull(getCommand("countheads")).setExecutor(new countheads(this, headWorldController, headScoreboardController)); - Objects.requireNonNull(getCommand("leaderboard")).setExecutor(new leaderboard(this, headChatController)); + Objects.requireNonNull(getCommand("leaderboard")).setExecutor(new leaderboard(this, headChatController, headQuery)); // Register leaderboard command + Objects.requireNonNull(getCommand("debugheadhunt")).setExecutor(new debugheadhunt(this, headChatController, headHatController, headScoreboardController, headWorldController, headQuery)); // Plugin Load Message console.sendMessage(ChatColor.GREEN + getDescription().getName() + " is now enabled."); @@ -69,33 +68,4 @@ public void onDisable() { // Plugin Shutdown Message console.sendMessage(ChatColor.RED + getDescription().getName() + " is now disabled."); } - - public void establishConnection() { - try { - Class.forName("com.mysql.jdbc.Driver"); - MysqlDataSource dataSource = new MysqlDataSource(); - dataSource.setServerName(config.getDatabaseHost()); - dataSource.setPort(config.getDatabasePort()); - dataSource.setDatabaseName(config.getDatabaseName()); - dataSource.setUser(config.getDatabaseUsername()); - dataSource.setPassword(config.getDatabasePassword()); - connection = dataSource.getConnection(); - } catch (SQLException | ClassNotFoundException e) { - getLogger().info(config.getLangDatabaseConnectionError()); - e.printStackTrace(); - } - } - - public Connection getConnection() { - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { - getLogger().info(config.getLangDatabaseConnectionError()); - e.printStackTrace(); - } - } - establishConnection(); - return connection; - } } diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/PluginConfig.java b/src/main/java/org/modularsoft/PlayerHeadHunt/PluginConfig.java index c9d3816..2ed8059 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/PluginConfig.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/PluginConfig.java @@ -14,12 +14,6 @@ public class PluginConfig { private final PlayerHeadHuntMain plugin; private final FileConfiguration config; - @Getter private final String databaseHost; - @Getter private final int databasePort; - @Getter private final String databaseName; - @Getter private final String databaseUsername; - @Getter private final String databasePassword; - @Getter private final boolean milestoneHatFeatureEnabled; @Getter private final boolean milestoneMessageFeatureEnabled; @@ -61,12 +55,6 @@ public PluginConfig(PlayerHeadHuntMain plugin) { this.plugin = plugin; this.config = plugin.getConfig(); - databaseHost = config.getString("DATABASE.HOST"); - databasePort = config.getInt("DATABASE.PORT"); - databaseName = config.getString("DATABASE.DATABASE"); - databaseUsername = config.getString("DATABASE.USERNAME"); - databasePassword = config.getString("DATABASE.PASSWORD"); - milestoneHatFeatureEnabled = config.getBoolean("FEATURE.MILESTONEHAT"); milestoneMessageFeatureEnabled = config.getBoolean("FEATURE.MILESTONEMESSAGE"); diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/commands/clearheads.java b/src/main/java/org/modularsoft/PlayerHeadHunt/commands/clearheads.java deleted file mode 100644 index 1770cbf..0000000 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/commands/clearheads.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.modularsoft.PlayerHeadHunt.commands; - -import org.modularsoft.PlayerHeadHunt.*; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public class clearheads implements CommandExecutor { - private final PlayerHeadHuntMain plugin; - private final HeadChatController headChatController; - private final HeadHatController headHatController; - private final HeadScoreboardController scoreboardController; - - public clearheads(PlayerHeadHuntMain plugin, HeadChatController headChatController, - HeadHatController headHatController, HeadScoreboardController scoreboardController) { - this.plugin = plugin; - this.headChatController = headChatController; - this.headHatController = headHatController; - this.scoreboardController = scoreboardController; - } - - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (!(sender instanceof Player player)) { - sender.sendMessage(plugin.config().getLangNotAPlayer()); - return true; - } - - if (!sender.hasPermission("playerheadhunt.clearhead") || !sender.isOp()) { - sender.sendMessage(plugin.config().getLangInsufficientPermissions()); - return true; - } - - if (!HeadQuery.clearHeads(plugin, player)) - return true; - - headChatController.playerClearedTheirHeadsResponse(player); - headHatController.clearHelmet(player); - scoreboardController.reloadScoreboard(player, HeadQuery.foundHeadsCount(plugin, player)); - return true; - } -} diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/commands/countheads.java b/src/main/java/org/modularsoft/PlayerHeadHunt/commands/countheads.java deleted file mode 100644 index 1bb92c9..0000000 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/commands/countheads.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.modularsoft.PlayerHeadHunt.commands; - -import org.modularsoft.PlayerHeadHunt.PlayerHeadHuntMain; -import org.modularsoft.PlayerHeadHunt.HeadWorldController; -import org.modularsoft.PlayerHeadHunt.HeadQuery; -import org.modularsoft.PlayerHeadHunt.HeadScoreboardController; -import com.sk89q.worldedit.math.BlockVector3; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public class countheads implements CommandExecutor { - private final PlayerHeadHuntMain plugin; - private final HeadWorldController headWorldController; - private final HeadScoreboardController headScoreboardController; - - public countheads(PlayerHeadHuntMain plugin, HeadWorldController headWorldController, HeadScoreboardController headScoreboardController) { - this.plugin = plugin; - this.headWorldController = headWorldController; - this.headScoreboardController = headScoreboardController; - } - - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage(plugin.config().getLangNotAPlayer()); - return true; - } - - if (!sender.hasPermission("playerheadhunt.clearhead") || !sender.isOp()) { - sender.sendMessage(plugin.config().getLangInsufficientPermissions()); - return true; - } - - headWorldController.countHeadsInRegion(); - BlockVector3 upper = plugin.config().getUpperRegion(); - BlockVector3 lower = plugin.config().getLowerRegion(); - sender.sendMessage("There are " + plugin.config().getTotalHeads() + - " total heads in " + lower + ", " + upper + "."); - - for (Player otherPlayer : plugin.getServer().getOnlinePlayers()) { - int headsFound = HeadQuery.foundHeadsCount(plugin, otherPlayer); - headScoreboardController.reloadScoreboard(otherPlayer, headsFound); - } - return true; - } -} diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/commands/debugheadhunt.java b/src/main/java/org/modularsoft/PlayerHeadHunt/commands/debugheadhunt.java new file mode 100644 index 0000000..c6e0714 --- /dev/null +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/commands/debugheadhunt.java @@ -0,0 +1,70 @@ +package org.modularsoft.PlayerHeadHunt.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.modularsoft.PlayerHeadHunt.*; + +public class debugheadhunt implements CommandExecutor { + private final PlayerHeadHuntMain plugin; + private final HeadChatController headChatController; + private final HeadHatController headHatController; + private final HeadScoreboardController scoreboardController; + private final HeadWorldController headWorldController; + private final HeadQuery headQuery; + + public debugheadhunt(PlayerHeadHuntMain plugin, + HeadChatController headChatController, + HeadHatController headHatController, + HeadScoreboardController scoreboardController, + HeadWorldController headWorldController, + HeadQuery headQuery) { + this.plugin = plugin; + this.headChatController = headChatController; + this.headHatController = headHatController; + this.scoreboardController = scoreboardController; + this.headWorldController = headWorldController; + this.headQuery = headQuery; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(plugin.config().getLangNotAPlayer()); + return true; + } + + if (!sender.hasPermission("playerheadhunt.debug") || !sender.isOp()) { + sender.sendMessage(plugin.config().getLangInsufficientPermissions()); + return true; + } + + if (args.length == 0) { + sender.sendMessage("Usage: /debugheadhunt "); + return true; + } + + switch (args[0].toLowerCase()) { + case "clearheads" -> { + if (!headQuery.clearHeads(player)) { + sender.sendMessage("No heads to clear."); + return true; + } + headChatController.playerClearedTheirHeadsResponse(player); + headHatController.clearHelmet(player); + scoreboardController.reloadScoreboard(player, headQuery.foundHeadsCount(player)); + sender.sendMessage("Heads cleared successfully."); + } + case "countheads" -> { + headWorldController.countHeadsInRegion(); + int totalHeads = plugin.config().getTotalHeads(); // Retrieve the updated total head count + scoreboardController.updateLeaderboard(totalHeads); // Update the leaderboard with the new total + sender.sendMessage("Heads counted and leaderboard updated successfully."); + } + default -> sender.sendMessage("Invalid subcommand. Use: clearheads or countheads."); + } + return true; + } +} \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/commands/leaderboard.java b/src/main/java/org/modularsoft/PlayerHeadHunt/commands/leaderboard.java index c8a582c..8b12021 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/commands/leaderboard.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/commands/leaderboard.java @@ -14,10 +14,12 @@ public class leaderboard implements CommandExecutor { private final PlayerHeadHuntMain plugin; private final HeadChatController headChatController; + private final HeadQuery headQuery; // Add HeadQuery instance - public leaderboard(PlayerHeadHuntMain plugin, HeadChatController headChatController) { + public leaderboard(PlayerHeadHuntMain plugin, HeadChatController headChatController, HeadQuery headQuery) { this.plugin = plugin; this.headChatController = headChatController; + this.headQuery = headQuery; // Initialize HeadQuery } @Override @@ -27,8 +29,9 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @N return true; } - List bestHunters = HeadQuery.getBestHunters(plugin, player, 5); + // Use the HeadQuery instance to call getBestHunters + List bestHunters = headQuery.getBestHunters(5); headChatController.showLeaderBoardResponse(player, bestHunters); return true; } -} +} \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadFindEvent.java b/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadFindEvent.java index 65e47fc..7b8a793 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadFindEvent.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadFindEvent.java @@ -1,14 +1,13 @@ package org.modularsoft.PlayerHeadHunt.events; +import org.bukkit.Material; import org.modularsoft.PlayerHeadHunt.*; import org.modularsoft.PlayerHeadHunt.helpers.HeadMileStone; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.EquipmentSlot; import java.util.Map; @@ -20,46 +19,51 @@ public class HeadFindEvent implements Listener { private final HeadScoreboardController headScoreboardController; private final Map milestones; + private final HeadQuery headQuery; + public HeadFindEvent(PlayerHeadHuntMain plugin, HeadWorldController headWorldController, HeadChatController headChatController, HeadHatController headHatController, - HeadScoreboardController headScoreboardController) { + HeadScoreboardController headScoreboardController, HeadQuery headQuery) { this.plugin = plugin; this.headWorldController = headWorldController; this.headChatController = headChatController; this.headHatController = headHatController; this.headScoreboardController = headScoreboardController; + this.headQuery = headQuery; this.milestones = plugin.config().getHeadMilestones(); } @EventHandler public void onHeadFind(PlayerInteractEvent event) { - if (!isFindHeadEvent(event)) + if (!isFindHeadEvent(event)) { return; + } event.setCancelled(true); Player player = event.getPlayer(); Block block = event.getClickedBlock(); - int x = block.getX(); // Can't be null. Would have been found by isFindHeadEvent + int x = block.getX(); int y = block.getY(); int z = block.getZ(); - if (HeadQuery.hasAlreadyCollectedHead(plugin, player, x, y, z)) { - headChatController.headFoundResponse(player, true, 0, x, y, z); - return; + + // Check if the head has already been collected + if (headQuery.hasAlreadyCollectedHead(player, x, y, z)) { + // Send the "head already found" message and stop further processing + headChatController.headFoundResponse(player, true, headQuery.foundHeadsCount(player), x, y, z); + return; // Ensure no further processing occurs } + // Process head collection headWorldController.playerCollectedHead(player, block, x, y, z); - int foundHeads = HeadQuery.foundHeadsCount(plugin, player); - headScoreboardController.reloadScoreboard(player, foundHeads); + // Retrieve the updated count of heads found + int foundHeads = headQuery.foundHeadsCount(player); - if (foundHeads == 1) { - headChatController.headMilestoneReachedEvent(player, false, foundHeads); - return; - } + // Update the scoreboard with the new count + headScoreboardController.reloadScoreboard(player, foundHeads); - // Trigger any milestones if they are relevant. We'll use the milestone text if it's available - // otherwise we'll draw the default text to the screen. + // Handle milestones or send a success message if (milestones.containsKey(foundHeads)) { milestones.get(foundHeads).trigger(headChatController, headHatController, player, event); } else { @@ -68,26 +72,23 @@ public void onHeadFind(PlayerInteractEvent event) { } private boolean isFindHeadEvent(PlayerInteractEvent event) { - if (event == null) - return false; - - Block block = event.getClickedBlock(); - if (block == null) + // Check if the event involves a block and if the block is a specific type (e.g., a head block) + if (event.getClickedBlock() == null) { return false; + } - EquipmentSlot equipSlot = event.getHand(); - if (equipSlot == null) - return false; + String headBlockConfig = plugin.getConfig().getString("HEAD.HEADBLOCK"); + if (headBlockConfig == null) { + return false; // Configuration is missing or invalid + } - // This stops the event from firing twice, since the event fires for each hand. - if (equipSlot.equals(EquipmentSlot.OFF_HAND) || - event.getAction().equals(Action.LEFT_CLICK_BLOCK) || - event.getAction().equals(Action.LEFT_CLICK_AIR) || - event.getAction().equals(Action.RIGHT_CLICK_AIR)) - return false; + Material headBlockMaterial; + try { + headBlockMaterial = Material.valueOf(headBlockConfig.toUpperCase()); + } catch (IllegalArgumentException e) { + return false; // Invalid material in the configuration + } - // Only continue if we clicked on a head - String blockType = "" + block.getType(); - return plugin.config().getHeadBlock().equals(blockType); + return event.getClickedBlock().getType() == headBlockMaterial; } } \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadHunterOnJoin.java b/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadHunterOnJoin.java index a534385..ae1f25e 100644 --- a/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadHunterOnJoin.java +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/events/HeadHunterOnJoin.java @@ -1,9 +1,6 @@ package org.modularsoft.PlayerHeadHunt.events; -import org.modularsoft.PlayerHeadHunt.PlayerHeadHuntMain; -import org.modularsoft.PlayerHeadHunt.HeadChatController; -import org.modularsoft.PlayerHeadHunt.HeadQuery; -import org.modularsoft.PlayerHeadHunt.HeadScoreboardController; +import org.modularsoft.PlayerHeadHunt.*; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -13,12 +10,19 @@ public class HeadHunterOnJoin implements Listener { private final PlayerHeadHuntMain plugin; private final HeadChatController headChatController; private final HeadScoreboardController headScoreboardController; + private final HeadQuery headQuery; + private final HeadWorldController headWorldController; // Add this field - public HeadHunterOnJoin(PlayerHeadHuntMain plugin, HeadChatController headChatController, - HeadScoreboardController headScoreboardController) { + public HeadHunterOnJoin(PlayerHeadHuntMain plugin, + HeadChatController headChatController, + HeadScoreboardController headScoreboardController, + HeadQuery headQuery, + HeadWorldController headWorldController) { this.plugin = plugin; this.headChatController = headChatController; this.headScoreboardController = headScoreboardController; + this.headQuery = headQuery; + this.headWorldController = headWorldController; // Initialize it here } @EventHandler @@ -26,14 +30,30 @@ public void onHeadHunterJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); String username = player.getName(); - // Give the new player a scoreboard - headScoreboardController.reloadScoreboard(player, HeadQuery.foundHeadsCount(plugin, player)); + // Use the instance of HeadQuery to call the method + headScoreboardController.reloadScoreboard(player, headQuery.foundHeadsCount(player)); - if (HeadQuery.addNewHunter(plugin, player)) { + if (headQuery.addNewHunter(player)) { // New player joined plugin.getServer().getConsoleSender().sendMessage(username + " is a new player, creating a player profile."); plugin.getServer().getConsoleSender().sendMessage("Added a new hunter, " + username + "."); headChatController.newPlayerJoinsTheHunt(player); } + + // Remove all existing Head Locator items from the player's inventory + player.getInventory().forEach(item -> { + if (item != null && + item.hasItemMeta() && + item.getItemMeta().hasDisplayName() && + item.getItemMeta().getDisplayName().equals("§6Head Locator")) { + player.getInventory().remove(item); + } + }); + + // Add a new Head Locator compass + player.getInventory().addItem(org.modularsoft.PlayerHeadHunt.items.HeadLocator.createHeadLocator()); + + // Start the HeadLocatorTask for the player + new org.modularsoft.PlayerHeadHunt.helpers.HeadLocatorTask(plugin, new org.modularsoft.PlayerHeadHunt.items.HeadLocator(), headWorldController).startTask(player); } -} +} \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/helpers/HeadLocatorTask.java b/src/main/java/org/modularsoft/PlayerHeadHunt/helpers/HeadLocatorTask.java new file mode 100644 index 0000000..975d9e7 --- /dev/null +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/helpers/HeadLocatorTask.java @@ -0,0 +1,54 @@ +package org.modularsoft.PlayerHeadHunt.helpers; + +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.modularsoft.PlayerHeadHunt.HeadWorldController; +import org.modularsoft.PlayerHeadHunt.items.HeadLocator; + +public class HeadLocatorTask { + private final JavaPlugin plugin; + private final HeadLocator headLocator; + private final HeadWorldController headWorldController; + + public HeadLocatorTask(JavaPlugin plugin, HeadLocator headLocator, HeadWorldController headWorldController) { + this.plugin = plugin; + this.headLocator = headLocator; + this.headWorldController = headWorldController; + } + + public void startTask(Player player) { + Bukkit.getScheduler().runTaskTimer(plugin, () -> { + // Check if the player is online + if (!player.isOnline()) { + return; // Stop if the player is offline + } + + // Check if the player is holding the Head Locator item + ItemStack itemInHand = player.getInventory().getItemInMainHand(); + if (itemInHand.hasItemMeta() && itemInHand.getItemMeta().hasDisplayName() && + itemInHand.getItemMeta().getDisplayName().equals("§6Head Locator")) { + + Location nearestHead = headWorldController.findNearestUnclaimedHead(player); + if (nearestHead != null) { + double distance = player.getLocation().distance(nearestHead); + if (distance > 10) { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("§aNearest unclaimed head is " + (int) distance + " meters away.")); + player.playSound(player.getLocation(), "minecraft:block.note_block.pling", 1.0f, 1.0f); // Play a sound for far distance + } else { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("§aYou are very close to an unclaimed head!")); + player.playSound(player.getLocation(), "minecraft:block.note_block.bell", 1.0f, 1.5f); // Play a sound for close distance + } + } else { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("§cNo unclaimed heads found.")); + } + } else { + player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("§cHold the Head Locator to track heads.")); + } + }, 0L, 1200L); // Runs every 60 seconds (1200 ticks) + } +} \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/helpers/YamlFileManager.java b/src/main/java/org/modularsoft/PlayerHeadHunt/helpers/YamlFileManager.java new file mode 100644 index 0000000..d608253 --- /dev/null +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/helpers/YamlFileManager.java @@ -0,0 +1,78 @@ +package org.modularsoft.PlayerHeadHunt.helpers; + +import lombok.Getter; +import lombok.Setter; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.representer.Representer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Map; + +public class YamlFileManager { + private final File file; + private final Yaml yaml; + + @Getter + @Setter + private Map data; + + public YamlFileManager(File file) { + this.file = file; + + // Configure YAML dump options + DumperOptions dumperOptions = new DumperOptions(); + dumperOptions.setIndent(2); + dumperOptions.setPrettyFlow(true); + dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + + // Configure YAML representer + Representer representer = new Representer(dumperOptions); + representer.getPropertyUtils().setSkipMissingProperties(true); + + // Configure YAML loader options + LoaderOptions loaderOptions = new LoaderOptions(); + + // Initialize YAML parser + this.yaml = new Yaml(new SafeConstructor(loaderOptions), representer, dumperOptions); + + // Load the YAML file contents + load(); + } + + @SuppressWarnings("unchecked") + public void load() { + try { + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + try (FileWriter writer = new FileWriter(file)) { + writer.write("{}"); + } + } + + try (FileInputStream inputStream = new FileInputStream(file)) { + data = yaml.load(inputStream); + if (data == null) { + data = new java.util.LinkedHashMap<>(); + } + } + } catch (IOException e) { + e.printStackTrace(); + data = new java.util.LinkedHashMap<>(); + } + } + + public void save() { + try (FileWriter writer = new FileWriter(file)) { + yaml.dump(data, writer); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/modularsoft/PlayerHeadHunt/items/HeadLocator.java b/src/main/java/org/modularsoft/PlayerHeadHunt/items/HeadLocator.java new file mode 100644 index 0000000..823cd8e --- /dev/null +++ b/src/main/java/org/modularsoft/PlayerHeadHunt/items/HeadLocator.java @@ -0,0 +1,19 @@ +package org.modularsoft.PlayerHeadHunt.items; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import java.util.List; + +public class HeadLocator { + public static ItemStack createHeadLocator() { + ItemStack headLocator = new ItemStack(Material.RECOVERY_COMPASS); // Use Recovery Compass + ItemMeta meta = headLocator.getItemMeta(); + if (meta != null) { + meta.setDisplayName("§6Head Locator"); + meta.setLore(List.of("§7Tracks the nearest unclaimed head.")); + headLocator.setItemMeta(meta); + } + return headLocator; + } +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 563f7e8..b963488 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,9 +1,3 @@ -DATABASE: - HOST: "127.0.0.1" - PORT: 3306 - DATABASE: "PlayerHeadHunt" - USERNAME: "root" - PASSWORD: "root" REGION: UPPERREGION: X: -54 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1ae75b5..d9482f5 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -11,15 +11,11 @@ commands: description: Grab the amount of heads you have. usage: /heads aliases: [eggs, presents] - clearheads: - description: Clear all heads from yourself. - usage: /clearheads - aliases: [cleareggs, clearpresents] - countheads: - description: Recalculates the number of heads in the world. - usage: /countheads - aliases: [counteggs, countpresents] leaderboard: description: Show the 5 best heads hunters on the Server. usage: /leaderboard - aliases: [lb] \ No newline at end of file + aliases: [lb] + debugheadhunt: + description: Debug command for developers. + usage: /debugheadhunt + aliases: [ dhh ] \ No newline at end of file