Added Chunk#setReadOnly and Chunk#isReadOnly

This commit is contained in:
themode 2020-10-24 00:17:23 +02:00
parent 86d6092547
commit fb26ec0f0b
4 changed files with 70 additions and 37 deletions

View File

@ -63,6 +63,7 @@ public abstract class Chunk implements Viewable, DataContainer {
// Options // Options
private final boolean shouldGenerate; private final boolean shouldGenerate;
private boolean readOnly;
// Packet cache // Packet cache
private volatile boolean enableCachePacket; private volatile boolean enableCachePacket;
@ -277,6 +278,24 @@ public abstract class Chunk implements Viewable, DataContainer {
return shouldGenerate; return shouldGenerate;
} }
/**
* Gets if this chunk is read-only.
*
* @return true if the chunk is read-only
*/
public boolean isReadOnly() {
return readOnly;
}
/**
* Changes the read state of the chunk.
*
* @param readOnly true to make the chunk read-only, false otherwise
*/
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
/** /**
* Gets if this chunk automatically cache the latest {@link ChunkDataPacket} version. * Gets if this chunk automatically cache the latest {@link ChunkDataPacket} version.
* <p> * <p>

View File

@ -160,6 +160,10 @@ public class InstanceContainer extends Instance {
* @param data the {@link Data}, null if none * @param data the {@link Data}, null if none
*/ */
private void UNSAFE_setBlock(Chunk chunk, int x, int y, int z, short blockStateId, CustomBlock customBlock, Data data) { private void UNSAFE_setBlock(Chunk chunk, int x, int y, int z, short blockStateId, CustomBlock customBlock, Data data) {
if (chunk.isReadOnly()) {
return;
}
synchronized (chunk) { synchronized (chunk) {
final boolean isCustomBlock = customBlock != null; final boolean isCustomBlock = customBlock != null;
@ -342,6 +346,11 @@ public class InstanceContainer extends Instance {
final Chunk chunk = getChunkAt(blockPosition); final Chunk chunk = getChunkAt(blockPosition);
// Cancel if the chunk is read-only
if (chunk.isReadOnly()) {
return false;
}
// Chunk unloaded, stop here // Chunk unloaded, stop here
if (!ChunkUtils.isLoaded(chunk)) if (!ChunkUtils.isLoaded(chunk))
return false; return false;

View File

@ -27,6 +27,7 @@ public class StaticChunk extends Chunk {
public StaticChunk(Instance instance, Biome[] biomes, int chunkX, int chunkZ, BlockProvider blockProvider) { public StaticChunk(Instance instance, Biome[] biomes, int chunkX, int chunkZ, BlockProvider blockProvider) {
super(instance, biomes, chunkX, chunkZ, false); super(instance, biomes, chunkX, chunkZ, false);
this.blockProvider = blockProvider; this.blockProvider = blockProvider;
setReadOnly(true);
} }
@Override @Override

View File

@ -80,46 +80,50 @@ public class BlockPlacementListener {
boolean refreshChunk = false; boolean refreshChunk = false;
if (material.isBlock()) { if (material.isBlock()) {
final Block block = material.getBlock(); if (!chunk.isReadOnly()) {
final Set<Entity> entities = instance.getChunkEntities(chunk); final Block block = material.getBlock();
// Check if the player is trying to place a block in an entity final Set<Entity> entities = instance.getChunkEntities(chunk);
boolean intersect = false; // Check if the player is trying to place a block in an entity
if (block.isSolid()) { boolean intersect = false;
for (Entity entity : entities) { if (block.isSolid()) {
intersect = entity.getBoundingBox().intersect(blockPosition); for (Entity entity : entities) {
if (intersect) intersect = entity.getBoundingBox().intersect(blockPosition);
break; if (intersect)
} break;
}
if (!intersect) {
// BlockPlacementRule check
final BlockManager blockManager = MinecraftServer.getBlockManager();
final BlockPlacementRule blockPlacementRule = blockManager.getBlockPlacementRule(block);
final short blockStateId = blockPlacementRule == null ? block.getBlockId() :
blockPlacementRule.blockPlace(instance, block, blockFace, player);
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, blockStateId, (short) 0, blockPosition, packet.hand);
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
// BlockPlacementRule check
final boolean canPlace = blockPlacementRule == null || blockPlacementRule.canPlace(instance, blockPosition);
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
if (!playerBlockPlaceEvent.isCancelled() && canPlace) {
final short customBlockId = playerBlockPlaceEvent.getCustomBlockId();
if (customBlockId != 0) {
instance.setSeparateBlocks(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockStateId(), playerBlockPlaceEvent.getCustomBlockId());
} else {
instance.setBlockStateId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockStateId());
} }
if (playerBlockPlaceEvent.doesConsumeBlock()) { }
// Consume the block in the player's hand
final ItemStack newUsedItem = usedItem.consume(1);
if (newUsedItem != null) { if (!intersect) {
playerInventory.setItemInHand(hand, newUsedItem); // BlockPlacementRule check
final BlockManager blockManager = MinecraftServer.getBlockManager();
final BlockPlacementRule blockPlacementRule = blockManager.getBlockPlacementRule(block);
final short blockStateId = blockPlacementRule == null ? block.getBlockId() :
blockPlacementRule.blockPlace(instance, block, blockFace, player);
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, blockStateId, (short) 0, blockPosition, packet.hand);
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
// BlockPlacementRule check
final boolean canPlace = blockPlacementRule == null || blockPlacementRule.canPlace(instance, blockPosition);
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
if (!playerBlockPlaceEvent.isCancelled() && canPlace) {
final short customBlockId = playerBlockPlaceEvent.getCustomBlockId();
if (customBlockId != 0) {
instance.setSeparateBlocks(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockStateId(), playerBlockPlaceEvent.getCustomBlockId());
} else {
instance.setBlockStateId(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockStateId());
} }
if (playerBlockPlaceEvent.doesConsumeBlock()) {
// Consume the block in the player's hand
final ItemStack newUsedItem = usedItem.consume(1);
if (newUsedItem != null) {
playerInventory.setItemInHand(hand, newUsedItem);
}
}
} else {
refreshChunk = true;
} }
} else { } else {
refreshChunk = true; refreshChunk = true;