The bug
When lava spread fire, it can sometimes calculate the blockstate for the fire from the block beneath the fire. This bug can be replicated as so:
[media]Doing so can sometimes create results like such: (Increasing the random tick speed will make it happen faster)
[media]Code analysis
Specifically, this bug occurs in the random tick method of the lava fluid, it will calculate the fire state for the block below where the fire will be placed, causing the above result.
Code analysis by @unknown can be found in this comment.
Attachments
Comments 7
Can Confirm
Man a lot of good ones today. So this has been in the game since 1.16 xD specifically 20w06a
Code Analysis (MojMap - 22w14a)
net.minecraft.world.level.material.LavaFluid.java
public void randomTick(Level level, BlockPos pos, FluidState fluid, RandomSource rand) {
// not relevant
int i = rand.nextInt(3);
if (i > 0) {
BlockPos blockPos = pos;
for(int c = 0; c < i; ++c) {
blockPos = blockPos.offset(rand.nextInt(3) - 1, 1, rand.nextInt(3) - 1);
if (!level.isLoaded(blockPos)) return;
BlockState state = level.getBlockState(blockPos);
if (state.isAir()) {
if (this.hasFlammableNeighbours(level, blockPos)) {
level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos));
return;
}
} else if (state.getMaterial().blocksMotion()) {
return;
}
}
} else {
for(int c = 0; c < 3; ++c) {
BlockPos newPos = pos.offset(rand.nextInt(3) - 1, 0, rand.nextInt(3) - 1);
if (!level.isLoaded(newPos)) return;
if (level.isEmptyBlock(newPos.above()) && this.isFlammable(level, newPos)) {
level.setBlockAndUpdate(newPos.above(), BaseFireBlock.getState(level, newPos));
}
}
}
}
So this is the lavaFluid randomTick code. Let's focus on these two parts:
net.minecraft.world.level.material.LavaFluid.java
// Top part (not broken)
BlockState state = level.getBlockState(blockPos);
if (state.isAir()) { // Is position we are placing the fire at air?
if (this.hasFlammableNeighbours(level, blockPos)) { // Is next to a flammable block?
// Set the block at pos to FireBlock with states that it should have at that pos
level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos));
return;
}
}
// Bottom part (broken)
// Is the block above the position selected empty?
// Is the block at the current position flammable?
if (level.isEmptyBlock(newPos.above()) && this.isFlammable(level, newPos)) {
// If so then set the block above the position selected to the state it should have if we placed it below that position...
level.setBlockAndUpdate(newPos.above(), BaseFireBlock.getState(level, newPos));
}
The code does the BaseFireBlock.getState(level, newPos) to generate the fire state at the wrong position, it should have been done one higher
The Fix:
Change the second BaseFireBlock.getState(level, newPos)
to BaseFireBlock.getState(level, newPos.above())
Technically the fire would have spread there anyways, and a fire in that state does nothing different. So it just looks cursed, and disappears when given a block update
Just to be clear, the bug you are referring to is the placement of the fire?