BlockPos.java

net.minecraft.core.BlockPos

信息

  • 全限定名:net.minecraft.core.BlockPos
  • 类型:public class
  • 包:net.minecraft.core
  • 源码路径:src/main/java/net/minecraft/core/BlockPos.java
  • 起始行号:L33
  • 继承:Vec3i
  • 职责:

    TODO

字段/常量

  • CODEC

    • 类型: Codec<BlockPos>
    • 修饰符: public static final
    • 源码定位: L34
    • 说明:

      TODO

  • STREAM_CODEC

    • 类型: StreamCodec<ByteBuf,BlockPos>
    • 修饰符: public static final public public
    • 源码定位: L39
    • 说明:

      TODO

  • ZERO

    • 类型: BlockPos
    • 修饰符: public static final
    • 源码定位: L48
    • 说明:

      TODO

  • PACKED_HORIZONTAL_LENGTH

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L49
    • 说明:

      TODO

  • PACKED_Y_LENGTH

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L50
    • 说明:

      TODO

  • PACKED_X_MASK

    • 类型: long
    • 修饰符: private static final
    • 源码定位: L51
    • 说明:

      TODO

  • PACKED_Y_MASK

    • 类型: long
    • 修饰符: private static final
    • 源码定位: L52
    • 说明:

      TODO

  • PACKED_Z_MASK

    • 类型: long
    • 修饰符: private static final
    • 源码定位: L53
    • 说明:

      TODO

  • Y_OFFSET

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L54
    • 说明:

      TODO

  • Z_OFFSET

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L55
    • 说明:

      TODO

  • X_OFFSET

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L56
    • 说明:

      TODO

  • MAX_HORIZONTAL_COORDINATE

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L57
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.core.BlockPos.MutableBlockPos

    • 类型: class
    • 修饰符: public static
    • 源码定位: L587
    • 说明:

      TODO

  • net.minecraft.core.BlockPos.TraversalNodeStatus

    • 类型: enum
    • 修饰符: public static
    • 源码定位: L705
    • 说明:

      TODO

构造器

public BlockPos(int x, int y, int z) @ L59

  • 构造器名:BlockPos
  • 源码定位:L59
  • 修饰符:public

参数:

  • x: int
  • y: int
  • z: int

说明:

TODO

public BlockPos(Vec3i vec3i) @ L63

  • 构造器名:BlockPos
  • 源码定位:L63
  • 修饰符:public

参数:

  • vec3i: Vec3i

说明:

TODO

方法

下面的方法块按源码顺序生成。

public static long offset(long blockNode, Direction offset) @ L67

  • 方法名:offset
  • 源码定位:L67
  • 返回类型:long
  • 修饰符:public static

参数:

  • blockNode: long
  • offset: Direction

说明:

TODO

public static long offset(long blockNode, int stepX, int stepY, int stepZ) @ L71

  • 方法名:offset
  • 源码定位:L71
  • 返回类型:long
  • 修饰符:public static

参数:

  • blockNode: long
  • stepX: int
  • stepY: int
  • stepZ: int

说明:

TODO

public static int getX(long blockNode) @ L75

  • 方法名:getX
  • 源码定位:L75
  • 返回类型:int
  • 修饰符:public static

参数:

  • blockNode: long

说明:

TODO

public static int getY(long blockNode) @ L79

  • 方法名:getY
  • 源码定位:L79
  • 返回类型:int
  • 修饰符:public static

参数:

  • blockNode: long

说明:

TODO

public static int getZ(long blockNode) @ L83

  • 方法名:getZ
  • 源码定位:L83
  • 返回类型:int
  • 修饰符:public static

参数:

  • blockNode: long

说明:

TODO

public static BlockPos of(long blockNode) @ L87

  • 方法名:of
  • 源码定位:L87
  • 返回类型:BlockPos
  • 修饰符:public static

参数:

  • blockNode: long

说明:

TODO

public static BlockPos containing(double x, double y, double z) @ L91

  • 方法名:containing
  • 源码定位:L91
  • 返回类型:BlockPos
  • 修饰符:public static

参数:

  • x: double
  • y: double
  • z: double

说明:

TODO

public static BlockPos containing(Position pos) @ L95

  • 方法名:containing
  • 源码定位:L95
  • 返回类型:BlockPos
  • 修饰符:public static

参数:

  • pos: Position

说明:

TODO

public static BlockPos min(BlockPos a, BlockPos b) @ L99

  • 方法名:min
  • 源码定位:L99
  • 返回类型:BlockPos
  • 修饰符:public static

参数:

  • a: BlockPos
  • b: BlockPos

说明:

TODO

public static BlockPos max(BlockPos a, BlockPos b) @ L103

  • 方法名:max
  • 源码定位:L103
  • 返回类型:BlockPos
  • 修饰符:public static

参数:

  • a: BlockPos
  • b: BlockPos

说明:

TODO

public long asLong() @ L107

  • 方法名:asLong
  • 源码定位:L107
  • 返回类型:long
  • 修饰符:public

参数:

说明:

TODO

public static long asLong(int x, int y, int z) @ L111

  • 方法名:asLong
  • 源码定位:L111
  • 返回类型:long
  • 修饰符:public static

参数:

  • x: int
  • y: int
  • z: int

说明:

TODO

public static long getFlatIndex(long neighborBlockNode) @ L118

  • 方法名:getFlatIndex
  • 源码定位:L118
  • 返回类型:long
  • 修饰符:public static

参数:

  • neighborBlockNode: long

