diff --git a/integrations/paper/src/main/java/net/scopenet/paper/commands/EconomyHandler.java b/integrations/paper/src/main/java/net/scopenet/paper/commands/EconomyHandler.java index de609d4..851ae4e 100644 --- a/integrations/paper/src/main/java/net/scopenet/paper/commands/EconomyHandler.java +++ b/integrations/paper/src/main/java/net/scopenet/paper/commands/EconomyHandler.java @@ -228,6 +228,10 @@ public final class EconomyHandler implements CommandExecutor, Listener { /** {@code guild}: the proceeds go to the player's guild bank instead of their balance. */ void handleSell(Player player, String[] args, boolean guild) { if (args.length > 0 && args[0].equalsIgnoreCase("hand")) { + if (!guild && !player.hasPermission("scopenet.command.sell.hand")) { + player.sendMessage(ChatColor.RED + "You do not have permission to use /sell hand."); + return; + } ItemStack hand = player.getInventory().getItemInMainHand(); if (hand.getType().isAir()) { player.sendMessage(ChatColor.RED + "You are not holding any item to sell."); @@ -280,6 +284,10 @@ public final class EconomyHandler implements CommandExecutor, Listener { return; } if (args.length >= 2 && args[0].equalsIgnoreCase("sell")) { + if (!asGuild && !player.hasPermission("scopenet.command.market.sell")) { + player.sendMessage(ChatColor.RED + "You do not have permission to list items on the market."); + return; + } ItemStack hand = player.getInventory().getItemInMainHand(); if (hand.getType().isAir()) { player.sendMessage(ChatColor.RED + "Hold the item you want to sell in your main hand."); @@ -458,6 +466,10 @@ public final class EconomyHandler implements CommandExecutor, Listener { int slot = event.getRawSlot(); Long listingId = activeMarketListings.getOrDefault(event.getInventory(), Collections.emptyMap()).get(slot); if (listingId == null || listingId < 0) return; + if (!player.hasPermission("scopenet.command.market.buy")) { + player.sendMessage(ChatColor.RED + "You do not have permission to buy from the market."); + return; + } JsonObject payload = new JsonObject(); payload.addProperty("listing_id", listingId); diff --git a/integrations/paper/src/main/java/net/scopenet/paper/commands/GuildHandler.java b/integrations/paper/src/main/java/net/scopenet/paper/commands/GuildHandler.java index 1b99cd6..3ef18e0 100644 --- a/integrations/paper/src/main/java/net/scopenet/paper/commands/GuildHandler.java +++ b/integrations/paper/src/main/java/net/scopenet/paper/commands/GuildHandler.java @@ -89,6 +89,10 @@ public final class GuildHandler implements CommandExecutor, Listener { if (cmd.equals("guild") || cmd.equals("g")) { if (args.length == 0 || args[0].equalsIgnoreCase("info") || args[0].equalsIgnoreCase("gui")) { + if (!player.hasPermission("scopenet.command.guild.info")) { + player.sendMessage(ChatColor.RED + "You do not have permission to use /guild info."); + return true; + } handleGuildDashboard(player); return true; } @@ -100,6 +104,14 @@ public final class GuildHandler implements CommandExecutor, Listener { player.sendMessage(ChatColor.RED + "You do not have permission to use /guild " + permission + "."); return true; } + // Finer nodes for the money subcommands that do several things. + String detail = args.length > 1 ? args[1].toLowerCase() : ""; + String fine = (sub.equals("sell") && detail.equals("hand")) ? "sell.hand" + : (sub.equals("market") && (detail.equals("sell") || detail.equals("buy"))) ? "market." + detail : null; + if (fine != null && !player.hasPermission("scopenet.command.guild." + fine)) { + player.sendMessage(ChatColor.RED + "You do not have permission to use /guild " + sub + " " + detail + "."); + return true; + } switch (sub) { case "create" -> handleCreate(player, args); case "leave" -> handleLeave(player); diff --git a/integrations/paper/src/main/java/net/scopenet/paper/commands/ScopenetCommandHandler.java b/integrations/paper/src/main/java/net/scopenet/paper/commands/ScopenetCommandHandler.java index 8454e90..605b121 100644 --- a/integrations/paper/src/main/java/net/scopenet/paper/commands/ScopenetCommandHandler.java +++ b/integrations/paper/src/main/java/net/scopenet/paper/commands/ScopenetCommandHandler.java @@ -20,6 +20,10 @@ public final class ScopenetCommandHandler implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if (args.length == 0 || args[0].equalsIgnoreCase("help")) { + if (!sender.hasPermission("scopenet.command.scopenet.help")) { + sender.sendMessage(ChatColor.RED + "You do not have permission to view SCOPENET help."); + return true; + } sendHelp(sender); return true; } diff --git a/integrations/paper/src/main/resources/plugin.yml b/integrations/paper/src/main/resources/plugin.yml index 1ab1f8a..d383d72 100644 --- a/integrations/paper/src/main/resources/plugin.yml +++ b/integrations/paper/src/main/resources/plugin.yml @@ -97,8 +97,12 @@ commands: permissions: scopenet.admin: - description: Legacy administrator permission + description: Legacy administrator permission (status, reload, claim bypass) default: op + children: + scopenet.command.scopenet.status: true + scopenet.command.scopenet.reload: true + scopenet.claims.bypass: true scopenet.command.scopenet: description: Use /scopenet default: true @@ -171,12 +175,18 @@ permissions: scopenet.command.unclaim: description: Use /unclaim default: true + scopenet.command.scopenet.help: + description: Use /scopenet help + default: true scopenet.command.scopenet.status: description: Use /scopenet status default: op scopenet.command.scopenet.reload: description: Use /scopenet reload default: op + scopenet.command.guild.info: + description: Open the guild dashboard (/guild, /guild info) + default: true scopenet.command.guild.create: description: Use /guild create default: true @@ -204,3 +214,157 @@ permissions: scopenet.command.guild.members: description: Use /guild members default: true + scopenet.command.guild.bank: + description: View the guild bank (/guild bank) + default: true + scopenet.command.guild.bank.deposit: + description: Deposit into the guild bank + default: true + scopenet.command.guild.bank.withdraw: + description: Withdraw from the guild bank (the panel also requires officer or leader) + default: true + scopenet.command.guild.sell: + description: Sell items to the shop for the guild bank (/guild sell) + default: true + scopenet.command.guild.sell.hand: + description: Use /guild sell hand + default: true + scopenet.command.guild.market: + description: Use the market as a guild (/guild market) + default: true + scopenet.command.guild.market.sell: + description: List items on the market for the guild + default: true + scopenet.command.guild.market.buy: + description: Buy market listings with guild money + default: true + scopenet.command.guild.pay: + description: Pay another guild (/guild pay) + default: true + scopenet.command.sell.hand: + description: Use /sell hand + default: true + scopenet.command.market.sell: + description: List an item with /market sell + default: true + scopenet.command.market.buy: + description: Buy listings from the /market GUI + default: true + scopenet.claims.bypass: + description: Build and break inside other guilds' claims + default: op + scopenet.command.guild.*: + description: Every /guild subcommand + default: false + children: + scopenet.command.guild: true + scopenet.command.guild.info: true + scopenet.command.guild.create: true + scopenet.command.guild.leave: true + scopenet.command.guild.claim: true + scopenet.command.guild.unclaim: true + scopenet.command.guild.map: true + scopenet.command.guild.chat: true + scopenet.command.guild.sethome: true + scopenet.command.guild.home: true + scopenet.command.guild.members: true + scopenet.command.guild.bank: true + scopenet.command.guild.bank.deposit: true + scopenet.command.guild.bank.withdraw: true + scopenet.command.guild.sell: true + scopenet.command.guild.sell.hand: true + scopenet.command.guild.market: true + scopenet.command.guild.market.sell: true + scopenet.command.guild.market.buy: true + scopenet.command.guild.pay: true + scopenet.command.*: + description: Every SCOPENET command and subcommand, including admin ones + default: false + children: + scopenet.command.scopenet: true + scopenet.command.spawn: true + scopenet.command.home: true + scopenet.command.sethome: true + scopenet.command.delhome: true + scopenet.command.back: true + scopenet.command.tpa: true + scopenet.command.tpaccept: true + scopenet.command.tpdeny: true + scopenet.command.rtp: true + scopenet.command.warp: true + scopenet.command.playtime: true + scopenet.command.balance: true + scopenet.command.pay: true + scopenet.command.baltop: true + scopenet.command.shop: true + scopenet.command.sell: true + scopenet.command.market: true + scopenet.command.orders: true + scopenet.command.trade: true + scopenet.command.transactions: true + scopenet.command.guild: true + scopenet.command.claim: true + scopenet.command.unclaim: true + scopenet.command.scopenet.help: true + scopenet.command.scopenet.status: true + scopenet.command.scopenet.reload: true + scopenet.command.guild.info: true + scopenet.command.guild.create: true + scopenet.command.guild.leave: true + scopenet.command.guild.claim: true + scopenet.command.guild.unclaim: true + scopenet.command.guild.map: true + scopenet.command.guild.chat: true + scopenet.command.guild.sethome: true + scopenet.command.guild.home: true + scopenet.command.guild.members: true + scopenet.command.guild.bank: true + scopenet.command.guild.bank.deposit: true + scopenet.command.guild.bank.withdraw: true + scopenet.command.guild.sell: true + scopenet.command.guild.sell.hand: true + scopenet.command.guild.market: true + scopenet.command.guild.market.sell: true + scopenet.command.guild.market.buy: true + scopenet.command.guild.pay: true + scopenet.command.sell.hand: true + scopenet.command.market.sell: true + scopenet.command.market.buy: true + scopenet.command.economy.*: + description: All economy commands + default: false + children: + scopenet.command.balance: true + scopenet.command.pay: true + scopenet.command.baltop: true + scopenet.command.shop: true + scopenet.command.sell: true + scopenet.command.sell.hand: true + scopenet.command.market: true + scopenet.command.market.sell: true + scopenet.command.market.buy: true + scopenet.command.orders: true + scopenet.command.trade: true + scopenet.command.transactions: true + scopenet.command.essentials.*: + description: All teleport and utility commands + default: false + children: + scopenet.command.spawn: true + scopenet.command.home: true + scopenet.command.sethome: true + scopenet.command.delhome: true + scopenet.command.back: true + scopenet.command.tpa: true + scopenet.command.tpaccept: true + scopenet.command.tpdeny: true + scopenet.command.rtp: true + scopenet.command.warp: true + scopenet.command.playtime: true + scopenet.*: + description: Everything SCOPENET + default: false + children: + scopenet.command.*: true + scopenet.admin: true + scopenet.claims.bypass: true