Помогите Получить рандомную локацию

Bezobrazie

Активный участник
Пользователь
Баллы
46
Имя в Minecraft
MySoulIsCry
Пытаюсь получить рандомную локацию путем использования класса Random и генерирования. Генерирую рандомные числа и уже их подставляю в локацию а далее пробегаюсь от 255 до 50 по y для того чтобы найти первый блок. Далее уже проверяю на то не вода ли он и проверяю блок на 1 выче на то что он воздух и делаю это все в бесконечном цикле дабы всетаки найти рандомную и безлопастную локацию. Но все же бывают моменты когда меня спавнит в воде или в блоках. Перепробовал уже все, пытался стырить код у плагинов на ртп но так и не понял что вытягивать. В общем что я делаю не так, и если есть способы оптимизировать этот метод то прошу объяснить мне как(Ибо чейчас эта штука может прогружать от 1 до 10 рандомных локаций и грузить чанки).
PHP:
    public Location getRandomLocation() {
        int iteration = 0;
        while(true) {
            iteration ++;
            Random rand = new Random();
            int x = rand.nextInt(EventSettings.RADIUS.toInt()) ;
            int z = rand.nextInt(EventSettings.RADIUS.toInt());
            World world = Bukkit.getWorld(EventSettings.WORLD.toString());
            Location loc = new Location(world, x, 255, z);
            for(int i = 255; i > 50; i--) {
                Material block = loc.getBlock().getType();
                if(block != Material.AIR) {
                    if(block != Material.WATER &&
                            block != Material.WATER_LILY &&
                            block != Material.STATIONARY_WATER ) {
                        Material block2 = loc.clone().add(0, 1, 0).getBlock().getType();
                        if(block2 == Material.AIR) {
                            Bukkit.broadcastMessage(iteration + "");
                            return loc.add(0.5f, 1, 0.5f);
                        }else {
                            break;   
                        }
                    }else {
                        break;
                    }
                }
                loc.subtract(0, 1, 0);
            }
        }
    }
 
Код:
Random random = new Random();
Location location = new Location(Bukkit.getWorld("world"), random.nextInt(255), 1, random.nextInt(255));
location.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
while(location.getBlock().getType() == Material.STATIONARY_WATER) {

location = new Location(Bukkit.getWorld("world"), random.nextInt(255), 1, random.nextInt(255));
location.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY())

}

player.teleport(location);
 
Последнее редактирование:
Код:
Random random = new Random();
Location location = new Location(Bukkit.getWorld("world"), random.nextInt(255), random.nextInt(255), random.nextInt(255));
while(location.getBlock().getType() == Material.STATIONARY_WATER) {

location = new Location(Bukkit.getWorld("world"), random.nextInt(255), random.nextInt(255), random.nextInt(255));

}

player.teleport(location);
Мне кажется это не то что мне нужно, оно будет телепортировать в блоки. И грузить еще больше чанков чем у меня и может телепортнуть на 255 высоту и тд
 
Отредактировал
Мне кажется это не то что мне нужно, оно будет телепортировать в блоки. И грузить еще больше чанков чем у меня и может телепортнуть на 255 высоту и тд
.
 
Код:
Random random = new Random();
Location location = new Location(Bukkit.getWorld("world"), random.nextInt(255), 1, random.nextInt(255));
location.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
while(location.getBlock().getType() == Material.STATIONARY_WATER) {

location = new Location(Bukkit.getWorld("world"), random.nextInt(255), 1, random.nextInt(255));
location.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY())

}

player.teleport(location);
Пока ты не телепортируешь игрока либо не прогрузишь чанк через код, в мире не будет прогружено.
 
Пока ты не телепортируешь игрока либо не прогрузишь чанк через код, в мире не будет прогружено.
Я когда пытался делать это все в асинк потоке мне говорило что нельзя грузить чанки в асинк потоке(В нем я только локацию получал, не телепортировал)
 
Я когда пытался делать это все в асинк потоке мне говорило что нельзя грузить чанки в асинк потоке(В нем я только локацию получал, не телепортировал)
Ну не знаю. Можно не создавать в цикле новую локацию, а просто к существующей добавлять блоки РАНДОМОМ, (т.к скорее всего рандомом ты позволишь циклу меньше работать, чем по одному блоку перебирать), так-же не надо забывать каждый раз проверять Y.
 
Ну что бы по 10 раз не загружать чанки, ищите безопасное место в уже полученом чанке из локации.
 
