diff --git a/pom.xml b/pom.xml index 799b8bfc2..d9b064db8 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,12 @@ + + org.bukkit + bukkit + 1.12.2-R0.1-SNAPSHOT + provided + org.mockito mockito-all @@ -71,28 +77,22 @@ test - org.bukkit - bukkit - 1.12.2-R0.1-SNAPSHOT - provided + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - org.powermock - powermock-api-mockito - ${powermock.version} - test - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + https://hub.spigotmc.org/nexus/content/repositories/snapshots diff --git a/src/main/java/us/tastybento/bskyblock/api/commands/User.java b/src/main/java/us/tastybento/bskyblock/api/commands/User.java index 1826e3848..ce59e3556 100644 --- a/src/main/java/us/tastybento/bskyblock/api/commands/User.java +++ b/src/main/java/us/tastybento/bskyblock/api/commands/User.java @@ -257,4 +257,10 @@ public class User { return Locale.forLanguageTag(plugin.getSettings().getDefaultLanguage()); } + + @SuppressWarnings("deprecation") + public void updateInventory() { + player.updateInventory(); + + } } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/FlagListener.java b/src/main/java/us/tastybento/bskyblock/listeners/FlagListener.java index 1ee308626..dedf42541 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/FlagListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/FlagListener.java @@ -3,20 +3,19 @@ */ package us.tastybento.bskyblock.listeners; +import java.util.Optional; + import org.bukkit.Location; import org.bukkit.entity.Entity; +import org.bukkit.event.Cancellable; import org.bukkit.event.Event; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.PlayerLeashEntityEvent; -import org.bukkit.event.inventory.InventoryMoveItemEvent; -import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.event.player.PlayerEvent; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.commands.User; +import us.tastybento.bskyblock.api.flags.Flag; +import us.tastybento.bskyblock.database.objects.Island; /** * Abstract class for flag listeners to inherit. Provides some common code. @@ -24,71 +23,74 @@ import us.tastybento.bskyblock.api.commands.User; * */ public abstract class FlagListener implements Listener { - - private static final boolean DEBUG = false; + protected BSkyBlock plugin; - protected User user; - + private User user = null; + public FlagListener(BSkyBlock plugin) { super(); this.plugin = plugin; } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onEvent(Event e) { - if (DEBUG) { - plugin.getLogger().info(e.getEventName()); - } + + /** + * Sets the player associated with this event. + * If the user is a fake player, they are not counted. + * @param e - the event + * @return user or empty + */ + protected Optional getEventUser(Event e) { + // Set the user + if (e instanceof PlayerEvent) { + user = User.getInstance(((PlayerEvent)e).getPlayer()); + // Handle fake players + if (plugin.getSettings().getFakePlayers().contains(user.getName())) user = null; + } + return Optional.ofNullable(user); + } + + /** + * Explicitly set the user + * @param user + */ + protected void setUser(User user) { + this.user = user; + } + + /** + * Get the user associated with this event + * @return User or null + */ + protected User getUser() { + return user; } /* * The following methods cover the cancellable events and enable a simple noGo(e) to be used to cancel and send the error message */ + /** - * Sends the island protected message to user - * @param e + * Cancels the event and sends the island protected message to user + * @param e Event */ - protected void noGo(BlockBreakEvent e) { - e.setCancelled(true); - user.sendMessage("protection.protected"); + protected void noGo(Event e) { + noGo(e, false); } - + /** - * Sends the island protected message to user - * @param e + * Cancels the event and sends the island protected message to user unless silent is true + * @param e Event + * @param silent - if true, message is not sent */ - protected void noGo(BlockPlaceEvent e) { - e.setCancelled(true); - user.sendMessage("protection.protected"); + protected void noGo(Event e, boolean silent) { + if (e instanceof Cancellable) + ((Cancellable)e).setCancelled(true); + if (user != null) { + if (!silent) + user.sendMessage("protection.protected"); + user.updateInventory(); + } } - - /** - * Sends the island protected message to user - * @param e - */ - protected void noGo(InventoryPickupItemEvent e) { - e.setCancelled(true); - user.sendMessage("protection.protected"); - } - - /** - * Sends the island protected message to user - * @param e - */ - protected void noGo(PlayerLeashEntityEvent e) { - e.setCancelled(true); - user.sendMessage("protection.protected"); - } - - /** - * Sends the island protected message to user - * @param e - */ - protected void noGo(InventoryMoveItemEvent e) { - e.setCancelled(true); - user.sendMessage("protection.protected"); - } - + /** * Check if loc is in the island worlds * @param loc @@ -99,7 +101,7 @@ public abstract class FlagListener implements Listener { || loc.getWorld().equals(plugin.getIslandWorldManager().getNetherWorld()) || loc.getWorld().equals(plugin.getIslandWorldManager().getEndWorld())) ? true : false; } - + /** * Check if the entity is in the island worlds * @param entity - the entity @@ -108,5 +110,64 @@ public abstract class FlagListener implements Listener { protected boolean inWorld(Entity entity) { return inWorld(entity.getLocation()); } - + + /** + * Check if user is in the island worlds + * @param user - a user + * @return true if in world + */ + protected boolean inWorld(User user) { + return inWorld(user.getLocation()); + } + + /** + * Generic place blocks checker + * @param e + * @param loc + * @return true if the check is okay, false if it was disallowed + */ + protected boolean checkIsland(Event e, Location loc, Flag flag) { + return checkIsland(e, loc, flag, false); + } + + + + /** + * Generic place blocks checker + * @param e + * @param loc + * @param silent - if true, no attempt is made to tell the user + * @return true if the check is okay, false if it was disallowed + */ + protected boolean checkIsland(Event e, Location loc, Flag flag, boolean silent) { + // If the user is not set, try to get it from the event + if (getUser() == null) { + // Set the user associated with this event + if (!getEventUser(e).isPresent()) return true; + } + // If this is not an Island World, skip + if (!inWorld(getUser())) return true; + + // Get the island and if present, check the flag, react if required and return + Optional island = plugin.getIslands().getIslandAt(loc); + + if (island.isPresent()) { + if (!island.get().isAllowed(getUser(), flag)) { + noGo(e, silent); + return false; + } else { + return true; + } + } + + // The player is in the world, but not on an island, so general world settings apply + if (!flag.isAllowed()) { + noGo(e, silent); + return false; + } else { + return true; + } + + } + } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/AnvilListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/AnvilListener.java new file mode 100644 index 000000000..0a662e69e --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/AnvilListener.java @@ -0,0 +1,39 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags; + +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.listeners.FlagListener; +import us.tastybento.bskyblock.lists.Flags; + +/** + * @author ben + * + */ +public class AnvilListener extends FlagListener { + + public AnvilListener() { + super(BSkyBlock.getInstance()); + } + + /** + * Handle placing of Anvils + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerInteract(final PlayerInteractEvent e) { + if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) { + return; + } + if (e.getClickedBlock().getType().equals(Material.ANVIL)) { + checkIsland(e, getUser().getLocation(), Flags.ANVIL); + } + } +} diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java index b29da55e2..d86e41742 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java @@ -1,8 +1,20 @@ package us.tastybento.bskyblock.listeners.flags; +import org.bukkit.Material; +import org.bukkit.World.Environment; +import org.bukkit.block.Block; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.vehicle.VehicleDamageEvent; +import org.bukkit.util.BlockIterator; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.commands.User; @@ -14,7 +26,7 @@ public class BreakBlocksListener extends FlagListener { public BreakBlocksListener() { super(BSkyBlock.getInstance()); } - + /** * Prevents blocks from being broken * @@ -22,23 +34,112 @@ public class BreakBlocksListener extends FlagListener { */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onBlockBreak(final BlockBreakEvent e) { - - // If this is not an Island World, skip - if (!inWorld(e.getPlayer())) return; - - // Handle fake players - if (plugin.getSettings().getFakePlayers().contains(e.getPlayer().getName())) return; - - // Real players - // Get the island and if present, check the flag, react if required and return - plugin.getIslands().getIslandAt(e.getBlock().getLocation()).ifPresent(x -> { - if (!x.isAllowed(User.getInstance(e.getPlayer()), Flags.BREAK_BLOCKS)) noGo(e); - return; - }); - - // The player is in the world, but not on an island, so general world settings apply - if (!Flags.BREAK_BLOCKS.isAllowed()) noGo(e); + checkIsland(e, e.getBlock().getLocation(), Flags.BREAK_BLOCKS); } - + /** + * Prevents the breakage of hanging items + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW) + public void onBreakHanging(final HangingBreakByEntityEvent e) { + if (e.getRemover() instanceof Player) { + setUser(User.getInstance(e.getRemover())); + checkIsland(e, e.getEntity().getLocation(), Flags.BREAK_BLOCKS); + } + } + + /** + * Handles breaking objects + * + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerInteract(final PlayerInteractEvent e) { + // Only handle hitting things + if (!e.getAction().equals(Action.LEFT_CLICK_BLOCK)) return; + + // Look along player's sight line to see if any blocks are skulls + try { + BlockIterator iter = new BlockIterator(e.getPlayer(), 10); + Block lastBlock = iter.next(); + while (iter.hasNext()) { + lastBlock = iter.next(); + if (lastBlock.getType().equals(Material.SKULL)) { + checkIsland(e, lastBlock.getLocation(), Flags.BREAK_BLOCKS); + return; + } + } + } catch (Exception ex) {} + + switch (e.getClickedBlock().getType()) { + case CAKE_BLOCK: + case DRAGON_EGG: + case MOB_SPAWNER: + checkIsland(e, e.getClickedBlock().getLocation(), Flags.BREAK_BLOCKS); + return; + case BED_BLOCK: + if (e.getPlayer().getWorld().getEnvironment().equals(Environment.NETHER)) { + // Prevent explosions checkIsland(e, e.getClickedBlock().getLocation(), Flags.BREAK_BLOCKS); + return; + } + default: + break; + } + } + + + /** + * Handles vehicle breaking + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onVehicleDamageEvent(VehicleDamageEvent e) { + if (inWorld(e.getVehicle()) && e.getAttacker() instanceof Player) { + User user = User.getInstance((Player) e.getAttacker()); + // Get the island and if present, check the flag, react if required and return + plugin.getIslands().getIslandAt(e.getVehicle().getLocation()).ifPresent(x -> { + if (!x.isAllowed(getUser(), Flags.BREAK_BLOCKS)) { + e.setCancelled(true); + user.sendMessage("protection.protected"); + } + return; + }); + + // The player is in the world, but not on an island, so general world settings apply + if (!Flags.BREAK_BLOCKS.isAllowed()) { + e.setCancelled(true); + user.sendMessage("protection.protected"); + } + } + } + + /** + * Protect item frames, armor stands, etc. Entities that are actually blocks... + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEntityDamage(EntityDamageByEntityEvent e) { + // Only handle item frames + if (!(e.getEntity() instanceof ItemFrame) && !e.getEntityType().toString().endsWith("STAND")) return; + + // Get the attacker + if (e.getDamager() instanceof Player) { + setUser(User.getInstance(e.getDamager())); + checkIsland(e, e.getEntity().getLocation(), Flags.BREAK_BLOCKS); + } else if (e.getDamager() instanceof Projectile) { + // Find out who fired the arrow + Projectile p = (Projectile) e.getDamager(); + if (p.getShooter() instanceof Player) { + setUser(User.getInstance((Player)p.getShooter())); + if (!checkIsland(e, e.getEntity().getLocation(), Flags.BREAK_BLOCKS)) { + e.getEntity().setFireTicks(0); + e.getDamager().remove(); + } + } + } + } + + } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/PlaceBlocksListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/PlaceBlocksListener.java index d4922b637..a1b212721 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/PlaceBlocksListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/PlaceBlocksListener.java @@ -1,11 +1,16 @@ package us.tastybento.bskyblock.listeners.flags; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.EntityBlockFormEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.listeners.FlagListener; import us.tastybento.bskyblock.lists.Flags; @@ -14,30 +19,76 @@ public class PlaceBlocksListener extends FlagListener { public PlaceBlocksListener() { super(BSkyBlock.getInstance()); } - + + /** - * Prevents blocks from being placed + * Check blocks being placed in general * * @param e */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onBlockPlace(final BlockPlaceEvent e) { + checkIsland(e, e.getBlock().getLocation(), Flags.PLACE_BLOCKS); + } - // If this is not an Island World, skip - if (!inWorld(e.getPlayer())) return; - - // Handle fake players - if (plugin.getSettings().getFakePlayers().contains(e.getPlayer().getName())) return; - - // Real players - // Get the island and if present, check the flag, react if required and return - plugin.getIslands().getIslandAt(e.getBlock().getLocation()).ifPresent(x -> { - if (!x.isAllowed(User.getInstance(e.getPlayer()), Flags.PLACE_BLOCKS)) noGo(e); - return; - }); - - // The player is in the world, but not on an island, so general world settings apply - if (!Flags.PLACE_BLOCKS.isAllowed()) noGo(e); + /** + * Handles placing items into ItemFrames + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerHitEntity(PlayerInteractEntityEvent e) { + if (e.getRightClicked().getType().equals(EntityType.ITEM_FRAME)) { + checkIsland(e, e.getRightClicked().getLocation(), Flags.PLACE_BLOCKS); + } + } + + /** + * Handle placing of fireworks, mine carts, end crystals, doors, chests and boats on land + * The doors and chests are related to an exploit. + * @param e + */ + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerInteract(final PlayerInteractEvent e) { + if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) { + return; + } + switch (e.getClickedBlock().getType()) { + case FIREWORK: + checkIsland(e, e.getClickedBlock().getLocation(), Flags.PLACE_BLOCKS); + return; + case RAILS: + case POWERED_RAIL: + case DETECTOR_RAIL: + case ACTIVATOR_RAIL: + if (e.getMaterial() != null && (e.getMaterial() == Material.MINECART || e.getMaterial() == Material.STORAGE_MINECART || e.getMaterial() == Material.HOPPER_MINECART + || e.getMaterial() == Material.EXPLOSIVE_MINECART || e.getMaterial() == Material.POWERED_MINECART)) { + checkIsland(e, e.getClickedBlock().getLocation(), Flags.PLACE_BLOCKS); + } + return; + default: + // Check in-hand items + if (e.getMaterial() != null) { + // This check protects against an exploit in 1.7.9 against cactus + // and sugar cane and placing boats on non-liquids + if (e.getMaterial().equals(Material.END_CRYSTAL) || e.getMaterial() == Material.WOOD_DOOR || e.getMaterial() == Material.CHEST + || e.getMaterial() == Material.TRAPPED_CHEST || e.getMaterial() == Material.IRON_DOOR + || (e.getMaterial().name().contains("BOAT") && !e.getClickedBlock().isLiquid())) { + checkIsland(e, getUser().getLocation(), Flags.PLACE_BLOCKS); + } + } + } } + /** + * Handles Frost Walking on visitor's islands. This creates ice blocks, which is like placing blocks + * @param e + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) + public void onBlockForm(EntityBlockFormEvent e) { + if (e.getNewState().getType().equals(Material.FROSTED_ICE)) { + // Silently check + checkIsland(e, getUser().getLocation(), Flags.PLACE_BLOCKS, true); + } + } + } diff --git a/src/main/java/us/tastybento/bskyblock/lists/Flags.java b/src/main/java/us/tastybento/bskyblock/lists/Flags.java index 58b551020..66edc3c7c 100644 --- a/src/main/java/us/tastybento/bskyblock/lists/Flags.java +++ b/src/main/java/us/tastybento/bskyblock/lists/Flags.java @@ -9,4 +9,48 @@ public class Flags { public static final Flag BREAK_BLOCKS = new FlagBuilder().id("BREAK_BLOCKS").icon(Material.STONE).listener(new BreakBlocksListener()).build(); public static final Flag PLACE_BLOCKS = new FlagBuilder().id("PLACE_BLOCKS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag ANVIL = new FlagBuilder().id("ANVIL").icon(Material.DIRT).listener(new AnvilListener()).build(); + public static final Flag ARMOR_STAND = new FlagBuilder().id("ARMOR_STAND").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag BEACON = new FlagBuilder().id("BEACON").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag BED = new FlagBuilder().id("BED").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag BREEDING = new FlagBuilder().id("BREEDING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag BREWING = new FlagBuilder().id("BREWING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag BUCKET = new FlagBuilder().id("BUCKET").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag COLLECT_LAVA = new FlagBuilder().id("COLLECT_LAVA").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag COLLECT_WATER = new FlagBuilder().id("COLLECT_WATER").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag CHEST = new FlagBuilder().id("CHEST").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag CHORUS_FRUIT = new FlagBuilder().id("CHORUS_FRUIT").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag CRAFTING = new FlagBuilder().id("CRAFTING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag CROP_TRAMPLE = new FlagBuilder().id("CROP_TRAMPLE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag DOOR = new FlagBuilder().id("DOOR").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag EGGS = new FlagBuilder().id("EGGS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag ENCHANTING = new FlagBuilder().id("ENCHANTING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag ENDER_PEARL = new FlagBuilder().id("ENDER_PEARL").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag FIRE = new FlagBuilder().id("FIRE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag FIRE_EXTINGUISH = new FlagBuilder().id("FIRE_EXTINGUISH").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag FIRE_SPREAD = new FlagBuilder().id("FIRE_SPREAD").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag FURNACE = new FlagBuilder().id("FURNACE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag GATE = new FlagBuilder().id("GATE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag MOUNT_INVENTORY = new FlagBuilder().id("MOUNT_INVENTORY").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag RIDING = new FlagBuilder().id("RIDING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag HURT_MOBS = new FlagBuilder().id("HURT_MOBS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag LEASH = new FlagBuilder().id("LEASH").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag LEVER_BUTTON = new FlagBuilder().id("LEVER_BUTTON").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag MOB_SPAWN = new FlagBuilder().id("MOB_SPAWN").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag MUSIC = new FlagBuilder().id("MUSIC").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag PORTAL = new FlagBuilder().id("PORTAL").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag PRESSURE_PLATE = new FlagBuilder().id("PRESSURE_PLATE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag PVP = new FlagBuilder().id("PVP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag MILKING = new FlagBuilder().id("MILKING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag NETHER_PVP = new FlagBuilder().id("NETHER_PVP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag END_PVP = new FlagBuilder().id("END_PVP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag REDSTONE = new FlagBuilder().id("REDSTONE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag SPAWN_EGGS = new FlagBuilder().id("SPAWN_EGGS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag SHEARING = new FlagBuilder().id("SHEARING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag TRADING = new FlagBuilder().id("TRADING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag VISITOR_ITEM_DROP = new FlagBuilder().id("VISITOR_ITEM_DROP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + public static final Flag VISITOR_ITEM_PICKUP = new FlagBuilder().id("VISITOR_ITEM_PICKUP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build(); + + }