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

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

Discussion in 'Разработка плагинов для новичков' started by CoolBoy, Jul 28, 2016.

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

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

    Trophy Points:
    76
    Skype:
    pavel.batalov1
    Code:
    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 Активный участник Пользователь

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Пока на ум пришла лишь следующая конструкция:
    Code:
    //Его использование
    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;
    }
    
     
    Last edited: Jul 29, 2016
  12. Novichock

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

    Trophy Points:
    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 Старожил Пользователь

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

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

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

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

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

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Можно код? :)
     
  17. Reality_SC

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

    Trophy Points:
    123
    Имя в Minecraft:
    Reality_SC
    Естественно, не проверял, только доверился интуиции.
    Code:
    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 вниз. Я сейчас его допишу в код.
    .
     
    Last edited: Jul 29, 2016
  18. Автор темы
    CoolBoy

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

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

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

    Спасибо @Reality_SC
     
Thread Status:
Not open for further replies.

Share This Page