diff --git a/build.gradle b/build.gradle index c97715e..b2c1bab 100644 --- a/build.gradle +++ b/build.gradle @@ -1,70 +1,70 @@ -plugins { - id 'java' - id "io.freefair.lombok" version "5.1.0" -} - -group 'sh.okx' -version '3.9-beta.2' - -repositories { - mavenCentral() - mavenLocal() - maven { - url 'https://hub.spigotmc.org/nexus/content/groups/public/' - } - maven { - url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' - } - maven { - url 'https://raw.github.com/PyvesB/AdvancedAchievements/mvn-repo/' - } - // for plugins without repos, namely mcmmo, votingplugin, and towny - maven { - url 'https://jitpack.io' - } -} - -dependencies { - testImplementation group: 'junit', name: 'junit', version: '4.12' - testImplementation 'com.github.seeseemelk:MockBukkit-v1.15:0.3.0-SNAPSHOT' - - compileOnly 'org.jetbrains:annotations:16.0.2' - implementation 'org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT' - implementation('com.github.Realizedd:TokenManager:3.2.4') { - transitive = false - } - - implementation('com.github.MilkBowl:VaultAPI:1.7') { - exclude group: 'org.bukkit' - } - implementation 'me.clip:placeholderapi:2.10.6' - implementation 'com.hm.achievement:advanced-achievements-api:1.1.0' - implementation('com.github.mcMMO-Dev:mcMMO:601297') { - exclude group: 'com.sk89q.worldguard' - } - implementation 'com.github.Ben12345rocks:VotingPlugin:5.21.1' - implementation 'com.github.LlmDl:Towny:25fc18a' -} - -// automatically copy the version to plugin.yml -processResources { - // do this again whenever version changes - inputs.property 'version', project.version - - // copy plugin.yml and replace version - from(sourceSets.main.resources.srcDirs) { - include 'plugin.yml' - expand 'version': project.version - } - - // copy everything else - from(sourceSets.main.resources.srcDirs) { - exclude 'plugin.yml' - } -} - -task spigot(type: Jar) { - from sourceSets.main.runtimeClasspath - destinationDirectory = file("./spigot/plugins/") - archiveFileName = "Rankup.jar" +plugins { + id 'java' + id "io.freefair.lombok" version "5.1.0" +} + +group 'sh.okx' +version '3.9' + +repositories { + mavenCentral() + mavenLocal() + maven { + url 'https://hub.spigotmc.org/nexus/content/groups/public/' + } + maven { + url 'https://repo.extendedclip.com/content/repositories/placeholderapi/' + } + maven { + url 'https://raw.github.com/PyvesB/AdvancedAchievements/mvn-repo/' + } + // for plugins without repos, namely mcmmo, votingplugin, and towny + maven { + url 'https://jitpack.io' + } +} + +dependencies { + testImplementation group: 'junit', name: 'junit', version: '4.12' + testImplementation 'com.github.seeseemelk:MockBukkit-v1.15:0.3.0-SNAPSHOT' + + compileOnly 'org.jetbrains:annotations:16.0.2' + implementation 'org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT' + implementation('com.github.Realizedd:TokenManager:3.2.4') { + transitive = false + } + + implementation('com.github.MilkBowl:VaultAPI:1.7') { + exclude group: 'org.bukkit' + } + implementation 'me.clip:placeholderapi:2.10.6' + implementation 'com.hm.achievement:advanced-achievements-api:1.1.0' + implementation('com.github.mcMMO-Dev:mcMMO:601297') { + exclude group: 'com.sk89q.worldguard' + } + implementation 'com.github.Ben12345rocks:VotingPlugin:5.21.1' + implementation 'com.github.LlmDl:Towny:25fc18a' +} + +// automatically copy the version to plugin.yml +processResources { + // do this again whenever version changes + inputs.property 'version', project.version + + // copy plugin.yml and replace version + from(sourceSets.main.resources.srcDirs) { + include 'plugin.yml' + expand 'version': project.version + } + + // copy everything else + from(sourceSets.main.resources.srcDirs) { + exclude 'plugin.yml' + } +} + +task spigot(type: Jar) { + from sourceSets.main.runtimeClasspath + destinationDirectory = file("./spigot/plugins/") + archiveFileName = "Rankup.jar" } \ No newline at end of file diff --git a/src/main/java/sh/okx/rankup/RankupPlugin.java b/src/main/java/sh/okx/rankup/RankupPlugin.java index dd73866..5d3e50b 100644 --- a/src/main/java/sh/okx/rankup/RankupPlugin.java +++ b/src/main/java/sh/okx/rankup/RankupPlugin.java @@ -1,500 +1,503 @@ -package sh.okx.rankup; - -import lombok.Getter; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.InventoryView; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.plugin.PluginManager; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.plugin.java.JavaPluginLoader; -import sh.okx.rankup.commands.*; -import sh.okx.rankup.economy.Economy; -import sh.okx.rankup.economy.EconomyProvider; -import sh.okx.rankup.economy.VaultEconomyProvider; -import sh.okx.rankup.gui.Gui; -import sh.okx.rankup.gui.GuiListener; -import sh.okx.rankup.hook.GroupProvider; -import sh.okx.rankup.hook.PermissionManager; -import sh.okx.rankup.hook.VaultPermissionManager; -import sh.okx.rankup.messages.Message; -import sh.okx.rankup.messages.MessageBuilder; -import sh.okx.rankup.messages.NullMessageBuilder; -import sh.okx.rankup.messages.Variable; -import sh.okx.rankup.placeholders.Placeholders; -import sh.okx.rankup.prestige.Prestige; -import sh.okx.rankup.prestige.Prestiges; -import sh.okx.rankup.ranks.Rank; -import sh.okx.rankup.ranks.RankList; -import sh.okx.rankup.ranks.Rankups; -import sh.okx.rankup.requirements.Requirement; -import sh.okx.rankup.requirements.RequirementRegistry; -import sh.okx.rankup.requirements.requirement.XpLevelDeductibleRequirement; -import sh.okx.rankup.requirements.requirement.*; -import sh.okx.rankup.requirements.requirement.advancedachievements.AdvancedAchievementsAchievementRequirement; -import sh.okx.rankup.requirements.requirement.advancedachievements.AdvancedAchievementsTotalRequirement; -import sh.okx.rankup.requirements.requirement.mcmmo.McMMOPowerLevelRequirement; -import sh.okx.rankup.requirements.requirement.mcmmo.McMMOSkillRequirement; -import sh.okx.rankup.requirements.requirement.tokenmanager.TokensDeductibleRequirement; -import sh.okx.rankup.requirements.requirement.tokenmanager.TokensRequirement; -import sh.okx.rankup.requirements.requirement.towny.*; -import sh.okx.rankup.requirements.requirement.votingplugin.VotingPluginPointsDeductibleRequirement; -import sh.okx.rankup.requirements.requirement.votingplugin.VotingPluginPointsRequirement; -import sh.okx.rankup.requirements.requirement.votingplugin.VotingPluginVotesRequirement; -import sh.okx.rankup.util.UpdateNotifier; -import sh.okx.rankup.util.VersionChecker; - -import java.io.File; -import java.text.DecimalFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -public class RankupPlugin extends JavaPlugin { - - public static final int CONFIG_VERSION = 8; - - @Getter - private GroupProvider permissions; - @Getter - private Economy economy; - /** - * The registry for listing the requirements to /rankup. - */ - @Getter - private RequirementRegistry requirements; - @Getter - private FileConfiguration messages; - @Getter - private FileConfiguration config; - @Getter - private Rankups rankups; - @Getter - private Prestiges prestiges; - @Getter - private Placeholders placeholders; - @Getter - private RankupHelper helper; - protected AutoRankup autoRankup = new AutoRankup(this); - private String errorMessage; - private PermissionManager permissionManager = new VaultPermissionManager(this); - private EconomyProvider economyProvider = new VaultEconomyProvider(); - - public RankupPlugin() { - super(); - } - - protected RankupPlugin(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file, PermissionManager permissionManager, EconomyProvider economyProvider) { - super(loader, description, dataFolder, file); - this.permissionManager = permissionManager; - this.economyProvider = economyProvider; - } - - @Override - public void onEnable() { - UpdateNotifier notifier = new UpdateNotifier(new VersionChecker(this)); - - reload(true); - - if (System.getProperty("TEST") == null) { - Metrics metrics = new Metrics(this); - metrics.addCustomChart(new Metrics.SimplePie("confirmation", - () -> config.getString("confirmation-type", "unknown"))); - metrics.addCustomChart(new Metrics.AdvancedPie("requirements", () -> { - Map map = new HashMap<>(); - addAll(map, rankups); - if (prestiges != null) { - addAll(map, prestiges); - } - return map; - })); - metrics.addCustomChart(new Metrics.SimplePie("prestige", - () -> config.getBoolean("prestige") ? "enabled" : "disabled")); - metrics.addCustomChart(new Metrics.SimplePie("permission-rankup", - () -> config.getBoolean("permission-rankup") ? "enabled" : "disabled")); - metrics.addCustomChart(new Metrics.SimplePie("notify-update", - () -> config.getBoolean("notify-update") ? "enabled" : "disabled")); - } - - if (config.getBoolean("ranks")) { - getCommand("ranks").setExecutor(new RanksCommand(this)); - } - if (config.getBoolean("prestige")) { - getCommand("prestige").setExecutor(new PrestigeCommand(this)); - if (config.getBoolean("prestiges")) { - getCommand("prestiges").setExecutor(new PrestigesCommand(this)); - } - } - if (config.getBoolean("max-rankup.enabled")) { - getCommand("maxrankup").setExecutor(new MaxRankupCommand(this)); - } - - getCommand("rankup").setExecutor(new RankupCommand(this)); - getCommand("rankup3").setExecutor(new InfoCommand(this, notifier)); - getServer().getPluginManager().registerEvents(new GuiListener(this), this); - getServer().getPluginManager().registerEvents( - new JoinUpdateNotifier(notifier, () -> getConfig().getBoolean("notify-update"), "rankup.notify"), this); - - placeholders = new Placeholders(this); - placeholders.register(); - } - - - @Override - public void onDisable() { - closeInventories(); - if (placeholders != null) { - placeholders.unregister(); - } - } - - public void reload(boolean init) { - errorMessage = null; - - config = loadConfig("config.yml"); - - if (config.getBoolean("permission-rankup")) { - permissions = permissionManager.permissionOnlyProvider(); - } else { - permissions = permissionManager.findPermissionProvider(); - if (permissions == null) { - errorMessage = "No permission plugin found"; - } - } - - setupEconomy(); - - closeInventories(); - loadConfigs(init); - - long time = (long) (config.getDouble("autorankup-interval") * 60 * 20); - if (time > 0) { - if (!autoRankup.isCancelled()) { - autoRankup.cancel(); - } - autoRankup.runTaskTimer(this, time, time); - } - - if (config.getInt("version") < CONFIG_VERSION) { - getLogger().severe("You are using an outdated config!"); - getLogger().severe("This means that some things might not work!"); - getLogger().severe("To update, please rename ALL your config files (or the folder they are in),"); - getLogger().severe("and run /pru reload to generate a new config file."); - getLogger().severe("If that does not work, restart your server."); - getLogger().severe("You may then copy in your config values manually from the old config."); - getLogger().severe("Check the changelog on the Rankup spigot page to see the changes."); - getLogger().severe("https://www.spigotmc.org/resources/rankup.76964/updates"); - } - - helper = new RankupHelper(this); - } - - public boolean error() { - return error(null); - } - - /** - * Notify the player of an error if there is one - * - * @return true if there was an error and action was taken - */ - public boolean error(CommandSender sender) { - if (errorMessage == null) { - return false; - } - - if (sender instanceof Player) { - sender.sendMessage( - ChatColor.RED + "Could not load Rankup, check console for more information."); - } else { - getLogger().severe("Failed to load Rankup"); - } - for (String line : errorMessage.split("\n")) { - getLogger().severe(line); - } - getLogger().severe("More information can be found in the console log at startup"); - return true; - } - - private void addAll(Map map, RankList ranks) { - for (Rank rank : ranks.getTree()) { - for (Requirement requirement : rank.getRequirements().getRequirements(null)) { - String name = requirement.getName(); - map.put(name, map.getOrDefault(name, 0) + 1); - } - } - } - - /** - * Closes all rankup inventories on disable so players cannot grab items from the inventory on a - * plugin reload. - */ - private void closeInventories() { - for (Player player : Bukkit.getOnlinePlayers()) { - InventoryView view = player.getOpenInventory(); - if (view.getType() == InventoryType.CHEST - && view.getTopInventory().getHolder() instanceof Gui) { - player.closeInventory(); - } - } - } - - private void loadConfigs(boolean init) { - saveLocales(); - - String locale = config.getString("locale", "en"); - File localeFile = new File(new File(getDataFolder(), "locale"), locale + ".yml"); - messages = YamlConfiguration.loadConfiguration(localeFile); - - if (init) { - Bukkit.getScheduler().runTask(this, () -> { - refreshRanks(); - error(); - }); - } else { - refreshRanks(); - } - } - - public void refreshRanks() { - try { - registerRequirements(); - Bukkit.getPluginManager().callEvent(new RankupRegisterEvent(this)); - - if (config.getBoolean("prestige")) { - prestiges = new Prestiges(this, loadConfig("prestiges.yml")); -// prestiges.getOrderedList(); - } else { - prestiges = null; - } - - rankups = new Rankups(this, loadConfig("rankups.yml")); - // check rankups are not in an infinite loop -// rankups.getOrderedList(); - - - - } catch (Exception e) { - this.errorMessage = e.getClass().getName() + ": " + e.getMessage(); - e.printStackTrace(); - } - } - - private void saveLocales() { - saveLocale("en"); - saveLocale("pt_br"); - saveLocale("ru"); - saveLocale("zh_cn"); - saveLocale("fr"); - } - - private void saveLocale(String locale) { - String name = "locale/" + locale + ".yml"; - File file = new File(getDataFolder(), name); - if (!file.exists()) { - saveResource(name, false); - } - } - - private FileConfiguration loadConfig(String name) { - File file = new File(getDataFolder(), name); - if (!file.exists()) { - saveResource(name, false); - } - return YamlConfiguration.loadConfiguration(file); - } - - private void registerRequirements() { - requirements = new RequirementRegistry(); - requirements.addRequirements( - new XpLevelRequirement(this, "xp-levelh"), - new XpLevelDeductibleRequirement(this, "xp-level"), - new PlaytimeMinutesRequirement(this), - new AdvancementRequirement(this), - new GroupRequirement(this), - new PermissionRequirement(this), - new PlaceholderRequirement(this), - new WorldRequirement(this), - new BlockBreakRequirement(this), - new PlayerKillsRequirement(this), - new MobKillsRequirement(this), - new ItemRequirement(this, "itemh"), - new ItemDeductibleRequirement(this, "item"), - new UseItemRequirement(this), - new TotalMobKillsRequirement(this), - new CraftItemRequirement(this)); - if (economy != null) { - requirements.addRequirements( - new MoneyRequirement(this, "moneyh"), - new MoneyDeductibleRequirement(this, "money")); - } - - PluginManager pluginManager = Bukkit.getPluginManager(); - if (pluginManager.isPluginEnabled("mcMMO")) { - requirements.addRequirements( - new McMMOSkillRequirement(this), - new McMMOPowerLevelRequirement(this)); - } - if (pluginManager.isPluginEnabled("AdvancedAchievements")) { - requirements.addRequirements( - new AdvancedAchievementsAchievementRequirement(this), - new AdvancedAchievementsTotalRequirement(this)); - } - if (pluginManager.isPluginEnabled("VotingPlugin")) { - requirements.addRequirements( - new VotingPluginVotesRequirement(this), - new VotingPluginPointsRequirement(this, "votingplugin-pointsh"), - new VotingPluginPointsDeductibleRequirement(this, "votingplugin-points")); - } - if (Bukkit.getPluginManager().isPluginEnabled("Towny")) { - requirements.addRequirements( - new TownyResidentRequirement(this), - new TownyMayorRequirement(this), - new TownyMayorNumberResidentsRequirement(this), - new TownyKingRequirement(this), - new TownyKingNumberResidentsRequirement(this), - new TownyKingNumberTownsRequirement(this)); - } - if (Bukkit.getPluginManager().isPluginEnabled("TokenManager")) { - requirements.addRequirements( - new TokensRequirement(this, "tokenmanager-tokensh"), - new TokensDeductibleRequirement(this, "tokenmanager-tokens")); - } - } - private void setupEconomy() { - economy = economyProvider.getEconomy(); - } - - public String formatMoney(double money) { - List shortened = config.getStringList("shorten"); - String suffix = ""; - - for (int i = shortened.size(); i > 0; i--) { - double value = Math.pow(10, 3 * i); - if (money >= value) { - money /= value; - suffix = shortened.get(i - 1); - break; - } - } - - return placeholders.getMoneyFormat().format(money) + suffix; - } - - public ConfigurationSection getSection(Rank rank, String path) { - ConfigurationSection rankSection = rank.getSection(); - if (rankSection == null || !rankSection.isConfigurationSection(path)) { - return this.messages.getConfigurationSection(path); - } - return rankSection.getConfigurationSection(path); - } - - public MessageBuilder getMessage(Rank rank, Message message) { - ConfigurationSection messages = rank.getSection(); - if (messages == null || !messages.isSet(message.getName())) { - messages = this.messages; - } - return MessageBuilder.of(messages, message); - } - - public MessageBuilder getMessage(Message message) { - return MessageBuilder.of(messages, message); - } - - public MessageBuilder replaceMoneyRequirements(MessageBuilder builder, CommandSender sender, - Rank rank) { - if (builder instanceof NullMessageBuilder) { - return builder; - } - - Requirement money = rank.getRequirement(sender instanceof Player ? (Player) sender : null, "money"); - if (money != null) { - Double amount = null; - if (sender instanceof Player && rank.isIn((Player) sender)) { - if (economy != null) { - amount = money.getRemaining((Player) sender); - } - } else { - amount = money.getValueDouble(); - } - if (amount != null && economy != null) { - builder.replace(Variable.MONEY_NEEDED, formatMoney(amount)); - builder.replace(Variable.MONEY, formatMoney(money.getValueDouble())); - } - } - if (sender instanceof Player) { - replaceRequirements(builder, (Player) sender, rank); - } - return builder; - } - - public MessageBuilder replaceRequirements(MessageBuilder builder, Player player, Rank rank) { - DecimalFormat simpleFormat = placeholders.getSimpleFormat(); - DecimalFormat percentFormat = placeholders.getPercentFormat(); - for (Requirement requirement : rank.getRequirements().getRequirements(player)) { - try { - replaceRequirements(builder, Variable.AMOUNT, requirement, - () -> simpleFormat.format(requirement.getTotal(player))); - if (rank.isIn(player)) { - replaceRequirements(builder, Variable.AMOUNT_NEEDED, requirement, - () -> simpleFormat.format(requirement.getRemaining(player))); - replaceRequirements(builder, Variable.PERCENT_LEFT, requirement, - () -> percentFormat.format(Math.max(0, - (requirement.getRemaining(player) / requirement.getTotal(player)) * 100))); - replaceRequirements(builder, Variable.PERCENT_DONE, requirement, - () -> percentFormat.format(Math.min(100, - (1 - (requirement.getRemaining(player) / requirement.getTotal(player))) * 100))); - replaceRequirements(builder, Variable.AMOUNT_DONE, requirement, - () -> simpleFormat - .format(requirement.getTotal(player) - requirement.getRemaining(player))); - } - } catch (NumberFormatException ignored) { - } - } - return builder; - } - - private void replaceRequirements(MessageBuilder builder, Variable variable, Requirement requirement, Supplier value) { - try { - builder.replace(variable + " " + requirement.getFullName(), value.get()); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public MessageBuilder getMessage(CommandSender player, Message message, Rank oldRank, Rank rankName) { - String oldRankName; - if (oldRank instanceof Prestige && oldRank.getRank() == null) { - oldRankName = ((Prestige) oldRank).getFrom(); - } else { - oldRankName = oldRank.getRank(); - } - - return replaceMoneyRequirements(getMessage(oldRank, message) - .replaceRanks(player, rankName.getRank()) - .replace(Variable.OLD_RANK, oldRankName), player, oldRank) - .replaceFromTo(oldRank); - } - - public void sendHeaderFooter(CommandSender sender, Rank rank, Message type) { - MessageBuilder builder; - if (rank == null) { - builder = getMessage(type) - .failIfEmpty() - .replace(Variable.PLAYER, sender.getName()); - } else { - builder = getMessage(rank, type) - .failIfEmpty() - .replaceRanks(sender, rank.getRank()) - .replaceFromTo(rank); - } - builder.send(sender); - } -} +package sh.okx.rankup; + +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.InventoryView; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.plugin.java.JavaPluginLoader; +import sh.okx.rankup.commands.*; +import sh.okx.rankup.economy.Economy; +import sh.okx.rankup.economy.EconomyProvider; +import sh.okx.rankup.economy.VaultEconomyProvider; +import sh.okx.rankup.gui.Gui; +import sh.okx.rankup.gui.GuiListener; +import sh.okx.rankup.hook.GroupProvider; +import sh.okx.rankup.hook.PermissionManager; +import sh.okx.rankup.hook.VaultPermissionManager; +import sh.okx.rankup.messages.Message; +import sh.okx.rankup.messages.MessageBuilder; +import sh.okx.rankup.messages.NullMessageBuilder; +import sh.okx.rankup.messages.Variable; +import sh.okx.rankup.placeholders.Placeholders; +import sh.okx.rankup.prestige.Prestige; +import sh.okx.rankup.prestige.Prestiges; +import sh.okx.rankup.ranks.Rank; +import sh.okx.rankup.ranks.RankList; +import sh.okx.rankup.ranks.Rankups; +import sh.okx.rankup.requirements.Requirement; +import sh.okx.rankup.requirements.RequirementRegistry; +import sh.okx.rankup.requirements.requirement.XpLevelDeductibleRequirement; +import sh.okx.rankup.requirements.requirement.*; +import sh.okx.rankup.requirements.requirement.advancedachievements.AdvancedAchievementsAchievementRequirement; +import sh.okx.rankup.requirements.requirement.advancedachievements.AdvancedAchievementsTotalRequirement; +import sh.okx.rankup.requirements.requirement.mcmmo.McMMOPowerLevelRequirement; +import sh.okx.rankup.requirements.requirement.mcmmo.McMMOSkillRequirement; +import sh.okx.rankup.requirements.requirement.tokenmanager.TokensDeductibleRequirement; +import sh.okx.rankup.requirements.requirement.tokenmanager.TokensRequirement; +import sh.okx.rankup.requirements.requirement.towny.*; +import sh.okx.rankup.requirements.requirement.votingplugin.VotingPluginPointsDeductibleRequirement; +import sh.okx.rankup.requirements.requirement.votingplugin.VotingPluginPointsRequirement; +import sh.okx.rankup.requirements.requirement.votingplugin.VotingPluginVotesRequirement; +import sh.okx.rankup.util.UpdateNotifier; +import sh.okx.rankup.util.VersionChecker; + +import java.io.File; +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +public class RankupPlugin extends JavaPlugin { + + public static final int CONFIG_VERSION = 8; + + @Getter + private GroupProvider permissions; + @Getter + private Economy economy; + /** + * The registry for listing the requirements to /rankup. + */ + @Getter + private RequirementRegistry requirements; + @Getter + private FileConfiguration messages; + @Getter + private FileConfiguration config; + @Getter + private Rankups rankups; + @Getter + private Prestiges prestiges; + @Getter + private Placeholders placeholders; + @Getter + private RankupHelper helper; + protected AutoRankup autoRankup = new AutoRankup(this); + private String errorMessage; + private PermissionManager permissionManager = new VaultPermissionManager(this); + private EconomyProvider economyProvider = new VaultEconomyProvider(); + + public RankupPlugin() { + super(); + } + + protected RankupPlugin(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file, PermissionManager permissionManager, EconomyProvider economyProvider) { + super(loader, description, dataFolder, file); + this.permissionManager = permissionManager; + this.economyProvider = economyProvider; + } + + @Override + public void onEnable() { + UpdateNotifier notifier = new UpdateNotifier(new VersionChecker(this)); + + reload(true); + + if (System.getProperty("TEST") == null) { + Metrics metrics = new Metrics(this); + metrics.addCustomChart(new Metrics.SimplePie("confirmation", + () -> config.getString("confirmation-type", "unknown"))); + metrics.addCustomChart(new Metrics.AdvancedPie("requirements", () -> { + Map map = new HashMap<>(); + addAll(map, rankups); + if (prestiges != null) { + addAll(map, prestiges); + } + return map; + })); + metrics.addCustomChart(new Metrics.SimplePie("prestige", + () -> config.getBoolean("prestige") ? "enabled" : "disabled")); + metrics.addCustomChart(new Metrics.SimplePie("permission-rankup", + () -> config.getBoolean("permission-rankup") ? "enabled" : "disabled")); + metrics.addCustomChart(new Metrics.SimplePie("notify-update", + () -> config.getBoolean("notify-update") ? "enabled" : "disabled")); + } + + if (config.getBoolean("ranks")) { + getCommand("ranks").setExecutor(new RanksCommand(this)); + } + if (config.getBoolean("prestige")) { + getCommand("prestige").setExecutor(new PrestigeCommand(this)); + if (config.getBoolean("prestiges")) { + getCommand("prestiges").setExecutor(new PrestigesCommand(this)); + } + } + if (config.getBoolean("max-rankup.enabled")) { + getCommand("maxrankup").setExecutor(new MaxRankupCommand(this)); + } + + getCommand("rankup").setExecutor(new RankupCommand(this)); + getCommand("rankup3").setExecutor(new InfoCommand(this, notifier)); + getServer().getPluginManager().registerEvents(new GuiListener(this), this); + getServer().getPluginManager().registerEvents( + new JoinUpdateNotifier(notifier, () -> getConfig().getBoolean("notify-update"), "rankup.notify"), this); + + placeholders = new Placeholders(this); + placeholders.register(); + } + + + @Override + public void onDisable() { + closeInventories(); + if (placeholders != null) { + placeholders.unregister(); + } + } + + public void reload(boolean init) { + errorMessage = null; + + config = loadConfig("config.yml"); + + if (config.getBoolean("permission-rankup")) { + permissions = permissionManager.permissionOnlyProvider(); + } else { + permissions = permissionManager.findPermissionProvider(); + if (permissions == null) { + errorMessage = "No permission plugin found"; + } + } + + setupEconomy(); + + closeInventories(); + loadConfigs(init); + + long time = (long) (config.getDouble("autorankup-interval") * 60 * 20); + if (time > 0) { + try { + if (!autoRankup.isCancelled()) { + autoRankup.cancel(); + } + } catch (IllegalStateException ignored) { + } + autoRankup.runTaskTimer(this, time, time); + } + + if (config.getInt("version") < CONFIG_VERSION) { + getLogger().severe("You are using an outdated config!"); + getLogger().severe("This means that some things might not work!"); + getLogger().severe("To update, please rename ALL your config files (or the folder they are in),"); + getLogger().severe("and run /pru reload to generate a new config file."); + getLogger().severe("If that does not work, restart your server."); + getLogger().severe("You may then copy in your config values manually from the old config."); + getLogger().severe("Check the changelog on the Rankup spigot page to see the changes."); + getLogger().severe("https://www.spigotmc.org/resources/rankup.76964/updates"); + } + + helper = new RankupHelper(this); + } + + public boolean error() { + return error(null); + } + + /** + * Notify the player of an error if there is one + * + * @return true if there was an error and action was taken + */ + public boolean error(CommandSender sender) { + if (errorMessage == null) { + return false; + } + + if (sender instanceof Player) { + sender.sendMessage( + ChatColor.RED + "Could not load Rankup, check console for more information."); + } else { + getLogger().severe("Failed to load Rankup"); + } + for (String line : errorMessage.split("\n")) { + getLogger().severe(line); + } + getLogger().severe("More information can be found in the console log at startup"); + return true; + } + + private void addAll(Map map, RankList ranks) { + for (Rank rank : ranks.getTree()) { + for (Requirement requirement : rank.getRequirements().getRequirements(null)) { + String name = requirement.getName(); + map.put(name, map.getOrDefault(name, 0) + 1); + } + } + } + + /** + * Closes all rankup inventories on disable so players cannot grab items from the inventory on a + * plugin reload. + */ + private void closeInventories() { + for (Player player : Bukkit.getOnlinePlayers()) { + InventoryView view = player.getOpenInventory(); + if (view.getType() == InventoryType.CHEST + && view.getTopInventory().getHolder() instanceof Gui) { + player.closeInventory(); + } + } + } + + private void loadConfigs(boolean init) { + saveLocales(); + + String locale = config.getString("locale", "en"); + File localeFile = new File(new File(getDataFolder(), "locale"), locale + ".yml"); + messages = YamlConfiguration.loadConfiguration(localeFile); + + if (init) { + Bukkit.getScheduler().runTask(this, () -> { + refreshRanks(); + error(); + }); + } else { + refreshRanks(); + } + } + + public void refreshRanks() { + try { + registerRequirements(); + Bukkit.getPluginManager().callEvent(new RankupRegisterEvent(this)); + + if (config.getBoolean("prestige")) { + prestiges = new Prestiges(this, loadConfig("prestiges.yml")); +// prestiges.getOrderedList(); + } else { + prestiges = null; + } + + rankups = new Rankups(this, loadConfig("rankups.yml")); + // check rankups are not in an infinite loop +// rankups.getOrderedList(); + + + + } catch (Exception e) { + this.errorMessage = e.getClass().getName() + ": " + e.getMessage(); + e.printStackTrace(); + } + } + + private void saveLocales() { + saveLocale("en"); + saveLocale("pt_br"); + saveLocale("ru"); + saveLocale("zh_cn"); + saveLocale("fr"); + } + + private void saveLocale(String locale) { + String name = "locale/" + locale + ".yml"; + File file = new File(getDataFolder(), name); + if (!file.exists()) { + saveResource(name, false); + } + } + + private FileConfiguration loadConfig(String name) { + File file = new File(getDataFolder(), name); + if (!file.exists()) { + saveResource(name, false); + } + return YamlConfiguration.loadConfiguration(file); + } + + private void registerRequirements() { + requirements = new RequirementRegistry(); + requirements.addRequirements( + new XpLevelRequirement(this, "xp-levelh"), + new XpLevelDeductibleRequirement(this, "xp-level"), + new PlaytimeMinutesRequirement(this), + new AdvancementRequirement(this), + new GroupRequirement(this), + new PermissionRequirement(this), + new PlaceholderRequirement(this), + new WorldRequirement(this), + new BlockBreakRequirement(this), + new PlayerKillsRequirement(this), + new MobKillsRequirement(this), + new ItemRequirement(this, "itemh"), + new ItemDeductibleRequirement(this, "item"), + new UseItemRequirement(this), + new TotalMobKillsRequirement(this), + new CraftItemRequirement(this)); + if (economy != null) { + requirements.addRequirements( + new MoneyRequirement(this, "moneyh"), + new MoneyDeductibleRequirement(this, "money")); + } + + PluginManager pluginManager = Bukkit.getPluginManager(); + if (pluginManager.isPluginEnabled("mcMMO")) { + requirements.addRequirements( + new McMMOSkillRequirement(this), + new McMMOPowerLevelRequirement(this)); + } + if (pluginManager.isPluginEnabled("AdvancedAchievements")) { + requirements.addRequirements( + new AdvancedAchievementsAchievementRequirement(this), + new AdvancedAchievementsTotalRequirement(this)); + } + if (pluginManager.isPluginEnabled("VotingPlugin")) { + requirements.addRequirements( + new VotingPluginVotesRequirement(this), + new VotingPluginPointsRequirement(this, "votingplugin-pointsh"), + new VotingPluginPointsDeductibleRequirement(this, "votingplugin-points")); + } + if (Bukkit.getPluginManager().isPluginEnabled("Towny")) { + requirements.addRequirements( + new TownyResidentRequirement(this), + new TownyMayorRequirement(this), + new TownyMayorNumberResidentsRequirement(this), + new TownyKingRequirement(this), + new TownyKingNumberResidentsRequirement(this), + new TownyKingNumberTownsRequirement(this)); + } + if (Bukkit.getPluginManager().isPluginEnabled("TokenManager")) { + requirements.addRequirements( + new TokensRequirement(this, "tokenmanager-tokensh"), + new TokensDeductibleRequirement(this, "tokenmanager-tokens")); + } + } + private void setupEconomy() { + economy = economyProvider.getEconomy(); + } + + public String formatMoney(double money) { + List shortened = config.getStringList("shorten"); + String suffix = ""; + + for (int i = shortened.size(); i > 0; i--) { + double value = Math.pow(10, 3 * i); + if (money >= value) { + money /= value; + suffix = shortened.get(i - 1); + break; + } + } + + return placeholders.getMoneyFormat().format(money) + suffix; + } + + public ConfigurationSection getSection(Rank rank, String path) { + ConfigurationSection rankSection = rank.getSection(); + if (rankSection == null || !rankSection.isConfigurationSection(path)) { + return this.messages.getConfigurationSection(path); + } + return rankSection.getConfigurationSection(path); + } + + public MessageBuilder getMessage(Rank rank, Message message) { + ConfigurationSection messages = rank.getSection(); + if (messages == null || !messages.isSet(message.getName())) { + messages = this.messages; + } + return MessageBuilder.of(messages, message); + } + + public MessageBuilder getMessage(Message message) { + return MessageBuilder.of(messages, message); + } + + public MessageBuilder replaceMoneyRequirements(MessageBuilder builder, CommandSender sender, + Rank rank) { + if (builder instanceof NullMessageBuilder) { + return builder; + } + + Requirement money = rank.getRequirement(sender instanceof Player ? (Player) sender : null, "money"); + if (money != null) { + Double amount = null; + if (sender instanceof Player && rank.isIn((Player) sender)) { + if (economy != null) { + amount = money.getRemaining((Player) sender); + } + } else { + amount = money.getValueDouble(); + } + if (amount != null && economy != null) { + builder.replace(Variable.MONEY_NEEDED, formatMoney(amount)); + builder.replace(Variable.MONEY, formatMoney(money.getValueDouble())); + } + } + if (sender instanceof Player) { + replaceRequirements(builder, (Player) sender, rank); + } + return builder; + } + + public MessageBuilder replaceRequirements(MessageBuilder builder, Player player, Rank rank) { + DecimalFormat simpleFormat = placeholders.getSimpleFormat(); + DecimalFormat percentFormat = placeholders.getPercentFormat(); + for (Requirement requirement : rank.getRequirements().getRequirements(player)) { + try { + replaceRequirements(builder, Variable.AMOUNT, requirement, + () -> simpleFormat.format(requirement.getTotal(player))); + if (rank.isIn(player)) { + replaceRequirements(builder, Variable.AMOUNT_NEEDED, requirement, + () -> simpleFormat.format(requirement.getRemaining(player))); + replaceRequirements(builder, Variable.PERCENT_LEFT, requirement, + () -> percentFormat.format(Math.max(0, + (requirement.getRemaining(player) / requirement.getTotal(player)) * 100))); + replaceRequirements(builder, Variable.PERCENT_DONE, requirement, + () -> percentFormat.format(Math.min(100, + (1 - (requirement.getRemaining(player) / requirement.getTotal(player))) * 100))); + replaceRequirements(builder, Variable.AMOUNT_DONE, requirement, + () -> simpleFormat + .format(requirement.getTotal(player) - requirement.getRemaining(player))); + } + } catch (NumberFormatException ignored) { + } + } + return builder; + } + + private void replaceRequirements(MessageBuilder builder, Variable variable, Requirement requirement, Supplier value) { + try { + builder.replace(variable + " " + requirement.getFullName(), value.get()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public MessageBuilder getMessage(CommandSender player, Message message, Rank oldRank, Rank rankName) { + String oldRankName; + if (oldRank instanceof Prestige && oldRank.getRank() == null) { + oldRankName = ((Prestige) oldRank).getFrom(); + } else { + oldRankName = oldRank.getRank(); + } + + return replaceMoneyRequirements(getMessage(oldRank, message) + .replaceRanks(player, rankName.getRank()) + .replace(Variable.OLD_RANK, oldRankName), player, oldRank) + .replaceFromTo(oldRank); + } + + public void sendHeaderFooter(CommandSender sender, Rank rank, Message type) { + MessageBuilder builder; + if (rank == null) { + builder = getMessage(type) + .failIfEmpty() + .replace(Variable.PLAYER, sender.getName()); + } else { + builder = getMessage(rank, type) + .failIfEmpty() + .replaceRanks(sender, rank.getRank()) + .replaceFromTo(rank); + } + builder.send(sender); + } +} diff --git a/src/main/java/sh/okx/rankup/commands/InfoCommand.java b/src/main/java/sh/okx/rankup/commands/InfoCommand.java index 191db2c..07a360f 100644 --- a/src/main/java/sh/okx/rankup/commands/InfoCommand.java +++ b/src/main/java/sh/okx/rankup/commands/InfoCommand.java @@ -1,253 +1,259 @@ -package sh.okx.rankup.commands; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabExecutor; -import org.bukkit.entity.Player; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.util.StringUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import sh.okx.rankup.RankupPlugin; -import sh.okx.rankup.prestige.Prestige; -import sh.okx.rankup.prestige.Prestiges; -import sh.okx.rankup.ranks.Rank; -import sh.okx.rankup.ranks.RankElement; -import sh.okx.rankup.ranks.Rankups; -import sh.okx.rankup.util.UpdateNotifier; - -import java.util.*; - -public class InfoCommand implements TabExecutor { - private final RankupPlugin plugin; - - private final UpdateNotifier notifier; - - public InfoCommand(RankupPlugin plugin, UpdateNotifier notifier) { - this.plugin = plugin; - this.notifier = notifier; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (args.length > 0) { - if (args[0].equalsIgnoreCase("reload") && sender.hasPermission("rankup.reload")) { - plugin.reload(false); - if (!plugin.error(sender)) { - sender.sendMessage(ChatColor.GREEN + "" + ChatColor.BOLD + "Rankup " + ChatColor.YELLOW + "Reloaded configuration files."); - } - return true; - } else if (args[0].equalsIgnoreCase("forcerankup") && sender.hasPermission("rankup.force")) { - if (args.length < 2) { - sender.sendMessage(ChatColor.YELLOW + "Usage: /" + label + " forcerankup "); - return true; - } - - Player player = Bukkit.getPlayer(args[1]); - if (player == null) { - sender.sendMessage(ChatColor.YELLOW + "Player not found."); - return true; - } - - Rankups rankups = plugin.getRankups(); - RankElement rankElement = rankups.getByPlayer(player); - if (rankElement == null) { - sender.sendMessage(ChatColor.YELLOW + "That player is not in any rankup groups."); - return true; - } else if (!rankElement.hasNext()) { - sender.sendMessage(ChatColor.YELLOW + "That player is at the last rank."); - return true; - } - - Rank rank = rankElement.getRank(); - - plugin.getHelper().doRankup(player, rankElement); - plugin.getHelper().sendRankupMessages(player, rankElement); - sender.sendMessage(ChatColor.GREEN + "Successfully forced " - + ChatColor.GOLD + player.getName() - + ChatColor.GREEN + " to rankup from " + ChatColor.GOLD + rank.getRank() - + ChatColor.GREEN + " to " + ChatColor.GOLD + rank.getNext()); - return true; - } else if (args[0].equalsIgnoreCase("forceprestige") && sender.hasPermission("rankup.force")) { - if (plugin.getPrestiges() == null) { - sender.sendMessage(ChatColor.RED + "Prestige is disabled."); - return true; - } - - if (args.length < 2) { - sender.sendMessage(ChatColor.YELLOW + "Usage: /" + label + " forceprestige "); - return true; - } - - Player player = Bukkit.getPlayer(args[1]); - if (player == null) { - sender.sendMessage(ChatColor.YELLOW + "Player not found."); - return true; - } - - Prestiges prestiges = plugin.getPrestiges(); - RankElement rankElement = prestiges.getByPlayer(player); - if (!rankElement.hasNext()) { - sender.sendMessage(ChatColor.YELLOW + "That player is at the last prestige."); - return true; - } - - Prestige prestige = rankElement.getRank(); - if (prestige == null) { - sender.sendMessage(ChatColor.YELLOW + "That player is not in any prestige groups."); - return true; - } - - plugin.getHelper().doPrestige(player, rankElement); - plugin.getHelper().sendPrestigeMessages(player, rankElement); - sender.sendMessage(ChatColor.GREEN + "Successfully forced " - + ChatColor.GOLD + player.getName() - + ChatColor.GREEN + " to prestige " - + ChatColor.GOLD + prestige.getRank() - + ChatColor.GREEN + " from " + ChatColor.GOLD + prestige.getFrom() - + ChatColor.GREEN + " to " + ChatColor.GOLD + prestige.getTo()); - return true; - } else if(args[0].equalsIgnoreCase("rankdown") && sender.hasPermission("rankup.force")) { - if (args.length < 2) { - sender.sendMessage(ChatColor.YELLOW + "Usage: /" + label + " rankdown "); - return true; - } - - Player player = Bukkit.getPlayer(args[1]); - if (player == null) { - sender.sendMessage(ChatColor.YELLOW + "Player not found."); - return true; - } - - RankElement currentRankElement = plugin.getRankups().getByPlayer(player); - if (currentRankElement == null) { - sender.sendMessage(ChatColor.YELLOW + "That player is not in any rankup groups."); - return true; - } - Rank currentRank = currentRankElement.getRank(); - - if (plugin.getRankups().getFirst().equals(currentRank)) { - sender.sendMessage(ChatColor.YELLOW + "That player is in the first rank and cannot be ranked down."); - - } - - RankElement prevRankElement = plugin.getRankups().getTree().getFirst(); - while(prevRankElement.hasNext() && !prevRankElement.getNext().getRank().equals(currentRank)) { - prevRankElement = prevRankElement.getNext(); - } - - if (!prevRankElement.hasNext()) { - sender.sendMessage(ChatColor.YELLOW + "Could not match previous rank."); - } - Rank prevRank = prevRankElement.getRank(); - - if (prevRankElement.getRank() != null) { - plugin.getPermissions().removeGroup(player.getUniqueId(), currentRank.getRank()); - } - plugin.getPermissions().addGroup(player.getUniqueId(), prevRank.getRank()); - - sender.sendMessage(ChatColor.GREEN + "Successfully forced " - + ChatColor.GOLD + player.getName() - + ChatColor.GREEN + " to rank down from " + ChatColor.GOLD + currentRank.getRank() - + ChatColor.GREEN + " to " + ChatColor.GOLD + prevRank.getRank()); - return true; - } else if (args[0].equalsIgnoreCase("placeholders") && sender.hasPermission("rankup.admin")) { - sender.sendMessage("--- Rankup placeholders ---"); - if (args.length > 1 && args[1].equalsIgnoreCase("status")) { - for (Rank rank : plugin.getRankups().getTree()) { - String placeholder = "status_" + rank.getRank(); - sender.sendMessage(placeholder + ": " + plugin.getPlaceholders().getExpansion().placeholder(sender instanceof Player ? (Player) sender : null, placeholder)); - } - return true; - } - - String[] placeholders = new String[] { - "prestige_money", - "prestige_money_formatted", - "prestige_percent_left_formatted", - "prestige_percent_done_formatted", - "money_formatted", - "money_left_formatted", - "percent_left_formatted", - "percent_done_formatted", - "current_prestige", - "next_prestige", - "current_rank", - "next_rank", - }; - for (String placeholder : placeholders) { - sender.sendMessage(placeholder + ": " + plugin.getPlaceholders().getExpansion().placeholder(sender instanceof Player ? (Player) sender : null, placeholder)); - } - return true; - } else if (args[0].equalsIgnoreCase("tree") && sender.hasPermission("rankup.admin")) { - RankElement element = plugin.getRankups().getTree().getFirst(); - while (element.hasNext()) { - Rank rank = element.getRank(); - RankElement next = element.getNext(); - Rank nextRank = next.getRank(); - sender.sendMessage(rank.getRank() + " (" + rank.getNext() + ") -> " + nextRank.getRank() + " (" + nextRank.getNext() + ")"); - element = next; - } - return true; - } - } - - PluginDescriptionFile description = plugin.getDescription(); - String version = description.getVersion(); - sender.sendMessage( - ChatColor.GREEN + "" + ChatColor.BOLD + description.getName() + " " + version + - ChatColor.YELLOW + " by " + ChatColor.BLUE + ChatColor.BOLD + String.join(", ", description.getAuthors())); - if (sender.hasPermission("rankup.reload")) { - sender.sendMessage(ChatColor.GREEN + "/" + label + " reload " + ChatColor.YELLOW + "Reloads configuration files."); - } - if (sender.hasPermission("rankup.force")) { - sender.sendMessage(ChatColor.GREEN + "/" + label + " forcerankup " + ChatColor.YELLOW + "Force a player to rankup, bypassing requirements."); - if (plugin.getPrestiges() != null) { - sender.sendMessage( - ChatColor.GREEN + "/" + label + " forceprestige " + ChatColor.YELLOW - + "Force a player to prestige, bypassing requirements."); - } - } - - if (sender.hasPermission("rankup.checkversion")) { - notifier.notify(sender, false); - } - - return true; - } - - @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { - if (args.length == 1) { - List list = new ArrayList<>(); - if (sender.hasPermission("rankup.reload")) { - list.add("reload"); - } - if (sender.hasPermission("rankup.force")) { - list.add("forcerankup"); - list.add("forceprestige"); - list.add("rankdown"); - } - return StringUtil.copyPartialMatches(args[0], list, new ArrayList<>()); - } else if (args.length == 2) { - if (args[0].equalsIgnoreCase("forcerankup") && sender.hasPermission("rankup.force")) { - return StringUtil.copyPartialMatches(args[1], players(), new ArrayList<>()); - } else if (args[0].equalsIgnoreCase("forceprestige") && sender.hasPermission("rankup.force")) { - return StringUtil.copyPartialMatches(args[1], players(), new ArrayList<>()); - } else if (args[0].equalsIgnoreCase("rankdown") && sender.hasPermission("rankup.force")) { - return StringUtil.copyPartialMatches(args[1], players(), new ArrayList<>()); - } - } - return Collections.emptyList(); - } - - private Iterable players() { - Set players = new HashSet<>(); - for (Player player : Bukkit.getOnlinePlayers()) { - players.add(player.getName()); - } - return players; - } -} +package sh.okx.rankup.commands; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.bukkit.entity.Player; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.util.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import sh.okx.rankup.RankupPlugin; +import sh.okx.rankup.prestige.Prestige; +import sh.okx.rankup.prestige.Prestiges; +import sh.okx.rankup.ranks.Rank; +import sh.okx.rankup.ranks.RankElement; +import sh.okx.rankup.ranks.Rankups; +import sh.okx.rankup.util.UpdateNotifier; + +import java.util.*; + +public class InfoCommand implements TabExecutor { + private final RankupPlugin plugin; + + private final UpdateNotifier notifier; + + public InfoCommand(RankupPlugin plugin, UpdateNotifier notifier) { + this.plugin = plugin; + this.notifier = notifier; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length > 0) { + if (args[0].equalsIgnoreCase("reload") && sender.hasPermission("rankup.reload")) { + plugin.reload(false); + if (!plugin.error(sender)) { + sender.sendMessage(ChatColor.GREEN + "" + ChatColor.BOLD + "Rankup " + ChatColor.YELLOW + "Reloaded configuration files."); + } + return true; + } else if (args[0].equalsIgnoreCase("forcerankup") && sender.hasPermission("rankup.force")) { + if (args.length < 2) { + sender.sendMessage(ChatColor.YELLOW + "Usage: /" + label + " forcerankup "); + return true; + } + + Player player = Bukkit.getPlayer(args[1]); + if (player == null) { + sender.sendMessage(ChatColor.YELLOW + "Player not found."); + return true; + } + + Rankups rankups = plugin.getRankups(); + RankElement rankElement = rankups.getByPlayer(player); + if (rankElement == null) { + sender.sendMessage(ChatColor.YELLOW + "That player is not in any rankup groups."); + return true; + } else if (!rankElement.hasNext()) { + sender.sendMessage(ChatColor.YELLOW + "That player is at the last rank."); + return true; + } + + Rank rank = rankElement.getRank(); + + plugin.getHelper().doRankup(player, rankElement); + plugin.getHelper().sendRankupMessages(player, rankElement); + sender.sendMessage(ChatColor.GREEN + "Successfully forced " + + ChatColor.GOLD + player.getName() + + ChatColor.GREEN + " to rankup from " + ChatColor.GOLD + rank.getRank() + + ChatColor.GREEN + " to " + ChatColor.GOLD + rank.getNext()); + return true; + } else if (args[0].equalsIgnoreCase("forceprestige") && sender.hasPermission("rankup.force")) { + if (plugin.getPrestiges() == null) { + sender.sendMessage(ChatColor.RED + "Prestige is disabled."); + return true; + } + + if (args.length < 2) { + sender.sendMessage(ChatColor.YELLOW + "Usage: /" + label + " forceprestige "); + return true; + } + + Player player = Bukkit.getPlayer(args[1]); + if (player == null) { + sender.sendMessage(ChatColor.YELLOW + "Player not found."); + return true; + } + + Prestiges prestiges = plugin.getPrestiges(); + RankElement rankElement = prestiges.getByPlayer(player); + if (!rankElement.hasNext()) { + sender.sendMessage(ChatColor.YELLOW + "That player is at the last prestige."); + return true; + } + + Prestige prestige = rankElement.getRank(); + if (prestige == null) { + sender.sendMessage(ChatColor.YELLOW + "That player is not in any prestige groups."); + return true; + } + + plugin.getHelper().doPrestige(player, rankElement); + plugin.getHelper().sendPrestigeMessages(player, rankElement); + sender.sendMessage(ChatColor.GREEN + "Successfully forced " + + ChatColor.GOLD + player.getName() + + ChatColor.GREEN + " to prestige " + + ChatColor.GOLD + prestige.getRank() + + ChatColor.GREEN + " from " + ChatColor.GOLD + prestige.getFrom() + + ChatColor.GREEN + " to " + ChatColor.GOLD + prestige.getTo()); + return true; + } else if(args[0].equalsIgnoreCase("rankdown") && sender.hasPermission("rankup.force")) { + if (args.length < 2) { + sender.sendMessage(ChatColor.YELLOW + "Usage: /" + label + " rankdown "); + return true; + } + + Player player = Bukkit.getPlayer(args[1]); + if (player == null) { + sender.sendMessage(ChatColor.YELLOW + "Player not found."); + return true; + } + + RankElement currentRankElement = plugin.getRankups().getByPlayer(player); + if (currentRankElement == null) { + sender.sendMessage(ChatColor.YELLOW + "That player is not in any rankup groups."); + return true; + } + Rank currentRank = currentRankElement.getRank(); + + if (plugin.getRankups().getFirst().equals(currentRank)) { + sender.sendMessage(ChatColor.YELLOW + "That player is in the first rank and cannot be ranked down."); + + } + + RankElement prevRankElement = plugin.getRankups().getTree().getFirst(); + while(prevRankElement.hasNext() && !prevRankElement.getNext().getRank().equals(currentRank)) { + prevRankElement = prevRankElement.getNext(); + } + + if (!prevRankElement.hasNext()) { + sender.sendMessage(ChatColor.YELLOW + "Could not match previous rank."); + } + Rank prevRank = prevRankElement.getRank(); + + if (prevRankElement.getRank() != null) { + plugin.getPermissions().removeGroup(player.getUniqueId(), currentRank.getRank()); + } + plugin.getPermissions().addGroup(player.getUniqueId(), prevRank.getRank()); + + sender.sendMessage(ChatColor.GREEN + "Successfully forced " + + ChatColor.GOLD + player.getName() + + ChatColor.GREEN + " to rank down from " + ChatColor.GOLD + currentRank.getRank() + + ChatColor.GREEN + " to " + ChatColor.GOLD + prevRank.getRank()); + return true; + } else if (args[0].equalsIgnoreCase("placeholders") && sender.hasPermission("rankup.admin")) { + sender.sendMessage("--- Rankup placeholders ---"); + if (args.length > 1 && args[1].equalsIgnoreCase("status")) { + for (Rank rank : plugin.getRankups().getTree()) { + String placeholder = "status_" + rank.getRank(); + sender.sendMessage(placeholder + ": " + plugin.getPlaceholders().getExpansion().placeholder(sender instanceof Player ? (Player) sender : null, placeholder)); + } + return true; + } + + String[] placeholders = new String[] { + "prestige_money", + "prestige_money_formatted", + "prestige_percent_left_formatted", + "prestige_percent_done_formatted", + "money_formatted", + "money_left_formatted", + "percent_left_formatted", + "percent_done_formatted", + "current_prestige", + "next_prestige", + "current_rank", + "next_rank", + }; + for (String placeholder : placeholders) { + String result; + try { + result = plugin.getPlaceholders().getExpansion().placeholder(sender instanceof Player ? (Player) sender : null, placeholder); + } catch (Exception e) { + result = e.getClass().getSimpleName() + ", " + e.getMessage(); + } + sender.sendMessage(placeholder + ": " + result); + } + return true; + } else if (args[0].equalsIgnoreCase("tree") && sender.hasPermission("rankup.admin")) { + RankElement element = plugin.getRankups().getTree().getFirst(); + while (element.hasNext()) { + Rank rank = element.getRank(); + RankElement next = element.getNext(); + Rank nextRank = next.getRank(); + sender.sendMessage(rank.getRank() + " (" + rank.getNext() + ") -> " + nextRank.getRank() + " (" + nextRank.getNext() + ")"); + element = next; + } + return true; + } + } + + PluginDescriptionFile description = plugin.getDescription(); + String version = description.getVersion(); + sender.sendMessage( + ChatColor.GREEN + "" + ChatColor.BOLD + description.getName() + " " + version + + ChatColor.YELLOW + " by " + ChatColor.BLUE + ChatColor.BOLD + String.join(", ", description.getAuthors())); + if (sender.hasPermission("rankup.reload")) { + sender.sendMessage(ChatColor.GREEN + "/" + label + " reload " + ChatColor.YELLOW + "Reloads configuration files."); + } + if (sender.hasPermission("rankup.force")) { + sender.sendMessage(ChatColor.GREEN + "/" + label + " forcerankup " + ChatColor.YELLOW + "Force a player to rankup, bypassing requirements."); + if (plugin.getPrestiges() != null) { + sender.sendMessage( + ChatColor.GREEN + "/" + label + " forceprestige " + ChatColor.YELLOW + + "Force a player to prestige, bypassing requirements."); + } + } + + if (sender.hasPermission("rankup.checkversion")) { + notifier.notify(sender, false); + } + + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + List list = new ArrayList<>(); + if (sender.hasPermission("rankup.reload")) { + list.add("reload"); + } + if (sender.hasPermission("rankup.force")) { + list.add("forcerankup"); + list.add("forceprestige"); + list.add("rankdown"); + } + return StringUtil.copyPartialMatches(args[0], list, new ArrayList<>()); + } else if (args.length == 2) { + if (args[0].equalsIgnoreCase("forcerankup") && sender.hasPermission("rankup.force")) { + return StringUtil.copyPartialMatches(args[1], players(), new ArrayList<>()); + } else if (args[0].equalsIgnoreCase("forceprestige") && sender.hasPermission("rankup.force")) { + return StringUtil.copyPartialMatches(args[1], players(), new ArrayList<>()); + } else if (args[0].equalsIgnoreCase("rankdown") && sender.hasPermission("rankup.force")) { + return StringUtil.copyPartialMatches(args[1], players(), new ArrayList<>()); + } + } + return Collections.emptyList(); + } + + private Iterable players() { + Set players = new HashSet<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + players.add(player.getName()); + } + return players; + } +} diff --git a/src/main/java/sh/okx/rankup/placeholders/RankupExpansion.java b/src/main/java/sh/okx/rankup/placeholders/RankupExpansion.java index 8592731..2e56ce1 100644 --- a/src/main/java/sh/okx/rankup/placeholders/RankupExpansion.java +++ b/src/main/java/sh/okx/rankup/placeholders/RankupExpansion.java @@ -120,9 +120,9 @@ public class RankupExpansion implements Expansion { case "money_formatted": return plugin.formatMoney(getMoney(player, rank).doubleValue()); case "money_left": - return String.valueOf(Math.max(0, orElse(rank, r -> simplify(plugin.getEconomy().getBalance(player) - r.getRequirement(player, "money").getValueDouble()), 0).doubleValue())); + return String.valueOf(Math.max(0, orElse(rank, r -> simplify(r.getRequirement(player, "money").getValueDouble() - plugin.getEconomy().getBalance(player)), 0).doubleValue())); case "money_left_formatted": - return plugin.formatMoney(Math.max(0D, orElse(rank, r -> plugin.getEconomy().getBalance(player) - r.getRequirement(player, "money").getValueDouble(), 0D))); + return plugin.formatMoney(Math.max(0D, orElse(rank, r -> r.getRequirement(player, "money").getValueDouble() - plugin.getEconomy().getBalance(player), 0D))); case "percent_left": return String.valueOf(Math.max(0D, orElse(rank, r -> (1 - (plugin.getEconomy().getBalance(player) / r.getRequirement(player, "money").getValueDouble())) * 100, 0).doubleValue())); case "percent_left_formatted": diff --git a/src/test/java/sh/okx/rankup/RankupCommandTest.java b/src/test/java/sh/okx/rankup/RankupCommandTest.java new file mode 100644 index 0000000..5ddb358 --- /dev/null +++ b/src/test/java/sh/okx/rankup/RankupCommandTest.java @@ -0,0 +1,35 @@ +package sh.okx.rankup; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import be.seeseemelk.mockbukkit.entity.PlayerMock; +import org.junit.Test; + +public class RankupCommandTest extends RankupTest { + @Test + public void testPlaceholders() { + // placeholders command should never throw an exception + PlayerMock player = server.addPlayer(); + player.addAttachment(plugin, "rankup.admin", true); + plugin.getCommand("rankup3").execute(player, "pru", new String[] {"placeholders"}); + + player.assertSaid("--- Rankup placeholders ---"); + } + + @Test + public void testForce() { + // forcing rankup should change group and not affect money + + PlayerMock player = server.addPlayer(); + player.addAttachment(plugin, "rankup.force", true); + plugin.getEconomy().setPlayer(player, 11); + groupProvider.addGroup(player.getUniqueId(), "A"); + + plugin.getCommand("rankup3").execute(player, "pru", new String[] {"forcerankup", player.getName()}); + + assertTrue(groupProvider.inGroup(player.getUniqueId(), "B")); + assertEquals(11, plugin.getEconomy().getBalance(player), 0.0001); + } + +} diff --git a/src/test/java/sh/okx/rankup/RankupPlaceholderTest.java b/src/test/java/sh/okx/rankup/RankupPlaceholderTest.java index 59ed812..f5fd920 100644 --- a/src/test/java/sh/okx/rankup/RankupPlaceholderTest.java +++ b/src/test/java/sh/okx/rankup/RankupPlaceholderTest.java @@ -1,11 +1,11 @@ package sh.okx.rankup; +import static org.junit.Assert.assertEquals; + import be.seeseemelk.mockbukkit.entity.PlayerMock; import org.junit.Test; import sh.okx.rankup.placeholders.RankupExpansion; -import static org.junit.Assert.assertEquals; - public class RankupPlaceholderTest extends RankupTest { @Test public void testCurrentRank() { @@ -52,4 +52,24 @@ public class RankupPlaceholderTest extends RankupTest { RankupExpansion expansion = plugin.getPlaceholders().getExpansion(); assertEquals("Incomplete", expansion.placeholder(player, "status_b")); } + + @Test + public void testMoneyLeft() { + PlayerMock player = server.addPlayer(); + groupProvider.addGroup(player.getUniqueId(), "A"); + plugin.getEconomy().setPlayer(player, 900); + + RankupExpansion expansion = plugin.getPlaceholders().getExpansion(); + assertEquals("100.0", expansion.placeholder(player, "money_left")); + } + + @Test + public void testMoney() { + PlayerMock player = server.addPlayer(); + groupProvider.addGroup(player.getUniqueId(), "A"); + plugin.getEconomy().setPlayer(player, 900); + + RankupExpansion expansion = plugin.getPlaceholders().getExpansion(); + assertEquals("1000", expansion.placeholder(player, "money")); + } }