mirror of https://github.com/Minestom/Minestom.git
254 lines
8.3 KiB
Java
254 lines
8.3 KiB
Java
package net.minestom.server.utils.chunk;
|
|
|
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
import it.unimi.dsi.fastutil.longs.LongList;
|
|
import net.minestom.server.instance.Chunk;
|
|
import net.minestom.server.instance.Instance;
|
|
import net.minestom.server.utils.BlockPosition;
|
|
import net.minestom.server.utils.MathUtils;
|
|
import net.minestom.server.utils.Position;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public final class ChunkUtils {
|
|
|
|
private ChunkUtils() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Gets if a chunk is loaded.
|
|
*
|
|
* @param chunk the chunk to check
|
|
* @return true if the chunk is loaded, false otherwise
|
|
*/
|
|
public static boolean isLoaded(@Nullable Chunk chunk) {
|
|
return chunk != null && chunk.isLoaded();
|
|
}
|
|
|
|
/**
|
|
* Gets if a chunk is loaded.
|
|
*
|
|
* @param instance the instance to check
|
|
* @param x instance X coordinate
|
|
* @param z instance Z coordinate
|
|
* @return true if the chunk is loaded, false otherwise
|
|
*/
|
|
public static boolean isLoaded(@NotNull Instance instance, float x, float z) {
|
|
final int chunkX = getChunkCoordinate((int) x);
|
|
final int chunkZ = getChunkCoordinate((int) z);
|
|
|
|
final Chunk chunk = instance.getChunk(chunkX, chunkZ);
|
|
return isLoaded(chunk);
|
|
}
|
|
|
|
/**
|
|
* @param xz the instance coordinate to convert
|
|
* @return the chunk X or Z based on the argument
|
|
*/
|
|
public static int getChunkCoordinate(int xz) {
|
|
assert Chunk.CHUNK_SIZE_X == Chunk.CHUNK_SIZE_Z;
|
|
return Math.floorDiv(xz, Chunk.CHUNK_SIZE_X);
|
|
}
|
|
|
|
/**
|
|
* Gets the chunk index of chunk coordinates.
|
|
*
|
|
* @param chunkX the chunk X
|
|
* @param chunkZ the chunk Z
|
|
* @return a number storing the chunk X and Z
|
|
*/
|
|
public static long getChunkIndex(int chunkX, int chunkZ) {
|
|
return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL);
|
|
}
|
|
|
|
public static long getChunkIndexWithSection(int chunkX, int chunkZ, int section) {
|
|
long l = 0L;
|
|
l |= ((long) chunkX & 4194303L) << 42;
|
|
l |= ((long) section & 1048575L);
|
|
l |= ((long) chunkZ & 4194303L) << 20;
|
|
return l;
|
|
}
|
|
|
|
/**
|
|
* Converts a chunk index to its chunk X position.
|
|
*
|
|
* @param index the chunk index computed by {@link #getChunkIndex(int, int)}
|
|
* @return the chunk X based on the index
|
|
*/
|
|
public static int getChunkCoordX(long index) {
|
|
return (int) (index >> 32);
|
|
}
|
|
|
|
/**
|
|
* Converts a chunk index to its chunk Z position.
|
|
*
|
|
* @param index the chunk index computed by {@link #getChunkIndex(int, int)}
|
|
* @return the chunk Z based on the index
|
|
*/
|
|
public static int getChunkCoordZ(long index) {
|
|
return (int) index;
|
|
}
|
|
|
|
public static int getSectionAt(int y) {
|
|
return y / Chunk.CHUNK_SECTION_SIZE;
|
|
}
|
|
|
|
/**
|
|
* Gets the chunks in range of a position.
|
|
*
|
|
* @param position the initial position
|
|
* @param range how far should it retrieves chunk
|
|
* @return an array containing chunks index
|
|
*/
|
|
@NotNull
|
|
public static long[] getChunksInRange(@NotNull Position position, int range) {
|
|
range = range * 2;
|
|
long[] visibleChunks = new long[MathUtils.square(range + 1)];
|
|
final int startLoop = -(range / 2);
|
|
final int endLoop = range / 2 + 1;
|
|
int counter = 0;
|
|
for (int x = startLoop; x < endLoop; x++) {
|
|
for (int z = startLoop; z < endLoop; z++) {
|
|
final int chunkX = getChunkCoordinate((int) (position.getX() + Chunk.CHUNK_SIZE_X * x));
|
|
final int chunkZ = getChunkCoordinate((int) (position.getZ() + Chunk.CHUNK_SIZE_Z * z));
|
|
visibleChunks[counter++] = getChunkIndex(chunkX, chunkZ);
|
|
}
|
|
}
|
|
return visibleChunks;
|
|
}
|
|
|
|
/**
|
|
* Gets all the loaded neighbours of a chunk and itself, no diagonals.
|
|
*
|
|
* @param instance the instance of the chunks
|
|
* @param chunkX the chunk X
|
|
* @param chunkZ the chunk Z
|
|
* @return an array containing all the loaded neighbours chunk index
|
|
*/
|
|
@NotNull
|
|
public static long[] getNeighbours(@NotNull Instance instance, int chunkX, int chunkZ) {
|
|
LongList chunks = new LongArrayList();
|
|
// Constants used to loop through the neighbors
|
|
final int[] posX = {1, 0, -1};
|
|
final int[] posZ = {1, 0, -1};
|
|
|
|
for (int x : posX) {
|
|
for (int z : posZ) {
|
|
|
|
// No diagonal check
|
|
if ((Math.abs(x) + Math.abs(z)) == 2)
|
|
continue;
|
|
|
|
final int targetX = chunkX + x;
|
|
final int targetZ = chunkZ + z;
|
|
final Chunk chunk = instance.getChunk(targetX, targetZ);
|
|
if (ChunkUtils.isLoaded(chunk)) {
|
|
// Chunk is loaded, add it
|
|
final long index = getChunkIndex(targetX, targetZ);
|
|
chunks.add(index);
|
|
}
|
|
|
|
}
|
|
}
|
|
return chunks.toArray(new long[0]);
|
|
}
|
|
|
|
/**
|
|
* Gets the block index of a position.
|
|
* <p>
|
|
* This can be cast as a short as long as you don't mind receiving a negative value (not array-friendly).
|
|
*
|
|
* @param x the block X
|
|
* @param y the block Y
|
|
* @param z the block Z
|
|
* @return an index which can be used to store and retrieve later data linked to a block position
|
|
*/
|
|
public static int getBlockIndex(int x, int y, int z) {
|
|
x = x % Chunk.CHUNK_SIZE_X;
|
|
z = z % Chunk.CHUNK_SIZE_Z;
|
|
|
|
short index = (short) (x & 0x000F);
|
|
index |= (y << 4) & 0x0FF0;
|
|
index |= (z << 12) & 0xF000;
|
|
return index & 0xffff;
|
|
}
|
|
|
|
/**
|
|
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
|
* @param chunkX the chunk X
|
|
* @param chunkZ the chunk Z
|
|
* @return the instance position of the block located in {@code index}
|
|
*/
|
|
@NotNull
|
|
public static BlockPosition getBlockPosition(int index, int chunkX, int chunkZ) {
|
|
final int x = blockIndexToPositionX(index, chunkX);
|
|
final int y = blockIndexToPositionY(index);
|
|
final int z = blockIndexToPositionZ(index, chunkZ);
|
|
return new BlockPosition(x, y, z);
|
|
}
|
|
|
|
/**
|
|
* Converts a block chunk index to its instance position X.
|
|
*
|
|
* @param index the block chunk index from {@link #getBlockIndex(int, int, int)}
|
|
* @param chunkX the chunk X
|
|
* @return the X coordinate of the block index
|
|
*/
|
|
public static int blockIndexToPositionX(int index, int chunkX) {
|
|
return (int) blockIndexToChunkPositionX(index) + Chunk.CHUNK_SIZE_X * chunkX;
|
|
}
|
|
|
|
/**
|
|
* Converts a block chunk index to its instance position Y.
|
|
*
|
|
* @param index the block chunk index from {@link #getBlockIndex(int, int, int)}
|
|
* @return the Y coordinate of the block index
|
|
*/
|
|
public static int blockIndexToPositionY(int index) {
|
|
return (index >>> 4 & 0xFF);
|
|
}
|
|
|
|
/**
|
|
* Converts a block chunk index to its instance position Z.
|
|
*
|
|
* @param index the block chunk index from {@link #getBlockIndex(int, int, int)}
|
|
* @param chunkZ the chunk Z
|
|
* @return the Z coordinate of the block index
|
|
*/
|
|
public static int blockIndexToPositionZ(int index, int chunkZ) {
|
|
return (int) blockIndexToChunkPositionZ(index) + Chunk.CHUNK_SIZE_Z * chunkZ;
|
|
}
|
|
|
|
/**
|
|
* Converts a block index to a chunk position X.
|
|
*
|
|
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
|
* @return the chunk position X (O-15) of the specified index
|
|
*/
|
|
public static byte blockIndexToChunkPositionX(int index) {
|
|
return (byte) (index & 0xF);
|
|
}
|
|
|
|
/**
|
|
* Converts a block index to a chunk position Y.
|
|
*
|
|
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
|
* @return the chunk position Y (O-255) of the specified index
|
|
*/
|
|
public static short blockIndexToChunkPositionY(int index) {
|
|
return (short) (index >>> 4 & 0xFF);
|
|
}
|
|
|
|
/**
|
|
* Converts a block index to a chunk position Z.
|
|
*
|
|
* @param index an index computed from {@link #getBlockIndex(int, int, int)}
|
|
* @return the chunk position Z (O-15) of the specified index
|
|
*/
|
|
public static byte blockIndexToChunkPositionZ(int index) {
|
|
return (byte) (index >> 12 & 0xF);
|
|
}
|
|
|
|
}
|