说明:

TODO

public BlockPos offset(int x, int y, int z) @ L122

  • 方法名:offset
  • 源码定位:L122
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • x: int
  • y: int
  • z: int

说明:

TODO

public Vec3 getCenter() @ L126

  • 方法名:getCenter
  • 源码定位:L126
  • 返回类型:Vec3
  • 修饰符:public

参数:

说明:

TODO

public Vec3 getBottomCenter() @ L130

  • 方法名:getBottomCenter
  • 源码定位:L130
  • 返回类型:Vec3
  • 修饰符:public

参数:

说明:

TODO

public BlockPos offset(Vec3i vec) @ L134

  • 方法名:offset
  • 源码定位:L134
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • vec: Vec3i

说明:

TODO

public BlockPos subtract(Vec3i vec) @ L138

  • 方法名:subtract
  • 源码定位:L138
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • vec: Vec3i

说明:

TODO

public BlockPos multiply(int scale) @ L142

  • 方法名:multiply
  • 源码定位:L142
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • scale: int

说明:

TODO

public BlockPos above() @ L150

  • 方法名:above
  • 源码定位:L150
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public BlockPos above(int steps) @ L154

  • 方法名:above
  • 源码定位:L154
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • steps: int

说明:

TODO

public BlockPos below() @ L158

  • 方法名:below
  • 源码定位:L158
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public BlockPos below(int steps) @ L162

  • 方法名:below
  • 源码定位:L162
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • steps: int

说明:

TODO

public BlockPos north() @ L166

  • 方法名:north
  • 源码定位:L166
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public BlockPos north(int steps) @ L170

  • 方法名:north
  • 源码定位:L170
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • steps: int

说明:

TODO

public BlockPos south() @ L174

  • 方法名:south
  • 源码定位:L174
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public BlockPos south(int steps) @ L178

  • 方法名:south
  • 源码定位:L178
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • steps: int

说明:

TODO

public BlockPos west() @ L182

  • 方法名:west
  • 源码定位:L182
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public BlockPos west(int steps) @ L186

  • 方法名:west
  • 源码定位:L186
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • steps: int

说明:

TODO

public BlockPos east() @ L190

  • 方法名:east
  • 源码定位:L190
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public BlockPos east(int steps) @ L194

  • 方法名:east
  • 源码定位:L194
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • steps: int

说明:

TODO

public BlockPos relative(Direction direction) @ L198

  • 方法名:relative
  • 源码定位:L198
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • direction: Direction

说明:

TODO

public BlockPos relative(Direction direction, int steps) @ L202

  • 方法名:relative
  • 源码定位:L202
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • direction: Direction
  • steps: int

说明:

TODO

public BlockPos relative(Direction.Axis axis, int steps) @ L208

  • 方法名:relative
  • 源码定位:L208
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • axis: Direction.Axis
  • steps: int

说明:

TODO

public BlockPos rotate(Rotation rotation) @ L219

  • 方法名:rotate
  • 源码定位:L219
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • rotation: Rotation

说明:

TODO

public BlockPos cross(Vec3i upVector) @ L228

  • 方法名:cross
  • 源码定位:L228
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • upVector: Vec3i

说明:

TODO

public BlockPos atY(int y) @ L236

  • 方法名:atY
  • 源码定位:L236
  • 返回类型:BlockPos
  • 修饰符:public

参数:

  • y: int

说明:

TODO

public BlockPos immutable() @ L240

  • 方法名:immutable
  • 源码定位:L240
  • 返回类型:BlockPos
  • 修饰符:public

参数:

说明:

TODO

public BlockPos.MutableBlockPos mutable() @ L244

  • 方法名:mutable
  • 源码定位:L244
  • 返回类型:BlockPos.MutableBlockPos
  • 修饰符:public

参数:

说明:

TODO

public Vec3 clampLocationWithin(Vec3 location) @ L248

  • 方法名:clampLocationWithin
  • 源码定位:L248
  • 返回类型:Vec3
  • 修饰符:public

参数:

  • location: Vec3

说明:

TODO

public static Iterable<BlockPos> randomInCube(RandomSource random, int limit, BlockPos center, int sizeToScanInAllDirections) @ L256

  • 方法名:randomInCube
  • 源码定位:L256
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • random: RandomSource
  • limit: int
  • center: BlockPos
  • sizeToScanInAllDirections: int

说明:

TODO

public static Stream<BlockPos> squareOutSouthEast(BlockPos from) @ L269

  • 方法名:squareOutSouthEast
  • 源码定位:L269
  • 返回类型:Stream
  • 修饰符:public static

参数:

  • from: BlockPos

说明:

TODO

public static Iterable<BlockPos> randomBetweenClosed(RandomSource random, int limit, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) @ L274

  • 方法名:randomBetweenClosed
  • 源码定位:L274
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • random: RandomSource
  • limit: int
  • minX: int
  • minY: int
  • minZ: int
  • maxX: int
  • maxY: int
  • maxZ: int

说明:

TODO

public static Iterable<BlockPos> withinManhattan(BlockPos origin, int reachX, int reachY, int reachZ) @ L294

  • 方法名:withinManhattan
  • 源码定位:L294
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • origin: BlockPos
  • reachX: int
  • reachY: int
  • reachZ: int

说明:

TODO

public static Optional<BlockPos> findClosestMatch(BlockPos startPos, int horizontalSearchRadius, int verticalSearchRadius, Predicate<BlockPos> predicate) @ L347

  • 方法名:findClosestMatch
  • 源码定位:L347
  • 返回类型:Optional
  • 修饰符:public static

参数:

  • startPos: BlockPos
  • horizontalSearchRadius: int
  • verticalSearchRadius: int
  • predicate: Predicate

说明:

TODO

public static Stream<BlockPos> withinManhattanStream(BlockPos origin, int reachX, int reachY, int reachZ) @ L357

  • 方法名:withinManhattanStream
  • 源码定位:L357
  • 返回类型:Stream
  • 修饰符:public static

参数:

  • origin: BlockPos
  • reachX: int
  • reachY: int
  • reachZ: int

说明:

TODO

public static Iterable<BlockPos> betweenClosed(AABB box) @ L361

  • 方法名:betweenClosed
  • 源码定位:L361
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • box: AABB

说明:

TODO

public static Iterable<BlockPos> betweenClosed(BlockPos a, BlockPos b) @ L367

  • 方法名:betweenClosed
  • 源码定位:L367
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • a: BlockPos
  • b: BlockPos

说明:

TODO

public static Stream<BlockPos> betweenClosedStream(BlockPos a, BlockPos b) @ L378

  • 方法名:betweenClosedStream
  • 源码定位:L378
  • 返回类型:Stream
  • 修饰符:public static

参数:

  • a: BlockPos
  • b: BlockPos

说明:

TODO

public static Stream<BlockPos> betweenClosedStream(BoundingBox boundingBox) @ L382

  • 方法名:betweenClosedStream
  • 源码定位:L382
  • 返回类型:Stream
  • 修饰符:public static

参数:

  • boundingBox: BoundingBox

说明:

TODO

public static Stream<BlockPos> betweenClosedStream(AABB box) @ L393

  • 方法名:betweenClosedStream
  • 源码定位:L393
  • 返回类型:Stream
  • 修饰符:public static

参数:

  • box: AABB

说明:

TODO

public static Stream<BlockPos> betweenClosedStream(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) @ L397

  • 方法名:betweenClosedStream
  • 源码定位:L397
  • 返回类型:Stream
  • 修饰符:public static

参数:

  • minX: int
  • minY: int
  • minZ: int
  • maxX: int
  • maxY: int
  • maxZ: int

说明:

TODO

public static Iterable<BlockPos> betweenClosed(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) @ L401

  • 方法名:betweenClosed
  • 源码定位:L401
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • minX: int
  • minY: int
  • minZ: int
  • maxX: int
  • maxY: int
  • maxZ: int

说明:

TODO

public static Iterable<BlockPos.MutableBlockPos> spiralAround(BlockPos center, int radius, Direction firstDirection, Direction secondDirection) @ L425

  • 方法名:spiralAround
  • 源码定位:L425
  • 返回类型:Iterable<BlockPos.MutableBlockPos>
  • 修饰符:public static

参数:

  • center: BlockPos
  • radius: int
  • firstDirection: Direction
  • secondDirection: Direction

说明:

TODO

public static int breadthFirstTraversal(BlockPos startPos, int maxDepth, int maxCount, BiConsumer<BlockPos,Consumer<BlockPos>> neighbourProvider, Function<BlockPos,BlockPos.TraversalNodeStatus> nodeProcessor) @ L461

  • 方法名:breadthFirstTraversal
  • 源码定位:L461
  • 返回类型:int
  • 修饰符:public static

参数:

  • startPos: BlockPos
  • maxDepth: int
  • maxCount: int
  • neighbourProvider: BiConsumer<BlockPos,Consumer>
  • nodeProcessor: Function<BlockPos,BlockPos.TraversalNodeStatus>

说明:

TODO

public static Iterable<BlockPos> betweenCornersInDirection(AABB aabb, Vec3 direction) @ L499

  • 方法名:betweenCornersInDirection
  • 源码定位:L499
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • aabb: AABB
  • direction: Vec3

说明:

TODO

public static Iterable<BlockPos> betweenCornersInDirection(BlockPos firstCorner, BlockPos secondCorner, Vec3 direction) @ L511

  • 方法名:betweenCornersInDirection
  • 源码定位:L511
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • firstCorner: BlockPos
  • secondCorner: BlockPos
  • direction: Vec3

说明:

TODO

public static Iterable<BlockPos> betweenCornersInDirection(int firstCornerX, int firstCornerY, int firstCornerZ, int secondCornerX, int secondCornerY, int secondCornerZ, Vec3 direction) @ L517

  • 方法名:betweenCornersInDirection
  • 源码定位:L517
  • 返回类型:Iterable
  • 修饰符:public static

参数:

  • firstCornerX: int
  • firstCornerY: int
  • firstCornerZ: int
  • secondCornerX: int
  • secondCornerY: int
  • secondCornerZ: int
  • direction: Vec3

说明:

TODO

代码

@Immutable
public class BlockPos extends Vec3i {
    public static final Codec<BlockPos> CODEC = Codec.INT_STREAM
        .<BlockPos>comapFlatMap(
            input -> Util.fixedSize(input, 3).map(ints -> new BlockPos(ints[0], ints[1], ints[2])), pos -> IntStream.of(pos.getX(), pos.getY(), pos.getZ())
        )
        .stable();
    public static final StreamCodec<ByteBuf, BlockPos> STREAM_CODEC = new StreamCodec<ByteBuf, BlockPos>() {
        public BlockPos decode(ByteBuf input) {
            return FriendlyByteBuf.readBlockPos(input);
        }
 
        public void encode(ByteBuf output, BlockPos value) {
            FriendlyByteBuf.writeBlockPos(output, value);
        }
    };
    public static final BlockPos ZERO = new BlockPos(0, 0, 0);
    public static final int PACKED_HORIZONTAL_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000));
    public static final int PACKED_Y_LENGTH = 64 - 2 * PACKED_HORIZONTAL_LENGTH;
    private static final long PACKED_X_MASK = (1L << PACKED_HORIZONTAL_LENGTH) - 1L;
    private static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L;
    private static final long PACKED_Z_MASK = (1L << PACKED_HORIZONTAL_LENGTH) - 1L;
    private static final int Y_OFFSET = 0;
    private static final int Z_OFFSET = PACKED_Y_LENGTH;
    private static final int X_OFFSET = PACKED_Y_LENGTH + PACKED_HORIZONTAL_LENGTH;
    public static final int MAX_HORIZONTAL_COORDINATE = (1 << PACKED_HORIZONTAL_LENGTH) / 2 - 1;
 
    public BlockPos(int x, int y, int z) {
        super(x, y, z);
    }
 
    public BlockPos(Vec3i vec3i) {
        this(vec3i.getX(), vec3i.getY(), vec3i.getZ());
    }
 
    public static long offset(long blockNode, Direction offset) {
        return offset(blockNode, offset.getStepX(), offset.getStepY(), offset.getStepZ());
    }
 
    public static long offset(long blockNode, int stepX, int stepY, int stepZ) {
        return asLong(getX(blockNode) + stepX, getY(blockNode) + stepY, getZ(blockNode) + stepZ);
    }
 
    public static int getX(long blockNode) {
        return (int)(blockNode << 64 - X_OFFSET - PACKED_HORIZONTAL_LENGTH >> 64 - PACKED_HORIZONTAL_LENGTH);
    }
 
    public static int getY(long blockNode) {
        return (int)(blockNode << 64 - PACKED_Y_LENGTH >> 64 - PACKED_Y_LENGTH);
    }
 
    public static int getZ(long blockNode) {
        return (int)(blockNode << 64 - Z_OFFSET - PACKED_HORIZONTAL_LENGTH >> 64 - PACKED_HORIZONTAL_LENGTH);
    }
 
    public static BlockPos of(long blockNode) {
        return new BlockPos(getX(blockNode), getY(blockNode), getZ(blockNode));
    }
 
    public static BlockPos containing(double x, double y, double z) {
        return new BlockPos(Mth.floor(x), Mth.floor(y), Mth.floor(z));
    }
 
    public static BlockPos containing(Position pos) {
        return containing(pos.x(), pos.y(), pos.z());
    }
 
    public static BlockPos min(BlockPos a, BlockPos b) {
        return new BlockPos(Math.min(a.getX(), b.getX()), Math.min(a.getY(), b.getY()), Math.min(a.getZ(), b.getZ()));
    }
 
    public static BlockPos max(BlockPos a, BlockPos b) {
        return new BlockPos(Math.max(a.getX(), b.getX()), Math.max(a.getY(), b.getY()), Math.max(a.getZ(), b.getZ()));
    }
 
    public long asLong() {
        return asLong(this.getX(), this.getY(), this.getZ());
    }
 
    public static long asLong(int x, int y, int z) {
        long node = 0L;
        node |= (x & PACKED_X_MASK) << X_OFFSET;
        node |= (y & PACKED_Y_MASK) << 0;
        return node | (z & PACKED_Z_MASK) << Z_OFFSET;
    }
 
    public static long getFlatIndex(long neighborBlockNode) {
        return neighborBlockNode & -16L;
    }
 
    public BlockPos offset(int x, int y, int z) {
        return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z);
    }
 
    public Vec3 getCenter() {
        return Vec3.atCenterOf(this);
    }
 
    public Vec3 getBottomCenter() {
        return Vec3.atBottomCenterOf(this);
    }
 
    public BlockPos offset(Vec3i vec) {
        return this.offset(vec.getX(), vec.getY(), vec.getZ());
    }
 
    public BlockPos subtract(Vec3i vec) {
        return this.offset(-vec.getX(), -vec.getY(), -vec.getZ());
    }
 
    public BlockPos multiply(int scale) {
        if (scale == 1) {
            return this;
        } else {
            return scale == 0 ? ZERO : new BlockPos(this.getX() * scale, this.getY() * scale, this.getZ() * scale);
        }
    }
 
    public BlockPos above() {
        return this.relative(Direction.UP);
    }
 
    public BlockPos above(int steps) {
        return this.relative(Direction.UP, steps);
    }
 
    public BlockPos below() {
        return this.relative(Direction.DOWN);
    }
 
    public BlockPos below(int steps) {
        return this.relative(Direction.DOWN, steps);
    }
 
    public BlockPos north() {
        return this.relative(Direction.NORTH);
    }
 
    public BlockPos north(int steps) {
        return this.relative(Direction.NORTH, steps);
    }
 
    public BlockPos south() {
        return this.relative(Direction.SOUTH);
    }
 
    public BlockPos south(int steps) {
        return this.relative(Direction.SOUTH, steps);
    }
 
    public BlockPos west() {
        return this.relative(Direction.WEST);
    }
 
    public BlockPos west(int steps) {
        return this.relative(Direction.WEST, steps);
    }
 
    public BlockPos east() {
        return this.relative(Direction.EAST);
    }
 
    public BlockPos east(int steps) {
        return this.relative(Direction.EAST, steps);
    }
 
    public BlockPos relative(Direction direction) {
        return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ());
    }
 
    public BlockPos relative(Direction direction, int steps) {
        return steps == 0
            ? this
            : new BlockPos(this.getX() + direction.getStepX() * steps, this.getY() + direction.getStepY() * steps, this.getZ() + direction.getStepZ() * steps);
    }
 
    public BlockPos relative(Direction.Axis axis, int steps) {
        if (steps == 0) {
            return this;
        } else {
            int xStep = axis == Direction.Axis.X ? steps : 0;
            int yStep = axis == Direction.Axis.Y ? steps : 0;
            int zStep = axis == Direction.Axis.Z ? steps : 0;
            return new BlockPos(this.getX() + xStep, this.getY() + yStep, this.getZ() + zStep);
        }
    }
 
    public BlockPos rotate(Rotation rotation) {
        return switch (rotation) {
            case CLOCKWISE_90 -> new BlockPos(-this.getZ(), this.getY(), this.getX());
            case CLOCKWISE_180 -> new BlockPos(-this.getX(), this.getY(), -this.getZ());
            case COUNTERCLOCKWISE_90 -> new BlockPos(this.getZ(), this.getY(), -this.getX());
            case NONE -> this;
        };
    }
 
    public BlockPos cross(Vec3i upVector) {
        return new BlockPos(
            this.getY() * upVector.getZ() - this.getZ() * upVector.getY(),
            this.getZ() * upVector.getX() - this.getX() * upVector.getZ(),
            this.getX() * upVector.getY() - this.getY() * upVector.getX()
        );
    }
 
    public BlockPos atY(int y) {
        return new BlockPos(this.getX(), y, this.getZ());
    }
 
    public BlockPos immutable() {
        return this;
    }
 
    public BlockPos.MutableBlockPos mutable() {
        return new BlockPos.MutableBlockPos(this.getX(), this.getY(), this.getZ());
    }
 
    public Vec3 clampLocationWithin(Vec3 location) {
        return new Vec3(
            Mth.clamp(location.x, (double)(this.getX() + 1.0E-5F), this.getX() + 1.0 - 1.0E-5F),
            Mth.clamp(location.y, (double)(this.getY() + 1.0E-5F), this.getY() + 1.0 - 1.0E-5F),
            Mth.clamp(location.z, (double)(this.getZ() + 1.0E-5F), this.getZ() + 1.0 - 1.0E-5F)
        );
    }
 
    public static Iterable<BlockPos> randomInCube(RandomSource random, int limit, BlockPos center, int sizeToScanInAllDirections) {
        return randomBetweenClosed(
            random,
            limit,
            center.getX() - sizeToScanInAllDirections,
            center.getY() - sizeToScanInAllDirections,
            center.getZ() - sizeToScanInAllDirections,
            center.getX() + sizeToScanInAllDirections,
            center.getY() + sizeToScanInAllDirections,
            center.getZ() + sizeToScanInAllDirections
        );
    }
 
    @Deprecated
    public static Stream<BlockPos> squareOutSouthEast(BlockPos from) {
        return Stream.of(from, from.south(), from.east(), from.south().east());
    }
 
    public static Iterable<BlockPos> randomBetweenClosed(RandomSource random, int limit, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
        int width = maxX - minX + 1;
        int height = maxY - minY + 1;
        int depth = maxZ - minZ + 1;
        return () -> new AbstractIterator<BlockPos>() {
            final BlockPos.MutableBlockPos nextPos = new BlockPos.MutableBlockPos();
            int counter = limit;
 
            protected BlockPos computeNext() {
                if (this.counter <= 0) {
                    return this.endOfData();
                } else {
                    BlockPos next = this.nextPos.set(minX + random.nextInt(width), minY + random.nextInt(height), minZ + random.nextInt(depth));
                    this.counter--;
                    return next;
                }
            }
        };
    }
 
    public static Iterable<BlockPos> withinManhattan(BlockPos origin, int reachX, int reachY, int reachZ) {
        int maxDepth = reachX + reachY + reachZ;
        int originX = origin.getX();
        int originY = origin.getY();
        int originZ = origin.getZ();
        return () -> new AbstractIterator<BlockPos>() {
            private final BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
            private int currentDepth;
            private int maxX;
            private int maxY;
            private int x;
            private int y;
            private boolean zMirror;
 
            protected BlockPos computeNext() {
                if (this.zMirror) {
                    this.zMirror = false;
                    this.cursor.setZ(originZ - (this.cursor.getZ() - originZ));
                    return this.cursor;
                } else {
                    BlockPos found;
                    for (found = null; found == null; this.y++) {
                        if (this.y > this.maxY) {
                            this.x++;
                            if (this.x > this.maxX) {
                                this.currentDepth++;
                                if (this.currentDepth > maxDepth) {
                                    return this.endOfData();
                                }
 
                                this.maxX = Math.min(reachX, this.currentDepth);
                                this.x = -this.maxX;
                            }
 
                            this.maxY = Math.min(reachY, this.currentDepth - Math.abs(this.x));
                            this.y = -this.maxY;
                        }
 
                        int xx = this.x;
                        int yy = this.y;
                        int zz = this.currentDepth - Math.abs(xx) - Math.abs(yy);
                        if (zz <= reachZ) {
                            this.zMirror = zz != 0;
                            found = this.cursor.set(originX + xx, originY + yy, originZ + zz);
                        }
                    }
 
                    return found;
                }
            }
        };
    }
 
    public static Optional<BlockPos> findClosestMatch(BlockPos startPos, int horizontalSearchRadius, int verticalSearchRadius, Predicate<BlockPos> predicate) {
        for (BlockPos blockPos : withinManhattan(startPos, horizontalSearchRadius, verticalSearchRadius, horizontalSearchRadius)) {
            if (predicate.test(blockPos)) {
                return Optional.of(blockPos);
            }
        }
 
        return Optional.empty();
    }
 
    public static Stream<BlockPos> withinManhattanStream(BlockPos origin, int reachX, int reachY, int reachZ) {
        return StreamSupport.stream(withinManhattan(origin, reachX, reachY, reachZ).spliterator(), false);
    }
 
    public static Iterable<BlockPos> betweenClosed(AABB box) {
        BlockPos startPos = containing(box.minX, box.minY, box.minZ);
        BlockPos endPos = containing(box.maxX, box.maxY, box.maxZ);
        return betweenClosed(startPos, endPos);
    }
 
    public static Iterable<BlockPos> betweenClosed(BlockPos a, BlockPos b) {
        return betweenClosed(
            Math.min(a.getX(), b.getX()),
            Math.min(a.getY(), b.getY()),
            Math.min(a.getZ(), b.getZ()),
            Math.max(a.getX(), b.getX()),
            Math.max(a.getY(), b.getY()),
            Math.max(a.getZ(), b.getZ())
        );
    }
 
    public static Stream<BlockPos> betweenClosedStream(BlockPos a, BlockPos b) {
        return StreamSupport.stream(betweenClosed(a, b).spliterator(), false);
    }
 
    public static Stream<BlockPos> betweenClosedStream(BoundingBox boundingBox) {
        return betweenClosedStream(
            Math.min(boundingBox.minX(), boundingBox.maxX()),
            Math.min(boundingBox.minY(), boundingBox.maxY()),
            Math.min(boundingBox.minZ(), boundingBox.maxZ()),
            Math.max(boundingBox.minX(), boundingBox.maxX()),
            Math.max(boundingBox.minY(), boundingBox.maxY()),
            Math.max(boundingBox.minZ(), boundingBox.maxZ())
        );
    }
 
    public static Stream<BlockPos> betweenClosedStream(AABB box) {
        return betweenClosedStream(Mth.floor(box.minX), Mth.floor(box.minY), Mth.floor(box.minZ), Mth.floor(box.maxX), Mth.floor(box.maxY), Mth.floor(box.maxZ));
    }
 
    public static Stream<BlockPos> betweenClosedStream(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
        return StreamSupport.stream(betweenClosed(minX, minY, minZ, maxX, maxY, maxZ).spliterator(), false);
    }
 
    public static Iterable<BlockPos> betweenClosed(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
        int width = maxX - minX + 1;
        int height = maxY - minY + 1;
        int depth = maxZ - minZ + 1;
        int end = width * height * depth;
        return () -> new AbstractIterator<BlockPos>() {
            private final BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
            private int index;
 
            protected BlockPos computeNext() {
                if (this.index == end) {
                    return this.endOfData();
                } else {
                    int x = this.index % width;
                    int slice = this.index / width;
                    int y = slice % height;
                    int z = slice / height;
                    this.index++;
                    return this.cursor.set(minX + x, minY + y, minZ + z);
                }
            }
        };
    }
 
    public static Iterable<BlockPos.MutableBlockPos> spiralAround(BlockPos center, int radius, Direction firstDirection, Direction secondDirection) {
        Validate.validState(firstDirection.getAxis() != secondDirection.getAxis(), "The two directions cannot be on the same axis");
        return () -> new AbstractIterator<BlockPos.MutableBlockPos>() {
            private final Direction[] directions = new Direction[]{
                firstDirection, secondDirection, firstDirection.getOpposite(), secondDirection.getOpposite()
            };
            private final BlockPos.MutableBlockPos cursor = center.mutable().move(secondDirection);
            private final int legs = 4 * radius;
            private int leg = -1;
            private int legSize;
            private int legIndex;
            private int lastX = this.cursor.getX();
            private int lastY = this.cursor.getY();
            private int lastZ = this.cursor.getZ();
 
            protected BlockPos.MutableBlockPos computeNext() {
                this.cursor.set(this.lastX, this.lastY, this.lastZ).move(this.directions[(this.leg + 4) % 4]);
                this.lastX = this.cursor.getX();
                this.lastY = this.cursor.getY();
                this.lastZ = this.cursor.getZ();
                if (this.legIndex >= this.legSize) {
                    if (this.leg >= this.legs) {
                        return this.endOfData();
                    }
 
                    this.leg++;
                    this.legIndex = 0;
                    this.legSize = this.leg / 2 + 1;
                }
 
                this.legIndex++;
                return this.cursor;
            }
        };
    }
 
    public static int breadthFirstTraversal(
        BlockPos startPos,
        int maxDepth,
        int maxCount,
        BiConsumer<BlockPos, Consumer<BlockPos>> neighbourProvider,
        Function<BlockPos, BlockPos.TraversalNodeStatus> nodeProcessor
    ) {
        Queue<Pair<BlockPos, Integer>> nodes = new ArrayDeque<>();
        LongSet visited = new LongOpenHashSet();
        nodes.add(Pair.of(startPos, 0));
        int count = 0;
 
        while (!nodes.isEmpty()) {
            Pair<BlockPos, Integer> node = nodes.poll();
            BlockPos currentPos = node.getLeft();
            int depth = node.getRight();
            long currentPosLong = currentPos.asLong();
            if (visited.add(currentPosLong)) {
                BlockPos.TraversalNodeStatus next = nodeProcessor.apply(currentPos);
                if (next != BlockPos.TraversalNodeStatus.SKIP) {
                    if (next == BlockPos.TraversalNodeStatus.STOP) {
                        break;
                    }
 
                    if (++count >= maxCount) {
                        return count;
                    }
 
                    if (depth < maxDepth) {
                        neighbourProvider.accept(currentPos, pos -> nodes.add(Pair.of(pos, depth + 1)));
                    }
                }
            }
        }
 
        return count;
    }
 
    public static Iterable<BlockPos> betweenCornersInDirection(AABB aabb, Vec3 direction) {
        Vec3 minCorner = aabb.getMinPosition();
        int firstCornerX = Mth.floor(minCorner.x());
        int firstCornerY = Mth.floor(minCorner.y());
        int firstCornerZ = Mth.floor(minCorner.z());
        Vec3 maxCorner = aabb.getMaxPosition();
        int secondCornerX = Mth.floor(maxCorner.x());
        int secondCornerY = Mth.floor(maxCorner.y());
        int secondCornerZ = Mth.floor(maxCorner.z());
        return betweenCornersInDirection(firstCornerX, firstCornerY, firstCornerZ, secondCornerX, secondCornerY, secondCornerZ, direction);
    }
 
    public static Iterable<BlockPos> betweenCornersInDirection(BlockPos firstCorner, BlockPos secondCorner, Vec3 direction) {
        return betweenCornersInDirection(
            firstCorner.getX(), firstCorner.getY(), firstCorner.getZ(), secondCorner.getX(), secondCorner.getY(), secondCorner.getZ(), direction
        );
    }
 
    public static Iterable<BlockPos> betweenCornersInDirection(
        int firstCornerX, int firstCornerY, int firstCornerZ, int secondCornerX, int secondCornerY, int secondCornerZ, Vec3 direction
    ) {
        int minCornerX = Math.min(firstCornerX, secondCornerX);
        int minCornerY = Math.min(firstCornerY, secondCornerY);
        int minCornerZ = Math.min(firstCornerZ, secondCornerZ);
        int maxCornerX = Math.max(firstCornerX, secondCornerX);
        int maxCornerY = Math.max(firstCornerY, secondCornerY);
        int maxCornerZ = Math.max(firstCornerZ, secondCornerZ);
        int diffX = maxCornerX - minCornerX;
        int diffY = maxCornerY - minCornerY;
        int diffZ = maxCornerZ - minCornerZ;
        int startCornerX = direction.x >= 0.0 ? minCornerX : maxCornerX;
        int startCornerY = direction.y >= 0.0 ? minCornerY : maxCornerY;
        int startCornerZ = direction.z >= 0.0 ? minCornerZ : maxCornerZ;
        List<Direction.Axis> axes = Direction.axisStepOrder(direction);
        Direction.Axis firstVisitAxis = axes.get(0);
        Direction.Axis secondVisitAxis = axes.get(1);
        Direction.Axis thirdVisitAxis = axes.get(2);
        Direction firstVisitDir = direction.get(firstVisitAxis) >= 0.0 ? firstVisitAxis.getPositive() : firstVisitAxis.getNegative();
        Direction secondVisitDir = direction.get(secondVisitAxis) >= 0.0 ? secondVisitAxis.getPositive() : secondVisitAxis.getNegative();
        Direction thirdVisitDir = direction.get(thirdVisitAxis) >= 0.0 ? thirdVisitAxis.getPositive() : thirdVisitAxis.getNegative();
        int firstMax = firstVisitAxis.choose(diffX, diffY, diffZ);
        int secondMax = secondVisitAxis.choose(diffX, diffY, diffZ);
        int thirdMax = thirdVisitAxis.choose(diffX, diffY, diffZ);
        return () -> new AbstractIterator<BlockPos>() {
            private final BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos();
            private int firstIndex;
            private int secondIndex;
            private int thirdIndex;
            private boolean end;
            private final int firstDirX = firstVisitDir.getStepX();
            private final int firstDirY = firstVisitDir.getStepY();
            private final int firstDirZ = firstVisitDir.getStepZ();
            private final int secondDirX = secondVisitDir.getStepX();
            private final int secondDirY = secondVisitDir.getStepY();
            private final int secondDirZ = secondVisitDir.getStepZ();
            private final int thirdDirX = thirdVisitDir.getStepX();
            private final int thirdDirY = thirdVisitDir.getStepY();
            private final int thirdDirZ = thirdVisitDir.getStepZ();
 
            protected BlockPos computeNext() {
                if (this.end) {
                    return this.endOfData();
                } else {
                    this.cursor
                        .set(
                            startCornerX + this.firstDirX * this.firstIndex + this.secondDirX * this.secondIndex + this.thirdDirX * this.thirdIndex,
                            startCornerY + this.firstDirY * this.firstIndex + this.secondDirY * this.secondIndex + this.thirdDirY * this.thirdIndex,
                            startCornerZ + this.firstDirZ * this.firstIndex + this.secondDirZ * this.secondIndex + this.thirdDirZ * this.thirdIndex
                        );
                    if (this.thirdIndex < thirdMax) {
                        this.thirdIndex++;
                    } else if (this.secondIndex < secondMax) {
                        this.secondIndex++;
                        this.thirdIndex = 0;
                    } else if (this.firstIndex < firstMax) {
                        this.firstIndex++;
                        this.thirdIndex = 0;
                        this.secondIndex = 0;
                    } else {
                        this.end = true;
                    }
 
                    return this.cursor;
                }
            }
        };
    }
 
    public static class MutableBlockPos extends BlockPos {
        public MutableBlockPos() {
            this(0, 0, 0);
        }
 
        public MutableBlockPos(int x, int y, int z) {
            super(x, y, z);
        }
 
        public MutableBlockPos(double x, double y, double z) {
            this(Mth.floor(x), Mth.floor(y), Mth.floor(z));
        }
 
        @Override
        public BlockPos offset(int x, int y, int z) {
            return super.offset(x, y, z).immutable();
        }
 
        @Override
        public BlockPos multiply(int scale) {
            return super.multiply(scale).immutable();
        }
 
        @Override
        public BlockPos relative(Direction direction, int steps) {
            return super.relative(direction, steps).immutable();
        }
 
        @Override
        public BlockPos relative(Direction.Axis axis, int steps) {
            return super.relative(axis, steps).immutable();
        }
 
        @Override
        public BlockPos rotate(Rotation rotation) {
            return super.rotate(rotation).immutable();
        }
 
        public BlockPos.MutableBlockPos set(int x, int y, int z) {
            this.setX(x);
            this.setY(y);
            this.setZ(z);
            return this;
        }
 
        public BlockPos.MutableBlockPos set(double x, double y, double z) {
            return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z));
        }
 
        public BlockPos.MutableBlockPos set(Vec3i vec) {
            return this.set(vec.getX(), vec.getY(), vec.getZ());
        }
 
        public BlockPos.MutableBlockPos set(long pos) {
            return this.set(getX(pos), getY(pos), getZ(pos));
        }
 
        public BlockPos.MutableBlockPos set(AxisCycle transform, int x, int y, int z) {
            return this.set(transform.cycle(x, y, z, Direction.Axis.X), transform.cycle(x, y, z, Direction.Axis.Y), transform.cycle(x, y, z, Direction.Axis.Z));
        }
 
        public BlockPos.MutableBlockPos setWithOffset(Vec3i pos, Direction direction) {
            return this.set(pos.getX() + direction.getStepX(), pos.getY() + direction.getStepY(), pos.getZ() + direction.getStepZ());
        }
 
        public BlockPos.MutableBlockPos setWithOffset(Vec3i pos, int x, int y, int z) {
            return this.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z);
        }
 
        public BlockPos.MutableBlockPos setWithOffset(Vec3i pos, Vec3i offset) {
            return this.set(pos.getX() + offset.getX(), pos.getY() + offset.getY(), pos.getZ() + offset.getZ());
        }
 
        public BlockPos.MutableBlockPos move(Direction direction) {
            return this.move(direction, 1);
        }
 
        public BlockPos.MutableBlockPos move(Direction direction, int steps) {
            return this.set(this.getX() + direction.getStepX() * steps, this.getY() + direction.getStepY() * steps, this.getZ() + direction.getStepZ() * steps);
        }
 
        public BlockPos.MutableBlockPos move(int x, int y, int z) {
            return this.set(this.getX() + x, this.getY() + y, this.getZ() + z);
        }
 
        public BlockPos.MutableBlockPos move(Vec3i pos) {
            return this.set(this.getX() + pos.getX(), this.getY() + pos.getY(), this.getZ() + pos.getZ());
        }
 
        public BlockPos.MutableBlockPos clamp(Direction.Axis axis, int minimum, int maximum) {
            return switch (axis) {
                case X -> this.set(Mth.clamp(this.getX(), minimum, maximum), this.getY(), this.getZ());
                case Y -> this.set(this.getX(), Mth.clamp(this.getY(), minimum, maximum), this.getZ());
                case Z -> this.set(this.getX(), this.getY(), Mth.clamp(this.getZ(), minimum, maximum));
            };
        }
 
        public BlockPos.MutableBlockPos setX(int x) {
            super.setX(x);
            return this;
        }
 
        public BlockPos.MutableBlockPos setY(int y) {
            super.setY(y);
            return this;
        }
 
        public BlockPos.MutableBlockPos setZ(int z) {
            super.setZ(z);
            return this;
        }
 
        @Override
        public BlockPos immutable() {
            return new BlockPos(this);
        }
    }
 
    public static enum TraversalNodeStatus {
        ACCEPT,
        SKIP,
        STOP;
    }
}

引用的其他类

  • Direction

    • 引用位置: 参数/方法调用
    • 关联成员: Direction.axisStepOrder()
  • Position

    • 引用位置: 参数
  • Vec3i

    • 引用位置: 参数/继承
  • FriendlyByteBuf

    • 引用位置: 方法调用
    • 关联成员: FriendlyByteBuf.readBlockPos(), FriendlyByteBuf.writeBlockPos()
  • StreamCodec

    • 引用位置: 字段
  • Mth

    • 引用位置: 方法调用
    • 关联成员: Mth.clamp(), Mth.floor(), Mth.log2(), Mth.smallestEncompassingPowerOfTwo()
  • RandomSource

    • 引用位置: 参数
  • Util

    • 引用位置: 方法调用
    • 关联成员: Util.fixedSize()
  • Rotation

    • 引用位置: 参数
  • BoundingBox

    • 引用位置: 参数
  • AABB

    • 引用位置: 参数
  • Vec3

    • 引用位置: 参数/方法调用/构造调用/返回值
    • 关联成员: Vec3(), Vec3.atBottomCenterOf(), Vec3.atCenterOf()