Add shouldLoadChunks in BlockBatch#flush

This commit is contained in:
KrystilizeNevaDies 2021-02-12 10:37:53 +10:00
parent 04c792c302
commit ee8815d2f8

View File

@ -6,6 +6,8 @@ import net.minestom.server.instance.Instance;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.utils.block.CustomBlockUtils;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -13,6 +15,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -76,44 +79,70 @@ public class BlockBatch implements InstanceBatch {
}
public void flush(@Nullable Runnable callback) {
this.flush(callback, false);
}
public void flush(@Nullable Runnable callback, boolean shouldLoadChunks) {
synchronized (data) {
AtomicInteger counter = new AtomicInteger();
for (Map.Entry<Chunk, List<BlockData>> entry : data.entrySet()) {
final Chunk chunk = entry.getKey();
final List<BlockData> dataList = entry.getValue();
BLOCK_BATCH_POOL.execute(() -> {
synchronized (chunk) {
if (!chunk.isLoaded())
return;
if (batchOption.isFullChunk()) {
chunk.reset();
}
for (BlockData data : dataList) {
data.apply(chunk);
}
// Refresh chunk for viewers
if (batchOption.isFullChunk()) {
chunk.sendChunk();
} else {
chunk.sendChunkUpdate();
}
final boolean isLast = counter.incrementAndGet() == data.size();
// Execute the callback if this was the last chunk to process
if (isLast) {
this.instance.refreshLastBlockChangeTime();
if (callback != null) {
this.instance.scheduleNextTick(inst -> callback.run());
}
}
// Load chunks if applicable
if (shouldLoadChunks) {
// Get chunks
Chunk[] chunks = data.keySet().toArray(new Chunk[data.size()]);
// Get chunk indexs
Long[] indexs = new Long[chunks.length];
for (int i = 0; i < chunks.length; i++) {
indexs[i] = ChunkUtils.getChunkIndex(chunks[i].getChunkX(), chunks[i].getChunkZ());
}
// Load all chunks + flush block data
ChunkUtils.optionalLoadAll(instance, null, null, (chunk) -> {
flushBlockData(callback);
});
} else {
flushBlockData(callback);
}
}
}
private void flushBlockData(@Nullable Runnable callback) {
AtomicInteger counter = new AtomicInteger();
for (Map.Entry<Chunk, List<BlockData>> entry : data.entrySet()) {
final Chunk chunk = entry.getKey();
final List<BlockData> dataList = entry.getValue();
BLOCK_BATCH_POOL.execute(() -> {
synchronized (chunk) {
if (!chunk.isLoaded())
return;
if (batchOption.isFullChunk()) {
chunk.reset();
}
});
}
for (BlockData data : dataList) {
data.apply(chunk);
}
// Refresh chunk for viewers
if (batchOption.isFullChunk()) {
chunk.sendChunk();
} else {
chunk.sendChunkUpdate();
}
final boolean isLast = counter.incrementAndGet() == data.size();
// Execute the callback if this was the last chunk to process
if (isLast) {
this.instance.refreshLastBlockChangeTime();
if (callback != null) {
this.instance.scheduleNextTick(inst -> callback.run());
}
}
}
});
}
}