Temp RelativeBlockBatch implementation

This commit is contained in:
Matt Worzala 2021-01-08 03:29:12 -05:00
parent 73249deb5a
commit 8531d3958d
2 changed files with 170 additions and 8 deletions

View File

@ -1,4 +1,97 @@
package net.minestom.server.instance.batch;
public class RelativeBlockBatch {
import it.unimi.dsi.fastutil.longs.*;
import net.minestom.server.data.Data;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.utils.BlockPosition;
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)
// Need to be synchronized manually
// Format: relative pos - blockStateId/customBlockId (16/16 bits)
private final Long2IntMap blockIdMap = new Long2IntOpenHashMap();
// Need to be synchronized manually
// relative pos - data
private final Long2ObjectMap<Data> blockDataMap = new Long2ObjectOpenHashMap<>();
@Override
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, @Nullable Data data) {
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.");
long pos = x;
pos = (pos << 16) | (short) y;
pos = (pos << 16) | (short) z;
final int block = (blockStateId << 16) | customBlockId;
synchronized (blockIdMap) {
this.blockIdMap.put(pos, block);
}
if (data != null) {
synchronized (blockDataMap) {
this.blockDataMap.put(pos, data);
}
}
}
@Override
public void clear() {
synchronized (blockIdMap) {
this.blockIdMap.clear();
}
}
@Override
public void apply(@NotNull InstanceContainer instance, @Nullable Runnable callback) {
apply(instance, 0, 0, 0, callback);
}
public void apply(@NotNull InstanceContainer instance, @NotNull BlockPosition position, @Nullable Runnable callback) {
apply(instance, position.getX(), position.getY(), position.getZ(), callback);
}
public void apply(@NotNull InstanceContainer instance, int x, int y, int z, @Nullable Runnable callback) {
apply(instance, x, y, z, callback, true);
}
public void applyUnsafe(@NotNull InstanceContainer instance, int x, int y, int z, @Nullable Runnable callback) {
apply(instance, x, y, z, callback, false);
}
protected void apply(@NotNull InstanceContainer instance, int x, int y, int z, @Nullable Runnable callback, boolean safeCallback) {
final 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);
int ids = entry.getValue();
short customBlockId = (short) (ids & 0xFFFF);
short blockStateId = (short) ((ids >> 16) & 0xFFFF);
Data data = null;
if (!blockDataMap.isEmpty()) {
synchronized (blockDataMap) {
data = blockDataMap.get(pos);
}
}
batch.setSeparateBlocks(x + relX, y + relY, z + relZ, blockStateId, customBlockId, data);
}
}
batch.apply(instance, callback, safeCallback);
}
}

View File

@ -10,6 +10,7 @@ import net.minestom.server.entity.Player;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.batch.AbsoluteBlockBatch;
import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.instance.batch.RelativeBlockBatch;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.time.TimeUnit;
@ -31,7 +32,8 @@ public class CubeBatchCommand extends Command {
Player player = sender.asPlayer();
InstanceContainer instance = (InstanceContainer) player.getInstance();
applyChunkShape(instance);
// applyChunkShape(instance);
applyBlockShape(instance);
// AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
//
@ -43,13 +45,82 @@ public class CubeBatchCommand extends Command {
// }
// }
// }
//
// batch.apply(instance, () -> sender.sendMessage(ColoredText.of(ChatColor.BRIGHT_GREEN, "Created cube.")));
// RelativeBlockBatch batch = new RelativeBlockBatch();
// for (int x = 0; x < 50; x += 2) {
// for (int y = 0; y < 50; y += 2) {
// for (int z = 0; z < 50; z += 2) {
// batch.setBlockStateId(x, y, z, Block.STONE.getBlockId());
// }
// }
// }
// batch.apply(instance, 0, 50, 0, () -> sender.sendMessage(ColoredText.of(ChatColor.BRIGHT_GREEN, "Created cube.")));
}
private void applyBlockShape(InstanceContainer instance) {
for (int i = 0; i < 5; i++) {
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
for (int x = -100; x < 101; x++) {
for (int z = -100; z < 101; z++) {
batch.setBlockStateId(x, 50, z, (short) (Block.BLUE_CONCRETE.getBlockId() + i));
}
}
MinecraftServer.getSchedulerManager().buildTask(() -> {
batch.apply(instance, null);
}).delay(i * 3, TimeUnit.TICK).repeat(15, TimeUnit.TICK).schedule();
}
// Bad
// for (int i = 0; i < 5; i++) {
// RelativeBlockBatch batch = makeBatch((short) (Block.BLUE_CONCRETE.getBlockId() + i));
// MinecraftServer.getSchedulerManager().buildTask(() -> {
// batch.apply(instance,
// ThreadLocalRandom.current().nextInt(100) - 100,
// 50,
// ThreadLocalRandom.current().nextInt(100) - 100,
// null);
// }).delay(10, TimeUnit.TICK).repeat(1, TimeUnit.TICK).schedule();
// }
// for (int i = 0; i < 5; i++) {
// RelativeBlockBatch batch = makeBatch((short) 0);
// MinecraftServer.getSchedulerManager().buildTask(() -> {
// batch.apply(instance,
// ThreadLocalRandom.current().nextInt(50) - 50,
// ThreadLocalRandom.current().nextInt(50) + 50,
// ThreadLocalRandom.current().nextInt(50) - 50,
// null);
// }).delay(10, TimeUnit.TICK).repeat(1, TimeUnit.TICK).schedule();
// }
// for (int i = 0; i < 5; i++) {
// RelativeBlockBatch batch = makeBatch((short) (Block.STONE.getBlockId() + i));
// MinecraftServer.getSchedulerManager().buildTask(() -> {
// batch.apply(instance,
// ThreadLocalRandom.current().nextInt(50) - 50,
// ThreadLocalRandom.current().nextInt(50) + 50,
// ThreadLocalRandom.current().nextInt(50) - 50,
// null);
// }).delay(10, TimeUnit.TICK).repeat(1, TimeUnit.TICK).schedule();
// }
}
private RelativeBlockBatch makeBatch(short block) {
final RelativeBlockBatch batch = new RelativeBlockBatch();
for (int x = 0; x < 100; x += 2) {
// for (int y = 0; y < 50; y += 2) {
for (int z = 0; z < 100; z += 2) {
batch.setBlockStateId(x, 0, z, block);
}
// }
}
return batch;
}
private void applyChunkShape(InstanceContainer instance) {
for (int i = 0; i < 20; i++) {
final ChunkBatch relBatch = new ChunkBatch();
@ -67,7 +138,5 @@ public class CubeBatchCommand extends Command {
null);
}).delay(10, TimeUnit.TICK).repeat(1, TimeUnit.TICK).schedule();
}
}
}