diff --git a/.gitignore b/.gitignore index be5de33..ad9c598 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ .idea/ libs/ out/ -ArmorStand.iml \ No newline at end of file +ArmorStand.iml +/bin/ + +*.project +.classpath \ No newline at end of file diff --git a/src/com/gmail/St3venAU/plugins/ArmorStandTools/Commands.java b/src/com/gmail/St3venAU/plugins/ArmorStandTools/Commands.java index 75dd1fc..9837334 100644 --- a/src/com/gmail/St3venAU/plugins/ArmorStandTools/Commands.java +++ b/src/com/gmail/St3venAU/plugins/ArmorStandTools/Commands.java @@ -1,11 +1,18 @@ package com.gmail.St3venAU.plugins.ArmorStandTools; +import net.minecraft.server.v1_8_R1.Material; + import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; +import java.util.List; import java.util.UUID; class Commands implements CommandExecutor { @@ -23,6 +30,9 @@ class Commands implements CommandExecutor { return false; } Player p = (Player) sender; + if (!Utils.hasPermissionNode(p, "astools.command")) { + p.sendMessage(ChatColor.RED + "You don't have permission to use this command"); + } if(args.length == 0) { UUID uuid = p.getUniqueId(); if(plugin.savedInventories.containsKey(uuid)) { @@ -38,8 +48,54 @@ class Commands implements CommandExecutor { return true; } } + if(args[0].equalsIgnoreCase("head")) { + // get the entity you are looking at + if(!Utils.hasPermissionNode(p, "astools.head")) { + p.sendMessage(ChatColor.RED + Config.noHeadPerm); + return true; + } + List nearby = p.getNearbyEntities(16, 16, 16); + if (nearby.size() == 0) { + p.sendMessage(ChatColor.RED + Config.notTarget); + return true; + } + double min = 0.5; + Entity closest = null; + Vector loc = p.getLocation().toVector(); + for (Entity entity : nearby) { + Vector eLoc = entity.getLocation().toVector().subtract(loc).normalize(); + Vector target = p.getLocation().getDirection().normalize(); + double diff = eLoc.subtract(target).length(); + if (diff < min) { + min = diff; + closest = entity; + } + } + if (closest == null || !(closest instanceof ArmorStand)) { + p.sendMessage(ChatColor.RED + Config.notTarget); + return true; + } + ArmorStand as = (ArmorStand) closest; + if (!MainListener.checkPermission(p, closest.getLocation().getBlock())) { + p.sendMessage(ChatColor.RED + Config.wgNoPerm); + return true; + } + ItemStack item = p.getItemInHand(); + if (item == null || item.getTypeId() == 0) { + as.setHelmet(new ItemStack(0)); + p.sendMessage(ChatColor.GREEN + Config.setHead); + return true; + } + if (!item.getType().isBlock()) { + p.sendMessage(ChatColor.RED + Config.notBlock); + return true; + } + as.setHelmet(item); + p.sendMessage(ChatColor.GREEN + Config.setHead); + return true; + } if(args[0].equalsIgnoreCase("reload")) { - if(p.hasPermission("astools.reload")) { + if(Utils.hasPermissionNode(p, "astools.reload")) { Config.reload(); p.sendMessage(ChatColor.GREEN + Config.conReload); return true; diff --git a/src/com/gmail/St3venAU/plugins/ArmorStandTools/Config.java b/src/com/gmail/St3venAU/plugins/ArmorStandTools/Config.java index 4dfab37..7d18567 100644 --- a/src/com/gmail/St3venAU/plugins/ArmorStandTools/Config.java +++ b/src/com/gmail/St3venAU/plugins/ArmorStandTools/Config.java @@ -34,9 +34,9 @@ class Config { asCloned, carrying, noPerm, cbCreated, size, small, normal, basePlate, isOn, isOff, gravity, arms, invul, equip, locked, unLocked, notConsole, giveMsg1, - giveMsg2, conReload, noRelPerm, noAirError, + giveMsg2, conReload, noRelPerm, noHeadPerm, notTarget, notBlock, noAirError, pleaseWait, appliedHead, noHead, invalidName, - wgNoPerm; + wgNoPerm, setHead; public static void reload(Main main) { plugin = main; @@ -74,12 +74,16 @@ class Config { giveMsg2 = languageConfig.getString("giveMsg2"); conReload = languageConfig.getString("conReload"); noRelPerm = languageConfig.getString("noRelPerm"); + noHeadPerm = languageConfig.getString("noHeadPerm"); + notTarget = languageConfig.getString("notTarget"); + notBlock = languageConfig.getString("notBlock"); noAirError = languageConfig.getString("noAirError"); pleaseWait = languageConfig.getString("pleaseWait"); appliedHead = languageConfig.getString("appliedHead"); noHead = languageConfig.getString("noHead"); invalidName = languageConfig.getString("invalidName"); wgNoPerm = languageConfig.getString("wgNoPerm"); + setHead = languageConfig.getString("setHead"); } private static void reloadMainConfig() { @@ -100,6 +104,12 @@ class Config { invulnerable = config.getBoolean("invulnerable"); equipmentLock = config.getBoolean("equipmentLock"); plugin.carryingArmorStand.clear(); + + Plugin plotSquared = plugin.getServer().getPluginManager().getPlugin("PlotSquared"); + if (plotSquared != null && plotSquared.isEnabled()) { + new PlotSquaredHook(plugin); + } + Plugin worldGuard = plugin.getServer().getPluginManager().getPlugin("WorldGuard"); worldGuardPlugin = worldGuard == null || !(worldGuard instanceof WorldGuardPlugin) ? null : (WorldGuardPlugin) worldGuard; if(config.getBoolean("integrateWithWorldGuard")) { diff --git a/src/com/gmail/St3venAU/plugins/ArmorStandTools/MainListener.java b/src/com/gmail/St3venAU/plugins/ArmorStandTools/MainListener.java index a9c7a92..80a49a6 100644 --- a/src/com/gmail/St3venAU/plugins/ArmorStandTools/MainListener.java +++ b/src/com/gmail/St3venAU/plugins/ArmorStandTools/MainListener.java @@ -1,5 +1,6 @@ package com.gmail.St3venAU.plugins.ArmorStandTools; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; @@ -14,6 +15,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; @@ -53,16 +55,24 @@ public class MainListener implements Listener { public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { if (event.getRightClicked() instanceof ArmorStand) { Player p = event.getPlayer(); - if(plugin.carryingArmorStand.containsKey(p.getUniqueId()) && playerHasPermission(p, plugin.carryingArmorStand.get(p.getUniqueId()).getLocation().getBlock(), null)) { - plugin.carryingArmorStand.remove(p.getUniqueId()); - Utils.actionBarMsg(p, Config.asDropped); - event.setCancelled(true); - return; + if(plugin.carryingArmorStand.containsKey(p.getUniqueId())) { + if (playerHasPermission(p, plugin.carryingArmorStand.get(p.getUniqueId()).getLocation().getBlock(), null)) { + plugin.carryingArmorStand.remove(p.getUniqueId()); + Utils.actionBarMsg(p, Config.asDropped); + event.setCancelled(true); + return; + } + else { + p.sendMessage(ChatColor.RED + Config.wgNoPerm); + } } ArmorStandTool tool = ArmorStandTool.get(p.getItemInHand()); if(tool == null) return; ArmorStand as = (ArmorStand) event.getRightClicked(); - if (!playerHasPermission(p, event.getRightClicked().getLocation().getBlock(), tool)) return; + if (!playerHasPermission(p, event.getRightClicked().getLocation().getBlock(), tool)) { + p.sendMessage(ChatColor.RED + Config.wgNoPerm); + return; + } double num = event.getClickedPosition().getY() - 0.05; if (num < 0) { num = 0; @@ -202,8 +212,9 @@ public class MainListener implements Listener { p.sendMessage(ChatColor.GREEN + "Deletion Protection: Enabled"); } break; - default: + default: { cancel = tool == ArmorStandTool.SUMMON || tool == ArmorStandTool.SAVE || event.isCancelled(); + } } event.setCancelled(cancel); } @@ -241,8 +252,8 @@ public class MainListener implements Listener { clone.setCustomNameVisible(as.isCustomNameVisible()); clone.setSmall(as.isSmall()); clone.setMaxHealth(as.getMaxHealth()); - NBT.setSlotsDisabled(clone, NBT.getDisabledSlots(as) == 2039583); - NBT.setInvulnerable(clone, NBT.isInvulnerable(as)); + NBT.setSlotsDisabled(as, Config.equipmentLock); + NBT.setInvulnerable(as, Config.invulnerable); return clone; } @@ -264,8 +275,12 @@ public class MainListener implements Listener { Utils.actionBarMsg(p, Config.asDropped); return; } - as.teleport(Utils.getLocationFacingPlayer(p)); - Utils.actionBarMsg(p, ChatColor.GREEN + Config.carrying); + Location loc = Utils.getLocationFacingPlayer(p); + Block block = loc.getBlock(); + if (playerHasPermission(p, block, null)) { + as.teleport(loc); + Utils.actionBarMsg(p, ChatColor.GREEN + Config.carrying); + } } } @@ -337,10 +352,16 @@ public class MainListener implements Listener { @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { Player p = event.getPlayer(); - if(plugin.carryingArmorStand.containsKey(p.getUniqueId()) && playerHasPermission(p, plugin.carryingArmorStand.get(p.getUniqueId()).getLocation().getBlock(), null)) { - plugin.carryingArmorStand.remove(p.getUniqueId()); - Utils.actionBarMsg(p, Config.asDropped); - event.setCancelled(true); + if(plugin.carryingArmorStand.containsKey(p.getUniqueId())) { + boolean perm = playerHasPermission(p, plugin.carryingArmorStand.get(p.getUniqueId()).getLocation().getBlock(), null); + if (perm) { + plugin.carryingArmorStand.remove(p.getUniqueId()); + Utils.actionBarMsg(p, Config.asDropped); + event.setCancelled(true); + } + else { + p.sendMessage(ChatColor.RED + Config.wgNoPerm); + } return; } Action action = event.getAction(); @@ -351,8 +372,11 @@ public class MainListener implements Listener { Utils.cycleInventory(p); return; } - if(action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) { - if(!playerHasPermission(p, p.getLocation().getBlock(), tool)) return; + else if(action == Action.RIGHT_CLICK_BLOCK) { + if (!playerHasPermission(p, event.getClickedBlock(), tool)) { + p.sendMessage(ChatColor.RED + Config.wgNoPerm); + return; + } switch (tool) { case SUMMON: event.setCancelled(true); @@ -523,7 +547,7 @@ public class MainListener implements Listener { @SuppressWarnings("deprecation") private void setName(Player p, ArmorStand as) { Block b = Utils.findAnAirBlock(p.getLocation()); - if(b == null) { + if(b == null || !checkPermission(p, b)) { p.sendMessage(ChatColor.RED + Config.noAirError); return; } @@ -537,7 +561,7 @@ public class MainListener implements Listener { @SuppressWarnings("deprecation") private void setPlayerSkull(Player p, ArmorStand as) { Block b = Utils.findAnAirBlock(p.getLocation()); - if(b == null) { + if(b == null || !checkPermission(p, b)) { p.sendMessage(ChatColor.RED + Config.noAirError); return; } @@ -547,7 +571,7 @@ public class MainListener implements Listener { b.setMetadata("armorStand", new FixedMetadataValue(plugin, as.getUniqueId())); b.setMetadata("setSkull", new FixedMetadataValue(plugin, true)); } - + private ArmorStand getArmorStand(Block b) { UUID uuid = null; for (MetadataValue value : b.getMetadata("armorStand")) { @@ -565,20 +589,49 @@ public class MainListener implements Listener { } return null; } - - boolean playerHasPermission(Player p, Block b, ArmorStandTool tool) { - if(!p.isOp() && (!p.hasPermission("astools.use") - || (ArmorStandTool.SAVE == tool && !p.hasPermission("astools.cmdblock")) - || (ArmorStandTool.CLONE == tool && !p.hasPermission("astools.clone")))) { + + public static boolean checkPermission(Player player, Block block) { + + // Check PlotSquared + Location loc = block.getLocation(); + if (PlotSquaredHook.api != null) { + if (PlotSquaredHook.isPlotWorld(loc)) { + boolean result = PlotSquaredHook.checkPermission(player, loc); + return result; + } + } + + // check WorldGuard + if(Config.worldGuardPlugin != null) { + boolean canBuild = Config.worldGuardPlugin.canBuild(player, block); + return canBuild; + } + + // Use standard permission checking (will support basically any plugin) + BlockBreakEvent mybreak = new BlockBreakEvent(block, player); + Bukkit.getServer().getPluginManager().callEvent(mybreak); + boolean hasperm; + if (mybreak.isCancelled()) { + hasperm = false; + } else { + hasperm = true; + } + BlockPlaceEvent place = new BlockPlaceEvent(block, block.getState(), block, null, player, true); + Bukkit.getServer().getPluginManager().callEvent(place); + if (place.isCancelled()) { + hasperm = false; + } + return hasperm; + } + + public static boolean playerHasPermission(Player p, Block b, ArmorStandTool tool) { + if(tool != null && !p.isOp() && (!Utils.hasPermissionNode(p, "astools.use") + || (ArmorStandTool.SAVE == tool && !Utils.hasPermissionNode(p, "astools.cmdblock")) + || (ArmorStandTool.CLONE == tool && !Utils.hasPermissionNode(p, "astools.clone")))) { p.sendMessage(ChatColor.RED + Config.noPerm); return false; } - if(Config.worldGuardPlugin == null) return true; - boolean canBuild = Config.worldGuardPlugin.canBuild(p, b); - if(!canBuild) { - p.sendMessage(ChatColor.RED + Config.wgNoPerm); - } - return canBuild; + return checkPermission(p, b); } void pickUpArmorStand(ArmorStand as, Player p, boolean newlySummoned) { diff --git a/src/com/gmail/St3venAU/plugins/ArmorStandTools/PlotSquaredHook.java b/src/com/gmail/St3venAU/plugins/ArmorStandTools/PlotSquaredHook.java new file mode 100644 index 0000000..b9b2442 --- /dev/null +++ b/src/com/gmail/St3venAU/plugins/ArmorStandTools/PlotSquaredHook.java @@ -0,0 +1,40 @@ +package com.gmail.St3venAU.plugins.ArmorStandTools; + +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import com.intellectualcrafters.plot.api.PlotAPI; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.util.Permissions; +import com.intellectualcrafters.plot.util.bukkit.BukkitUtil; + +public class PlotSquaredHook { + + public static PlotAPI api = null; + + public PlotSquaredHook(Main plugin) { + PlotSquaredHook.api = new PlotAPI(plugin); + } + + public static boolean isPlotWorld(Location loc) { + World world = loc.getWorld(); + return api.isPlotWorld(world); + } + + public static boolean checkPermission(Player player, Location loc) { + Plot plot = api.getPlot(loc); + if (plot == null) { + return Permissions.hasPermission(BukkitUtil.getPlayer(player), "plots.admin.build.road"); + } + PlotPlayer pp = BukkitUtil.getPlayer(player); + UUID uuid = pp.getUUID(); + if (plot.isAdded(uuid)) { + return true; + } + return Permissions.hasPermission(pp, "plots.admin.build.other"); + } +} diff --git a/src/com/gmail/St3venAU/plugins/ArmorStandTools/Utils.java b/src/com/gmail/St3venAU/plugins/ArmorStandTools/Utils.java index 21ac61a..fd933e4 100644 --- a/src/com/gmail/St3venAU/plugins/ArmorStandTools/Utils.java +++ b/src/com/gmail/St3venAU/plugins/ArmorStandTools/Utils.java @@ -24,6 +24,24 @@ class Utils { } return false; } + + public static boolean hasPermissionNode(Player player, String perm) { + if ((player == null) || player.isOp()) { + return true; + } + if (player.hasPermission(perm)) { + return true; + } + final String[] nodes = perm.split("\\."); + final StringBuilder n = new StringBuilder(); + for (int i = 0; i < (nodes.length - 1); i++) { + n.append(nodes[i] + (".")); + if (player.hasPermission(n + "*")) { + return true; + } + } + return false; + } static boolean hasItems(Player p) { for(ItemStack i : p.getInventory()) { diff --git a/src/language.yml b/src/language.yml index ad8561c..82763af 100644 --- a/src/language.yml +++ b/src/language.yml @@ -42,12 +42,16 @@ giveMsg1: 'Given armor stand tools. L-click any tool to cycle through tools.' giveMsg2: 'Run this command again to return your inventory.' conReload: 'Armor Stand Tools config reloaded' noRelPerm: 'You do not have permission to reload the plugin' +noHeadPerm: 'You do not have permission to set a head' +notTarget: 'You are not looking at an ArmorStand' noAirError: 'Error: Failed to find a near-by air block. Move and try again.' pleaseWait: 'Please wait, this may take a few seconds...' appliedHead: 'Applied the head of player' noHead: 'No player head found for player' invalidName: 'is not a valid minecraft username' wgNoPerm: 'You do not have permission to alter an armor stand in this region' +notBlock: 'You are not holding a block' +setHead: 'Set the head block' # ############################# # Tool names & descriptions # diff --git a/src/plugin.yml b/src/plugin.yml index 726383e..0cc163a 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -8,6 +8,4 @@ commands: astools: description: Give yourself all of the armor stand tools (Warning; clears your inventory). aliases: ast - usage: Usage /astools or /astools reload - permission: astools.command - permission-message: You don't have permission to use this command \ No newline at end of file + usage: Usage /astools or /astools reload or /astools head \ No newline at end of file