#937: Fixes related to unplaced BlockStates and the recent world generation changes.

* CraftBlockState#getWorldHandle() would previously run into a NPE when being invoked for a non-placed BlockState. It now returns null in this case.
* CraftChest#getInventory() would previously encounter this NPE when being called for a non-placed BlockState. It will now automatically forward the call to #getBlockInventory() when it is being called for either a non-placed BlockState, or during world generation.
* CraftStructureBlock#applyTo was able to run into a NPE when being called for non-placed BlockStates (this is for example called by #getSnapshotNBT()).
* Replaced all no-world-generation preconditions with a general 'ensureNoWorldGeneration' method.
* Removed a few superfluous #isPlaced() calls. If getWorldHandle() reutrns a World, this already implies that the BlockState is placed.
This commit is contained in:
blablubbabc 2021-10-10 07:55:53 +11:00 committed by md_5
parent 4faf479e6c
commit 960f31098d
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
9 changed files with 23 additions and 17 deletions

View File

@ -23,7 +23,7 @@ public class CraftBeacon extends CraftBlockEntityState<TileEntityBeacon> impleme
@Override @Override
public Collection<LivingEntity> getEntitiesInRange() { public Collection<LivingEntity> getEntitiesInRange() {
Preconditions.checkState(getWorldHandle() instanceof net.minecraft.world.level.World, "Can't get entities during world generation"); ensureNoWorldGeneration();
TileEntity tileEntity = this.getTileEntityFromWorld(); TileEntity tileEntity = this.getTileEntityFromWorld();
if (tileEntity instanceof TileEntityBeacon) { if (tileEntity instanceof TileEntityBeacon) {

View File

@ -60,7 +60,7 @@ public class CraftBeehive extends CraftBlockEntityState<TileEntityBeehive> imple
@Override @Override
public List<Bee> releaseEntities() { public List<Bee> releaseEntities() {
Preconditions.checkState(getWorldHandle() instanceof net.minecraft.world.level.World, "Can't release entities during world generation"); ensureNoWorldGeneration();
List<Bee> bees = new ArrayList<>(); List<Bee> bees = new ArrayList<>();

View File

@ -57,20 +57,33 @@ public class CraftBlockState implements BlockState {
} }
} }
// Returns null if weakWorld is not available and the BlockState is not placed.
// If this returns a World instead of only a GeneratorAccess, this implies that this BlockState is placed.
public GeneratorAccess getWorldHandle() { public GeneratorAccess getWorldHandle() {
if (weakWorld == null) { if (weakWorld == null) {
return world.getHandle(); return this.isPlaced() ? world.getHandle() : null;
} }
GeneratorAccess access = weakWorld.get(); GeneratorAccess access = weakWorld.get();
if (access == null) { if (access == null) {
weakWorld = null; weakWorld = null;
return world.getHandle(); return this.isPlaced() ? world.getHandle() : null;
} }
return access; return access;
} }
protected final boolean isWorldGeneration() {
GeneratorAccess generatorAccess = this.getWorldHandle();
return generatorAccess != null && !(generatorAccess instanceof World);
}
protected final void ensureNoWorldGeneration() {
if (isWorldGeneration()) {
throw new IllegalStateException("This operation is not supported during world generation!");
}
}
@Override @Override
public World getWorld() { public World getWorld() {
requirePlaced(); requirePlaced();

View File

@ -37,10 +37,8 @@ public class CraftChest extends CraftLootable<TileEntityChest> implements Chest
@Override @Override
public Inventory getInventory() { public Inventory getInventory() {
Preconditions.checkState(getWorldHandle() instanceof net.minecraft.world.level.World, "Can't get inventory during world generation, use getBlockInventory() instead");
CraftInventory inventory = (CraftInventory) this.getBlockInventory(); CraftInventory inventory = (CraftInventory) this.getBlockInventory();
if (!isPlaced()) { if (!isPlaced() || isWorldGeneration()) {
return inventory; return inventory;
} }

View File

@ -47,10 +47,8 @@ public class CraftDispenser extends CraftLootable<TileEntityDispenser> implement
@Override @Override
public boolean dispense() { public boolean dispense() {
Preconditions.checkState(getWorldHandle() instanceof net.minecraft.world.level.World, "Can't dispense during world generation"); ensureNoWorldGeneration();
Block block = getBlock(); Block block = getBlock();
if (block.getType() == Material.DISPENSER) { if (block.getType() == Material.DISPENSER) {
CraftWorld world = (CraftWorld) this.getWorld(); CraftWorld world = (CraftWorld) this.getWorld();
BlockDispenser dispense = (BlockDispenser) Blocks.DISPENSER; BlockDispenser dispense = (BlockDispenser) Blocks.DISPENSER;

View File

@ -34,10 +34,8 @@ public class CraftDropper extends CraftLootable<TileEntityDropper> implements Dr
@Override @Override
public void drop() { public void drop() {
Preconditions.checkState(getWorldHandle() instanceof net.minecraft.world.level.World, "Can't drop during world generation"); ensureNoWorldGeneration();
Block block = getBlock(); Block block = getBlock();
if (block.getType() == Material.DROPPER) { if (block.getType() == Material.DROPPER) {
CraftWorld world = (CraftWorld) this.getWorld(); CraftWorld world = (CraftWorld) this.getWorld();
BlockDropper drop = (BlockDropper) Blocks.DROPPER; BlockDropper drop = (BlockDropper) Blocks.DROPPER;

View File

@ -81,9 +81,8 @@ public class CraftJukebox extends CraftBlockEntityState<TileEntityJukeBox> imple
@Override @Override
public boolean eject() { public boolean eject() {
Preconditions.checkState(getWorldHandle() instanceof net.minecraft.world.level.World, "Can't eject during world generation"); ensureNoWorldGeneration();
requirePlaced();
TileEntity tileEntity = this.getTileEntityFromWorld(); TileEntity tileEntity = this.getTileEntityFromWorld();
if (!(tileEntity instanceof TileEntityJukeBox)) return false; if (!(tileEntity instanceof TileEntityJukeBox)) return false;

View File

@ -42,7 +42,7 @@ public class CraftLectern extends CraftBlockEntityState<TileEntityLectern> imple
public boolean update(boolean force, boolean applyPhysics) { public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics); boolean result = super.update(force, applyPhysics);
if (result && this.isPlaced() && this.getType() == Material.LECTERN && getWorldHandle() instanceof net.minecraft.world.level.World) { if (result && this.getType() == Material.LECTERN && getWorldHandle() instanceof net.minecraft.world.level.World) {
BlockLectern.a(this.world.getHandle(), this.getPosition(), this.getHandle()); BlockLectern.a(this.world.getHandle(), this.getPosition(), this.getHandle());
} }

View File

@ -180,7 +180,7 @@ public class CraftStructureBlock extends CraftBlockEntityState<TileEntityStructu
// Ensure block type is correct // Ensure block type is correct
if (access instanceof net.minecraft.world.level.World) { if (access instanceof net.minecraft.world.level.World) {
tileEntity.setUsageMode(tileEntity.getUsageMode()); tileEntity.setUsageMode(tileEntity.getUsageMode());
} else { } else if (access != null) {
// Custom handle during world generation // Custom handle during world generation
// From TileEntityStructure#setUsageMode(BlockPropertyStructureMode) // From TileEntityStructure#setUsageMode(BlockPropertyStructureMode)
net.minecraft.world.level.block.state.IBlockData data = access.getType(this.getPosition()); net.minecraft.world.level.block.state.IBlockData data = access.getType(this.getPosition());