mirror of
https://github.com/Minestom/Minestom.git
synced 2025-03-13 07:09:51 +01:00
Small cleanup and reduce memory usage with AbsoluteBlockBatch
This commit is contained in:
parent
c35b8887e8
commit
6bd09256f3
@ -1,5 +1,7 @@
|
||||
package net.minestom.server.instance.batch.v2;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.InstanceContainer;
|
||||
@ -7,12 +9,11 @@ import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A Batch which can be used when changes are required across chunk borders,
|
||||
* A {@link Batch} which can be used when changes are required across chunk borders,
|
||||
* but the changes do not need any translation. If translation is required,
|
||||
* use a {@link RelativeBlockBatch} instead.
|
||||
* <p>
|
||||
@ -24,9 +25,10 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public class AbsoluteBlockBatch implements Batch<Runnable> {
|
||||
|
||||
// In the form of <Chunk Index, Batch>
|
||||
private final Map<Long, ChunkBatch> data = new HashMap<>();
|
||||
private final Long2ObjectMap<ChunkBatch> chunkBatchesMap = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
public AbsoluteBlockBatch() {}
|
||||
public AbsoluteBlockBatch() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data) {
|
||||
@ -34,7 +36,10 @@ public class AbsoluteBlockBatch implements Batch<Runnable> {
|
||||
final int chunkZ = ChunkUtils.getChunkCoordinate(z);
|
||||
final long chunkIndex = ChunkUtils.getChunkIndex(chunkX, chunkZ);
|
||||
|
||||
final ChunkBatch chunkBatch = this.data.computeIfAbsent(chunkIndex, i -> new ChunkBatch());
|
||||
final ChunkBatch chunkBatch;
|
||||
synchronized (chunkBatchesMap) {
|
||||
chunkBatch = chunkBatchesMap.computeIfAbsent(chunkIndex, i -> new ChunkBatch());
|
||||
}
|
||||
|
||||
final int relativeX = x - (chunkX * Chunk.CHUNK_SIZE_X);
|
||||
final int relativeZ = z - (chunkZ * Chunk.CHUNK_SIZE_Z);
|
||||
@ -43,13 +48,13 @@ public class AbsoluteBlockBatch implements Batch<Runnable> {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
synchronized (data) {
|
||||
this.data.clear();
|
||||
synchronized (chunkBatchesMap) {
|
||||
this.chunkBatchesMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this batch to the given instance.
|
||||
* Applies this batch to the given instance.
|
||||
*
|
||||
* @param instance The instance in which the batch should be applied
|
||||
* @param callback The callback to be executed when the batch is applied
|
||||
@ -60,7 +65,7 @@ public class AbsoluteBlockBatch implements Batch<Runnable> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this batch to the given instance, and execute the callback immediately when the
|
||||
* Applies this batch to the given instance, and execute the callback immediately when the
|
||||
* blocks have been applied, in an unknown thread.
|
||||
*
|
||||
* @param instance The instance in which the batch should be applied
|
||||
@ -71,32 +76,33 @@ public class AbsoluteBlockBatch implements Batch<Runnable> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this batch to the given instance, and execute the callback depending on safeCallback.
|
||||
* Applies this batch to the given instance, and execute the callback depending on safeCallback.
|
||||
*
|
||||
* @param instance The instance in which the batch should be applied
|
||||
* @param callback The callback to be executed when the batch is applied
|
||||
* @param instance The instance in which the batch should be applied
|
||||
* @param callback The callback to be executed when the batch is applied
|
||||
* @param safeCallback If true, the callback will be executed in the next instance update. Otherwise it will be executed immediately upon completion
|
||||
*
|
||||
*/
|
||||
protected void apply(@NotNull InstanceContainer instance, @Nullable Runnable callback, boolean safeCallback) {
|
||||
synchronized (data) {
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
for (Map.Entry<Long, ChunkBatch> entry : data.entrySet()) {
|
||||
synchronized (chunkBatchesMap) {
|
||||
AtomicInteger counter = new AtomicInteger();
|
||||
for (Map.Entry<Long, ChunkBatch> entry : chunkBatchesMap.long2ObjectEntrySet()) {
|
||||
final long chunkIndex = entry.getKey();
|
||||
final int chunkX = ChunkUtils.getChunkCoordX(chunkIndex);
|
||||
final int chunkZ = ChunkUtils.getChunkCoordZ(chunkIndex);
|
||||
final ChunkBatch batch = entry.getValue();
|
||||
|
||||
batch.apply(instance, chunkX, chunkZ, c -> {
|
||||
final boolean isLast = counter.incrementAndGet() == data.size();
|
||||
final boolean isLast = counter.incrementAndGet() == chunkBatchesMap.size();
|
||||
|
||||
// Execute the callback if this was the last chunk to process
|
||||
if (isLast) {
|
||||
instance.refreshLastBlockChangeTime();
|
||||
if (callback != null) {
|
||||
if (safeCallback)
|
||||
if (safeCallback) {
|
||||
instance.scheduleNextTick(inst -> callback.run());
|
||||
else callback.run();
|
||||
} else {
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ import java.util.concurrent.ExecutorService;
|
||||
* A Batch is a tool used to cache a list of block changes, and apply the changes whenever you want.
|
||||
* <p>
|
||||
* Batches offer a performance benefit because clients are not notified of any change until all of
|
||||
* the blocks have been placed.
|
||||
* the blocks have been placed, and because changes can happen with less synchronization.
|
||||
* <p>
|
||||
* All batches may be rotated using {link}, however rotate operations do not mutate the batch, so the
|
||||
* result should be cached if used multiple times.
|
||||
@ -30,6 +30,7 @@ import java.util.concurrent.ExecutorService;
|
||||
* @see RelativeBlockBatch
|
||||
*/
|
||||
public interface Batch<Callback> extends BlockModifier {
|
||||
|
||||
ExecutorService BLOCK_BATCH_POOL = new MinestomThread(MinecraftServer.THREAD_COUNT_BLOCK_BATCH, MinecraftServer.THREAD_NAME_BLOCK_BATCH);
|
||||
|
||||
@Override
|
||||
|
@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @see Batch
|
||||
*/
|
||||
public class ChunkBatch implements Batch<ChunkCallback> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ChunkBatch.class);
|
||||
|
||||
// Need to be synchronized manually
|
||||
@ -187,7 +188,7 @@ public class ChunkBatch implements Batch<ChunkCallback> {
|
||||
/**
|
||||
* Updates the given chunk for all of its viewers, and executes the callback.
|
||||
*/
|
||||
private void updateChunk(InstanceContainer instance, Chunk chunk, @Nullable ChunkCallback callback, boolean safeCallback) {
|
||||
private void updateChunk(@NotNull InstanceContainer instance, @NotNull Chunk chunk, @Nullable ChunkCallback callback, boolean safeCallback) {
|
||||
// Refresh chunk for viewers
|
||||
|
||||
// Formerly this had an option to do a Chunk#sendChunkUpdate
|
||||
|
Loading…
Reference in New Issue
Block a user