mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-23 00:21:26 +01:00
Optimize block retrieval from Instance
Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
parent
c56cd1054a
commit
384126e3b4
@ -30,6 +30,7 @@ import net.minestom.server.timer.Schedulable;
|
||||
import net.minestom.server.timer.Scheduler;
|
||||
import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import net.minestom.server.utils.chunk.ChunkCache;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.utils.time.Cooldown;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
@ -79,6 +80,8 @@ public abstract class Instance implements Block.Getter, Block.Setter, Tickable,
|
||||
|
||||
private final EntityTracker entityTracker = new EntityTrackerImpl();
|
||||
|
||||
private final ChunkCache blockRetriever = new ChunkCache(this, null, null);
|
||||
|
||||
// the uuid of this instance
|
||||
protected UUID uniqueId;
|
||||
|
||||
@ -517,11 +520,9 @@ public abstract class Instance implements Block.Getter, Block.Setter, Tickable,
|
||||
|
||||
@Override
|
||||
public @Nullable Block getBlock(int x, int y, int z, @NotNull Condition condition) {
|
||||
final Chunk chunk = getChunkAt(x, z);
|
||||
Check.notNull(chunk, "The chunk at {0}:{1} is not loaded", x, z);
|
||||
synchronized (chunk) {
|
||||
return chunk.getBlock(x, y, z, condition);
|
||||
}
|
||||
final Block block = blockRetriever.getBlock(x, y, z, condition);
|
||||
if (block == null) throw new NullPointerException("Unloaded chunk at " + x + "," + y + "," + z);
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,98 +2,33 @@ package net.minestom.server.instance;
|
||||
|
||||
import net.minestom.server.api.Env;
|
||||
import net.minestom.server.api.EnvTest;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.BlockHandler;
|
||||
import net.minestom.server.network.packet.server.play.BlockChangePacket;
|
||||
import net.minestom.server.network.packet.server.play.BlockEntityDataPacket;
|
||||
import net.minestom.server.tag.Tag;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import org.jglrxavpok.hephaistos.parser.SNBTParser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@EnvTest
|
||||
public class InstanceBlockIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void replaceAir(Env env) {
|
||||
public void basic(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
connection.connect(instance, new Pos(0, 40, 0)).join();
|
||||
assertThrows(NullPointerException.class, () -> instance.getBlock(0, 0, 0),
|
||||
"No exception throw when getting a block in an unloaded chunk");
|
||||
|
||||
var blockPoint = new Vec(5, 41, 0);
|
||||
instance.loadChunk(0, 0).join();
|
||||
assertEquals(Block.AIR, instance.getBlock(0, 50, 0));
|
||||
|
||||
assertEquals(Block.AIR, instance.getBlock(blockPoint));
|
||||
instance.setBlock(0, 50, 0, Block.GRASS);
|
||||
assertEquals(Block.GRASS, instance.getBlock(0, 50, 0));
|
||||
|
||||
var tracker = connection.trackIncoming();
|
||||
instance.setBlock(blockPoint, Block.STONE);
|
||||
tracker.assertSingle(BlockChangePacket.class, packet -> {
|
||||
assertEquals(blockPoint, packet.blockPosition());
|
||||
assertEquals(Block.STONE.stateId(), packet.blockStateId());
|
||||
});
|
||||
instance.setBlock(0, 50, 0, Block.STONE);
|
||||
assertEquals(Block.STONE, instance.getBlock(0, 50, 0));
|
||||
|
||||
assertEquals(Block.STONE, instance.getBlock(blockPoint));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeBlockEntity(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
connection.connect(instance, new Pos(0, 40, 0)).join();
|
||||
|
||||
var blockPoint = new Vec(5, 41, 0);
|
||||
|
||||
BlockHandler signHandler = new BlockHandler() {
|
||||
@Override
|
||||
public @NotNull Collection<Tag<?>> getBlockEntityTags() {
|
||||
return List.of(Tag.Byte("GlowingText"),
|
||||
Tag.String("Color"),
|
||||
Tag.String("Text1"),
|
||||
Tag.String("Text2"),
|
||||
Tag.String("Text3"),
|
||||
Tag.String("Text4"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NamespaceID getNamespaceId() {
|
||||
return NamespaceID.from("minecraft:sign");
|
||||
}
|
||||
};
|
||||
|
||||
assertEquals(Block.AIR, instance.getBlock(blockPoint));
|
||||
|
||||
final Block block;
|
||||
final NBTCompound data;
|
||||
try {
|
||||
data = (NBTCompound) new SNBTParser(new StringReader("{\"GlowingText\":0B,\"Color\":\"black\",\"Text1\":\"{\\\"text\\\":\\\"wawsd\\\"}\"," +
|
||||
"\"Text2\":\"{\\\"text\\\":\\\"\\\"}\",\"Text3\":\"{\\\"text\\\":\\\"\\\"}\",\"Text4\":\"{\\\"text\\\":\\\"\\\"}\"}")).parse();
|
||||
block = Block.OAK_SIGN.withHandler(signHandler).withNbt(data);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
var blockChangeTracker = connection.trackIncoming(BlockChangePacket.class);
|
||||
var blockEntityTracker = connection.trackIncoming(BlockEntityDataPacket.class);
|
||||
instance.setBlock(blockPoint, block);
|
||||
blockChangeTracker.assertSingle(packet -> {
|
||||
assertEquals(blockPoint, packet.blockPosition());
|
||||
assertEquals(block.stateId(), packet.blockStateId());
|
||||
});
|
||||
blockEntityTracker.assertSingle(packet -> {
|
||||
assertEquals(blockPoint, packet.blockPosition());
|
||||
assertEquals(block.registry().blockEntityId(), packet.action());
|
||||
assertEquals(data, packet.data());
|
||||
});
|
||||
|
||||
assertEquals(block, instance.getBlock(blockPoint));
|
||||
assertThrows(NullPointerException.class, () -> instance.getBlock(16, 0, 0),
|
||||
"No exception throw when getting a block in an unloaded chunk");
|
||||
instance.loadChunk(1, 0).join();
|
||||
assertEquals(Block.AIR, instance.getBlock(16, 50, 0));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
package net.minestom.server.instance;
|
||||
|
||||
import net.minestom.server.api.Env;
|
||||
import net.minestom.server.api.EnvTest;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.BlockHandler;
|
||||
import net.minestom.server.network.packet.server.play.BlockChangePacket;
|
||||
import net.minestom.server.network.packet.server.play.BlockEntityDataPacket;
|
||||
import net.minestom.server.tag.Tag;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import org.jglrxavpok.hephaistos.parser.SNBTParser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@EnvTest
|
||||
public class InstanceBlockPacketIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void replaceAir(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
connection.connect(instance, new Pos(0, 40, 0)).join();
|
||||
|
||||
var blockPoint = new Vec(5, 41, 0);
|
||||
|
||||
assertEquals(Block.AIR, instance.getBlock(blockPoint));
|
||||
|
||||
var tracker = connection.trackIncoming();
|
||||
instance.setBlock(blockPoint, Block.STONE);
|
||||
tracker.assertSingle(BlockChangePacket.class, packet -> {
|
||||
assertEquals(blockPoint, packet.blockPosition());
|
||||
assertEquals(Block.STONE.stateId(), packet.blockStateId());
|
||||
});
|
||||
|
||||
assertEquals(Block.STONE, instance.getBlock(blockPoint));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeBlockEntity(Env env) {
|
||||
var instance = env.createFlatInstance();
|
||||
var connection = env.createConnection();
|
||||
connection.connect(instance, new Pos(0, 40, 0)).join();
|
||||
|
||||
var blockPoint = new Vec(5, 41, 0);
|
||||
|
||||
BlockHandler signHandler = new BlockHandler() {
|
||||
@Override
|
||||
public @NotNull Collection<Tag<?>> getBlockEntityTags() {
|
||||
return List.of(Tag.Byte("GlowingText"),
|
||||
Tag.String("Color"),
|
||||
Tag.String("Text1"),
|
||||
Tag.String("Text2"),
|
||||
Tag.String("Text3"),
|
||||
Tag.String("Text4"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NamespaceID getNamespaceId() {
|
||||
return NamespaceID.from("minecraft:sign");
|
||||
}
|
||||
};
|
||||
|
||||
assertEquals(Block.AIR, instance.getBlock(blockPoint));
|
||||
|
||||
final Block block;
|
||||
final NBTCompound data;
|
||||
try {
|
||||
data = (NBTCompound) new SNBTParser(new StringReader("{\"GlowingText\":0B,\"Color\":\"black\",\"Text1\":\"{\\\"text\\\":\\\"wawsd\\\"}\"," +
|
||||
"\"Text2\":\"{\\\"text\\\":\\\"\\\"}\",\"Text3\":\"{\\\"text\\\":\\\"\\\"}\",\"Text4\":\"{\\\"text\\\":\\\"\\\"}\"}")).parse();
|
||||
block = Block.OAK_SIGN.withHandler(signHandler).withNbt(data);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
var blockChangeTracker = connection.trackIncoming(BlockChangePacket.class);
|
||||
var blockEntityTracker = connection.trackIncoming(BlockEntityDataPacket.class);
|
||||
instance.setBlock(blockPoint, block);
|
||||
blockChangeTracker.assertSingle(packet -> {
|
||||
assertEquals(blockPoint, packet.blockPosition());
|
||||
assertEquals(block.stateId(), packet.blockStateId());
|
||||
});
|
||||
blockEntityTracker.assertSingle(packet -> {
|
||||
assertEquals(blockPoint, packet.blockPosition());
|
||||
assertEquals(block.registry().blockEntityId(), packet.action());
|
||||
assertEquals(data, packet.data());
|
||||
});
|
||||
|
||||
assertEquals(block, instance.getBlock(blockPoint));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user