Implement offset for RelativeBlockBatch + optimization

This commit is contained in:
themode 2021-01-08 15:33:48 +01:00 committed by Matt Worzala
parent 8531d3958d
commit 66a5829c3e
2 changed files with 44 additions and 20 deletions

View File

@ -9,7 +9,6 @@ import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -85,8 +84,8 @@ public class AbsoluteBlockBatch implements Batch<Runnable> {
protected void apply(@NotNull InstanceContainer instance, @Nullable Runnable callback, boolean safeCallback) {
synchronized (chunkBatchesMap) {
AtomicInteger counter = new AtomicInteger();
for (Map.Entry<Long, ChunkBatch> entry : chunkBatchesMap.long2ObjectEntrySet()) {
final long chunkIndex = entry.getKey();
for (Long2ObjectMap.Entry<ChunkBatch> entry : chunkBatchesMap.long2ObjectEntrySet()) {
final long chunkIndex = entry.getLongKey();
final int chunkX = ChunkUtils.getChunkCoordX(chunkIndex);
final int chunkZ = ChunkUtils.getChunkCoordZ(chunkIndex);
final ChunkBatch batch = entry.getValue();

View File

@ -1,6 +1,9 @@
package net.minestom.server.instance.batch;
import it.unimi.dsi.fastutil.longs.*;
import it.unimi.dsi.fastutil.longs.Long2IntMap;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
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.InstanceContainer;
import net.minestom.server.utils.BlockPosition;
@ -8,8 +11,6 @@ import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class RelativeBlockBatch implements Batch<Runnable> {
// relative pos format: nothing/relative x/relative y/relative z (16/16/16/16 bits)
@ -21,8 +22,27 @@ public class RelativeBlockBatch implements Batch<Runnable> {
// relative pos - data
private final Long2ObjectMap<Data> blockDataMap = new Long2ObjectOpenHashMap<>();
private volatile boolean firstEntry = true;
private int offsetX, offsetY, offsetZ;
@Override
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data) {
// Save the offsets if it is the first entry
if (!firstEntry) {
this.firstEntry = true;
this.offsetX = x;
this.offsetY = y;
this.offsetZ = z;
}
// Subtract offset
x -= offsetX;
y -= offsetY;
z -= offsetZ;
// Verify that blocks are not too far from each other
Check.argCondition(Math.abs(x) > Short.MAX_VALUE, "Relative x position may not be more than 16 bits long.");
Check.argCondition(Math.abs(y) > Short.MAX_VALUE, "Relative y position may not be more than 16 bits long.");
Check.argCondition(Math.abs(z) > Short.MAX_VALUE, "Relative z position may not be more than 16 bits long.");
@ -34,11 +54,12 @@ public class RelativeBlockBatch implements Batch<Runnable> {
final int block = (blockStateId << 16) | customBlockId;
synchronized (blockIdMap) {
this.blockIdMap.put(pos, block);
}
if (data != null) {
synchronized (blockDataMap) {
this.blockDataMap.put(pos, data);
// Save data if present
if (data != null) {
synchronized (blockDataMap) {
this.blockDataMap.put(pos, data);
}
}
}
}
@ -68,18 +89,18 @@ public class RelativeBlockBatch implements Batch<Runnable> {
}
protected void apply(@NotNull InstanceContainer instance, int x, int y, int z, @Nullable Runnable callback, boolean safeCallback) {
final AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
synchronized (blockIdMap) {
for (Map.Entry<Long, Integer> entry : blockIdMap.long2IntEntrySet()) {
long pos = entry.getKey();
short relZ = (short) (pos & 0xFFFF);
short relY = (short) ((pos >> 16) & 0xFFFF);
short relX = (short) ((pos >> 32) & 0xFFFF);
for (Long2IntMap.Entry entry : blockIdMap.long2IntEntrySet()) {
final long pos = entry.getLongKey();
final short relZ = (short) (pos & 0xFFFF);
final short relY = (short) ((pos >> 16) & 0xFFFF);
final short relX = (short) ((pos >> 32) & 0xFFFF);
int ids = entry.getValue();
short customBlockId = (short) (ids & 0xFFFF);
short blockStateId = (short) ((ids >> 16) & 0xFFFF);
final int ids = entry.getIntValue();
final short customBlockId = (short) (ids & 0xFFFF);
final short blockStateId = (short) ((ids >> 16) & 0xFFFF);
Data data = null;
if (!blockDataMap.isEmpty()) {
@ -88,7 +109,11 @@ public class RelativeBlockBatch implements Batch<Runnable> {
}
}
batch.setSeparateBlocks(x + relX, y + relY, z + relZ, blockStateId, customBlockId, data);
final int finalX = x + offsetX + relX;
final int finalY = y + offsetY + relY;
final int finalZ = z + offsetZ + relZ;
batch.setSeparateBlocks(finalX, finalY, finalZ, blockStateId, customBlockId, data);
}
}