mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-04 23:47:59 +01:00
Reduce chunk entities Set allocation
This commit is contained in:
parent
266ecd5b64
commit
a0bb437c4c
@ -1434,10 +1434,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
|||||||
*/
|
*/
|
||||||
public void refreshVisibleChunks(@NotNull Chunk newChunk) {
|
public void refreshVisibleChunks(@NotNull Chunk newChunk) {
|
||||||
// Previous chunks indexes
|
// Previous chunks indexes
|
||||||
final long[] lastVisibleChunks = viewableChunks.stream().mapToLong(viewableChunks ->
|
final long[] lastVisibleChunks = viewableChunks.stream().mapToLong(ChunkUtils::getChunkIndex).toArray();
|
||||||
ChunkUtils.getChunkIndex(viewableChunks.getChunkX(), viewableChunks.getChunkZ())
|
|
||||||
).toArray();
|
|
||||||
|
|
||||||
// New chunks indexes
|
// New chunks indexes
|
||||||
final long[] updatedVisibleChunks = ChunkUtils.getChunksInRange(newChunk.toPosition(), getChunkRange());
|
final long[] updatedVisibleChunks = ChunkUtils.getChunksInRange(newChunk.toPosition(), getChunkRange());
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.minestom.server.instance;
|
package net.minestom.server.instance;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.pointer.Pointers;
|
import net.kyori.adventure.pointer.Pointers;
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
@ -83,8 +85,8 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
|
|||||||
protected final Set<EntityCreature> creatures = ConcurrentHashMap.newKeySet();
|
protected final Set<EntityCreature> creatures = ConcurrentHashMap.newKeySet();
|
||||||
protected final Set<ExperienceOrb> experienceOrbs = ConcurrentHashMap.newKeySet();
|
protected final Set<ExperienceOrb> experienceOrbs = ConcurrentHashMap.newKeySet();
|
||||||
// Entities per chunk
|
// Entities per chunk
|
||||||
protected final Map<Long, Set<Entity>> chunkEntities = new ConcurrentHashMap<>();
|
protected final Object entitiesLock = new Object(); // Lock used to prevent the entities Set and Map to be subject to race condition
|
||||||
private final Object entitiesLock = new Object(); // Lock used to prevent the entities Set and Map to be subject to race condition
|
protected final Long2ObjectMap<Set<Entity>> chunkEntities = new Long2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
// the uuid of this instance
|
// the uuid of this instance
|
||||||
protected UUID uniqueId;
|
protected UUID uniqueId;
|
||||||
@ -486,9 +488,12 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
|
|||||||
public @NotNull Set<Entity> getChunkEntities(Chunk chunk) {
|
public @NotNull Set<Entity> getChunkEntities(Chunk chunk) {
|
||||||
if (!ChunkUtils.isLoaded(chunk))
|
if (!ChunkUtils.isLoaded(chunk))
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
|
final Set<Entity> entities;
|
||||||
final long index = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ());
|
synchronized (entitiesLock) {
|
||||||
final Set<Entity> entities = getEntitiesInChunk(index);
|
if ((entities = chunkEntities.get(ChunkUtils.getChunkIndex(chunk))) == null) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
return Collections.unmodifiableSet(entities);
|
return Collections.unmodifiableSet(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,15 +647,15 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
|
|||||||
final long oldIndex = ChunkUtils.getChunkIndex(lastChunk);
|
final long oldIndex = ChunkUtils.getChunkIndex(lastChunk);
|
||||||
final long newIndex = ChunkUtils.getChunkIndex(newChunk);
|
final long newIndex = ChunkUtils.getChunkIndex(newChunk);
|
||||||
synchronized (entitiesLock) {
|
synchronized (entitiesLock) {
|
||||||
getEntitiesInChunk(oldIndex).remove(entity);
|
removeEntityChunk(oldIndex, entity);
|
||||||
getEntitiesInChunk(newIndex).add(entity);
|
addEntityChunk(newIndex, entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UNSAFE_addEntityToChunk(@NotNull Entity entity, @NotNull Chunk chunk) {
|
private void UNSAFE_addEntityToChunk(@NotNull Entity entity, @NotNull Chunk chunk) {
|
||||||
final long chunkIndex = ChunkUtils.getChunkIndex(chunk);
|
final long chunkIndex = ChunkUtils.getChunkIndex(chunk);
|
||||||
synchronized (entitiesLock) {
|
synchronized (entitiesLock) {
|
||||||
getEntitiesInChunk(chunkIndex).add(entity);
|
addEntityChunk(chunkIndex, entity);
|
||||||
this.entities.add(entity);
|
this.entities.add(entity);
|
||||||
if (entity instanceof Player) {
|
if (entity instanceof Player) {
|
||||||
this.players.add((Player) entity);
|
this.players.add((Player) entity);
|
||||||
@ -665,7 +670,7 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
|
|||||||
private void UNSAFE_removeEntityFromChunk(@NotNull Entity entity, @NotNull Chunk chunk) {
|
private void UNSAFE_removeEntityFromChunk(@NotNull Entity entity, @NotNull Chunk chunk) {
|
||||||
final long chunkIndex = ChunkUtils.getChunkIndex(chunk);
|
final long chunkIndex = ChunkUtils.getChunkIndex(chunk);
|
||||||
synchronized (entitiesLock) {
|
synchronized (entitiesLock) {
|
||||||
getEntitiesInChunk(chunkIndex).remove(entity);
|
removeEntityChunk(chunkIndex, entity);
|
||||||
this.entities.remove(entity);
|
this.entities.remove(entity);
|
||||||
if (entity instanceof Player) {
|
if (entity instanceof Player) {
|
||||||
this.players.remove(entity);
|
this.players.remove(entity);
|
||||||
@ -677,9 +682,18 @@ public abstract class Instance implements BlockGetter, BlockSetter, Tickable, Ta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private void addEntityChunk(long index, Entity entity) {
|
||||||
private Set<Entity> getEntitiesInChunk(long index) {
|
this.chunkEntities.computeIfAbsent(index, i -> ConcurrentHashMap.newKeySet()).add(entity);
|
||||||
return chunkEntities.computeIfAbsent(index, i -> ConcurrentHashMap.newKeySet());
|
}
|
||||||
|
|
||||||
|
private void removeEntityChunk(long index, Entity entity) {
|
||||||
|
var chunkEntities = this.chunkEntities.get(index);
|
||||||
|
if (chunkEntities != null) {
|
||||||
|
chunkEntities.remove(entity);
|
||||||
|
if (chunkEntities.isEmpty()) {
|
||||||
|
this.chunkEntities.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -566,7 +566,9 @@ public class InstanceContainer extends Instance {
|
|||||||
|
|
||||||
// Clear cache
|
// Clear cache
|
||||||
this.chunks.remove(index);
|
this.chunks.remove(index);
|
||||||
this.chunkEntities.remove(index);
|
synchronized (entitiesLock){
|
||||||
|
this.chunkEntities.remove(index);
|
||||||
|
}
|
||||||
|
|
||||||
chunk.unload();
|
chunk.unload();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user