1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

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

  1. Автор темы
    SergK35

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

    Баллы:
    76
    Имя в Minecraft:
    Sergk35
    Доброго времени суток. Подскажите пожалуйста, как можно проверить, чанк, на котором находится игрок, содержит границу мира или нет? (worldborder)

    P.S Плагин с worldborder'ом связал
     
  2. Автор темы
    SergK35

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

    Баллы:
    76
    Имя в Minecraft:
    Sergk35
  3. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Речь про ванильный, или же плагин?
     
  4. Автор темы
    SergK35

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

    Баллы:
    76
    Имя в Minecraft:
    Sergk35
    Пишу плагин, получаю чанк, на котором стоит игрок, надо проверить, есть ли граница из worldborder'а в этом чанке
     
  5. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Примерно так, наверно.
    Код:
    public static boolean containsBorder(Chunk chunk) {
        BorderData border = Config.Border(chunk.getWorld().getName());
        if (border == null) return false;
        Block block = chunk.getBlock(0, 0, 0);
        int x = block.getX(); int z = block.getZ();
        boolean round = Config.ShapeRound();
        return border.insideBorder(x, z, round) ||
                border.insideBorder(x + 15, z, round) ||
                border.insideBorder(x + 15, z + 15, round) ||
                border.insideBorder(x, z + 15, round);
    }
    Config - класс из WorldBorder'а
     
  6. Автор темы
    SergK35

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

    Баллы:
    76
    Имя в Minecraft:
    Sergk35
    Странно, но любой чанк, который я отправляю, является границей
     
  7. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    А, ну да. Borderdata#insideBorder проверяет, находится ли координата в пределах границы. Попробуй так.
    Код:
        return border.insideBorder(x, z, round) &&
                border.insideBorder(x + 15, z, round) &&
                border.insideBorder(x + 15, z + 15, round) &&
                border.insideBorder(x, z + 15, round);
     
  8. Dymeth

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

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Так будет возвращать true для всех чанков, которые находятся внутри (а не только на границе)
     
  9. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    И то верно. Тогда, два счетчика, которые будут проверять наличие хотя бы одного угла в пределах границы и одного за ней?
     
  10. Dymeth

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

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Должно сработать
     
  11. alexandrage

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

    Баллы:
    173
    Да этого достаточно будет, чтоб узнать что игрок за границей.
     
  12. Dymeth

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

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Причём тут игрок, если речь о чанке?
    Чанк - это 4 точки на плоскости и 8 точек в пространстве.
    Так?
    PHP:
    public static boolean isChunkOnBorder(Chunk chunk) {
        
    BorderData border Config.Border(chunk.getWorld().getName());
        
    boolean round Config.ShapeRound();
        return 
    isAreaSplitsChunk(chunk, (xz) -> border.insideBorder(point.getKey(), point.getValue(), round));
    }

    public static 
    boolean isAreaSplitsChunk(Chunk chunkBiPredicate<IntegerIntegerisPointInArea) {
        
    int minX chunk.getX() << 4;
        
    int minZ chunk.getZ() << 4;
        
    int maxX minX 15;
        
    int maxZ minZ 15;
        
    Collection<Pair<IntegerInteger>> points = new ArrayList<>();
        
    points.add(new Pair<>(minXminZ));
        
    points.add(new Pair<>(minXmaxZ));
        
    points.add(new Pair<>(maxXminZ));
        
    points.add(new Pair<>(maxXmaxZ));
        
    boolean inside false;
        
    boolean outside false;
        for (
    Pair<IntegerIntegerpoint points) {
            if (
    isPointInArea.test(point.getKey(), point.getValue())) inside true;
            else 
    outside true;
        }
        return 
    inside && outside;
    }
     
    Последнее редактирование: 2 авг 2019
  13. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Угу. Только, на мой взгляд такой вариант выглядит несколько излишне усложненным. Впрочем, не мне судить.
     
  14. Dymeth

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

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Окей.
    PHP:
        public static boolean containsBorder(Chunk chunk) {
            
    BorderData border Config.Border(chunk.getWorld().getName());
            
    boolean round Config.ShapeRound();
            
    int minX chunk.getX() << 4;
            
    int minZ chunk.getZ() << 4;
            
    int maxX minX 15;
            
    int maxZ minZ 15;
            
    int[] pointsXZ = new int[]{
                    
    minXminZ,
                    
    minXmaxZ,
                    
    maxXminZ,
                    
    maxXmaxZ
            
    };
            
    boolean inside false;
            
    boolean outside false;
            for (
    int i 0pointsXZ.lengthi++) {
                if (
    border.insideBorder(pointsXZ[i++], pointsXZ[i], round)) inside true;
                else 
    outside true;
            }
            return 
    inside && outside;
        }
    PHP:
    public static boolean containsBorder(Chunk chunk) {
        
    BorderData border Config.Border(chunk.getWorld().getName());
        
    boolean round Config.ShapeRound();
        return 
    is2DAreaSplitPoints((xz) -> border.insideBorder(xzround), getChunk2DPoints(chunk));
    }

    private static 
    int[] getChunk2DPoints(Chunk chunk) {
        
    int minX chunk.getX() << 4;
        
    int minZ chunk.getZ() << 4;
        
    int maxX minX 15;
        
    int maxZ minZ 15;
        return new 
    int[]{
                
    minXminZ,
                
    minXmaxZ,
                
    maxXminZ,
                
    maxXmaxZ
        
    };
    }

    private static 
    Location[] getChunk3DPoints(Chunk chunk) {
        return 
    getChunk3DPoints(chunk0255);
    }

    private static 
    Location[] getChunk3DPoints(Chunk chunkint minYint maxY) {
        
    World world chunk.getWorld();
        
    int minX chunk.getX() << 4;
        
    int minZ chunk.getZ() << 4;
        
    int maxX minX 15;
        
    int maxZ minZ 15;
        return new 
    Location[]{
                new 
    Location(worldminXminYminZ),
                new 
    Location(worldminXminYmaxZ),
                new 
    Location(worldmaxXminYminZ),
                new 
    Location(worldmaxXminYmaxZ),
                new 
    Location(worldminXmaxYminZ),
                new 
    Location(worldminXmaxYmaxZ),
                new 
    Location(worldmaxXmaxYminZ),
                new 
    Location(worldmaxXmaxYmaxZ)
        };
    }

    public static 
    boolean is2DAreaSplitPoints(BiPredicate<IntegerIntegerisPointInAreaint... pointsXZ) {
        
    boolean inside false;
        
    boolean outside false;
        for (
    int i 0pointsXZ.lengthi++) {
            if (
    isPointInArea.test(pointsXZ[i++], pointsXZ[i])) inside true;
            else 
    outside true;
            if (
    inside && outside) return true;
        }
        return 
    false;
    }

    public static 
    boolean is3DAreaSplitPoints(Predicate<LocationisPointInAreaLocation... points) {
        
    boolean inside false;
        
    boolean outside false;
        for (
    Location point points.) {
            if (
    isPointInArea.test(point)) inside true;
            else 
    outside true;
            if (
    inside && outside) return true;
        }
        return 
    false;
    }
    :D
     
    Последнее редактирование: 2 авг 2019
  15. Автор темы
    SergK35

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

    Баллы:
    76
    Имя в Minecraft:
    Sergk35
    Спасибо. Отправил несколько чанков на проверку, вроде все работает.

    Можешь пожалуйста объяснить вот это действие
    Код:
    int minX = chunk.getX() << 4;
    Понимаю, что идет сдвиг битов, но не совсем понимаю для чего
     
  16. Dymeth

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

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Получает координаты в мире по координатам чанка.
    chunk.getBlock(x, y, z) работает по тому же принципу.
    У меня просто уже привычка не использовать этот метод по некоторым причинам
     
  17. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Простым языком - считай, что умножение на 16(это 2 в степени 4). В данном случае нужно потому что чанки - это участки 16 на 16 (на 256) блоков, и chunk.getX() и chunk.getZ() вернёт тебе координату чанка, а не крайнего блока чанка.
    Более сложным - ты и сам ответил, а дальше достаточно посмотреть на двоичный код/двоичную систему счисления. Загляни сюда для примера, например.
     
  18. alexandrage

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

    Баллы:
    173
    Вот это правильно. Оно будет дергать блокстату, почем зря.
     
  19. Автор темы
    SergK35

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

    Баллы:
    76
    Имя в Minecraft:
    Sergk35
    Спасибо
     

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