Ensure proper chunk synchronization

This commit is contained in:
themode 2022-03-17 00:14:12 +01:00
parent 058e645c33
commit 055cc409ed
4 changed files with 22 additions and 6 deletions

View File

@ -60,6 +60,7 @@ public class DynamicChunk extends Chunk {
@Override
public void setBlock(int x, int y, int z, @NotNull Block block) {
assertLock();
this.lastChange = System.currentTimeMillis();
this.chunkCache.invalidate();
this.lightCache.invalidate();
@ -91,6 +92,7 @@ public class DynamicChunk extends Chunk {
@Override
public void setBiome(int x, int y, int z, @NotNull Biome biome) {
assertLock();
this.chunkCache.invalidate();
Section section = getSectionAt(y);
section.biomePalette().set(
@ -124,6 +126,7 @@ public class DynamicChunk extends Chunk {
@Override
public @Nullable Block getBlock(int x, int y, int z, @NotNull Condition condition) {
assertLock();
if (y < minSection * CHUNK_SECTION_SIZE || y >= maxSection * CHUNK_SECTION_SIZE)
return Block.AIR; // Out of bounds
@ -144,6 +147,7 @@ public class DynamicChunk extends Chunk {
@Override
public @NotNull Biome getBiome(int x, int y, int z) {
assertLock();
final Section section = getSectionAt(y);
final int id = section.biomePalette()
.get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4);
@ -255,4 +259,8 @@ public class DynamicChunk extends Chunk {
clonedSections, entries.clone(), entityIds, updater.reference(instance),
TagReadable.fromCompound(Objects.requireNonNull(getTag(Tag.NBT))));
}
private void assertLock() {
assert Thread.holdsLock(this) : "Chunk must be locked before access";
}
}

View File

@ -20,6 +20,7 @@ import net.minestom.server.network.packet.server.play.UnloadChunkPacket;
import net.minestom.server.utils.PacketUtils;
import net.minestom.server.utils.async.AsyncUtils;
import net.minestom.server.utils.block.BlockUtils;
import net.minestom.server.utils.chunk.ChunkCache;
import net.minestom.server.utils.chunk.ChunkSupplier;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType;
@ -492,6 +493,7 @@ public class InstanceContainer extends Instance {
* @param blockPosition the position of the modified block
*/
private void executeNeighboursBlockPlacementRule(@NotNull Point blockPosition) {
ChunkCache cache = new ChunkCache(this, null, null);
for (int offsetX = -1; offsetX < 2; offsetX++) {
for (int offsetY = -1; offsetY < 2; offsetY++) {
for (int offsetZ = -1; offsetZ < 2; offsetZ++) {
@ -502,10 +504,9 @@ public class InstanceContainer extends Instance {
final int neighborZ = blockPosition.blockZ() + offsetZ;
if (neighborY < getDimensionType().getMinY() || neighborY > getDimensionType().getTotalHeight())
continue;
final Chunk chunk = getChunkAt(neighborX, neighborZ);
if (chunk == null) continue;
final Block neighborBlock = chunk.getBlock(neighborX, neighborY, neighborZ);
final Block neighborBlock = cache.getBlock(neighborX, neighborY, neighborZ, Condition.TYPE);
if (neighborBlock == null)
continue;
final BlockPlacementRule neighborBlockPlacementRule = MinecraftServer.getBlockManager().getBlockPlacementRule(neighborBlock);
if (neighborBlockPlacementRule == null) continue;

View File

@ -35,6 +35,10 @@ public final class ChunkCache implements Block.Getter {
if (chunk == null || chunk.getChunkX() != chunkX || chunk.getChunkZ() != chunkZ) {
this.chunk = chunk = this.instance.getChunk(chunkX, chunkZ);
}
return chunk != null ? chunk.getBlock(x, y, z, condition) : defaultBlock;
if (chunk != null) {
synchronized (chunk) {
return chunk.getBlock(x, y, z, condition);
}
} else return defaultBlock;
}
}

View File

@ -18,7 +18,10 @@ public final class EntityUtils {
final Pos entityPosition = entity.getPosition();
// TODO: check entire bounding box
try {
final Block block = chunk.getBlock(entityPosition.sub(0, 1, 0));
final Block block;
synchronized (chunk) {
block = chunk.getBlock(entityPosition.sub(0, 1, 0));
}
return block.isSolid();
} catch (NullPointerException e) {
// Probably an entity at the border of an unloaded chunk