diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index b31c3fd..66b812d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -20,15 +20,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '21' distribution: 'temurin' cache: maven - - run: mvn clean install + - run: mvn clean install -U - run: mkdir artifact && cp target/*.jar artifact - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: Package path: artifact diff --git a/pom.xml b/pom.xml index 7580859..cb57a8a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.wasteofplastic mwmoney - 3.1 + 3.2 MultiWorldMoney MultiWorldMoney is a plugin that enables money to be kept separately across worlds @@ -26,7 +26,7 @@ UTF-8 UTF-8 - 17 + 21 1.7.4 @@ -45,12 +45,29 @@ + + + + com.github.multiversecore + multiverse-core + 9999.0.0-IGNORED + provided + + + * + * + + + + + + io.papermc.paper paper-api - 1.20.2-R0.1-SNAPSHOT + 1.21.8-R0.1-SNAPSHOT provided @@ -62,9 +79,9 @@ - com.github.multiversecore + org.mvplugins.multiverse.core multiverse-core - 4.3.12 + 5.1.2 provided @@ -121,7 +138,7 @@ org.apache.maven.plugins maven-clean-plugin - 3.3.1 + 3.3.2 org.apache.maven.plugins @@ -131,7 +148,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.12.1 17 @@ -139,7 +156,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.5 org.apache.maven.plugins diff --git a/src/main/java/com/wasteofplastic/multiworldmoney/AdminCommands.java b/src/main/java/com/wasteofplastic/multiworldmoney/AdminCommands.java index 4d739d9..084cfa1 100644 --- a/src/main/java/com/wasteofplastic/multiworldmoney/AdminCommands.java +++ b/src/main/java/com/wasteofplastic/multiworldmoney/AdminCommands.java @@ -1,219 +1,82 @@ package com.wasteofplastic.multiworldmoney; -import java.util.List; -import java.util.UUID; - +import net.milkbowl.vault.economy.Economy; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.mvplugins.multiverse.core.MultiverseCoreApi; +import org.mvplugins.multiverse.core.world.MultiverseWorld; -import com.onarandombox.MultiverseCore.api.MultiverseWorld; - -import net.milkbowl.vault.economy.EconomyResponse; - -class AdminCommands implements CommandExecutor { +import java.util.UUID; +public class AdminCommands implements CommandExecutor { private final MultiWorldMoney plugin; - /** - * @param plugin - plugin - */ public AdminCommands(MultiWorldMoney plugin) { this.plugin = plugin; } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player) { - // Check permission - if (plugin.getVh().checkPerm((Player) sender, "mwm.admin")) { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.noPermission); - return true; - } + if (!sender.hasPermission("mwm.admin")) { + sender.sendMessage(ChatColor.RED + "You don't have permission to use this command."); + return true; } - switch (args.length) { - case 1: - if (args[0].equalsIgnoreCase("reload")) { - plugin.reloadConfig(); - plugin.loadGroups(); - plugin.reloadLocale(); - sender.sendMessage(ChatColor.GREEN + Lang.reloaded); - return true; - } else { - printHelp(sender); - return true; - } - case 4: - // Check player name - UUID targetUUID = plugin.getPlayers().getUUID(args[1]); - Player target= plugin.getServer().getPlayer(targetUUID); - if (targetUUID == null || target == null) { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.noPlayer); - return true; - } - // Check amount - double amount; - try { - amount = Double.valueOf(args[2]); - } catch (Exception e) { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.unknownAmount); - return true; - } - // Round down to 2 dp's - amount = plugin.roundDown(amount, 2); - // Check world - World world = plugin.getServer().getWorld(args[3]); - if (world == null) { - // Try MV - if (plugin.getCore() != null) { - MultiverseWorld mvWorld = plugin.getCore().getMVWorldManager().getMVWorld(args[3]); - if (mvWorld == null) { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.unknownWorld); - return true; - } else { - // Found - world = mvWorld.getCBWorld(); - } - } else { - // No luck - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.unknownWorld); - return true; - } - } - // Get group worlds - List groupWorlds = plugin.getGroupWorlds(world); - if (args[0].equalsIgnoreCase("set")) { - if (groupWorlds.contains(target.getWorld())) { - // Set - double oldBalance = plugin.roundDown(plugin.getVh().getEcon().getBalance(target), 2); - if (oldBalance > amount) { - EconomyResponse er = plugin.getVh().getEcon().withdrawPlayer(target, oldBalance - amount); - if (!er.transactionSuccess()) { - // Cannot set - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + er.errorMessage); - return true; - } - } else if (oldBalance < amount) { - EconomyResponse er = plugin.getVh().getEcon().depositPlayer(target, amount - oldBalance); - if (!er.transactionSuccess()) { - // Cannot set - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + er.errorMessage); - return true; - } - } - } else { - if (amount < 0D) { - // It will - see if loans are allowed - double balance = plugin.getVh().getEcon().getBalance(target) - amount; - // Try to withdraw an amount and see what happens - EconomyResponse er = plugin.getVh().getEcon().withdrawPlayer(target, balance); - if (er.transactionSuccess()) { - // Put it back - plugin.getVh().getEcon().depositPlayer(target, balance); - } else { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + er.errorMessage); - return true; - } - } - plugin.getPlayers().setBalance(target, world, amount); - } - if (!sender.equals(target)) { - sender.sendMessage(ChatColor.GREEN + ((Lang.setBalanceTo - .replace("[name]", target.getName())) - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", plugin.getWorldName(world))); - } - target.sendMessage(ChatColor.GREEN + (Lang.yourBalanceSetTo - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", plugin.getWorldName(world))); - return true; - } else if (args[0].equalsIgnoreCase("take")) { - if (amount < 0D) { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.amountPositive); - return true; - } - if (groupWorlds.contains(target.getWorld())) { - // Same group - let the economy handle any loan issues - EconomyResponse er = plugin.getVh().getEcon().withdrawPlayer(target, amount); - if (!er.transactionSuccess()) { - // Cannot set - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + er.errorMessage); - return true; - } - } else { - // Not in the same group - // Check to see if loans are allowed - // Check to see if this will result in a negative balance - if (amount > plugin.getPlayers().getBalance(target, world)) { - // It will - see if loans are allowed - double balance = plugin.getVh().getEcon().getBalance(target) + amount - plugin.getPlayers().getBalance(target, world); - // Try to withdraw an amount and see what happens - EconomyResponse er = plugin.getVh().getEcon().withdrawPlayer(target, balance); - if (er.transactionSuccess()) { - // Put it back - plugin.getVh().getEcon().depositPlayer(target, balance); - } else { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + er.errorMessage); - return true; - } - } - plugin.getPlayers().withdraw(target, world, amount); - } - if (!sender.equals(target)) { - sender.sendMessage(ChatColor.GREEN + ((Lang.withdrew - .replace("[name]", target.getName())) - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", plugin.getWorldName(world))); - } - target.sendMessage(ChatColor.GREEN + (Lang.reduceBalance - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", plugin.getWorldName(world))); - return true; - } else if (args[0].equalsIgnoreCase("give")) { - if (amount < 0D) { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.amountPositive); - return true; - } - // Check which world the player is in - if (groupWorlds.contains(target.getWorld())) { - EconomyResponse er = plugin.getVh().getEcon().depositPlayer(target, amount); - if (!er.transactionSuccess()) { - // Cannot set - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + er.errorMessage); - return true; - } - } else { - plugin.getPlayers().deposit(target, world, amount); - } - if (!sender.equals(target)) { - sender.sendMessage(ChatColor.GREEN + ((Lang.deposited - .replace("[name]", target.getName())) - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", plugin.getWorldName(world))); - } - target.sendMessage(ChatColor.GREEN + (Lang.increasedBalance - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", plugin.getWorldName(world))); - return true; - } - return false; - default: - // Print help - printHelp(sender); + + if (args.length < 3) { + sender.sendMessage(ChatColor.RED + "Usage: /mvm "); return true; } - } - private void printHelp(CommandSender sender) { - sender.sendMessage("/mwm reload - " + Lang.reloadHelp); - sender.sendMessage("/mwm set " + Lang.playerHelp + " " + Lang.balanceHelp + " " + Lang.worldHelp + " - " + Lang.setHelp); - sender.sendMessage("/mwm take " + Lang.playerHelp + " " + Lang.amountHelp + " " + Lang.worldHelp + " - " + Lang.takeHelp); - sender.sendMessage("/mwm give " + Lang.playerHelp + " " + Lang.balanceHelp + " " + Lang.worldHelp + " - " + Lang.giveHelp); - } + String action = args[0].toLowerCase(); + Player target = Bukkit.getPlayer(args[1]); + double amount; + + try { + amount = Double.parseDouble(args[2]); + } catch (NumberFormatException e) { + sender.sendMessage(ChatColor.RED + "Invalid amount: " + args[2]); + return true; + } + // Round amount + amount = plugin.roundToTwoDecimals(amount); + if (target == null) { + sender.sendMessage(ChatColor.RED + "Player not found: " + args[1]); + return true; + } + + UUID uuid = target.getUniqueId(); + World world = target.getWorld(); + + switch (action) { + case "give": + plugin.getVh().deposit(uuid, world, amount); + sender.sendMessage(ChatColor.GREEN + "Gave $" + amount + " to " + target.getName()); + break; + case "take": + double currentBalance = plugin.getVh().getBalance(uuid, world); + if (currentBalance < amount) { + sender.sendMessage(ChatColor.RED + target.getName() + " does not have enough money."); + return true; + } + plugin.getVh().withdraw(uuid, world, amount); + sender.sendMessage(ChatColor.GREEN + "Took $" + amount + " from " + target.getName()); + break; + case "set": + plugin.getVh().set(uuid, world, amount); + sender.sendMessage(ChatColor.GREEN + "Set " + target.getName() + "'s balance to $" + amount); + break; + default: + sender.sendMessage(ChatColor.RED + "Unknown action: " + action); + break; + } + return true; + } } diff --git a/src/main/java/com/wasteofplastic/multiworldmoney/MultiWorldMoney.java b/src/main/java/com/wasteofplastic/multiworldmoney/MultiWorldMoney.java index 84911e1..2a326d7 100644 --- a/src/main/java/com/wasteofplastic/multiworldmoney/MultiWorldMoney.java +++ b/src/main/java/com/wasteofplastic/multiworldmoney/MultiWorldMoney.java @@ -1,39 +1,27 @@ package com.wasteofplastic.multiworldmoney; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.PluginCommand; +import org.bukkit.event.HandlerList; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; +import org.mvplugins.multiverse.core.MultiverseCoreApi; + import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - -import org.bukkit.ChatColor; -import org.bukkit.World; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.PluginManager; -import org.bukkit.plugin.java.JavaPlugin; - -import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.api.MultiverseWorld; public class MultiWorldMoney extends JavaPlugin { - private final HashMap> worldGroups = new HashMap<>(); - private final HashMap reverseWorldGroups = new HashMap<>(); + private final HashMap> worldGroups = new HashMap<>(); + private final HashMap reverseWorldGroups = new HashMap<>(); private PlayerCache players; - private MultiverseCore core; private VaultHelper vh; private Settings settings; - @Override public void onEnable() { // Load Settings @@ -42,13 +30,30 @@ public void onEnable() { // Load cache players = new PlayerCache(this); - // Load MVCore if it is available - core = (MultiverseCore) this.getServer().getPluginManager().getPlugin("Multiverse-Core"); - if (core != null) { + // Load Vault + vh = new VaultHelper(this); + + // Load world groups + GroupLoader.loadGroups(this); + + // Register listener + getServer().getPluginManager().registerEvents(new WorldChangeListener(this), this); + + // Register commands + PluginCommand mvmCommand = this.getCommand("mvm"); + if (mvmCommand != null) { + AdminCommands adminCommands = new AdminCommands(this); + mvmCommand.setExecutor(adminCommands); + } + + // Log Multiverse-Core availability + Plugin mvPlugin = this.getServer().getPluginManager().getPlugin("Multiverse-Core"); + if (mvPlugin != null && mvPlugin.isEnabled()) { getLogger().info("Multiverse-Core found."); } else { getLogger().info("Multiverse-Core not found."); } + // Check if this is an upgrade File userDataFolder = new File(getDataFolder(),"userdata"); if (userDataFolder.exists()) { @@ -57,288 +62,36 @@ public void onEnable() { if (!playersFolder.exists()) { playersFolder.mkdir(); } - for (File playerFile : Objects.requireNonNull(userDataFolder.listFiles())) { - if (playerFile.getName().endsWith(".yml")) { - // Load the file - YamlConfiguration player = new YamlConfiguration(); - try { - player.load(playerFile); - // Extract the data - String uuidString = player.getString("playerinfo.uuid"); - if (uuidString != null) { - UUID uuid = UUID.fromString(uuidString); - File convert = new File(playersFolder,uuid.toString() + ".yml"); - if (convert.exists()) { - getLogger().severe(uuid.toString() + ".yml exists already! Skipping import..."); - } else { - YamlConfiguration newPlayer = new YamlConfiguration(); - String name = player.getString("playerinfo.name"); - newPlayer.set("name", name); - newPlayer.set("uuid", uuidString); - newPlayer.set("logoffworld", player.getString("offline_world.name")); - // Get the balances - for (String key : player.getKeys(false)) { - if (!key.equalsIgnoreCase("offline_world") && !key.equalsIgnoreCase("playerinfo")) { - World world = getServer().getWorld(key); - if (world == null && core != null) { - MultiverseWorld mvWorld = core.getMVWorldManager().getMVWorld(key); - if (mvWorld != null) { - world = mvWorld.getCBWorld(); - } - } - if (world != null) { - // It's a recognized world - newPlayer.set("balances." + world.getName(), roundDown(player.getDouble(key + ".money",0D), 2)); - } else { - getLogger().severe("Could not recognize world: " + key + ". Skipping..."); - } - } - } - newPlayer.save(convert); - if (name != null) { - players.addName(name, uuid); - } - getLogger().info("Converted " + name); - } - } else { - getLogger().severe("Could not import " + playerFile.getName() + " - no known UUID. Skipping..."); - } - } catch (Exception e) { - getLogger().severe("Could not import " + playerFile.getName() + ". Skipping..."); - e.printStackTrace(); - } - } - } - // Save names (just in case) - players.savePlayerNames(); - // Rename the folder - File newName = new File(getDataFolder(),"userdata.old"); - userDataFolder.renameTo(newName); } - - saveDefaultConfig(); - loadConfig(); - // Load locale - new Lang(this); - - // Hook into the Vault economy system - vh = new VaultHelper(); - if (!vh.setupEconomy()) { - getLogger().severe("Could not link to Vault and Economy!"); - } else { - getLogger().info("Set up economy successfully"); - } - if (!vh.setupPermissions()) { - getLogger().severe("Could not set up permissions!"); - } else { - getLogger().info("Set up permissions successfully"); - } - // Load world groups - loadGroups(); - - // Load online player balances - for (Player player: getServer().getOnlinePlayers()) { - players.addPlayer(player); - } - - // Register events - PluginManager pm = getServer().getPluginManager(); - pm.registerEvents(new LogInOutListener(this), this); - pm.registerEvents(new WorldChangeListener(this), this); - - // Register commands - getCommand("pay").setExecutor(new PayCommand(this)); - getCommand("balance").setExecutor(new BalanceCommand(this)); - getCommand("mwm").setExecutor(new AdminCommands(this)); - - } - - - /** - * Load the settings for the plugin from config.yml and set up defaults. - */ - private void loadConfig() { - FileConfiguration config = getConfig(); - settings.setShowBalance(config.getBoolean("shownewworldmessage", true)); - settings.setNewWorldMessage(ChatColor.translateAlternateColorCodes('&', config.getString("newworldmessage", "Your balance in this world is [balance]."))); } - @Override public void onDisable() { - players.savePlayerNames(); - // Remove and save each player - for (Player player : getServer().getOnlinePlayers()) { - players.removePlayer(player); - } + HandlerList.unregisterAll(this); + players.saveAll(); } - /** - * Loads the world groups from groups.yml into the hashmap worldgroups - */ - public void loadGroups() { - worldGroups.clear(); - YamlConfiguration groups = loadYamlFile(); - Set keys = groups.getKeys(false); - // Each key is a group name - for(String group : keys) { - List worlds = groups.getStringList(group); - List worldList = new ArrayList<>(); - for(String world : worlds) { - // Try to parse world into a known world - World importedWorld = getServer().getWorld(world); - if (importedWorld != null) { - // Build the world list - worldList.add(importedWorld); - // Add immediately to the reverse hashmap - reverseWorldGroups.put(importedWorld, group); - } else { - getLogger().warning("Could not recognize world " + world + " in groups.yml. Skipping..."); - } - } - worldGroups.put(group,worldList); - } - } - - /** - * Tries to load a YML file. If it does not exist, it looks in the jar for it and tries to create it. - * @return config object - */ - private YamlConfiguration loadYamlFile() { - File dataFolder = getDataFolder(); - File yamlFile = new File(dataFolder, "groups.yml"); - YamlConfiguration config = new YamlConfiguration(); - if(yamlFile.exists()) { - try { - config.load(yamlFile); - } catch (FileNotFoundException e) { - getLogger().severe("File not found: " + "groups.yml"); - } catch (IOException e) { - e.printStackTrace(); - } catch (InvalidConfigurationException e) { - getLogger().severe("YAML file has errors: " + "groups.yml"); - e.printStackTrace(); - } - } else { - // Try to make it from a built-in file - if (getResource("groups.yml") != null) { - saveResource("groups.yml",true); - try { - config.load(yamlFile); - } catch (FileNotFoundException e) { - getLogger().severe("File not found: " + "groups.yml"); - } catch (IOException e) { - e.printStackTrace(); - } catch (InvalidConfigurationException e) { - getLogger().severe("YAML file has errors: " + "groups.yml"); - e.printStackTrace(); - } - } else { - getLogger().severe("File not found: " + "groups.yml"); - } - } - return config; - } - /** - * @param yamlFile - config file - * @param fileLocation - file name location - */ - public void saveYamlFile(YamlConfiguration yamlFile, String fileLocation) { - File dataFolder = getDataFolder(); - File file = new File(dataFolder, fileLocation); - try { - yamlFile.save(file); - } catch(Exception e) { - e.printStackTrace(); - } - } - - - - /** - * Finds what other worlds are in the group this world is in, or just itself - * @param world - world - * @return List of worlds in group - */ - public List getGroupWorlds(World world) { - if (reverseWorldGroups.containsKey(world)) { - return worldGroups.get(reverseWorldGroups.get(world)); - } else { - List result = new ArrayList<>(); - result.add(world); - return result; - } - } - - /** - * Rounds a double down to a set number of places - * @param value - value - * @param places - number of placed - * @return - rounded value - */ - public double roundDown(double value, int places) { - BigDecimal bd = new BigDecimal(value); - bd = bd.setScale(places, RoundingMode.HALF_DOWN); - return bd.doubleValue(); - } - - - /** - * @return player cache - */ public PlayerCache getPlayers() { return players; } - /** - * Returns the name of world, uses MultiverseCore alias if available - * @param world - world - * @return world name or alias - */ - public String getWorldName(World world) { - // Grab the Multiverse world name if it is available - if (core != null) { - try { - return core.getMVWorldManager().getMVWorld(world).getAlias(); - } catch (Exception e) { - // do nothing if it does not work - e.printStackTrace(); - } - } - //getLogger().info("DEBUG: core is null"); - return world.getName(); + public VaultHelper getVh() { + return vh; } - - /** - * @return the core - */ - public MultiverseCore getCore() { - return core; + public Settings getSettings() { + return settings; } - - /** - * Reload locale - */ - public void reloadLocale() { - new Lang(this); + public HashMap> getWorldGroups() { + return worldGroups; } - - /** - * Get VaultHelper - * @return the vh - */ - public VaultHelper getVh() { - return vh; + public HashMap getReverseWorldGroups() { + return reverseWorldGroups; } - - /** - * @return the settings - */ - public Settings getSettings() { - return settings; + public double roundToTwoDecimals(double amount) { + return new BigDecimal(amount).setScale(2, RoundingMode.HALF_UP).doubleValue(); } -} +} diff --git a/src/main/java/com/wasteofplastic/multiworldmoney/PayCommand.java b/src/main/java/com/wasteofplastic/multiworldmoney/PayCommand.java index 7f8ad8b..eab723d 100644 --- a/src/main/java/com/wasteofplastic/multiworldmoney/PayCommand.java +++ b/src/main/java/com/wasteofplastic/multiworldmoney/PayCommand.java @@ -1,8 +1,6 @@ package com.wasteofplastic.multiworldmoney; -import java.util.List; -import java.util.UUID; - +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.World; import org.bukkit.command.Command; @@ -10,127 +8,77 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import net.milkbowl.vault.economy.EconomyResponse; - -class PayCommand implements CommandExecutor { +import java.util.UUID; +public class PayCommand implements CommandExecutor { private final MultiWorldMoney plugin; - /** - * @param plugin - plugin - */ public PayCommand(MultiWorldMoney plugin) { this.plugin = plugin; } - @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (!(sender instanceof Player)) { - sender.sendMessage("Error: /pay is only available in game."); + sender.sendMessage("This command can only be run by a player."); return true; } - Player player = (Player)sender; - if (plugin.getVh().checkPerm(player, "mwm.pay")) { - player.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.noPermission); + + if (args.length != 2) { + sender.sendMessage(ChatColor.RED + "Usage: /pay "); return true; } - if (args.length == 2) { - // correctly formed pay command /pay name amount - // Check name - UUID targetUUID = plugin.getPlayers().getUUID(args[0]); - - if (targetUUID != null) { - if (targetUUID.equals(player.getUniqueId())) { - player.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.youCannotPayYourself); - return true; - } - double amount; - // Check that the amount is a number - try { - amount = Double.valueOf(args[1]); // May throw NumberFormatException - } catch (Exception ex) { - // Failure on the number - player.sendMessage(Lang.payHelp); - player.sendMessage("/pay " + Lang.playerHelp + " " + Lang.amountHelp); - return true; - } - if (amount < 0D) { - player.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.amountPositive); - return true; - } - // Check if online or offline - Player target = plugin.getServer().getPlayer(targetUUID); - if (target != null) { - // online player - // Check worlds - if (!target.getWorld().equals(player.getWorld())) { - // Not same world - // Check if worlds are in the same group - List groupWorlds = plugin.getGroupWorlds(target.getWorld()); - //plugin.getLogger().info("DEBUG: from group worlds = " + groupWorlds); - if (!groupWorlds.contains(player.getWorld())) { - // They are not in the same group - // Try to withdraw the amount - EconomyResponse er = plugin.getVh().getEcon().withdrawPlayer(player, amount); - if (er.transactionSuccess()) { - // Set the balance in the sender's world - plugin.getPlayers().deposit(target, player.getWorld(), amount); - sender.sendMessage(ChatColor.GREEN + ((Lang.sendTo - .replace("[name]", target.getName())) - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", player.getWorld().getName())); - target.sendMessage(ChatColor.GREEN + (Lang.receiveFrom - .replace("[name]", sender.getName()) - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", player.getWorld().getName())); - // Override the payment - return true; - } else { - // Cannot pay - let pay handle the error - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.insufficientFunds); - return true; - } - } else { - // else allow the payment - pay(target, player, amount); - return true; - } - } - // Same world - allow the transfer - pay(target, player, amount); - return true; - } else { - // Offline player - not supported - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.noPlayer); - return true; - } - } else { - sender.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.noPlayer); - return true; - } + + Player payer = (Player) sender; + Player payee = Bukkit.getPlayer(args[0]); + double amount; + + try { + amount = Double.parseDouble(args[1]); + } catch (NumberFormatException e) { + payer.sendMessage(ChatColor.RED + "Invalid amount: " + args[1]); + return true; } - player.sendMessage(Lang.payHelp); - player.sendMessage("/pay " + Lang.playerHelp + " " + Lang.amountHelp); - return true; - } + // Round to 2 decimal places + amount = plugin.roundToTwoDecimals(amount); - private void pay(Player target, Player player, double amount) { - EconomyResponse erw = plugin.getVh().getEcon().withdrawPlayer(player, amount); - if (erw.transactionSuccess()) { - plugin.getVh().getEcon().depositPlayer(target, amount); - player.sendMessage(ChatColor.GREEN + ((Lang.sendTo - .replace("[name]", target.getName())) - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", player.getWorld().getName())); - target.sendMessage(ChatColor.GREEN + (Lang.receiveFrom - .replace("[name]", player.getName()) - .replace("[amount]", plugin.getVh().getEcon().format(amount))) - .replace("[world]", player.getWorld().getName())); - } else { - // Cannot pay - let pay handle the error - player.sendMessage(ChatColor.RED + Lang.error + " " + ChatColor.DARK_RED + Lang.insufficientFunds); + if (amount <= 0) { + payer.sendMessage(ChatColor.RED + "Amount must be positive."); + return true; } + + if (payee == null || !payee.isOnline()) { + payer.sendMessage(ChatColor.RED + "Player not found or not online: " + args[0]); + return true; + } + + UUID payerUUID = payer.getUniqueId(); + UUID payeeUUID = payee.getUniqueId(); + World payerWorld = payer.getWorld(); + World payeeWorld = payee.getWorld(); + + // Ensure both players are in the same group + String payerGroup = plugin.getSettings().getWorldGroup(payerWorld); + String payeeGroup = plugin.getSettings().getWorldGroup(payeeWorld); + + if (payerGroup == null || payeeGroup == null || !payerGroup.equalsIgnoreCase(payeeGroup)) { + payer.sendMessage(ChatColor.RED + "You can only pay players in your current world group."); + return true; + } + + double balance = plugin.getVh().getBalance(payerUUID, payerWorld); + if (balance < amount) { + payer.sendMessage(ChatColor.RED + "You don't have enough money to send that amount."); + return true; + } + + plugin.getVh().withdraw(payerUUID, payerWorld, amount); + plugin.getVh().deposit(payeeUUID, payeeWorld, amount); + + payer.sendMessage(ChatColor.GREEN + "You paid $" + amount + " to " + payee.getName()); + payee.sendMessage(ChatColor.GREEN + "You received $" + amount + " from " + payer.getName()); + + return true; } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 492967f..7345dfe 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: MultiWorldMoney main: com.wasteofplastic.multiworldmoney.MultiWorldMoney version: ${version} -api-version: "1.20" +api-version: "1.21" depend: [Vault] softdepend: [Multiverse-Core, Essentials] commands: