package net.minecraft.core; import it.unimi.dsi.fastutil.longs.LongConsumer; import java.util.Spliterators.AbstractSpliterator; import java.util.function.Consumer; import java.util.stream.Stream; import java.util.stream.StreamSupport; import net.minecraft.util.Mth; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.entity.EntityAccess; public class SectionPos extends Vec3i { public static final int SECTION_BITS = 4; public static final int SECTION_SIZE = 16; public static final int SECTION_MASK = 15; public static final int SECTION_HALF_SIZE = 8; public static final int SECTION_MAX_INDEX = 15; private static final int PACKED_X_LENGTH = 22; private static final int PACKED_Y_LENGTH = 20; private static final int PACKED_Z_LENGTH = 22; private static final long PACKED_X_MASK = 4194303L; private static final long PACKED_Y_MASK = 1048575L; private static final long PACKED_Z_MASK = 4194303L; private static final int Y_OFFSET = 0; private static final int Z_OFFSET = 20; private static final int X_OFFSET = 42; private static final int RELATIVE_X_SHIFT = 8; private static final int RELATIVE_Y_SHIFT = 0; private static final int RELATIVE_Z_SHIFT = 4; SectionPos(int i, int j, int k) { super(i, j, k); } public static SectionPos of(int chunkX, int chunkY, int chunkZ) { return new SectionPos(chunkX, chunkY, chunkZ); } public static SectionPos of(BlockPos pos) { return new SectionPos(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ())); } public static SectionPos of(ChunkPos chunkPos, int y) { return new SectionPos(chunkPos.x, y, chunkPos.z); } public static SectionPos of(EntityAccess entity) { return of(entity.blockPosition()); } public static SectionPos of(Position position) { return new SectionPos(blockToSectionCoord(position.x()), blockToSectionCoord(position.y()), blockToSectionCoord(position.z())); } public static SectionPos of(long packed) { return new SectionPos(x(packed), y(packed), z(packed)); } public static SectionPos bottomOf(ChunkAccess chunk) { return of(chunk.getPos(), chunk.getMinSectionY()); } public static long offset(long packed, Direction direction) { return offset(packed, direction.getStepX(), direction.getStepY(), direction.getStepZ()); } public static long offset(long packed, int dx, int dy, int dz) { return asLong(x(packed) + dx, y(packed) + dy, z(packed) + dz); } public static int posToSectionCoord(double pos) { return blockToSectionCoord(Mth.floor(pos)); } public static int blockToSectionCoord(int blockCoord) { return blockCoord >> 4; } public static int blockToSectionCoord(double coord) { return Mth.floor(coord) >> 4; } public static int sectionRelative(int rel) { return rel & 15; } public static short sectionRelativePos(BlockPos pos) { int i = sectionRelative(pos.getX()); int j = sectionRelative(pos.getY()); int k = sectionRelative(pos.getZ()); return (short)(i << 8 | k << 4 | j << 0); } public static int sectionRelativeX(short x) { return x >>> 8 & 15; } public static int sectionRelativeY(short y) { return y >>> 0 & 15; } public static int sectionRelativeZ(short z) { return z >>> 4 & 15; } public int relativeToBlockX(short x) { return this.minBlockX() + sectionRelativeX(x); } public int relativeToBlockY(short y) { return this.minBlockY() + sectionRelativeY(y); } public int relativeToBlockZ(short z) { return this.minBlockZ() + sectionRelativeZ(z); } public BlockPos relativeToBlockPos(short pos) { return new BlockPos(this.relativeToBlockX(pos), this.relativeToBlockY(pos), this.relativeToBlockZ(pos)); } public static int sectionToBlockCoord(int sectionCoord) { return sectionCoord << 4; } public static int sectionToBlockCoord(int pos, int offset) { return sectionToBlockCoord(pos) + offset; } public static int x(long packed) { return (int)(packed << 0 >> 42); } public static int y(long packed) { return (int)(packed << 44 >> 44); } public static int z(long packed) { return (int)(packed << 22 >> 42); } public int x() { return this.getX(); } public int y() { return this.getY(); } public int z() { return this.getZ(); } public int minBlockX() { return sectionToBlockCoord(this.x()); } public int minBlockY() { return sectionToBlockCoord(this.y()); } public int minBlockZ() { return sectionToBlockCoord(this.z()); } public int maxBlockX() { return sectionToBlockCoord(this.x(), 15); } public int maxBlockY() { return sectionToBlockCoord(this.y(), 15); } public int maxBlockZ() { return sectionToBlockCoord(this.z(), 15); } public static long blockToSection(long levelPos) { return asLong(blockToSectionCoord(BlockPos.getX(levelPos)), blockToSectionCoord(BlockPos.getY(levelPos)), blockToSectionCoord(BlockPos.getZ(levelPos))); } public static long getZeroNode(int x, int z) { return getZeroNode(asLong(x, 0, z)); } public static long getZeroNode(long pos) { return pos & -1048576L; } public static long sectionToChunk(long pos) { return ChunkPos.asLong(x(pos), z(pos)); } public BlockPos origin() { return new BlockPos(sectionToBlockCoord(this.x()), sectionToBlockCoord(this.y()), sectionToBlockCoord(this.z())); } public BlockPos center() { int i = 8; return this.origin().offset(8, 8, 8); } public ChunkPos chunk() { return new ChunkPos(this.x(), this.z()); } public static long asLong(BlockPos blockPos) { return asLong(blockToSectionCoord(blockPos.getX()), blockToSectionCoord(blockPos.getY()), blockToSectionCoord(blockPos.getZ())); } public static long asLong(int x, int y, int z) { long l = 0L; l |= (x & 4194303L) << 42; l |= (y & 1048575L) << 0; return l | (z & 4194303L) << 20; } public long asLong() { return asLong(this.x(), this.y(), this.z()); } public SectionPos offset(int i, int j, int k) { return i == 0 && j == 0 && k == 0 ? this : new SectionPos(this.x() + i, this.y() + j, this.z() + k); } public Stream blocksInside() { return BlockPos.betweenClosedStream(this.minBlockX(), this.minBlockY(), this.minBlockZ(), this.maxBlockX(), this.maxBlockY(), this.maxBlockZ()); } public static Stream cube(SectionPos center, int radius) { int i = center.x(); int j = center.y(); int k = center.z(); return betweenClosedStream(i - radius, j - radius, k - radius, i + radius, j + radius, k + radius); } public static Stream aroundChunk(ChunkPos chunkPos, int x, int y, int z) { int i = chunkPos.x; int j = chunkPos.z; return betweenClosedStream(i - x, y, j - x, i + x, z, j + x); } public static Stream betweenClosedStream(int x1, int y1, int z1, int x2, int y2, int z2) { return StreamSupport.stream(new AbstractSpliterator((x2 - x1 + 1) * (y2 - y1 + 1) * (z2 - z1 + 1), 64) { final Cursor3D cursor = new Cursor3D(x1, y1, z1, x2, y2, z2); public boolean tryAdvance(Consumer consumer) { if (this.cursor.advance()) { consumer.accept(new SectionPos(this.cursor.nextX(), this.cursor.nextY(), this.cursor.nextZ())); return true; } else { return false; } } }, false); } public static void aroundAndAtBlockPos(BlockPos pos, LongConsumer consumer) { aroundAndAtBlockPos(pos.getX(), pos.getY(), pos.getZ(), consumer); } public static void aroundAndAtBlockPos(long pos, LongConsumer consumer) { aroundAndAtBlockPos(BlockPos.getX(pos), BlockPos.getY(pos), BlockPos.getZ(pos), consumer); } public static void aroundAndAtBlockPos(int x, int y, int z, LongConsumer consumer) { int i = blockToSectionCoord(x - 1); int j = blockToSectionCoord(x + 1); int k = blockToSectionCoord(y - 1); int l = blockToSectionCoord(y + 1); int m = blockToSectionCoord(z - 1); int n = blockToSectionCoord(z + 1); if (i == j && k == l && m == n) { consumer.accept(asLong(i, k, m)); } else { for (int o = i; o <= j; o++) { for (int p = k; p <= l; p++) { for (int q = m; q <= n; q++) { consumer.accept(asLong(o, p, q)); } } } } } }