Ну не знаю. Можно не создавать в цикле новую локацию, а просто к существующей добавлять блоки РАНДОМОМ, (т.к скорее всего рандомом ты позволишь циклу меньше работать, чем по одному блоку перебирать), так-же не надо забывать каждый раз проверять Y.
Немного изменил метод но принцип оставил тотже
PHP:
    public Location getRandomLocation() {
        Random random = new Random();
        Location loc = new Location(Bukkit.getWorld("world"), random.nextInt(EventSettings.RADIUS.toInt()), 1, random.nextInt(EventSettings.RADIUS.toInt()));
        loc.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
        while(loc.clone().subtract(0,1,0).getBlock().getType() == Material.STATIONARY_WATER ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.WATER_LILY ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.WATER ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.LAVA||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.STATIONARY_LAVA) {
            loc = new Location(Bukkit.getWorld("world"), random.nextInt(EventSettings.RADIUS.toInt()), 1, random.nextInt(EventSettings.RADIUS.toInt()));
            loc.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
        }
        return loc.add(0.5f, 0, 0.5f);
    }
Оно все равно понижает тпс с 20 до 18 если по кд спамить но это не критично так как этот метод будет вызыватся не более чем раз в 5 минут.
Вопрос в другом. Почему оно не считает листву как за блок и может телепортировать как под листву так и в листву?
Также бывали моменты когда меня телепортировало в маленькие озёра с водой. Тоже не критично но не приятно.
UPD: Бывает телепортирует в ствол дерева. Тоже не могу понять почему.
 
Немного изменил метод но принцип оставил тотже
PHP:
    public Location getRandomLocation() {
        Random random = new Random();
        Location loc = new Location(Bukkit.getWorld("world"), random.nextInt(EventSettings.RADIUS.toInt()), 1, random.nextInt(EventSettings.RADIUS.toInt()));
        loc.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
        while(loc.clone().subtract(0,1,0).getBlock().getType() == Material.STATIONARY_WATER ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.WATER_LILY ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.WATER ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.LAVA||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.STATIONARY_LAVA) {
            loc = new Location(Bukkit.getWorld("world"), random.nextInt(EventSettings.RADIUS.toInt()), 1, random.nextInt(EventSettings.RADIUS.toInt()));
            loc.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
        }
        return loc.add(0.5f, 0, 0.5f);
    }
Оно все равно понижает тпс с 20 до 18 если по кд спамить но это не критично так как этот метод будет вызыватся не более чем раз в 5 минут.
Вопрос в другом. Почему оно не считает листву как за блок и может телепортировать как под листву так и в листву?
Также бывали моменты когда меня телепортировало в маленькие озёра с водой. Тоже не критично но не приятно.
UPD: Бывает телепортирует в ствол дерева. Тоже не могу понять почему.
Не могу понять для чего ты в цикле делаешь subtract
 
Немного изменил метод но принцип оставил тотже
PHP:
    public Location getRandomLocation() {
        Random random = new Random();
        Location loc = new Location(Bukkit.getWorld("world"), random.nextInt(EventSettings.RADIUS.toInt()), 1, random.nextInt(EventSettings.RADIUS.toInt()));
        loc.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
        while(loc.clone().subtract(0,1,0).getBlock().getType() == Material.STATIONARY_WATER ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.WATER_LILY ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.WATER ||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.LAVA||
                loc.clone().subtract(0,1,0).getBlock().getType() == Material.STATIONARY_LAVA) {
            loc = new Location(Bukkit.getWorld("world"), random.nextInt(EventSettings.RADIUS.toInt()), 1, random.nextInt(EventSettings.RADIUS.toInt()));
            loc.setY(loc.getWorld().getHighestBlockAt(loc).getLocation().getY());
        }
        return loc.add(0.5f, 0, 0.5f);
    }
Оно все равно понижает тпс с 20 до 18 если по кд спамить но это не критично так как этот метод будет вызыватся не более чем раз в 5 минут.
Вопрос в другом. Почему оно не считает листву как за блок и может телепортировать как под листву так и в листву?
Также бывали моменты когда меня телепортировало в маленькие озёра с водой. Тоже не критично но не приятно.
UPD: Бывает телепортирует в ствол дерева. Тоже не могу понять почему.
new Random() следует заменить на ThreadLocalRandom.current() - нет штрафа за синхронизацию.
Основной мир можно получить через Bukkit.getWorlds().get(0), да сохранить его в переменную.
В твоей конструкции получения высшего Y для локации нет смысла - можно сразу получить блок и взять оттуда локацию когда нужно. Этим же можно убрать постоянное использование getBlock().
Проверять нужно не блок снизу, а именно имеющийся блок. Поэтому тебя и телепортирует в пруд.
Вместо while стоит использовать do-while - можно будет избавиться от первого получения локации вне цикла и делать всё внутри него.
Вместо проверки всех типов по-отдельности лучше использовать заготовленный заранее (мб даже статичной константой) EnumSet, где будут нужные значения.
 
Назад
Верх