Improve block indexing

This commit is contained in:
TheMode 2021-06-22 14:13:51 +02:00
parent f183c76afa
commit 3b6b1e9859
3 changed files with 19 additions and 77 deletions

View File

@ -18,10 +18,7 @@ import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.ArrayUtils;
import net.minestom.server.utils.PacketUtils;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.chunk.ChunkCallback;
import net.minestom.server.utils.chunk.ChunkSupplier;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.player.PlayerUtils;
import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull;
@ -37,9 +34,6 @@ import java.util.concurrent.ConcurrentHashMap;
* Should contains all the blocks located at those positions and manage their tick updates.
* Be aware that implementations do not need to be thread-safe, all chunks are guarded by their own instance ('this').
* <p>
* Chunks can be serialized using {@link #getSerializedData()} and deserialized back with {@link #readChunk(BinaryReader, ChunkCallback)},
* allowing you to implement your own storage solution if needed.
* <p>
* You can create your own implementation of this class by extending it
* and create the objects in {@link InstanceContainer#setChunkSupplier(ChunkSupplier)}.
* <p>
@ -472,16 +466,4 @@ public abstract class Chunk implements BlockGetter, BlockSetter, Viewable, Ticka
ChunkDataPacket.CACHE.invalidate(getIdentifier());
UpdateLightPacket.CACHE.invalidate(getIdentifier());
}
/**
* Gets the index of a position, used to store blocks.
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the block index
*/
protected int getBlockIndex(int x, int y, int z) {
return ChunkUtils.getBlockIndex(x, y, z);
}
}

View File

@ -53,7 +53,7 @@ public class DynamicChunk extends Chunk {
Section section = retrieveSection(y);
section.setBlockAt(x, y, z, block.stateId());
final int index = getBlockIndex(x, y, z);
final int index = ChunkUtils.getBlockIndex(x, y, z);
// Handler
final BlockHandler handler = block.handler();
if (handler != null) {
@ -93,9 +93,9 @@ public class DynamicChunk extends Chunk {
for (var entry : tickableMap.int2ObjectEntrySet()) {
final int index = entry.getIntKey();
final byte x = ChunkUtils.blockIndexToChunkPositionX(index);
final short y = ChunkUtils.blockIndexToChunkPositionY(index);
final byte z = ChunkUtils.blockIndexToChunkPositionZ(index);
final int x = ChunkUtils.blockIndexToChunkPositionX(index);
final int y = ChunkUtils.blockIndexToChunkPositionY(index);
final int z = ChunkUtils.blockIndexToChunkPositionZ(index);
final BlockPosition blockPosition = new BlockPosition(x, y, z);
final Block block = getBlock(blockPosition);

View File

@ -1,7 +1,5 @@
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;
@ -32,7 +30,7 @@ public final class ChunkUtils {
* @param eachCallback the optional callback when a chunk get loaded
* @param endCallback the optional callback when all the chunks have been loaded
*/
public static void optionalLoadAll(@NotNull Instance instance, @NotNull long[] chunks,
public static void optionalLoadAll(@NotNull Instance instance, long @NotNull [] chunks,
@Nullable ChunkCallback eachCallback, @Nullable ChunkCallback endCallback) {
final int length = chunks.length;
AtomicInteger counter = new AtomicInteger(0);
@ -176,7 +174,7 @@ public final class ChunkUtils {
* @param range how far should it retrieves chunk
* @return an array containing chunks index
*/
public static @NotNull long[] getChunksInRange(@NotNull Position position, int range) {
public static long @NotNull [] getChunksInRange(@NotNull Position position, int range) {
long[] visibleChunks = new long[MathUtils.square(range * 2 + 1)];
int xDistance = 0;
int xDirection = 1;
@ -217,46 +215,8 @@ public final class ChunkUtils {
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
@ -267,10 +227,10 @@ public final class ChunkUtils {
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;
int index = x & 0xF; // 4 bits
index |= (y << 24) & 0x0FFFFFF0; // 24 bits
index |= (z << 28) & 0xF0000000; // 4 bits
return index;
}
/**
@ -295,7 +255,7 @@ public final class ChunkUtils {
* @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;
return blockIndexToChunkPositionX(index) + Chunk.CHUNK_SIZE_X * chunkX;
}
/**
@ -316,7 +276,7 @@ public final class ChunkUtils {
* @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;
return blockIndexToChunkPositionZ(index) + Chunk.CHUNK_SIZE_Z * chunkZ;
}
/**
@ -325,18 +285,18 @@ public final class ChunkUtils {
* @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);
public static int blockIndexToChunkPositionX(int index) {
return index & 0xF; // 0-4 bits
}
/**
* 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
* @return the chunk position Y of the specified index
*/
public static short blockIndexToChunkPositionY(int index) {
return (short) (index >>> 4 & 0xFF);
public static int blockIndexToChunkPositionY(int index) {
return (index >> 4) & 0x0FFFFFF; // 4-28 bits
}
/**
@ -345,8 +305,8 @@ public final class ChunkUtils {
* @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);
public static int blockIndexToChunkPositionZ(int index) {
return (index >> 28) & 0xF; // 28-32 bits
}
/**