Chunk memory optimization

This commit is contained in:
TheMode 2019-08-19 00:48:49 +02:00
parent 0d40be1552
commit 4263a3965b
8 changed files with 53 additions and 28 deletions

View File

@ -39,7 +39,7 @@ public class Main {
blockManager = new BlockManager();
entityManager = new EntityManager();
blockManager.registerBlock("stone", StoneBlock::new);
blockManager.registerBlock(StoneBlock::new);
server = new TCPServer(new MinecraftProtocol()).addHandler(new ServerHandler() {
@Override

View File

@ -6,14 +6,23 @@ import java.util.function.Supplier;
public class BlockManager {
private Map<String, CustomBlock> blocks = new HashMap<>();
private Map<Integer, CustomBlock> blocksInternalId = new HashMap<>();
private Map<String, CustomBlock> blocksId = new HashMap<>();
public void registerBlock(String id, Supplier<CustomBlock> blocks) {
this.blocks.put(id, blocks.get());
public void registerBlock(Supplier<CustomBlock> blocks) {
CustomBlock customBlock = blocks.get();
String identifier = customBlock.getIdentifier();
int id = customBlock.getId();
this.blocksInternalId.put(id, customBlock);
this.blocksId.put(identifier, customBlock);
}
public CustomBlock getBlock(String id) {
return this.blocks.get(id);
public CustomBlock getBlock(String identifier) {
return blocksId.get(identifier);
}
public CustomBlock getBlock(int id) {
return blocksInternalId.get(id);
}
}

View File

@ -18,7 +18,7 @@ public class Chunk {
private int chunkX, chunkZ;
private Biome biome;
private short[] blocksId = new short[CHUNK_SIZE];
private String[] customBlocks = new String[CHUNK_SIZE];
private int[] customBlocks = new int[CHUNK_SIZE];
public Chunk(Biome biome, int chunkX, int chunkZ) {
this.biome = biome;
@ -30,23 +30,27 @@ public class Chunk {
int index = getIndex(x, y, z);
this.blocksId[index] = blockId;
if (blockId == 0) {
this.customBlocks[index] = null;
this.customBlocks[index] = 0;
}
}
protected void setBlock(byte x, byte y, byte z, String blockId) {
int index = getIndex(x, y, z);
CustomBlock customBlock = Main.getBlockManager().getBlock(blockId);
if (customBlock == null)
throw new IllegalArgumentException("The block " + blockId + " does not exist or isn't registered");
int index = getIndex(x, y, z);
this.blocksId[index] = customBlock.getType();
this.customBlocks[index] = blockId;
this.customBlocks[index] = customBlock.getId();
}
public short getBlockId(byte x, byte y, byte z) {
return this.blocksId[getIndex(x, y, z)];
}
public String getCustomBlockId(byte x, byte y, byte z) {
return this.customBlocks[getIndex(x, y, z)];
public CustomBlock getCustomBlock(byte x, byte y, byte z) {
int id = this.customBlocks[getIndex(x, y, z)];
return id != 0 ? Main.getBlockManager().getBlock(id) : null;
}
public void addEntity(Entity entity) {

View File

@ -2,20 +2,28 @@ package fr.themode.minestom.instance;
import fr.themode.minestom.entity.Player;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class CustomBlock {
private short type;
private static final AtomicInteger idCounter = new AtomicInteger();
public CustomBlock(short type) {
this.type = type;
private int id;
public CustomBlock() {
this.id = idCounter.incrementAndGet();
}
public abstract short getType();
public abstract String getIdentifier();
/*
Time in ms
*/
public abstract int getBreakDelay(Player player);
public short getType() {
return type;
public int getId() {
return id;
}
}

View File

@ -19,7 +19,7 @@ public class Instance {
private GroupedCollections<EntityCreature> creatures = new GroupedCollections<>(new CopyOnWriteArrayList());
private GroupedCollections<Player> players = new GroupedCollections<>(new CopyOnWriteArrayList());
private Set<Chunk> chunksSet = new CopyOnWriteArraySet<>();
private Set<Chunk> chunksSet = new CopyOnWriteArraySet<>(); // TODO change for a map with position as key and chunk as value
public Instance(UUID uniqueId) {
this.uniqueId = uniqueId;
@ -46,9 +46,9 @@ public class Instance {
return chunk.getBlockId((byte) (x % 16), (byte) y, (byte) (z % 16));
}
public String getCustomBlockId(int x, int y, int z) {
public CustomBlock getCustomBlock(int x, int y, int z) {
Chunk chunk = getChunkAt(x, z);
return chunk.getCustomBlockId((byte) (x % 16), (byte) y, (byte) (z % 16));
return chunk.getCustomBlock((byte) (x % 16), (byte) y, (byte) (z % 16));
}
public BlockBatch createBlockBatch() {

View File

@ -5,12 +5,18 @@ import fr.themode.minestom.instance.CustomBlock;
public class StoneBlock extends CustomBlock {
public StoneBlock() {
super((short) 1);
@Override
public short getType() {
return 1;
}
@Override
public String getIdentifier() {
return "stone_block";
}
@Override
public int getBreakDelay(Player player) {
return 750;
}
}
}

View File

@ -25,7 +25,7 @@ public class ClientPlayerBlockPlacementPacket implements ClientPlayPacket {
int offsetY = blockFace == ClientPlayerDiggingPacket.BlockFace.BOTTOM ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.TOP ? 1 : 0;
int offsetZ = blockFace == ClientPlayerDiggingPacket.BlockFace.NORTH ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.SOUTH ? 1 : 0;
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, "stone");
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, "stone_block");
player.getInventory().refreshSlot(player.getHeldSlot());
// TODO consume block in hand for survival players
/*Random random = new Random();

View File

@ -1,7 +1,6 @@
package fr.themode.minestom.net.packet.client.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.Main;
import fr.themode.minestom.entity.GameMode;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.instance.CustomBlock;
@ -30,9 +29,8 @@ public class ClientPlayerDiggingPacket implements ClientPlayPacket {
} else if (player.getGameMode() == GameMode.SURVIVAL) {
Instance instance = player.getInstance();
if (instance != null) {
String customBlockId = instance.getCustomBlockId(position.getX(), position.getY(), position.getZ());
if (customBlockId != null) {
CustomBlock customBlock = Main.getBlockManager().getBlock(customBlockId);
CustomBlock customBlock = instance.getCustomBlock(position.getX(), position.getY(), position.getZ());
if (customBlock != null) {
player.refreshTargetBlock(customBlock, position);
addEffect(player);
} else {