diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index 72f71a6b7..c5122884e 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -1,5 +1,7 @@ package net.minestom.server.instance; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Vec; @@ -28,7 +30,6 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; @@ -49,7 +50,8 @@ public class InstanceContainer extends Instance { // the chunk generator used, can be null private ChunkGenerator chunkGenerator; // (chunk index -> chunk) map, contains all the chunks in the instance - private final Map chunks = new ConcurrentHashMap<>(); + // used as a monitor when access is required + private final Long2ObjectMap chunks = new Long2ObjectOpenHashMap<>(); // contains all the chunks to remove during the next instance tick, should be synchronized protected final Set scheduledChunksToRemove = new HashSet<>(); @@ -251,7 +253,9 @@ public class InstanceContainer extends Instance { @Override public Chunk getChunk(int chunkX, int chunkZ) { final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ); - return chunks.get(index); + synchronized (chunks) { + return chunks.get(index); + } } @Override @@ -261,8 +265,7 @@ public class InstanceContainer extends Instance { @Override public @NotNull CompletableFuture saveChunksToStorage() { - Collection chunksCollection = chunks.values(); - return chunkLoader.saveChunks(chunksCollection); + return chunkLoader.saveChunks(getChunks()); } protected @NotNull CompletableFuture<@NotNull Chunk> retrieveChunk(int chunkX, int chunkZ) { @@ -407,17 +410,17 @@ public class InstanceContainer extends Instance { InstanceContainer copiedInstance = new InstanceContainer(UUID.randomUUID(), getDimensionType()); copiedInstance.srcInstance = this; copiedInstance.lastBlockChangeTime = lastBlockChangeTime; + synchronized (chunks) { + for (Chunk chunk : chunks.values()) { + final int chunkX = chunk.getChunkX(); + final int chunkZ = chunk.getChunkZ(); - for (Chunk chunk : chunks.values()) { - final int chunkX = chunk.getChunkX(); - final int chunkZ = chunk.getChunkZ(); + final Chunk copiedChunk = chunk.copy(copiedInstance, chunkX, chunkZ); - final Chunk copiedChunk = chunk.copy(copiedInstance, chunkX, chunkZ); - - copiedInstance.cacheChunk(copiedChunk); - UPDATE_MANAGER.signalChunkLoad(copiedChunk); + copiedInstance.cacheChunk(copiedChunk); + UPDATE_MANAGER.signalChunkLoad(copiedChunk); + } } - return copiedInstance; } @@ -462,7 +465,9 @@ public class InstanceContainer extends Instance { */ public void cacheChunk(@NotNull Chunk chunk) { final long index = ChunkUtils.getChunkIndex(chunk); - this.chunks.put(index, chunk); + synchronized (chunks) { + this.chunks.put(index, chunk); + } } @Override @@ -482,7 +487,9 @@ public class InstanceContainer extends Instance { */ @Override public @NotNull Collection<@NotNull Chunk> getChunks() { - return Collections.unmodifiableCollection(chunks.values()); + synchronized (chunks) { + return List.copyOf(chunks.values()); + } } /** @@ -565,8 +572,10 @@ public class InstanceContainer extends Instance { }); // Clear cache - this.chunks.remove(index); - synchronized (entitiesLock){ + synchronized (chunks) { + this.chunks.remove(index); + } + synchronized (entitiesLock) { this.chunkEntities.remove(index); }