Problems teleporting inside the Nether?

Discussion in 'Spigot Plugin Development' started by Dimon6, Jun 25, 2015.

  1. To learn making plugins, I started making some simple things with commands and teleporting, nothing it doesn't exist for sure but for practicing is always good.

    I think I made succesfuly a teleporting program that works both in the overworld and in the end_world.

    I tried then implementing the teleport to the Nether and it didn't work.
    My question is not exactly what is wrong in the code, since I tried changing things to more simple things but things to assure it was not other code and it did not work properly either.

    The command takes an X and Y coordinates and teleports you to the location always looking for the highest block in that location.

    I had to change it for the nether case since I read on the forums that the game wont let you teleport on top the nether world, since my code would make exactly that, search the highest block and teleport you on top of that block, but that would mean to appear over the nether.

    I tried then giving a fixed location to teleport to and tried to give a fixed height but I always seem to be teleported to the x: 0 and y:0 coordinates.

    In one of the tries I appeared inside a netherrack wall, so if it was in survival mode I would have sufocated.

    Is it made so you cant use tp commands in the nether or something? Am I missing something?
    My code might be a bit messy and not well structured, I have not much experience with structuring the code properly I think and it would have be made more efficiently. If you want I can put it here.

    Thanks in advance.
     
  2. It is very difficult to TP to the nether ... what I do is something along the lines of

    1. Look for a safe location starting at the target Y location and going down
    2. If that fails, do the same thing but going up

    In both cases, stop before you reach the floor/ceiling- so around Y=3 and Y=125 ... or so.

    If neither of those works, I just give up and cancel the TP. It'd be possible to start looking around more in X and Z for a safe place, but that starts to get a little fishy and extremely inefficient.

    For "safe" place, you can basically look for solid non-lava ground with 2 air blocks above it. If you want to get fancier, you can account for blocks that are ok to stand in (torches, signs, tall grass, open doors, etc).

    One additional note that might get you hung up- the vanilla TP code does some weird stuff with cross-world TP. It basically tries to look for a "safe place", but what it considers safe is a little stricter than what I would consider- it won't, for instance, let you TP on top of an entity. So a lot of the time, you'll find what you consider a safe spot, but won't end up there due to the vanilla code changing the target location.

    You can work around this hackily with a "double TP" when going cross-world- TP them once so they're in the target world at least, then if necessary TP them again to get them to the spot you intended.

    None of those should change the X,Z coords though.. so if you're always ending up at 0,0 I can't really explain that.
     
  3. Code (Text):
    Location loc = player.getLocation();
    World nether = Bukkit.getWorld("world_nether");
    loc.setWorld(nether);
    player.teleport(loc)
     
  4. The thing is I do a tp within the world im in. If i am in the nether the top will be for the nether. No cross world tp.
    But, no matter what I try, the nether wont let me create a proper teleport code for some reason.
    I tried to check Y axys from 5 to 110 (to assure it a little bit more) and when it finds a solid block it checks if both blocks above the solid blocks are air. If so it creates a new valid location and teleports to it, if it is not valid the location remains null, and the teleport is executed, but cause the location being null the teleport fails on purpose.
    The thing is when the teleport executes correctly with a valid location with an X, Y and Z coords, no matter if I enter -1000 343 or 12 44, the command will teleport me to 0.xxx 0.xxx, always to the same points of posible, like it was hard coded not to let me teleport anywhere in the nether.
     
  5. Just teleport them to the World "world_nether", or what you have your nether world called.
     
  6. This might be the result of the world/chunk not being loaded already or from editing the locations in a wrong way.
    I remember having this issue once on my own when playing around with custom worlds, but I can't seem to remember exactly how I solved this.
    Would you mind to share some more of the surrounding code of your teleport?
     
  7. I screwed something up, now the tp comand does not work in the overworld either, now it's not only a problem in the nether.
    I'll have to check what is wrong...
    As soon as I check if something is wrong I'll post the code.
    I did something and touched some part I had not to touch :p

    Aha! I fixed it! now it seems it works pretty much all the time.
    Here's the code.
    The stupid error was that I was trying to use a Double wrapper for the isNumber method thinking the value would pass by reference so that I had not to use the parseDouble or parseInt method again, but I had to remove it cause the value was not changing and the value for X and Z was always 0 from the begining.
    You'll probably think the code is improvable and can be mor effiecient and things like that but my knowledge about efficiency is not very high i think :p

    @NathanWolf
    @Noxyro
    The Utilities class:
    Code (Text):

    package com.Dimon6.teleportPlus;

    import org.bukkit.Location;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.block.BlockFace;
    import org.bukkit.entity.Player;

    public class Utilities {

        public static boolean isNumber(String numberStr){
            try {
             
                Double.parseDouble(numberStr);
                return true;
             
            } catch(NumberFormatException e){
                return false;
            }
        }
     
        //Method to check the proper location where the player should teleport to.
        //It takes the highest block given the x and z coordinates.
        private static Location getProperLocationOverWorldEnd(World world,
                Player player, double x,  double z) {
         
            Location location = null;
            Block block = world.getHighestBlockAt((int)x, (int)z);
            location = new Location(world, x, (double)block.getY(), z);
            return location;
        }
     

        private static boolean chkRelativeBlock(Block block, BlockFace face, int distance){
         
            Block relativeBlock = block.getRelative(face, distance);
         
            Block footBlock = relativeBlock.getRelative(BlockFace.UP);
            Block headBlock = relativeBlock.getRelative(BlockFace.UP, 2);
         
            if(!relativeBlock.isLiquid() && !relativeBlock.isEmpty()){
                if(footBlock.isEmpty() && headBlock.isEmpty()){
                    return true;
                }
            }
         
            return false;
        }
     
        private static Location getProperLocationNether(World world, double x, double y, double z){
         
            int y2 = (int)y;
            Location location = null;
            Block centerBlock = null;
            loop: while(y2 <= 120){
                centerBlock = world.getBlockAt((int)x, y2, (int)z);
                if(chkRelativeBlock(centerBlock, BlockFace.SELF, 0)){
                    location = new Location(world, x, (double)y2+2d, z);
                    break loop;
                }
             
                y2++;
            }
         
         
            return location;
        }
     
        //Method to teleport taking in account the world the player is in.
        //The method for finding the safest location posible for the player
        //differs between the overworld/the_end and the nether.
        public static boolean teleporTo(World world, Player player, double x, double z){
            String worldName = world.getName();
            Location location = null;

            if(worldName.equals("world") || worldName.equals("world_the_end")){
                location = getProperLocationOverWorldEnd(world, player, x, z);
                return player.teleport(location);
            }
            else if(worldName.equals("world_nether")){
             
                location = getProperLocationNether(world, x, 3, z);
             
                if(location == null)
                    player.sendMessage("Not a safe location");
             
                return player.teleport(location);
            }
            else {
                return false;
            }
        }
    }
     
     
    #7 Dimon6, Jun 25, 2015
    Last edited: Jun 26, 2015