diff --git a/src/main/java/me/nvus/nvus_prison_setup/Listeners/PlayerSpawn.java b/src/main/java/me/nvus/nvus_prison_setup/Listeners/PlayerSpawn.java index ffc7fdc..238e317 100644 --- a/src/main/java/me/nvus/nvus_prison_setup/Listeners/PlayerSpawn.java +++ b/src/main/java/me/nvus/nvus_prison_setup/Listeners/PlayerSpawn.java @@ -30,6 +30,8 @@ public class PlayerSpawn implements Listener { if (joinedPlayer.hasPermission("nvus.prisoner") && configManager.getConfig("config.yml").getBoolean("PrisonerArmor", true)) { equipPrisonerArmor(joinedPlayer); } + + } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) diff --git a/src/main/java/me/nvus/nvus_prison_setup/PrisonSetup.java b/src/main/java/me/nvus/nvus_prison_setup/PrisonSetup.java index 522d016..1bd3030 100644 --- a/src/main/java/me/nvus/nvus_prison_setup/PrisonSetup.java +++ b/src/main/java/me/nvus/nvus_prison_setup/PrisonSetup.java @@ -10,6 +10,9 @@ import me.nvus.nvus_prison_setup.Listeners.PlayerSpawn; import me.nvus.nvus_prison_setup.Listeners.BlockListener; import me.nvus.nvus_prison_setup.Listeners.ToolSwitchListener; import me.nvus.nvus_prison_setup.Placeholders.GangPlaceholders; +import me.nvus.nvus_prison_setup.Ranks.RankCommands; +import me.nvus.nvus_prison_setup.Ranks.RankListener; +import me.nvus.nvus_prison_setup.Ranks.RankManager; import me.nvus.nvus_prison_setup.Updater.UpdateChecker; import me.nvus.nvus_prison_setup.Listeners.ToolDamageListener; import me.nvus.nvus_prison_setup.TreeFarm.TreeFarmListener; @@ -42,7 +45,9 @@ public final class PrisonSetup extends JavaPlugin { private ConfigManager configManager; private DatabaseManager dbManager; - private GangManager gangManager; // Added reference to GangManager + private GangManager gangManager; + + private RankManager rankManager; private static Economy econ = null; // Vault / Economy @@ -52,8 +57,15 @@ public final class PrisonSetup extends JavaPlugin { // Initialize the ConfigManager configManager = new ConfigManager(this); + // Save the default configs, if they don't exist + configManager.saveDefaultConfig("config.yml"); + configManager.saveDefaultConfig("banned_items.yml"); + configManager.saveDefaultConfig("auto_switch.yml"); + configManager.saveDefaultConfig("item_prices.yml"); + configManager.saveDefaultConfig("ranks.yml"); + // Initialize the DatabaseManager with ConfigManager - dbManager = new DatabaseManager(configManager); // Correctly assign to the class field + dbManager = new DatabaseManager(configManager); // Correctly assign to the configManager // Initialize the GangManager with the DatabaseManager gangManager = new GangManager(dbManager); // Use the corrected dbManager @@ -67,11 +79,6 @@ public final class PrisonSetup extends JavaPlugin { getLogger().info("SQLite database already exists."); } - // Save the default configs, if they don't exist - configManager.saveDefaultConfig("config.yml"); - configManager.saveDefaultConfig("banned_items.yml"); - configManager.saveDefaultConfig("auto_switch.yml"); - configManager.saveDefaultConfig("item_prices.yml"); configManager.loadItemPricesConfig(this.getDataFolder()); @@ -130,9 +137,24 @@ public final class PrisonSetup extends JavaPlugin { getServer().getPluginManager().registerEvents(new TreeFarmListener(this), this); } + // Ranks Manager + boolean prisonerRanksEnabled = configManager.getConfig("config.yml").getBoolean("PrisonerRanks", true); + if (prisonerRanksEnabled) { + // Initialize RankManager and other initializations + rankManager = new RankManager(this); + + // Register RankListener + getServer().getPluginManager().registerEvents(new RankListener(rankManager), this); + + // Register commands + this.getCommand("rankup").setExecutor(new RankCommands(this)); + this.getCommand("ranks").setExecutor(new RankCommands(this)); + } + // Successful Startup/Enable getLogger().info(ChatColor.translateAlternateColorCodes('&',"&a&lNVus Prison Setup has been successfully enabled!")); + // UPDATE CHECKER new UpdateChecker(this, 12345).getVersion(version -> { if (!this.getDescription().getVersion().equals(version)) { @@ -194,6 +216,10 @@ public final class PrisonSetup extends JavaPlugin { return econ; } + public RankManager getRankManager() { + return rankManager; + } + public ConfigManager getConfigManager() { return configManager; } diff --git a/src/main/java/me/nvus/nvus_prison_setup/Ranks/PlayerRankData.java b/src/main/java/me/nvus/nvus_prison_setup/Ranks/PlayerRankData.java new file mode 100644 index 0000000..0f35af2 --- /dev/null +++ b/src/main/java/me/nvus/nvus_prison_setup/Ranks/PlayerRankData.java @@ -0,0 +1,31 @@ +package me.nvus.nvus_prison_setup.Ranks; + +import java.util.UUID; + +public class PlayerRankData { + private UUID uuid; + private String username; + private String rankName; + + public PlayerRankData(UUID uuid, String username, String rankName) { + this.uuid = uuid; + this.username = username; + this.rankName = rankName; + } + + // Getters + public UUID getUuid() { + return uuid; + } + + public String getUsername() { + return username; + } + + public String getRankName() { + return rankName; + } + + +} + diff --git a/src/main/java/me/nvus/nvus_prison_setup/Ranks/Rank.java b/src/main/java/me/nvus/nvus_prison_setup/Ranks/Rank.java new file mode 100644 index 0000000..59970b2 --- /dev/null +++ b/src/main/java/me/nvus/nvus_prison_setup/Ranks/Rank.java @@ -0,0 +1,30 @@ +package me.nvus.nvus_prison_setup.Ranks; + +import java.util.List; + +public class Rank { + private String name; + private double cost; + private List commands; + + public Rank(String name, double cost, List commands) { + this.name = name; + this.cost = cost; + this.commands = commands; + } + + // Getters + public String getName() { + return name; + } + + public double getCost() { + return cost; + } + + public List getCommands() { + return commands; + } + + // Setters and other methods as necessary +} diff --git a/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankCommands.java b/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankCommands.java new file mode 100644 index 0000000..27abe1d --- /dev/null +++ b/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankCommands.java @@ -0,0 +1,58 @@ +package me.nvus.nvus_prison_setup.Ranks; + +import me.nvus.nvus_prison_setup.PrisonSetup; +import me.nvus.nvus_prison_setup.Ranks.RankManager; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class RankCommands implements CommandExecutor { + + private final RankManager rankManager; + + public RankCommands(PrisonSetup plugin) { + this.rankManager = plugin.getRankManager(); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(ChatColor.RED + "This command can only be used by players."); + return true; + } + Player player = (Player) sender; + + switch (label.toLowerCase()) { + case "rankup": + return handleRankUpCommand(player); + case "ranks": + return handleRanksCommand(player); + default: + return false; + } + } + + private boolean handleRankUpCommand(Player player) { + // Check if the player has a rank, assign the default rank if not + Rank currentRank = rankManager.getCurrentRank(player); + if (currentRank == null) { + rankManager.assignDefaultRank(player); + player.sendMessage(ChatColor.YELLOW + "We couldn't find you in the ranks database. Assigning default rank now!"); + return true; + } + + boolean success = rankManager.rankUp(player); + if (!success) { + player.sendMessage(ChatColor.RED + "Unable to rank up. Please check your rank and balance using /ranks"); + } + return true; + } + + private boolean handleRanksCommand(Player player) { + String ranksMessage = rankManager.getRanksDisplay(player); + player.sendMessage(ranksMessage); + return true; + } +} diff --git a/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankListener.java b/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankListener.java new file mode 100644 index 0000000..f10c3fe --- /dev/null +++ b/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankListener.java @@ -0,0 +1,32 @@ +package me.nvus.nvus_prison_setup.Ranks; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.entity.Player; + +public class RankListener implements Listener { + private RankManager rankManager; + + public RankListener(RankManager rankManager) { + this.rankManager = rankManager; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + handleNewPlayer(player); +// if (rankManager.getCurrentRank(player) == null) { +// // Assign to the default rank +// rankManager.assignDefaultRank(player); +// } + } + + private void handleNewPlayer(Player player) { + Rank currentRank = rankManager.getCurrentRank(player); + if (currentRank == null) { + rankManager.assignDefaultRank(player); + } + + } +} diff --git a/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankManager.java b/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankManager.java new file mode 100644 index 0000000..67d3197 --- /dev/null +++ b/src/main/java/me/nvus/nvus_prison_setup/Ranks/RankManager.java @@ -0,0 +1,317 @@ +package me.nvus.nvus_prison_setup.Ranks; + +import com.google.gson.Gson; +import me.nvus.nvus_prison_setup.PrisonSetup; +import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault.economy.EconomyResponse; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.entity.Player; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import java.io.FileReader; +import java.io.FileWriter; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class RankManager { + + private JavaPlugin plugin; + private List ranks = new ArrayList<>(); + private Map playerRanks = new HashMap<>(); + + + public RankManager(JavaPlugin plugin) { + this.plugin = plugin; + ensureRankDataFile(); + loadRanksFromConfig(); + loadPlayerRanks(); + loadRanksFromRankDataFile(); + } + + private void ensureRankDataFile() { + File rankDataFile = new File(plugin.getDataFolder(), "rank_data.json"); + if (!rankDataFile.exists()) { + try { + plugin.saveResource("ranks.yml", false); + File ranksYmlFile = new File(plugin.getDataFolder(), "ranks.yml"); + FileConfiguration ranksConfig = YamlConfiguration.loadConfiguration(ranksYmlFile); + updateRankDataFromYml(ranksConfig, rankDataFile); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void updateRankDataFromYml(FileConfiguration ranksConfig, File rankDataFile) { + try { + Set rankKeys = ranksConfig.getConfigurationSection("Ranks").getKeys(false); + List ranks = rankKeys.stream().map(rankKey -> { + String path = "Ranks." + rankKey; + String name = rankKey; + double cost = ranksConfig.getDouble(path + ".Cost"); + List commands = ranksConfig.getStringList(path + ".Commands"); + return new Rank(name, cost, commands); + }).collect(Collectors.toList()); + + Map rankData = new HashMap<>(); + rankData.put("ranks", ranks); + // Add a dummy player data for demonstration. Replace with actual player data logic. + rankData.put("players", Collections.singletonList(new PlayerRankData(UUID.randomUUID(), "DummyPlayer", "Default"))); + + try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(rankDataFile), StandardCharsets.UTF_8))) { + new Gson().toJson(rankData, writer); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void loadRanksFromConfig() { + File ranksYmlFile = new File(plugin.getDataFolder(), "ranks.yml"); + if (ranksYmlFile.exists()) { + FileConfiguration ranksConfig = YamlConfiguration.loadConfiguration(ranksYmlFile); + File rankDataFile = new File(plugin.getDataFolder(), "rank_data.json"); + updateRankDataFromYml(ranksConfig, rankDataFile); + // Debug log to check ranks loading + System.out.println("Loaded ranks: " + ranks.size()); + ranks.forEach(rank -> System.out.println(rank.getName() + ": $" + rank.getCost())); + } + } + + private void loadRanksFromRankDataFile() { + File rankDataFile = new File(plugin.getDataFolder(), "rank_data.json"); + if (rankDataFile.exists()) { + try (Reader reader = new FileReader(rankDataFile)) { + Gson gson = new Gson(); + Type type = new TypeToken>() {}.getType(); + Map rankDataMap = gson.fromJson(reader, type); + + List> ranksList = (List>) rankDataMap.get("ranks"); + if (ranksList != null) { + this.ranks.clear(); // Clear existing ranks before loading new ones + for (Map rankMap : ranksList) { + String name = (String) rankMap.get("name"); + double cost = ((Number) rankMap.get("cost")).doubleValue(); + List commands = (List) rankMap.get("commands"); + Rank rank = new Rank(name, cost, commands); + this.ranks.add(rank); + } + } + System.out.println("Loaded ranks from rank_data.json: " + ranks.size()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + + public Rank getCurrentRank(Player player) { + String currentRankName = playerRanks.get(player.getUniqueId()); + if (currentRankName == null) { + // Reload ranks from config to ensure they are up to date + loadRanksFromConfig(); + loadPlayerRanks(); + + // Assign default rank if the player has no current rank + assignDefaultRank(player); + currentRankName = playerRanks.get(player.getUniqueId()); + } + + // Use a final variable for the lambda expression + final String rankNameForLambda = currentRankName; + + return ranks.stream() + .filter(rank -> rank.getName().equals(rankNameForLambda)) + .findFirst() + .orElse(null); // Consider handling the default rank if not found. + } + + + public Rank getNextRank(Player player) { + Rank currentRank = getCurrentRank(player); + if (currentRank == null) { + return null; // Handle appropriately, maybe return the first rank if implementing a default catch-up mechanism. + } + int currentIndex = ranks.indexOf(currentRank); + if (currentIndex < ranks.size() - 1) { + return ranks.get(currentIndex + 1); + } + return null; // Player is at the highest rank. + } + + public boolean rankUp(Player player) { + // Directly retrieve the next rank using the player object + Rank nextRank = getNextRank(player); + + if (nextRank == null) { + player.sendMessage(ChatColor.RED + "You are already at the highest rank!"); + return false; + } + + Economy economy = PrisonSetup.getEconomy(); // Assuming this static method access is correct + double balance = economy.getBalance(player); + + if (balance < nextRank.getCost()) { + player.sendMessage(ChatColor.RED + "You cannot afford to rank up. You have " + balance + ", but need " + nextRank.getCost() + "."); + return false; + } + + EconomyResponse response = economy.withdrawPlayer(player, nextRank.getCost()); + if (!response.transactionSuccess()) { + player.sendMessage(ChatColor.RED + "Transaction failed: " + response.errorMessage); + return false; + } + + // Update the player's rank in memory and any persistent storage + playerRanks.put(player.getUniqueId(), nextRank.getName()); + saveRankData(); // Ensure to implement this method to persist changes to 'rank_data.json' + + // Execute rank-up commands + executeRankCommands(player, nextRank.getCommands()); + + player.sendMessage(ChatColor.GREEN + "You've been ranked up to " + nextRank.getName() + "!"); + return true; + } + + + private void updatePlayerRank(Player player, Rank nextRank) { + // Update the player's current rank in memory (if you're keeping a cache) + playerRanks.put(player.getUniqueId(), nextRank.getName()); + // Save the player's current rank to persistent storage + saveRankData(); + } + + + + private void executeRankCommands(Player player, List commands) { + if (commands == null || commands.isEmpty()) return; + String playerName = player.getName(); + commands.forEach(command -> + Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), command.replace("%player%", playerName)) + ); + } + + + private void saveRankData() { + File rankDataFile = new File(plugin.getDataFolder(), "rank_data.json"); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + // Load existing rank data to merge with updates + Map existingData = new HashMap<>(); + try (Reader reader = new FileReader(rankDataFile)) { + Type type = new TypeToken>() {}.getType(); + existingData = gson.fromJson(reader, type); + } catch (Exception e) { + e.printStackTrace(); + } + + // If there's no existing data or it's the first time, initialize structures + if (existingData == null) { + existingData = new HashMap<>(); + } + + // Prepare rank data to be saved + List> serializedRanks = ranks.stream().map(rank -> { + Map rankMap = new HashMap<>(); + rankMap.put("name", rank.getName()); + rankMap.put("cost", rank.getCost()); + rankMap.put("commands", rank.getCommands()); + return rankMap; + }).collect(Collectors.toList()); + + // Prepare player rank data to be saved + List> serializedPlayerRanks = playerRanks.entrySet().stream().map(entry -> { + Map playerRankMap = new HashMap<>(); + playerRankMap.put("uuid", entry.getKey().toString()); + playerRankMap.put("rankName", entry.getValue()); + return playerRankMap; + }).collect(Collectors.toList()); + + // Update the existing data map + existingData.put("ranks", serializedRanks); + existingData.put("players", serializedPlayerRanks); + + // Save the updated data back to the file + try (Writer writer = new FileWriter(rankDataFile)) { + gson.toJson(existingData, writer); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getRanksDisplay(Player player) { + StringBuilder ranksMessage = new StringBuilder(ChatColor.GOLD + "Available Ranks:\n"); + for (Rank rank : ranks) { + ranksMessage.append(ChatColor.YELLOW).append(rank.getName()) + .append(ChatColor.WHITE).append(" - $") + .append(ChatColor.GREEN).append(rank.getCost()).append("\n"); + } + + // Fetch the player's current rank from the stored data + String currentRankName = playerRanks.getOrDefault(player.getUniqueId(), "Unranked"); + // Using Vault to get the player's balance + Economy economy = PrisonSetup.getEconomy(); + double balance = economy.getBalance(player); + + // Append the player's current rank and balance to the message + ranksMessage.append(ChatColor.GOLD + "\nYour current rank: " + ChatColor.YELLOW + currentRankName); + ranksMessage.append(ChatColor.GOLD + "\nYour balance: " + ChatColor.GREEN + "$" + balance); + + return ranksMessage.toString(); + } + + public void assignDefaultRank(Player player) { + if (!playerRanks.containsKey(player.getUniqueId())) { + // Ensure this method successfully finds and assigns the default rank + Rank defaultRank = ranks.stream().filter(r -> r.getName().equalsIgnoreCase("Default")).findFirst().orElse(null); + if (defaultRank != null) { + playerRanks.put(player.getUniqueId(), defaultRank.getName()); + // Debug log + System.out.println("Assigning default rank to " + player.getName()); + saveRankData(); + player.sendMessage(ChatColor.GREEN + "You've been assigned the default rank: " + defaultRank.getName()); + } else { + System.out.println("Default rank not found in loaded ranks."); + } + } + } + + + private void loadPlayerRanks() { + File rankDataFile = new File(plugin.getDataFolder(), "rank_data.json"); + if (rankDataFile.exists()) { + try (Reader reader = new FileReader(rankDataFile)) { + Type type = new TypeToken>>() {}.getType(); + Map> data = new Gson().fromJson(reader, type); + List playerRankDataList = data.get("players"); + if (playerRankDataList != null) { + playerRankDataList.forEach(playerRankData -> playerRanks.put(playerRankData.getUuid(), playerRankData.getRankName())); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + + + + + + + + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 44ab3f2..4727973 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -64,6 +64,14 @@ ToolDamage: false # It will then place down a sapling in the same spot where the tree base was destroyed. TreeFarm: true +######################################################################################## +# PRISONER RANKS FEATURE # +######################################################################################## + +# Do you want to use the built-in /rankup and /maxrankup commands to rank prisoners up? +# Can configure the ranks in the ranks.yml file! +PrisonerRanks: true + ######################################################################################## # DATABASE SETTINGS # ######################################################################################## diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f6b1075..bba07cc 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -60,6 +60,16 @@ commands: usage: | /setprice - Set the price of the block being held in item_prices.yml. aliases: [ setblockprice ] + rankup: + description: Rank up to the next rank. + usage: | + /rankup - Rank up to the next rank. + aliases: [ nextrank ] + ranks: + description: Display all available ranks, their cost and your current rank and balance. + usage: | + /ranks - Rank up to the max rank. + aliases: [ allranks ] permissions: nvus.admin: diff --git a/src/main/resources/ranks.yml b/src/main/resources/ranks.yml new file mode 100644 index 0000000..b386fe3 --- /dev/null +++ b/src/main/resources/ranks.yml @@ -0,0 +1,16 @@ +#======================================================================================# +# NVus PRISON GOLD EDITION # +# by never2nv # +# www.FNGnation.net # +# Discord: FNGnation.net/discord # +#======================================================================================# +Ranks: + Default: # DO NOT CHANGE THE NAME 'Default' or this will break the plugin! This is the first/default rank! + Cost: 100 + Commands: + - broadcast %player% has been processed as a new inmate! + Tier2: + Cost: 200 + Commands: + - broadcast %player% has been promoted to Tier 2! + - lp user %player% permission set nvus.gang.create true