[Lib] PlayerBlockSelector v1.1 - An abstract class to get blocks chosen by a player

Discussion in 'Resources' started by MrFigg, Sep 4, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    MrFigg

    I was bored and decided to refine my BlockSelector class from this thread to make it into a proper stand alone class. This class addresses the task of having a player select a block by punching it, and doing something with that block afterwords. (It's been done to death I'm sure, but I was just that bored...)

    To use just put PlayerBlockSelector.java anywhere in your project. Update the package declaration and you're good to go.

    PlayerBlockSelector.java (open)
    Code:
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
     
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.HandlerList;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.event.player.PlayerTeleportEvent;
    import org.bukkit.plugin.java.JavaPlugin;
     
    /*
    * PlayerBlockSelector
    *
    * This program is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    *
    * @author MrFigg
    * @version 1.1
    */
     
    public abstract class PlayerBlockSelector implements Runnable {
        private static HashMap<String, PlayerBlockSelector> playerBlockSelectors = new HashMap<String, PlayerBlockSelector>();
     
        public static void cancelAllBlockSelectors() {
            for(PlayerBlockSelector selector : playerBlockSelectors.values()) {
                selector.cancel();
            }
        }
     
        /**
        * Called when a player selects a block
        *
        * @param event - the PlayerInteractEvent
        */
        public abstract void onBlockSelected(PlayerInteractEvent event);
     
        /**
        * Called when something cancels the PlayerBlockSelector
        *
        * @param cancelReason - 0 = expired, 1 = manually canceled, 2 = player quit, 3 = player left world, 4 = interrupted
        */
        public abstract void onCancel(int cancelReason);
     
        private JavaPlugin plugin;
        protected String playerName;
        private long time = 1200L;
        private boolean lockWorld = true;
        private List<Material> punch = Arrays.asList(new Material[]{Material.AIR});
        private World startWorld;
        private int schedulerTaskID = 0;
        private PlayerBlockListener listener;
        private boolean keepAlive = false;
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player) {
            this.plugin = plugin;
            playerName = player.getName();
       
            start(player);
        }
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player, long time) {
            this.plugin = plugin;
            playerName = player.getName();
            this.time = time;
       
            start(player);
        }
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player, boolean lockWorld) {
            this.plugin = plugin;
            playerName = player.getName();
            this.lockWorld = lockWorld;
       
            start(player);
        }
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player, Material... punch) {
            this.plugin = plugin;
            playerName = player.getName();
            if(punch==null) punch = new Material[]{null};
            this.punch = Arrays.asList(punch);
       
            start(player);
        }
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player, long time, boolean lockWorld) {
            this.plugin = plugin;
            playerName = player.getName();
            this.time = time;
            this.lockWorld = lockWorld;
       
            start(player);
        }
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player, long time, Material... punch) {
            this.plugin = plugin;
            playerName = player.getName();
            this.time = time;
            if(punch==null) punch = new Material[]{null};
            this.punch = Arrays.asList(punch);
       
            start(player);
        }
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player, boolean lockWorld, Material... punch) {
            this.plugin = plugin;
            playerName = player.getName();
            this.lockWorld = lockWorld;
            if(punch==null) punch = new Material[]{null};
            this.punch = Arrays.asList(punch);
       
            start(player);
        }
     
        public PlayerBlockSelector(JavaPlugin plugin, Player player, long time, boolean lockWorld, Material... punch) {
            this.plugin = plugin;
            playerName = player.getName();
            this.time = time;
            this.lockWorld = lockWorld;
            if(punch==null) punch = new Material[]{null};
            this.punch = Arrays.asList(punch);
       
            start(player);
        }
     
        private void start(Player player) {
            startWorld = player.getWorld();
            if(punch.isEmpty()) punch.add(Material.AIR);
            listener = new PlayerBlockListener();
       
            if(playerBlockSelectors.containsKey(playerName)) playerBlockSelectors.get(playerName).interrupt();
            playerBlockSelectors.put(playerName, this);
       
            schedulerTaskID = plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, this, time);
            plugin.getServer().getPluginManager().registerEvents(listener, plugin);
        }
     
        public Player getPlayer() {
            return plugin.getServer().getPlayer(playerName);
        }
     
        @Override
        public void run() {
            destroy();
            onCancel(0);
        }
     
        public void cancel() {
            destroy();
            onCancel(1);
        }
     
        public void interrupt() {
            destroy();
            onCancel(4);
        }
     
        private void destroy() {
            HandlerList.unregisterAll(listener);
            if(schedulerTaskID!=0 && plugin.getServer().getScheduler().isQueued(schedulerTaskID)) plugin.getServer().getScheduler().cancelTask(schedulerTaskID);
            schedulerTaskID = 0;
       
            playerBlockSelectors.remove(playerName);
        }
     
        protected void keepAlive() {
            keepAlive = true;
        }
     
        protected class PlayerBlockListener implements Listener {
            @EventHandler
            public void onPlayerInteract(PlayerInteractEvent event) {
                if(event.isCancelled()) return;
                if(!event.getPlayer().getName().equals(playerName)) return;
                if(!event.hasBlock()) return;
                if(!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)&&!event.getAction().equals(Action.LEFT_CLICK_BLOCK)) return;
                if(punch.size()>1||punch.get(0)!=null) {
                    Material itemInHand = Material.AIR;
                    if(event.getPlayer().getItemInHand()!=null){
                        itemInHand = event.getPlayer().getItemInHand().getType();
                    }
                    if(!punch.contains(itemInHand)) return;
                }
                onBlockSelected(event);
                if(!keepAlive) destroy();
                keepAlive = false;
                event.setCancelled(true);
            }
     
            @EventHandler
            public void onPlayerLeaveWorld(PlayerTeleportEvent event) {
                if(!lockWorld) return;
                if(event.isCancelled()) return;
                if(!event.getPlayer().getName().equals(playerName)) return;
                if(event.getTo().getWorld().equals(startWorld)) return;
                destroy();
                onCancel(3);
            }
       
            @EventHandler
            public void onPlayerQuit(PlayerQuitEvent event) {
                if(!event.getPlayer().getName().equals(playerName)) return;
                destroy();
                onCancel(2);
            }
        }
    }
    

    For your basic block selection all you have to do is put the following somewhere in your code. (Usually in a CommandExecutor.)
    Code:
    new PlayerBlockSelector(plugin, player) {
        @Override
        public void onBlockSelected(PlayerInteractEvent event) {
            /**
            * Called when a player selects a block
            *
            * @param event - the PlayerInteractEvent of the player punching
            */
            // Do whatever you want with the selected block here
        }
     
        @Override
        public void onCancel(int cancelReason) {
            /**
            * Called when something cancels the PlayerBlockSelector
            *
            * @param cancelReason - 0 = expired, 1 = manually canceled, 2 = player quit, 3 = player left world, 4 = interrupted (usually by another PlayerBlockSelector)
            */
            // Do whatever you need to when the PlayerBlockSelector gets canceled here
        }
    };
    The class will automatically set up using a 1 minute expiration timer, locking the block selector to the players current world, and making the player use his bare fists to select the block.

    Here's an example using some of the more advanced options:
    Code:
    new PlayerBlockSelector(plugin, player, 12000L, false, Material.WOOD_AXE, Material.STONE_AXE, Material.GOLD_AXE) {
        public List<Location> locations = new ArrayList<Location>();
     
        @Override
        public void onBlockSelected(PlayerInteractEvent event) {
            if(locations.size()>=10) return;
            locations.add(event.getBlock().getLocation().add(new Vector(0, 1, 0)));
            event.getPlayer().sendMessage("Spawn Location Added");
            if(locations.size()<10) keepAlive();
            else {
                event.getPlayer().sendMessage("All 10 Spawn Locations Set");
                // Do something with the spawn locations
            }
        }
     
        @Override
        public void onCancel(int cancelReason) {
            Player player = getPlayer();
            if(player==null||!player.isOnline()) return;
            if(cancelReason==0) player.sendMessage("Block selector has expired. Please retype the command to start again.");
        }
    };
     

    Attached Files:

Thread Status:
Not open for further replies.

Share This Page