mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-07 16:01:55 +01:00
Added ChunkUtils#isLoaded + optimization of the thread providers
This commit is contained in:
parent
13275eb534
commit
c2165abe1f
@ -142,7 +142,7 @@ public class CollisionUtils {
|
||||
blockPos.setZ((int) Math.floor(corner.getZ()));
|
||||
|
||||
final Chunk chunk = instance.getChunkAt(blockPos);
|
||||
if (ChunkUtils.isChunkUnloaded(chunk)) {
|
||||
if (!ChunkUtils.isLoaded(chunk)) {
|
||||
// Collision at chunk border
|
||||
return false;
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean chunkUnloaded = ChunkUtils.isChunkUnloaded(instance, position.getX(), position.getZ());
|
||||
boolean chunkUnloaded = !ChunkUtils.isLoaded(instance, position.getX(), position.getZ());
|
||||
if (chunkUnloaded) {
|
||||
// No update for entities in unloaded chunk
|
||||
return;
|
||||
@ -461,7 +461,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
chunkUnloaded = ChunkUtils.isChunkUnloaded(instance, x, z);
|
||||
chunkUnloaded = !ChunkUtils.isLoaded(instance, x, z);
|
||||
if (chunkUnloaded)
|
||||
continue;
|
||||
final CustomBlock customBlock = instance.getCustomBlock(x, y, z);
|
||||
|
@ -368,7 +368,7 @@ public abstract class EntityCreature extends LivingEntity {
|
||||
|
||||
// Can't path in an unloaded chunk
|
||||
final Chunk chunk = instance.getChunkAt(position);
|
||||
if (ChunkUtils.isChunkUnloaded(chunk)) {
|
||||
if (!ChunkUtils.isLoaded(chunk)) {
|
||||
this.pathLock.unlock();
|
||||
return false;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public class ClosestEntityTarget extends TargetSelector {
|
||||
final int targetX = chunkX + x;
|
||||
final int targetZ = chunkZ + z;
|
||||
final Chunk chunk = instance.getChunk(targetX, targetZ);
|
||||
if (!ChunkUtils.isChunkUnloaded(chunk)) {
|
||||
if (ChunkUtils.isLoaded(chunk)) {
|
||||
// Chunk is loaded, add it
|
||||
chunks.add(chunk);
|
||||
}
|
||||
|
@ -455,7 +455,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
||||
* if {@code chunk} is unloaded, return an empty {@link HashSet}
|
||||
*/
|
||||
public Set<Entity> getChunkEntities(Chunk chunk) {
|
||||
if (ChunkUtils.isChunkUnloaded(chunk))
|
||||
if (!ChunkUtils.isLoaded(chunk))
|
||||
return new HashSet<>();
|
||||
|
||||
final long index = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
|
||||
|
@ -236,7 +236,7 @@ public class InstanceContainer extends Instance {
|
||||
final Chunk chunk = getChunkAt(blockPosition);
|
||||
|
||||
// Chunk unloaded, stop here
|
||||
if (ChunkUtils.isChunkUnloaded(chunk))
|
||||
if (!ChunkUtils.isLoaded(chunk))
|
||||
return false;
|
||||
|
||||
final int x = blockPosition.getX();
|
||||
@ -316,7 +316,8 @@ public class InstanceContainer extends Instance {
|
||||
|
||||
@Override
|
||||
public void unloadChunk(Chunk chunk) {
|
||||
if (ChunkUtils.isChunkUnloaded(chunk)) {
|
||||
// Already unloaded chunk
|
||||
if (!ChunkUtils.isLoaded(chunk)) {
|
||||
return;
|
||||
}
|
||||
// Schedule the chunk removal
|
||||
@ -328,7 +329,7 @@ public class InstanceContainer extends Instance {
|
||||
@Override
|
||||
public Chunk getChunk(int chunkX, int chunkZ) {
|
||||
final Chunk chunk = chunks.get(ChunkUtils.getChunkIndex(chunkX, chunkZ));
|
||||
return ChunkUtils.isChunkUnloaded(chunk) ? null : chunk;
|
||||
return ChunkUtils.isLoaded(chunk) ? chunk : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,7 +51,7 @@ public class PlayerPositionListener {
|
||||
float yaw, float pitch, boolean onGround) {
|
||||
|
||||
// Try to move in an unloaded chunk, prevent it
|
||||
if (ChunkUtils.isChunkUnloaded(player.getInstance(), x, z)) {
|
||||
if (!ChunkUtils.isLoaded(player.getInstance(), x, z)) {
|
||||
player.teleport(player.getPosition());
|
||||
return;
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package net.minestom.server.thread;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@ -19,28 +22,28 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
/**
|
||||
* Chunk -> its chunk group
|
||||
*/
|
||||
private Map<Instance, Map<ChunkCoordinate, Set<ChunkCoordinate>>> instanceChunksGroupMap = new ConcurrentHashMap<>();
|
||||
private Map<Instance, Long2ObjectMap<LongSet>> instanceChunksGroupMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Used to know to which instance is linked a Set of chunks
|
||||
*/
|
||||
private Map<Instance, Map<Set<ChunkCoordinate>, Instance>> instanceInstanceMap = new ConcurrentHashMap<>();
|
||||
private Map<Instance, Map<LongSet, Instance>> instanceInstanceMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||
Map<ChunkCoordinate, Set<ChunkCoordinate>> chunksGroupMap = getChunksGroupMap(instance);
|
||||
Map<Set<ChunkCoordinate>, Instance> instanceMap = getInstanceMap(instance);
|
||||
Long2ObjectMap<LongSet> chunksGroupMap = getChunksGroupMap(instance);
|
||||
Map<LongSet, Instance> instanceMap = getInstanceMap(instance);
|
||||
|
||||
// List of groups which are neighbours
|
||||
List<Set<ChunkCoordinate>> neighboursGroups = new ArrayList<>();
|
||||
List<LongSet> neighboursGroups = new ArrayList<>();
|
||||
|
||||
final List<ChunkCoordinate> chunks = getNeighbours(instance, chunkX, chunkZ);
|
||||
final long[] chunks = ChunkUtils.getNeighbours(instance, chunkX, chunkZ);
|
||||
boolean findGroup = false;
|
||||
for (ChunkCoordinate chunkCoordinate : chunks) {
|
||||
if (chunksGroupMap.containsKey(chunkCoordinate)) {
|
||||
final Set<ChunkCoordinate> group = chunksGroupMap.get(chunkCoordinate);
|
||||
for (long chunkIndex : chunks) {
|
||||
if (chunksGroupMap.containsKey(chunkIndex)) {
|
||||
final LongSet group = chunksGroupMap.get(chunkIndex);
|
||||
neighboursGroups.add(group);
|
||||
chunksGroupMap.remove(chunkCoordinate);
|
||||
chunksGroupMap.remove(chunkIndex);
|
||||
instanceMap.remove(group);
|
||||
findGroup = true;
|
||||
}
|
||||
@ -48,30 +51,31 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
|
||||
if (!findGroup) {
|
||||
// Create group of one chunk
|
||||
final ChunkCoordinate chunkCoordinate = new ChunkCoordinate(chunkX, chunkZ);
|
||||
Set<ChunkCoordinate> chunkCoordinates = new CopyOnWriteArraySet<>();
|
||||
chunkCoordinates.add(chunkCoordinate);
|
||||
final long chunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
LongSet chunkIndexes = new LongArraySet();
|
||||
chunkIndexes.add(chunkIndex);
|
||||
|
||||
chunksGroupMap.put(chunkCoordinate, chunkCoordinates);
|
||||
instanceMap.put(chunkCoordinates, instance);
|
||||
chunksGroupMap.put(chunkIndex, chunkIndexes);
|
||||
instanceMap.put(chunkIndexes, instance);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Represent the merged group of all the neighbours
|
||||
Set<ChunkCoordinate> finalGroup = new CopyOnWriteArraySet<>();
|
||||
LongSet finalGroup = new LongArraySet();
|
||||
|
||||
// Add the newly loaded chunk to the group
|
||||
finalGroup.add(new ChunkCoordinate(chunkX, chunkZ));
|
||||
final long chunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
finalGroup.add(chunkIndex);
|
||||
|
||||
// Add all the neighbours groups to the final one
|
||||
for (Set<ChunkCoordinate> chunkCoordinates : neighboursGroups) {
|
||||
for (LongSet chunkCoordinates : neighboursGroups) {
|
||||
finalGroup.addAll(chunkCoordinates);
|
||||
}
|
||||
|
||||
// Complete maps
|
||||
for (ChunkCoordinate chunkCoordinate : finalGroup) {
|
||||
chunksGroupMap.put(chunkCoordinate, finalGroup);
|
||||
for (long index : finalGroup) {
|
||||
chunksGroupMap.put(index, finalGroup);
|
||||
}
|
||||
|
||||
instanceMap.put(finalGroup, instance);
|
||||
@ -80,15 +84,15 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
|
||||
@Override
|
||||
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||
Map<ChunkCoordinate, Set<ChunkCoordinate>> chunksGroupMap = getChunksGroupMap(instance);
|
||||
Map<Set<ChunkCoordinate>, Instance> instanceMap = getInstanceMap(instance);
|
||||
Long2ObjectMap<LongSet> chunksGroupMap = getChunksGroupMap(instance);
|
||||
Map<LongSet, Instance> instanceMap = getInstanceMap(instance);
|
||||
|
||||
final ChunkCoordinate chunkCoordinate = new ChunkCoordinate(chunkX, chunkZ);
|
||||
if (chunksGroupMap.containsKey(chunkCoordinate)) {
|
||||
final long chunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
if (chunksGroupMap.containsKey(chunkIndex)) {
|
||||
// The unloaded chunk is part of a group, remove it from the group
|
||||
Set<ChunkCoordinate> chunkCoordinates = chunksGroupMap.get(chunkCoordinate);
|
||||
chunkCoordinates.remove(chunkCoordinate);
|
||||
chunksGroupMap.remove(chunkCoordinate);
|
||||
LongSet chunkCoordinates = chunksGroupMap.get(chunkIndex);
|
||||
chunkCoordinates.remove(chunkIndex);
|
||||
chunksGroupMap.remove(chunkIndex);
|
||||
|
||||
if (chunkCoordinates.isEmpty()) {
|
||||
// The chunk group is empty, remove it entirely
|
||||
@ -102,17 +106,16 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
// Set of already-updated instances this tick
|
||||
final Set<Instance> updatedInstance = new HashSet<>();
|
||||
|
||||
getLock().lock();
|
||||
instanceInstanceMap.entrySet().forEach(entry -> {
|
||||
final Instance instance = entry.getKey();
|
||||
final Map<Set<ChunkCoordinate>, Instance> instanceMap = entry.getValue();
|
||||
final Map<LongSet, Instance> instanceMap = entry.getValue();
|
||||
|
||||
// True if the instance ended its tick call
|
||||
AtomicBoolean instanceUpdated = new AtomicBoolean(false);
|
||||
|
||||
// Update all the chunks + instances
|
||||
for (Map.Entry<Set<ChunkCoordinate>, Instance> ent : instanceMap.entrySet()) {
|
||||
final Set<ChunkCoordinate> chunks = ent.getKey();
|
||||
for (Map.Entry<LongSet, Instance> ent : instanceMap.entrySet()) {
|
||||
final LongSet chunksIndexes = ent.getKey();
|
||||
|
||||
final boolean shouldUpdateInstance = updatedInstance.add(instance);
|
||||
pool.execute(() -> {
|
||||
@ -127,9 +130,10 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
while (!instanceUpdated.get()) {
|
||||
}
|
||||
|
||||
for (ChunkCoordinate chunkCoordinate : chunks) {
|
||||
final Chunk chunk = instance.getChunk(chunkCoordinate.chunkX, chunkCoordinate.chunkZ);
|
||||
if (ChunkUtils.isChunkUnloaded(chunk)) {
|
||||
for (long chunkIndex : chunksIndexes) {
|
||||
final int[] chunkCoordinates = ChunkUtils.getChunkCoord(chunkIndex);
|
||||
final Chunk chunk = instance.getChunk(chunkCoordinates[0], chunkCoordinates[1]);
|
||||
if (!ChunkUtils.isLoaded(chunk)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -142,49 +146,14 @@ public class PerGroupChunkProvider extends ThreadProvider {
|
||||
}
|
||||
|
||||
});
|
||||
getLock().unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the 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 the loaded neighbours of the chunk
|
||||
*/
|
||||
private List<ChunkCoordinate> getNeighbours(Instance instance, int chunkX, int chunkZ) {
|
||||
List<ChunkCoordinate> chunks = new ArrayList<>();
|
||||
// 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.isChunkUnloaded(chunk)) {
|
||||
// Chunk is loaded, add it
|
||||
chunks.add(toChunkCoordinate(chunk));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
private Long2ObjectMap<LongSet> getChunksGroupMap(Instance instance) {
|
||||
return instanceChunksGroupMap.computeIfAbsent(instance, inst -> new Long2ObjectOpenHashMap<>());
|
||||
}
|
||||
|
||||
private Map<ChunkCoordinate, Set<ChunkCoordinate>> getChunksGroupMap(Instance instance) {
|
||||
return instanceChunksGroupMap.computeIfAbsent(instance, inst -> new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
private Map<Set<ChunkCoordinate>, Instance> getInstanceMap(Instance instance) {
|
||||
return instanceInstanceMap.computeIfAbsent(instance, inst -> new ConcurrentHashMap<>());
|
||||
private Map<LongSet, Instance> getInstanceMap(Instance instance) {
|
||||
return instanceInstanceMap.computeIfAbsent(instance, inst -> new HashMap<>());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,50 +1,51 @@
|
||||
package net.minestom.server.thread;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Separate work between instance (1 instance = 1 thread execution)
|
||||
*/
|
||||
public class PerInstanceThreadProvider extends ThreadProvider {
|
||||
|
||||
private Map<Instance, Set<ChunkCoordinate>> instanceChunkMap = new HashMap<>();
|
||||
private Map<Instance, LongSet> instanceChunkMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onChunkLoad(Instance instance, int chunkX, int chunkZ) {
|
||||
// Add the loaded chunk to the instance chunks list
|
||||
Set<ChunkCoordinate> chunkCoordinates = getChunkCoordinates(instance);
|
||||
chunkCoordinates.add(new ChunkCoordinate(chunkX, chunkZ));
|
||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
chunkCoordinates.add(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkUnload(Instance instance, int chunkX, int chunkZ) {
|
||||
Set<ChunkCoordinate> chunkCoordinates = getChunkCoordinates(instance);
|
||||
LongSet chunkCoordinates = getChunkCoordinates(instance);
|
||||
final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
// Remove the unloaded chunk from the instance list
|
||||
chunkCoordinates.removeIf(chunkCoordinate -> chunkCoordinate.chunkX == chunkX &&
|
||||
chunkCoordinate.chunkZ == chunkZ);
|
||||
chunkCoordinates.remove(index);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(long time) {
|
||||
getLock().lock();
|
||||
for (Map.Entry<Instance, Set<ChunkCoordinate>> entry : instanceChunkMap.entrySet()) {
|
||||
for (Map.Entry<Instance, LongSet> entry : instanceChunkMap.entrySet()) {
|
||||
final Instance instance = entry.getKey();
|
||||
final Set<ChunkCoordinate> chunkCoordinates = entry.getValue();
|
||||
final LongSet chunkIndexes = entry.getValue();
|
||||
|
||||
pool.execute(() -> {
|
||||
updateInstance(instance, time);
|
||||
|
||||
for (ChunkCoordinate chunkCoordinate : chunkCoordinates) {
|
||||
final Chunk chunk = instance.getChunk(chunkCoordinate.chunkX, chunkCoordinate.chunkZ);
|
||||
if (ChunkUtils.isChunkUnloaded(chunk))
|
||||
for (long chunkIndex : chunkIndexes) {
|
||||
final int[] chunkCoordinates = ChunkUtils.getChunkCoord(chunkIndex);
|
||||
final Chunk chunk = instance.getChunk(chunkCoordinates[0], chunkCoordinates[1]);
|
||||
if (!ChunkUtils.isLoaded(chunk))
|
||||
continue;
|
||||
|
||||
updateChunk(instance, chunk, time);
|
||||
@ -53,12 +54,11 @@ public class PerInstanceThreadProvider extends ThreadProvider {
|
||||
|
||||
}
|
||||
});
|
||||
getLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private Set<ChunkCoordinate> getChunkCoordinates(Instance instance) {
|
||||
return instanceChunkMap.computeIfAbsent(instance, inst -> new HashSet<>());
|
||||
private LongSet getChunkCoordinates(Instance instance) {
|
||||
return instanceChunkMap.computeIfAbsent(instance, inst -> new LongArraySet());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,10 +6,8 @@ import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.thread.MinestomThread;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@ -27,8 +25,6 @@ public abstract class ThreadProvider {
|
||||
*/
|
||||
private int threadCount;
|
||||
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
{
|
||||
// Default thread count in the pool
|
||||
setThreadCount(5);
|
||||
@ -78,15 +74,6 @@ public abstract class ThreadProvider {
|
||||
refreshPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lock of this thread provider
|
||||
*
|
||||
* @return the thread provider lock
|
||||
*/
|
||||
public ReentrantLock getLock() {
|
||||
return lock;
|
||||
}
|
||||
|
||||
private void refreshPool() {
|
||||
this.pool = new MinestomThread(threadCount, MinecraftServer.THREAD_NAME_TICK);
|
||||
}
|
||||
@ -195,41 +182,4 @@ public abstract class ThreadProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link Chunk} to a {@link ChunkCoordinate}
|
||||
*
|
||||
* @param chunk the chunk to convert
|
||||
* @return the converted {@link ChunkCoordinate}
|
||||
*/
|
||||
protected ChunkCoordinate toChunkCoordinate(Chunk chunk) {
|
||||
return new ChunkCoordinate(chunk.getChunkX(), chunk.getChunkZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent the coordinates of a {@link Chunk}
|
||||
* Used so the chunks objects can be cleared by the garbage collector properly¬
|
||||
*/
|
||||
protected static class ChunkCoordinate {
|
||||
public int chunkX, chunkZ;
|
||||
|
||||
public ChunkCoordinate(int chunkX, int chunkZ) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ChunkCoordinate that = (ChunkCoordinate) o;
|
||||
return chunkX == that.chunkX &&
|
||||
chunkZ == that.chunkZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
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;
|
||||
@ -13,29 +15,29 @@ public final class ChunkUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if a chunk is unloaded
|
||||
* Get if a chunk is loaded
|
||||
*
|
||||
* @param chunk the chunk to check
|
||||
* @return true if the chunk is unloaded, false otherwise
|
||||
* @return true if the chunk is loaded, false otherwise
|
||||
*/
|
||||
public static boolean isChunkUnloaded(Chunk chunk) {
|
||||
return chunk == null || !chunk.isLoaded();
|
||||
public static boolean isLoaded(Chunk chunk) {
|
||||
return chunk != null && chunk.isLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if a chunk is unloaded
|
||||
* Get 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 unloaded, false otherwise
|
||||
* @return true if the chunk is loaded, false otherwise
|
||||
*/
|
||||
public static boolean isChunkUnloaded(Instance instance, float x, float z) {
|
||||
public static boolean isLoaded(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 isChunkUnloaded(chunk);
|
||||
return isLoaded(chunk);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,6 +50,8 @@ public final class ChunkUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get 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
|
||||
@ -71,6 +75,8 @@ public final class ChunkUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get 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 which can be converted using {@link #getChunkCoord(long)}
|
||||
@ -92,6 +98,44 @@ public final class ChunkUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get 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
|
||||
* can be deserialized using {@link #indexToChunkPosition(int)}
|
||||
*/
|
||||
public static long[] getNeighbours(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]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block index of a position
|
||||
*
|
||||
* @param x the block X
|
||||
* @param y the block Y
|
||||
* @param z the block Z
|
||||
|
Loading…
Reference in New Issue
Block a user