RandomTP issues...

Discussion in 'Plugin Development' started by DarkBladee12, Apr 30, 2013.

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

    DarkBladee12

    Hey guys, I recently worked on a plugin for a friend which teleports you to a random spot in the world inside a min and max range, but sometimes it teleports you and you're stuck in a wall or hangs up when it couldn't find an applicable place to teleport :/ That's my current code:

    Code:
    public void teleportPlayer(Player p) {
            Random rn = new Random();
            World w = p.getWorld();
            int rx = plugin.min + rn.nextInt(plugin.max - plugin.min);
            int rz = plugin.min + rn.nextInt(plugin.max - plugin.min);
            int y = 170;
            while (y > 50) {
                Block b = w.getBlockAt(rx, y, rz);
                if (b.getType() != Material.AIR && isValidBlock(b)) {
                    if (b.getType() == Material.AIR || b.getType() == Material.SNOW && b.getRelative(BlockFace.UP).getType() == Material.AIR || b.getRelative(BlockFace.UP).getType() == Material.SNOW) {
                        b.getLocation().getChunk().load();
                        p.teleport(b.getLocation());
                        p.sendMessage("§aYou have been teleported into the wilderness!");
                        return;
                    }
                }
                y--;
            }
            teleportPlayer(p);
        }
     
        public boolean isValidBlock(Block b) {
            if (b.getType() == Material.STATIONARY_LAVA || b.getType() == Material.STATIONARY_WATER || b.getType() == Material.LAVA || b.getType() == Material.WATER) {
                return false;
            }
            return true;
        }
     
  2. Offline

    SWISA

    Code:
    public static Location GetHighestYBlock(Location location){
            int HighestY = location.getWorld().getHighestBlockYAt(location);
            while(true){
                Block block = location.getWorld().getBlockAt(location.getBlockX(), HighestY, location.getBlockZ());
                if(block.getType() == Material.GLASS || block.getType() == Material.WATER){
                    HighestY++;
                }else{
                    break;
                }
            }
            Location loc = location;
            loc.setY(HighestY+1.0);
            return loc;
        }
    Try this method.
    It gets the highest free spot @ Y.
     
  3. Offline

    Nitnelave

    Well, currently, what I see is that it's looking for an empty spot starting at y = 170, stops as soon as it finds one, and goes down all the way to y = 50, and if it still hasn't found anything, it starts again with other coordinates.

    So, basically, there are two (potential) errors in your code:
    • You check that b.getType () != air and then right after that b.getType == air! How would you suppose to find anything (apart from snow, of course). Since that isValidBlock(b) (approximately) means that b is solid enough to step on (in which case you shouldn't really need the != air comparison, would you?), you should be checking that b.getRelative(up) == air and b.getRelative (0, 2, 0) == air
    • The other potential pitfall is the Random. Why create a new object for each call? Create a static one for the class, and simply call nextInt. Here, I'm not sure, but you might be risking generating a random number generator with the same seed over and over again, giving you the same numbers every time.
     
  4. Offline

    DarkBladee12

    Nitnelave Ok, I cleaned my code and got to this now:
    Code:
    public void teleportPlayer(Player p) {
            World w = p.getWorld();
            int rx = plugin.min + rn.nextInt(plugin.max - plugin.min);
            int rz = plugin.min + rn.nextInt(plugin.max - plugin.min);
            for (int y = 50; y < 170; y++) {
                Block b = w.getBlockAt(rx, y, rz);
                if (b.getRelative(BlockFace.DOWN).getType().isSolid()) {
                    if (b.getType().isTransparent() && b.getRelative(BlockFace.UP).getType().isTransparent()) {
                        b.getLocation().getChunk().load();
                        p.teleport(b.getLocation().add(0.5D, 0.0D, 0.5D));
                        p.sendMessage("§aYou have been teleported into the wilderness!");
                        return;
                    }
                }
            }
            teleportPlayer(p);
        }
    I also changed that it counts up from 50, because it's more likely to find an applicable spot in the heigth 50 ~ 90. But sometimes I get stuck in a wall, can I prevent that or occurs that when the chunk isn't loaded/generated?
     
  5. Offline

    Nitnelave

    You can group the two ifs into one, and split the test into several lines to make it look nicer (it won't change anything in the meaning, though).

    You could load the chunk before the for loop, if that's what you're worried about. Be careful about isTransparent, because I believe glass is considered transparent.

    Are you sure about adding 0.5 to x and z? It sounds right to me, but check anyway.

    And for clarity, instead of doing a recursive method, I would do a while loop (and I think it's marginally more efficient, because you're not passing arguments or recalculating the world).
     
Thread Status:
Not open for further replies.

Share This Page