Prevent crash with mods calling getFluidState recursively

The returned fluid is meaningless, but vanilla doesn't crash here

Fixes #238
This commit is contained in:
embeddedt 2023-09-15 09:32:30 -04:00
parent 22559131cc
commit a0c5c90c8d
2 changed files with 29 additions and 2 deletions

View File

@ -87,8 +87,19 @@ public abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState>
// don't generate the full cache here as mods will iterate for the fluid state a lot
// assume blockstates will not change their contained fluidstate at runtime more than once
// this is how Lithium's implementation used to work, so it should be fine
if(this.cacheInvalid && this.fluidState == MFIX$VANILLA_DEFAULT_FLUID)
this.fluidState = this.owner.getFluidState(this.asState());
if(this.cacheInvalid && this.fluidState == MFIX$VANILLA_DEFAULT_FLUID) {
synchronized (BlockBehaviour.BlockStateBase.class) {
if(!buildingCache) {
buildingCache = true;
try {
this.fluidState = this.owner.getFluidState(this.asState());
} finally {
buildingCache = false;
}
}
}
}
return this.fluidState;
}

View File

@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.material.FluidState;
import org.embeddedt.modernfix.duck.IBlockState;
import org.embeddedt.modernfix.testing.util.BootstrapMinecraft;
import org.junit.jupiter.api.*;
@ -74,4 +75,19 @@ public class BlockStateCacheTest {
}
}
}
@Test
@Order(5)
public void checkRecursiveFluidState() {
Block b = new Block(BlockBehaviour.Properties.copy(Blocks.STONE)) {
@Override
public FluidState getFluidState(BlockState state) {
return state.getFluidState();
}
};
BlockState state = b.getStateDefinition().any();
((IBlockState)state).clearCache();
// this should not throw
state.getFluidState();
}
}