How to cancel teleport on movement

Discussion in 'Plugin Development' started by Alkerti, Feb 24, 2014.

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

    Alkerti

    Hey guys, I need some help with my code. I just fixed up because it was really outdated ect.. Anyways I need help with the on movement cancellation of my Teleport to spawn because I could never get it working.

    here's my playerlistener
    Code:
    package me.kieran.hearthstone;
     
    import java.util.ArrayList;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.block.Block;
    import org.bukkit.entity.Item;
    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.BlockPlaceEvent;
    import org.bukkit.event.player.PlayerDropItemEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerMoveEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.potion.PotionEffect;
    import org.bukkit.potion.PotionEffectType;
     
    public class PlayerListener implements Listener {
     
        private Main plugin;
        public PlayerListener(Main plugin)
        {
            this.plugin = plugin;
        }
       
        ArrayList<Player> cooldown = new ArrayList<Player>();
       
        @EventHandler
        public void onPlayerJoinEvent(PlayerJoinEvent e) {
            Player p = e.getPlayer();
            if(!p.getInventory().contains(Material.PORTAL)) {
                p.getInventory().addItem(new ItemStack[] { new ItemStack(Material.PORTAL, 1) });
                p.sendMessage(ChatColor.LIGHT_PURPLE + "Your Hearthstone returns to you");
            }
        }
     
        @EventHandler
        public void onBlockPlace (BlockPlaceEvent e) {
         
            Block block = e.getBlockPlaced();
            if (block.getType() == Material.PORTAL) {
                e.setCancelled(true);
            }
        }
     
        @EventHandler
        public void onItemDrop (PlayerDropItemEvent e) {
            Player p = e.getPlayer();
         
                Item drop = e.getItemDrop();
                if (drop.getItemStack().getType() == Material.PORTAL) {
                    e.setCancelled(true);
                    p.getInventory().removeItem(new ItemStack[] { new ItemStack(Material.PORTAL, 1) });
                    p.sendMessage(ChatColor.DARK_GRAY + "Your Hearthstone vanishes!");
                }
        }
       
        @EventHandler
        public void onPlayerMove(PlayerMoveEvent e){
            final Player p = e.getPlayer();
            if(cooldown.contains(p.getName())){
                p.sendMessage(ChatColor.GRAY + "Teleport cancelled.");
                return;
            }
        }
     
            @EventHandler
            public void onPlayerInteract(PlayerInteractEvent e) {
                final Player p = e.getPlayer();
                if(e.getAction() == Action.LEFT_CLICK_AIR);
                if (e.getItem() != null && e.getItem().getType() == Material.PORTAL){
               
                    if(cooldown.contains(p.getName())) {
                        p.sendMessage(ChatColor.GRAY + "You can't do that yet!");
                        return;
                    }
                 
                cooldown.add(p);
                Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
                   
                        public void run(){
                            cooldown.remove(p.getName());
                            p.sendMessage(ChatColor.GRAY + "Your Hearthstone starts to glow.");
                        }
                    }, 12000);
             
                if(cooldown.add(p))
                    p.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, 210, 0));
                    p.sendMessage(ChatColor.LIGHT_PURPLE + "Warping to Spawn..");
                 
                Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
                    @Override
                    public void run() {
                        p.sendMessage(ChatColor.LIGHT_PURPLE + "Warping..");
                        p.teleport(p.getWorld().getSpawnLocation());
                    }
                }, 180);
                }
            }
    }
    My code is a bit messy :p
     
  2. Offline

    Alshain01

    Short of sending a message, your not doing anything in PlayerMoveEvent. Shouldn't you cancel something?

    EDIT: Oh, I'm sorry, is that what you were asking? You need to store the player name or UUID and the scheduler for that player in class Map so you can retrieve and cancel it.
     
  3. Offline

    Alkerti

    I have no idea how to do that. XD I'm still pretty new at this. I'm pulling my hair out on this problem though,

    EDIT* I cancelled the move event before if the player was under the 'cooldown' just stopped him from moving :p (obviously was expecting that.)
     
  4. Offline

    CrazyGuy3000

    Question.. do you know Java :??
     
  5. Offline

    Alkerti

    I'm trying to learn it, I know some of it though.
     
  6. Offline

    Jnorr44

    I believe there is a PlayerInteract method setCancelled(boolean cancel), if so, try:

    event.setCancelled(true);

    before you return onPlayerInteract.
     
  7. Offline

    CrazyGuy3000

    This doesn't work for the teleport event. AFAIK
     
  8. Offline

    Alkerti

    Code:
        @EventHandler
        public void onPlayerMove(PlayerMoveEvent e){
            final Player p = e.getPlayer();
            if(cooldown.contains(p.getName())){
                p.sendMessage(ChatColor.GRAY + "Teleport cancelled.");
                return;
    also my cool down doesn't seem to work? whenever I interact with the 'hearthstone' (portal) its supposed to put a 10 minute timer till i can use it again, doesn't seem to work. just keeps teleporting me whenever i left click it or right click it.

    edit* Ill play around with it tomorrow again, I think I know whats wrong Ill get back to you guys see how it goes.
     
  9. Offline

    Alshain01

    Ok, you need to create a BukkitRunnable on a repeating task. That runnable should control both the countdown and the final warp. This WILL NOT be Asynchronous. So the simple way to do this is start with an integer at the number of countdown seconds you want, and each time the task runs

    Then create a new instance of that runnable to runTaskTimer(this, 0, 20). Note 20 is approximately 1 second, but not exact because it's actually server ticks. runTaskTimer returns a BukkitTask object.

    You need to store that BukkitTask in a Map<UUID, BukkitTask>, where the UUID is the player.getUniqueID(). If the player moves, retrieve the Bukkit task from the Map and .cancel().

    Due to the complexity here, I would make the task a separate class or inner class. Don't make it hard to read by writing an in-line class like you did above.

    Code:java
    1. //This is a class variable, it needs to be final for the inner class to see it. (don't worry, only the outer object is final, you can still add and remove stuff)
    2. final Map<UUID, BukkitTask> tpQueue = new Map<UUID, BukkitTask>();


    In the PlayerMoveEvent, do:

    Code:java
    1. tpQueue.get(player.getUniqueId()).cancel();
    2. tpQueue.remove(player.getUniqueId());
     
  10. Offline

    Jnorr44

    Well, I only saw the PlayerMoveEvent in his code. Also, PlayerTeleport may be part of PlayerMove (or related to it), since moving is just a lot of teleporting.
     
  11. Offline

    Alkerti

    Map<UUID, BukkitTask>();

    Map comes up with an error,

    + still haven't figured this out :p fixed some of the code at school (other parts) but i'm still stuck on this problem.
    also ran into another problem!
    Code:
                if(cooldown.add(p))
                    p.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, 210, 0));
                    p.sendMessage(ChatColor.LIGHT_PURPLE + "Warping to Spawn..");
                 
                    Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
                       
                        @Override
                        public void run() {
                            if(cooldown.add(p))
                                p.sendMessage(ChatColor.LIGHT_PURPLE + "Warping..");
                                p.teleport(p.getWorld().getSpawnLocation());
                            }
                        }
                ,180L);
                }
            }
    }
    works fine but when I right click after teleporting i tp again? this code here: is supposed to prevent it. can you help me fix this issue too?

    Code:
                  if(cooldown.contains(p.getName())) {
                        p.sendMessage(ChatColor.GRAY + "You can't do that yet!");
                        return;
                    }
                   
                Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable(){
                   
                    @Override
                        public void run(){
                            cooldown.remove(p.getName());
                            p.sendMessage(ChatColor.GRAY + "Your Hearthstone starts to glow.");
                        }
                    }, 12000);
     
  12. Offline

    Alshain01

    Ah sorry, should be




    • final Map<UUID, BukkitTask> tpQueue = new HashMap<UUID, BukkitTask>();



     
  13. Offline

    Alkerti

    so it would look something like this...?
    Code:
        @EventHandler
        public void onPlayerMove(PlayerMoveEvent e){
            final Player p = e.getPlayer();
            if(cooldown.contains(p.getName())) {
            new BukkitRunnable() {
           
            final Map<UUID, BukkitTask> tpQueue = new HashMap<UUID, BukkitTask>();
           
            @Override
            public void run(){
                tpQueue.get(p.getUniqueId()).cancel();
                tpQueue.remove(p.getUniqueId());
                        p.sendMessage(ChatColor.GRAY + "Teleport cancelled.");
        }
     
  14. Offline

    LCastr0

    Use a List<String> player = new ArrayList<String>();
    then on the command to teleport, do player.add(p.getName());
    then on the movement to cancel, do:
    if(player.contains(p.getName()){
    player.remove(p.getName());
    }

    Then, where you want it to the player be teleported, do:
    if(player.contains(p.getName()){
    p.teleport(Location);
    }
     
  15. Offline

    Alshain01

    No, the map should be a class variable, and onPlayerMove should just remove it from the map

    Code:
    final Map<UUID, BukkitTask> tpQueue = new HashMap<UUID, BukkitTask>();
        @EventHandler
        public void onPlayerMove(PlayerMoveEvent e){
            final Player p = e.getPlayer();
            if(tpQueue.contains(p.getUniqueID())) {
                tpQueue.get(p.getUniqueId()).cancel();
                tpQueue.remove(p.getUniqueId());
                p.sendMessage(ChatColor.GRAY + "Teleport cancelled.");
            }
         }
    Now, adding players to the queue will happen elsewhere, wherever it is your scheduling the countdown..

    Code:
    tpQueue.put(p.getUniqueID, new BukkitRunnable() {
    // Do the countdown and the teleport here.  If they move it will just get cancelled anyway.
    // Make sure you remove from the queue if the teleport succeeds!
    }.runTaskLater(plugin, delay));
    
     
  16. Offline

    Alkerti

    Alshain01
    Okay! Everything is okay now but 1 last thing,

    I tried :
    Code:
                            @Override
                            public void run() {
                                (tpqueue.put(p.getUniqueId(), new BukkitRunnable()) {
                                    p.sendMessage(ChatColor.LIGHT_PURPLE + "Warping..");
                                p.teleport(p.getWorld().getSpawnLocation());
                                tpqueue.remove(p.getUniqueId());
                                }
                            }
                        }.runTaskLater(plugin, 220));
            }
        }
    }
    edit
    tpqueue.put(p.getUniqueID, new BukkitRunnable()error right here > ) <{
    for some reason... .-. says to add ; but it just causes more errors.

    + whenever i move it says teleport cancelled. .-.
     
  17. Offline

    Alshain01

    I would do this as an inner class and let the same timer handle both the countdown AND the final warp. That way you can even construct it with the total count, so it doesn't always have to be the same (future expansion maybe?, let the operator choose in config.yml?).

    Code:java
    1. private class Teleport extends BukkitRunnable {
    2. int count;
    3. String player
    4. Teleport(int count, String player) {
    5. this.count = count;
    6. this.player = player;
    7. }
    8.  
    9. @Override
    10. public run() {
    11. if(count > 0) {
    12. //Send a message saying count till warp
    13. count--;
    14. } else {
    15. //Teleport code here
    16. tpQueue.remove(player.getUniqueID());
    17. this.cancel();
    18. }
    19. }
    20. }


    So then up in your command handler or whatever is starting the warp process...

    tpQueue.put(player.getUniqueID(), new Teleport().runTaskTimer(this, 0, 20));

    runTaskTimer returns the BukkitTask, which can be cancelled later by PlayerMoveEvent.

    The task will run approx every second until it reaches 0 at which point it will self cancel OR PlayerMoveEvent can cancel it prematurely.

    should have been tpQueue.put(player.getUniqueID(), new Teleport(5, player.getName()).runTaskTimer(this, 0, 20));

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 6, 2016
Thread Status:
Not open for further replies.

Share This Page