Chunk cleanup (removed useless methods)

This commit is contained in:
themode 2020-09-12 12:45:37 +02:00
parent 0ad2394d16
commit 5d733fa6e9
7 changed files with 189 additions and 125 deletions

View File

@ -77,28 +77,12 @@ public abstract class Chunk implements Viewable {
this.chunkZ = chunkZ;
}
public void UNSAFE_setBlock(int x, int y, int z, short blockStateId, Data data) {
setBlock(x, y, z, blockStateId, (short) 0, data, null);
}
public void UNSAFE_setCustomBlock(int x, int y, int z, short blockStateId, short customBlockId, Data data) {
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
Check.notNull(customBlock, "The custom block " + customBlockId + " does not exist or isn't registered");
UNSAFE_setCustomBlock(x, y, z, blockStateId, customBlock, data);
}
protected void UNSAFE_setCustomBlock(int x, int y, int z, short blockStateId, CustomBlock customBlock, Data data) {
final UpdateConsumer updateConsumer = customBlock.hasUpdate() ? customBlock::update : null;
setBlock(x, y, z, blockStateId, customBlock.getCustomBlockId(), data, updateConsumer);
}
public abstract void UNSAFE_removeCustomBlock(int x, int y, int z);
/**
* Set a block at a position
* <p>
* WARNING: this method is not thread-safe (in order to bring performance improvement with {@link ChunkBatch} & {@link BlockBatch}
* This is used when the previous block has to be destroyed, meaning that it clears the previous data and update method
* <p>
* WARNING: this method is not thread-safe (in order to bring performance improvement with {@link ChunkBatch} & {@link BlockBatch})
* The thread-safe version is {@link InstanceContainer#setSeparateBlocks(int, int, int, short, short, Data)} (or any similar instance methods)
*
* @param x the block X
@ -109,8 +93,16 @@ public abstract class Chunk implements Viewable {
* @param data the data of the block, can be null
* @param updateConsumer the update method of the block, can be null
*/
protected abstract void setBlock(int x, int y, int z, short blockStateId, short customId, Data data, UpdateConsumer updateConsumer);
public abstract void setBlock(int x, int y, int z, short blockStateId, short customId, Data data, UpdateConsumer updateConsumer);
/**
* Set the {@link Data} at a position
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param data the new data
*/
public void setBlockData(int x, int y, int z, Data data) {
final int index = getBlockIndex(x, y, z);
if (data != null) {
@ -120,12 +112,45 @@ public abstract class Chunk implements Viewable {
}
}
/**
* Get the block state id at a position
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the block state id at the position
*/
public abstract short getBlockStateId(int x, int y, int z);
/**
* Get the custom block id at a position
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the custom block id at the position
*/
public abstract short getCustomBlockId(int x, int y, int z);
public abstract CustomBlock getCustomBlock(int x, int y, int z);
/**
* Get the {@link CustomBlock} at a position
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the {@link CustomBlock} at the position
*/
public CustomBlock getCustomBlock(int x, int y, int z) {
final short customBlockId = getCustomBlockId(x, y, z);
return customBlockId != 0 ? BLOCK_MANAGER.getCustomBlock(customBlockId) : null;
}
/**
* Get the {@link CustomBlock} at a block index
*
* @param index the block index
* @return the {@link CustomBlock} at the block index
*/
protected CustomBlock getCustomBlock(int index) {
final int x = ChunkUtils.blockIndexToChunkPositionX(index);
final int y = ChunkUtils.blockIndexToChunkPositionY(index);
@ -133,25 +158,48 @@ public abstract class Chunk implements Viewable {
return getCustomBlock(x, y, z);
}
/**
* Change the block state id and the custom block id at a position
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the new block state id
* @param customId the new custom block id
*/
protected abstract void refreshBlockValue(int x, int y, int z, short blockStateId, short customId);
/**
* Change the block state id at a position (the custom block id stays the same)
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @param blockStateId the new block state id
*/
protected abstract void refreshBlockStateId(int x, int y, int z, short blockStateId);
protected void refreshBlockValue(int x, int y, int z, short blockStateId) {
final CustomBlock customBlock = getCustomBlock(x, y, z);
final short customBlockId = customBlock == null ? 0 : customBlock.getCustomBlockId();
refreshBlockValue(x, y, z, blockStateId, customBlockId);
}
public Data getData(int x, int y, int z) {
final int index = getBlockIndex(x, y, z);
return getData(index);
}
/**
* Get the {@link Data} at a block index
*
* @param index the block index
* @return the {@link Data} at the block index
*/
protected Data getData(int index) {
return blocksData.get(index);
}
/**
* Execute a tick update for all the updatable blocks in this chunk
*
* @param time the time of the update in milliseconds
* @param instance the instance linked to this chunk
*/
public synchronized void updateBlocks(long time, Instance instance) {
if (updatableBlocks.isEmpty())
return;
@ -181,10 +229,20 @@ public abstract class Chunk implements Viewable {
return biomes;
}
/**
* Get the chunk X
*
* @return the chunk X
*/
public int getChunkX() {
return chunkX;
}
/**
* Get the chunk Z
*
* @return the chunk Z
*/
public int getChunkZ() {
return chunkZ;
}
@ -455,6 +513,14 @@ public abstract class Chunk implements Viewable {
this.loaded = false;
}
/**
* Get the index of a position, used to store blocks
*
* @param x the block X
* @param y the block Y
* @param z the block Z
* @return the block index
*/
protected int getBlockIndex(int x, int y, int z) {
return ChunkUtils.getBlockIndex(x, y, z);
}

View File

@ -7,7 +7,6 @@ import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap;
import net.minestom.server.data.Data;
import net.minestom.server.data.SerializableData;
import net.minestom.server.entity.pathfinding.PFBlockDescription;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.instance.block.UpdateConsumer;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.reader.ChunkReader;
@ -31,19 +30,7 @@ public class DynamicChunk extends Chunk {
}
@Override
public void UNSAFE_removeCustomBlock(int x, int y, int z) {
final int index = getBlockIndex(x, y, z);
this.customBlocksId[index] = 0; // Set to none
this.blocksData.remove(index);
this.updatableBlocks.remove(index);
this.updatableBlocksLastUpdate.remove(index);
this.blockEntities.remove(index);
}
@Override
protected void setBlock(int x, int y, int z, short blockStateId, short customId, Data data, UpdateConsumer updateConsumer) {
public void setBlock(int x, int y, int z, short blockStateId, short customId, Data data, UpdateConsumer updateConsumer) {
{
// Update pathfinder
@ -121,16 +108,6 @@ public class DynamicChunk extends Chunk {
return customBlocksId[index];
}
@Override
public CustomBlock getCustomBlock(int x, int y, int z) {
final int index = getBlockIndex(x, y, z);
if (!MathUtils.isBetween(index, 0, blocksStateId.length)) {
return null; // TODO: custom invalid block
}
final short id = customBlocksId[index];
return id != 0 ? BLOCK_MANAGER.getCustomBlock(id) : null;
}
@Override
protected void refreshBlockValue(int x, int y, int z, short blockStateId, short customId) {
final int blockIndex = getBlockIndex(x, y, z);

View File

@ -13,6 +13,7 @@ import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockProvider;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.instance.block.UpdateConsumer;
import net.minestom.server.instance.block.rule.BlockPlacementRule;
import net.minestom.server.network.packet.server.play.BlockChangePacket;
import net.minestom.server.network.packet.server.play.ParticlePacket;
@ -22,6 +23,7 @@ import net.minestom.server.particle.ParticleCreator;
import net.minestom.server.storage.StorageLocation;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.block.CustomBlockUtils;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.thread.MinestomThread;
import net.minestom.server.utils.time.TimeUnit;
@ -135,14 +137,18 @@ public class InstanceContainer extends Instance {
// Change id based on neighbors
blockStateId = executeBlockPlacementRule(blockStateId, blockPosition);
// Set the block
// Retrieve custom block values
short customBlockId = 0;
UpdateConsumer updateConsumer = null;
if (isCustomBlock) {
customBlockId = customBlock.getCustomBlockId();
data = customBlock.createData(this, blockPosition, data);
chunk.UNSAFE_setCustomBlock(x, y, z, blockStateId, customBlock, data);
} else {
chunk.UNSAFE_setBlock(x, y, z, blockStateId, data);
updateConsumer = CustomBlockUtils.getCustomBlockUpdate(customBlock);
}
// Set the block
chunk.setBlock(x, y, z, blockStateId, customBlockId, data, updateConsumer);
// Refresh neighbors since a new block has been placed
executeNeighboursBlockPlacementRule(blockPosition);
@ -197,7 +203,6 @@ public class InstanceContainer extends Instance {
private void callBlockDestroy(Chunk chunk, int index, CustomBlock previousBlock, BlockPosition blockPosition) {
final Data previousData = chunk.getData(index);
previousBlock.onDestroy(this, blockPosition, previousData);
chunk.UNSAFE_removeCustomBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
}
/**

View File

@ -3,7 +3,6 @@ package net.minestom.server.instance;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minestom.server.data.Data;
import net.minestom.server.instance.block.BlockProvider;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.instance.block.UpdateConsumer;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.utils.chunk.ChunkUtils;
@ -21,12 +20,7 @@ public class StaticChunk extends Chunk {
}
@Override
public void UNSAFE_removeCustomBlock(int x, int y, int z) {
//noop
}
@Override
protected void setBlock(int x, int y, int z, short blockStateId, short customId, Data data, UpdateConsumer updateConsumer) {
public void setBlock(int x, int y, int z, short blockStateId, short customId, Data data, UpdateConsumer updateConsumer) {
//noop
}
@ -41,12 +35,6 @@ public class StaticChunk extends Chunk {
return 0;
}
@Override
public CustomBlock getCustomBlock(int x, int y, int z) {
//noop
return null;
}
@Override
protected void refreshBlockValue(int x, int y, int z, short blockStateId, short customId) {
//noop

View File

@ -4,11 +4,13 @@ import net.minestom.server.data.Data;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.utils.block.CustomBlockUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
public class BlockBatch implements InstanceBatch {
@ -23,23 +25,23 @@ public class BlockBatch implements InstanceBatch {
@Override
public synchronized void setBlockStateId(int x, int y, int z, short blockStateId, Data data) {
final Chunk chunk = this.instance.getChunkAt(x, z);
addBlockData(chunk, x, y, z, false, blockStateId, (short) 0, data);
addBlockData(chunk, x, y, z, blockStateId, (short) 0, data);
}
@Override
public void setCustomBlock(int x, int y, int z, short customBlockId, Data data) {
final Chunk chunk = this.instance.getChunkAt(x, z);
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
addBlockData(chunk, x, y, z, true, customBlock.getDefaultBlockStateId(), customBlockId, data);
addBlockData(chunk, x, y, z, customBlock.getDefaultBlockStateId(), customBlockId, data);
}
@Override
public synchronized void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, Data data) {
final Chunk chunk = this.instance.getChunkAt(x, z);
addBlockData(chunk, x, y, z, true, blockStateId, customBlockId, data);
addBlockData(chunk, x, y, z, blockStateId, customBlockId, data);
}
private void addBlockData(Chunk chunk, int x, int y, int z, boolean customBlock, short blockStateId, short customBlockId, Data data) {
private void addBlockData(Chunk chunk, int x, int y, int z, short blockStateId, short customBlockId, Data data) {
List<BlockData> blocksData = this.data.get(chunk);
if (blocksData == null)
blocksData = new ArrayList<>();
@ -48,7 +50,6 @@ public class BlockBatch implements InstanceBatch {
blockData.x = x;
blockData.y = y;
blockData.z = z;
blockData.hasCustomBlock = customBlock;
blockData.blockStateId = blockStateId;
blockData.customBlockId = customBlockId;
blockData.data = data;
@ -59,48 +60,45 @@ public class BlockBatch implements InstanceBatch {
}
public void flush(Runnable callback) {
int counter = 0;
for (Map.Entry<Chunk, List<BlockData>> entry : data.entrySet()) {
counter++;
final Chunk chunk = entry.getKey();
final List<BlockData> dataList = entry.getValue();
final boolean isLast = counter == data.size();
batchesPool.execute(() -> {
synchronized (chunk) {
if (!chunk.isLoaded())
return;
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();
batchesPool.execute(() -> {
synchronized (chunk) {
if (!chunk.isLoaded())
return;
for (BlockData data : dataList) {
data.apply(chunk);
}
// Refresh chunk for viewers
chunk.sendChunkUpdate();
final boolean isLast = counter.incrementAndGet() == data.size();
if (isLast) {
if (callback != null)
callback.run();
}
for (BlockData data : dataList) {
data.apply(chunk);
}
// Refresh chunk for viewers
chunk.sendChunkUpdate();
if (isLast) {
if (callback != null)
callback.run();
}
}
});
});
}
}
}
private static class BlockData {
private int x, y, z;
private boolean hasCustomBlock;
private short blockStateId;
private short customBlockId;
private Data data;
public void apply(Chunk chunk) {
if (!hasCustomBlock) {
chunk.UNSAFE_setBlock(x, y, z, blockStateId, data);
} else {
chunk.UNSAFE_setCustomBlock(x, y, z, blockStateId, customBlockId, data);
}
chunk.setBlock(x, y, z, blockStateId, customBlockId, data, CustomBlockUtils.getCustomBlockUpdate(customBlockId));
}
}

View File

@ -6,6 +6,7 @@ import net.minestom.server.instance.ChunkGenerator;
import net.minestom.server.instance.ChunkPopulator;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.utils.block.CustomBlockUtils;
import java.util.ArrayList;
import java.util.Collections;
@ -32,27 +33,26 @@ public class ChunkBatch implements InstanceBatch {
@Override
public void setBlockStateId(int x, int y, int z, short blockStateId, Data data) {
addBlockData((byte) x, y, (byte) z, false, blockStateId, (short) 0, data);
addBlockData((byte) x, y, (byte) z, blockStateId, (short) 0, data);
}
@Override
public void setCustomBlock(int x, int y, int z, short customBlockId, Data data) {
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
addBlockData((byte) x, y, (byte) z, true, customBlock.getDefaultBlockStateId(), customBlockId, data);
addBlockData((byte) x, y, (byte) z, customBlock.getDefaultBlockStateId(), customBlockId, data);
}
@Override
public void setSeparateBlocks(int x, int y, int z, short blockStateId, short customBlockId, Data data) {
addBlockData((byte) x, y, (byte) z, true, blockStateId, customBlockId, data);
addBlockData((byte) x, y, (byte) z, blockStateId, customBlockId, data);
}
private void addBlockData(byte x, int y, byte z, boolean customBlock, short blockStateId, short customBlockId, Data data) {
private void addBlockData(byte x, int y, byte z, short blockStateId, short customBlockId, Data data) {
// TODO store a single long with bitwise operators (xyz;boolean,short,short,boolean) with the data in a map
BlockData blockData = new BlockData();
blockData.x = x;
blockData.y = y;
blockData.z = z;
blockData.hasCustomBlock = customBlock;
blockData.blockStateId = blockStateId;
blockData.customBlockId = customBlockId;
blockData.data = data;
@ -92,36 +92,33 @@ public class ChunkBatch implements InstanceBatch {
}
private void singleThreadFlush(Consumer<Chunk> callback) {
synchronized (chunk) {
if (!chunk.isLoaded())
return;
synchronized (dataList) {
synchronized (chunk) {
if (!chunk.isLoaded())
return;
for (BlockData data : dataList) {
data.apply(chunk);
for (BlockData data : dataList) {
data.apply(chunk);
}
// Refresh chunk for viewers
chunk.sendChunkUpdate();
if (callback != null)
callback.accept(chunk);
}
// Refresh chunk for viewers
chunk.sendChunkUpdate();
if (callback != null)
callback.accept(chunk);
}
}
private static class BlockData {
private int x, y, z;
private boolean hasCustomBlock;
private short blockStateId;
private short customBlockId;
private Data data;
public void apply(Chunk chunk) {
if (!hasCustomBlock) {
chunk.UNSAFE_setBlock(x, y, z, blockStateId, data);
} else {
chunk.UNSAFE_setCustomBlock(x, y, z, blockStateId, customBlockId, data);
}
chunk.setBlock(x, y, z, blockStateId, customBlockId, data, CustomBlockUtils.getCustomBlockUpdate(customBlockId));
}
}

View File

@ -0,0 +1,33 @@
package net.minestom.server.utils.block;
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.CustomBlock;
import net.minestom.server.instance.block.UpdateConsumer;
public class CustomBlockUtils {
private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
/**
* Get the {@link UpdateConsumer} of a custom block id
*
* @param customBlockId the custom block id
* @return the {@link UpdateConsumer} of the custom block
*/
public static UpdateConsumer getCustomBlockUpdate(short customBlockId) {
final CustomBlock customBlock = BLOCK_MANAGER.getCustomBlock(customBlockId);
return getCustomBlockUpdate(customBlock);
}
/**
* Get the {@link UpdateConsumer} of a {@link CustomBlock}
*
* @param customBlock the {@link CustomBlock}
* @return the {@link UpdateConsumer} of the {@link CustomBlock}
*/
public static UpdateConsumer getCustomBlockUpdate(CustomBlock customBlock) {
return customBlock != null && customBlock.hasUpdate() ? customBlock::update : null;
}
}