Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

[Решено] Заполнить территорию определённым блоком

Тема в разделе "Разработка плагинов для новичков", создана пользователем CoolBoy, 28 июл 2016.

Статус темы:
Закрыта.
  1. Novichock

    Novichock Активный участник Пользователь

    Баллы:
    76
    Skype:
    pavel.batalov1
    Код:
    x= player.getLocation().getX-2;//тут два по причине того что при делении 5 на 2 без остатка будет 2
    y= player.getLocation().getY-2;
    z= player.getLocation().getZ-2;
    
    x2= player.getLocation().getX+2;
    y2= player.getLocation().getY+2;
    z2= player.getLocation().getZ+2;
    
    for(;y<y2;y++){
    for(;x<x2;x++){
       for(;z<z2;z++){
        //здесь устанавливаем блок по полученным координатам при выполнении нужных условий
        }
       }
    }
    [DOUBLEPOST=1469739275,1469739191][/DOUBLEPOST]Теперь тыкните меня лицом в место где я не прав.
     
  2. Хостинг MineCraft
    <
  3. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Проверьте код и убедитесь в моих словах :)
     
  4. Novichock

    Novichock Активный участник Пользователь

    Баллы:
    76
    Skype:
    pavel.batalov1
    Уже нашёл,я просто скопипастил свой код выше.
     
  5. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Заполнили всё пространство вокруг игрока на радиус 3 блока?
     
  6. Novichock

    Novichock Активный участник Пользователь

    Баллы:
    76
    Skype:
    pavel.batalov1
    Ты про что?Я исправил код в своём ответе,страничку обнови.
     
  7. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Проверьте этот код в майнкрафте. Он будет работать не совсем так как нужно :)
    Также, хочу заметить, что getZ(), getY() и getX() - это методы. Поэтому нужны скобки.
     
  8. Novichock

    Novichock Активный участник Пользователь

    Баллы:
    76
    Skype:
    pavel.batalov1
    P.S.Мне как показалось мы не вокруг игрока заполняли, а относительно его кубоид.
    P.S.Мне как показалось мы не вокруг игрока заполняли, а относительно его кубоид.Это разные вещи.Если хотите круг,то вам нужно каждый блок этого кубоида при постановке проверять принадлежит ли он окружности.[DOUBLEPOST=1469739920,1469739851][/DOUBLEPOST]У меня уже 3 часа ночи,не обращай внимания на повтор фраз.
     
  9. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Именно в этом и дело. С кубойдом я бы, надеюсь, и один справился :)
    А тут задачка посложнее.

    Я уже писал, что можно решить мою задачу в 4 цикла, в каждом из которых будет ещё 2. Но это не лучшее решение, как по мне.
     
  10. Novichock

    Novichock Активный участник Пользователь

    Баллы:
    76
    Skype:
    pavel.batalov1
    Ну как я и сказал,просто проверь каждый блок на принадлежность к окружности,ну и чтобы всё было нормально,то лучше получать целочисленные координаты от игрока.
     
  11. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Пока на ум пришла лишь следующая конструкция:
    Код:
    //Его использование
    for (Block blocks : this.getBlocksInRadius(player.getLocation(), 5) {
        blocks.setType(Material.<MY_VALUE>);
    }
    
    //Метод
    public static List<Block> getBlocksInRadius(Location location, int radius) {
        List<Block> blocks = new ArrayList<>();
    
        int bX = location.getBlockX(),
                bY = location.getBlockY(),
                bZ = location.getBlockZ();
    
        for (int x = bX - radius; x <= bX + radius; x++) {
            for (int y = bY - radius; y <= bY + radius; y++) {
                for (int z = bZ - radius; z <= bZ + radius; z++) {
                    double distance = ((bX - x) * (bX - x) + (bY - y) * (bY - y) + (bZ - z) * (bZ - z));
    
                    if (distance < radius * radius
                                && !(distance < ((radius - 1) * (radius - 1)))) {
                        Location l = new Location(location.getWorld(), x, y, z);
    
                        if (l.getBlock().getType() != Material.BARRIER) {
                            blocks.add(l.getBlock());
                        }
                    }
                }
            }
        }
    
        return blocks;
    }
    
     
    Последнее редактирование: 29 июл 2016
  12. Novichock

    Novichock Активный участник Пользователь

    Баллы:
    76
    Skype:
    pavel.batalov1
    Вроде как всё верно,но с 14 по 16 строку не всё ясно(может быть я плохо знаю геометрию).Но мне кажется,что запись стоит сократить вот так: r==Math.sqrt((x-xp)*(x-xp)+(z-zp)*(z-zp)) ,где r-радиус,x,z - координаты центра окражности; xp и zp - координаты проверяемой точки.
    Мне кажется или тут все ненавидят "Math.pow(число, степень);"
     
  13. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    @CoolBoy, я не очень внимательно читал посты в теме, вопрос: тебе нужен алгоритм floodfill?
    То, как это работает в WorldEdit (/fillr ...)?
    Например, первое с гугла. Ну там тебе надо только вставить проверку на принадлежность твоему радиусу.
    P.S. Ну и плюс переделать чтобы не было рекурсии, если ты хочешь иметь возможность указывать действительно большие радиусы без переполнения стека.
     
  14. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Именно. Проблема в том, что заполняю я пространство из центральной точки.[DOUBLEPOST=1469782743,1469775183][/DOUBLEPOST]UP, не решено!
     
  15. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    1. Получаешь начальную точку, пусть это будет loc.
    2. Рекурсивно бегаешь по соседним координатам (6 блоков вокруг текущего), если это не воздух или он выше loc.getY() или он дальше, чем нужный тебе радиус, то просто return.
    Иначе заменяешь его на что-то нужное тебе и вызываешь этот же метод для 6 блоков соседей уже этого блока-соседа.
     
  16. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Можно код? :)
     
  17. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Естественно, не проверял, только доверился интуиции.
    Код:
    public void doFloodFill(Player p, Material m, double radius)
    {
        Location loc = p.getLocation().clone().add(0.0, -1.0, 0.0);
        recursive(loc, loc, m, radius * radius);
    }
    private final Vector[] vs = new Vector[]
    {
        new Vector(+1, 0, 0), new Vector(0, +1, 0), new Vector(0, 0, +1),
        new Vector(-1, 0, 0), new Vector(0, -1, 0), new Vector(0, 0, -1),
    };
    private void recursive(Location src, Location loc, Material m, double r2)
    {
        Block block = loc.getBlock();
        if(block == null)
            return;
        boolean isUnder  = block.getY() >= 0 && block.getY() <= src.getBlockY();
        boolean isInside = loc.distanceSquared(src) <= r2;
        boolean isEmpty  = block.getType().equals(Material.AIR);
        if(isUnder && isInside && isEmpty)
        {
            block.setType(m);
            for(Vector v : vs)
            {
                recursive(src, loc.clone().add(v), m, r2);
            }
        }
    }
    Смотри, чтобы были импортированы правильные вектора (org.bukkit.vector).
    Снаружи нужно вызывать doFloodFill. Ну и там может быть когда у игрока берется положение, может быть его ещё ниже надо утащить.
    P.S. Предполагается, что внизу мир перекрыт блоками (бедрок тот же), иначе надо добавить ограничение по y вниз. Я сейчас его допишу в код.
    .
     
    Последнее редактирование: 29 июл 2016
  18. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Огромное вам спасибо, уже не в первый раз выручаете. Метод работает как раз так, как нужно.

    Решено. Закрыто.

    Спасибо @Reality_SC
     
Статус темы:
Закрыта.

Поделиться этой страницей