Следуйте инструкциям в видео ниже, чтобы узнать, как установить наш сайт как веб-приложение на главный экран вашего устройства.
Примечание: Эта функция может быть недоступна в некоторых браузерах.
Пишу плагин, получаю чанк, на котором стоит игрок, надо проверить, есть ли граница из worldborder'а в этом чанкеРечь про ванильный, или же плагин?
Примерно так, наверно.Пишу плагин, получаю чанк, на котором стоит игрок, надо проверить, есть ли граница из worldborder'а в этом чанке
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'аКод: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); }
А, ну да. 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);
Так будет возвращать true для всех чанков, которые находятся внутри (а не только на границе)А, ну да. 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);
И то верно. Тогда, два счетчика, которые будут проверять наличие хотя бы одного угла в пределах границы и одного за ней?Так будет возвращать true для всех чанков, которые находятся внутри (а не только на границе)
Должно сработатьИ то верно. Тогда, два счетчика, которые будут проверять наличие хотя бы одного угла в пределах границы и одного за ней?
Да этого достаточно будет, чтоб узнать что игрок за границей.Так будет возвращать true для всех чанков, которые находятся внутри (а не только на границе)
Причём тут игрок, если речь о чанке?Да этого достаточно будет, чтоб узнать что игрок за границей.
Так?И то верно. Тогда, два счетчика, которые будут проверять наличие хотя бы одного угла в пределах границы и одного за ней?
public static boolean isChunkOnBorder(Chunk chunk) {
BorderData border = Config.Border(chunk.getWorld().getName());
boolean round = Config.ShapeRound();
return isAreaSplitsChunk(chunk, (x, z) -> border.insideBorder(point.getKey(), point.getValue(), round));
}
public static boolean isAreaSplitsChunk(Chunk chunk, BiPredicate<Integer, Integer> isPointInArea) {
int minX = chunk.getX() << 4;
int minZ = chunk.getZ() << 4;
int maxX = minX + 15;
int maxZ = minZ + 15;
Collection<Pair<Integer, Integer>> points = new ArrayList<>();
points.add(new Pair<>(minX, minZ));
points.add(new Pair<>(minX, maxZ));
points.add(new Pair<>(maxX, minZ));
points.add(new Pair<>(maxX, maxZ));
boolean inside = false;
boolean outside = false;
for (Pair<Integer, Integer> point : points) {
if (isPointInArea.test(point.getKey(), point.getValue())) inside = true;
else outside = true;
}
return inside && outside;
}
Угу. Только, на мой взгляд такой вариант выглядит несколько излишне усложненным. Впрочем, не мне судить.Так?
PHP:public static boolean isChunkOnBorder(Chunk chunk) { BorderData border = Config.Border(chunk.getWorld().getName()); boolean round = Config.ShapeRound(); return isAreaSplitsChunk(chunk, (x, z) -> border.insideBorder(point.getKey(), point.getValue(), round)); } public static boolean isAreaSplitsChunk(Chunk chunk, BiPredicate<Integer, Integer> isPointInArea) { int minX = chunk.getX() << 4; int minZ = chunk.getZ() << 4; int maxX = minX + 15; int maxZ = minZ + 15; Collection<Pair<Integer, Integer>> points = new ArrayList<>(); points.add(new Pair<>(minX, minZ)); points.add(new Pair<>(minX, maxZ)); points.add(new Pair<>(maxX, minZ)); points.add(new Pair<>(maxX, maxZ)); boolean inside = false; boolean outside = false; for (Pair<Integer, Integer> point : points) { if (isPointInArea.test(point.getKey(), point.getValue())) inside = true; else outside = true; } return inside && outside; }
Окей.Угу. Только, на мой взгляд такой вариант выглядит несколько излишне усложненным. Впрочем, не мне судить.
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[]{
minX, minZ,
minX, maxZ,
maxX, minZ,
maxX, maxZ
};
boolean inside = false;
boolean outside = false;
for (int i = 0; i < pointsXZ.length; i++) {
if (border.insideBorder(pointsXZ[i++], pointsXZ[i], round)) inside = true;
else outside = true;
}
return inside && outside;
}
public static boolean containsBorder(Chunk chunk) {
BorderData border = Config.Border(chunk.getWorld().getName());
boolean round = Config.ShapeRound();
return is2DAreaSplitPoints((x, z) -> border.insideBorder(x, z, round), 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[]{
minX, minZ,
minX, maxZ,
maxX, minZ,
maxX, maxZ
};
}
private static Location[] getChunk3DPoints(Chunk chunk) {
return getChunk3DPoints(chunk, 0, 255);
}
private static Location[] getChunk3DPoints(Chunk chunk, int minY, int 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(world, minX, minY, minZ),
new Location(world, minX, minY, maxZ),
new Location(world, maxX, minY, minZ),
new Location(world, maxX, minY, maxZ),
new Location(world, minX, maxY, minZ),
new Location(world, minX, maxY, maxZ),
new Location(world, maxX, maxY, minZ),
new Location(world, maxX, maxY, maxZ)
};
}
public static boolean is2DAreaSplitPoints(BiPredicate<Integer, Integer> isPointInArea, int... pointsXZ) {
boolean inside = false;
boolean outside = false;
for (int i = 0; i < pointsXZ.length; i++) {
if (isPointInArea.test(pointsXZ[i++], pointsXZ[i])) inside = true;
else outside = true;
if (inside && outside) return true;
}
return false;
}
public static boolean is3DAreaSplitPoints(Predicate<Location> isPointInArea, Location... 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;
}
Спасибо. Отправил несколько чанков на проверку, вроде все работает.Окей.
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[]{ minX, minZ, minX, maxZ, maxX, minZ, maxX, maxZ }; boolean inside = false; boolean outside = false; for (int i = 0; i < pointsXZ.length; i++) { 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((x, z) -> border.insideBorder(x, z, round), 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[]{ minX, minZ, minX, maxZ, maxX, minZ, maxX, maxZ }; } private static Location[] getChunk3DPoints(Chunk chunk) { return getChunk3DPoints(chunk, 0, 255); } private static Location[] getChunk3DPoints(Chunk chunk, int minY, int 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(world, minX, minY, minZ), new Location(world, minX, minY, maxZ), new Location(world, maxX, minY, minZ), new Location(world, maxX, minY, maxZ), new Location(world, minX, maxY, minZ), new Location(world, minX, maxY, maxZ), new Location(world, maxX, maxY, minZ), new Location(world, maxX, maxY, maxZ) }; } public static boolean is2DAreaSplitPoints(BiPredicate<Integer, Integer> isPointInArea, int... pointsXZ) { boolean inside = false; boolean outside = false; for (int i = 0; i < pointsXZ.length; i++) { if (isPointInArea.test(pointsXZ[i++], pointsXZ[i])) inside = true; else outside = true; if (inside && outside) return true; } return false; } public static boolean is3DAreaSplitPoints(Predicate<Location> isPointInArea, Location... 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; }
int minX = chunk.getX() << 4;
Получает координаты в мире по координатам чанка.Можешь пожалуйста объяснить вот это действиеКод:int minX = chunk.getX() << 4;
Понимаю, что идет сдвиг битов, но не совсем понимаю для чего
Простым языком - считай, что умножение на 16(это 2 в степени 4). В данном случае нужно потому что чанки - это участки 16 на 16 (на 256) блоков, и chunk.getX() и chunk.getZ() вернёт тебе координату чанка, а не крайнего блока чанка.Спасибо. Отправил несколько чанков на проверку, вроде все работает.
Можешь пожалуйста объяснить вот это действиеКод:int minX = chunk.getX() << 4;
Понимаю, что идет сдвиг битов, но не совсем понимаю для чего
Вот это правильно. Оно будет дергать блокстату, почем зря.chunk.getBlock(x, y, z) работает по тому же принципу.
СпасибоПростым языком - считай, что умножение на 16(это 2 в степени 4). В данном случае нужно потому что чанки - это участки 16 на 16 (на 256) блоков, и chunk.getX() и chunk.getZ() вернёт тебе координату чанка, а не крайнего блока чанка.
Более сложным - ты и сам ответил, а дальше достаточно посмотреть на двоичный код/двоичную систему счисления. Загляни сюда для примера, например.