Teleporation lag

Discussion in 'Plugin Development' started by girardcome, Jun 17, 2019.

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

    girardcome

    Hello, I'm exposing my problem below:

    What I want: A player must be teleported instantly without waiting in the void (lag).

    What I did:
    PHP:
    @SuppressWarnings("deprecation")
        public 
    void teleportRandomLocation(Player p, final Location locint xint z) {

            
    loc.setX(x);
            
    loc.setZ(z);
            
    loc.setY(p.getWorld().getHighestBlockYAt(loc) + 10);

            
    Chunk c loc.getChunk();
            
    loc.getWorld().loadChunk(c);
            
    loc.getWorld().refreshChunk(c.getX(), c.getZ());
            if (
    c.isLoaded()) {
                
    Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getInstance(), new Runnable() {
                    public 
    void run() {

                
    Material type loc.getBlock().getType();
                if (
    type == Material.AIR && type != Material.WATER && type != Material.LAVA) {
                    
    p.teleport(loc);
                }
                    }
                }, 
    2L);
            }
        }
    What I got: Nothing changes .. I received the message "LOADED." but it always teleports me into the void, and I have to wait 2 or 3 seconds before landing on a block.

    I thank those who will help me.
     
  2. Offline

    Kars

    You do everything correctly but you need to add in delay. The chunk gets "loaded" but does not finish loading until a couple of seconds in. Your command teleports you there straight away.

    c.isLoaded does not wait for the chunk to finish loading its blocks. And if it did, the if {} would not execute because it wasn'tloaded. The code execution wouldn't wait. You need the delay
     
  3. Offline

    girardcome

    So if I add a "while" loop, and tell the server that "while the chunck is not loaded, the player will not be teleported"?
     
  4. Offline

    Kars

    Yes but that would cause a dead-loop. You should schedule the teleportation in a seperate task to be safe. Execute that task with a delay. Also i'm not sure if you can check for your definition of loaded.
     
  5. Offline

    girardcome

    Okay so i updated it with your adivse.. but steel doesn't worked. I still got the "Loadeed chunks at..." message, but i'm always teleport into the void for 2 seconds or 3 before landing on a block back.

    PHP:
        @SuppressWarnings("deprecation")
        public 
    void teleportRandomLocation(Player pLocation locint xint z) {
            
    loc.setX(x);
            
    loc.setZ(z);
            
    loc.setY(p.getWorld().getHighestBlockYAt(loc) + 10);

            
    Chunk c loc.getChunk();
            
    loc.getWorld().loadChunk(c);
            
    loc.getWorld().refreshChunk(c.getX(), c.getZ());
           
            
    taskID Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Main.getInstance(), new Runnable() {

                public 
    void run() {
                    if(
    c.isLoaded()) {
                        
    Bukkit.getScheduler().cancelTask(taskID);
                        
    p.sendMessage("Loaded chunk at " ", " z);
                        
    p.teleport(loc);
                    }
                }
            }, 
    1L1L);
        }
     
  6. Offline

    Kars

    PHP:
    ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
    Runnable task = () -> {
        
    p.sendMessage("Loaded chunk at " ", " z);
        
    p.teleport(loc);
    }
    scheduler.schedule(task5TimeUnit.SECONDS);
    scheduler.shutdown();
    This will teleport you there after a 5 second delay.
    I can't make any promises about the chunk being "loaded" when you arrive. This depends on the 3 lines you use for loading them to work like you expect them to. But it will teleport you with a delay.

    There is no need to check for c.isLoaded(). This will return true as you called c.Load before. Like i said code execution does not wait till it is "loaded" by your definition. The game has started to load it, therefore it returns true.
     
    Last edited: Jun 17, 2019
  7. Offline

    Zombie_Striker

    @girardcome
    A few improvements to the code:
    1. Use BukkitRunnables instead of using the regular scheduler. BukkitRunnables have a built-in cancel method (BukkitRunnable#cancel()) and you can pass around the whole runnable instance, that way you don't need to work with just IDs (Below is an example ofd the runnable)
    2. If you only want the code to run once, use a delayed task instead of canceling a repeating task.
    3. If you want the delay to last 5 seconds, instead of using 1L, use 100L (20*5L), since that value takes in ticks, and there are 20 ticks in one second.
    Here's an example of what you want to use:
    Code:java
    1.  
    2. new BukkitRunnable(){
    3. public void run()
    4. if(c.isLoaded()) {
    5. p.sendMessage("Loaded chunk at " + x + ", " + z);
    6. p.teleport(loc);
    7. }
    8. }
    9. }.runTaskLater(Main.getInstance(), 100L);
    10.  
     
  8. Offline

    girardcome

    I did what you've done but it's not even working.. it's teleporting me 5 seconds later but still in the void..
     
Thread Status:
Not open for further replies.

Share This Page