--- a/net/minecraft/world/level/block/BlockFire.java +++ b/net/minecraft/world/level/block/BlockFire.java @@ -28,6 +28,14 @@ import net.minecraft.world.phys.shapes.VoxelShapeCollision; import net.minecraft.world.phys.shapes.VoxelShapes; +// CraftBukkit start +import org.bukkit.craftbukkit.block.CraftBlockState; +import org.bukkit.craftbukkit.block.CraftBlockStates; +import org.bukkit.craftbukkit.event.CraftEventFactory; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockFadeEvent; +// CraftBukkit end + public class BlockFire extends BlockFireAbstract { public static final int MAX_AGE = 15; @@ -93,7 +101,24 @@ @Override public IBlockData updateShape(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - return this.canSurvive(iblockdata, generatoraccess, blockposition) ? this.getStateWithAge(generatoraccess, blockposition, (Integer) iblockdata.getValue(BlockFire.AGE)) : Blocks.AIR.defaultBlockState(); + // CraftBukkit start + if (!this.canSurvive(iblockdata, generatoraccess, blockposition)) { + // Suppress during worldgen + if (!(generatoraccess instanceof World)) { + return Blocks.AIR.defaultBlockState(); + } + CraftBlockState blockState = CraftBlockStates.getBlockState(generatoraccess, blockposition); + blockState.setData(Blocks.AIR.defaultBlockState()); + + BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState); + ((World) generatoraccess).getCraftServer().getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + return blockState.getHandle(); + } + } + return this.getStateWithAge(generatoraccess, blockposition, (Integer) iblockdata.getValue(BlockFire.AGE)); + // CraftBukkit end } @Override @@ -142,7 +167,7 @@ worldserver.scheduleTick(blockposition, (Block) this, getFireTickDelay(worldserver.random)); if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { if (!iblockdata.canSurvive(worldserver, blockposition)) { - worldserver.removeBlock(blockposition, false); + fireExtinguished(worldserver, blockposition); // CraftBukkit - invalid place location } IBlockData iblockdata1 = worldserver.getBlockState(blockposition.below()); @@ -150,7 +175,7 @@ int i = (Integer) iblockdata.getValue(BlockFire.AGE); if (!flag && worldserver.isRaining() && this.isNearRain(worldserver, blockposition) && randomsource.nextFloat() < 0.2F + (float) i * 0.03F) { - worldserver.removeBlock(blockposition, false); + fireExtinguished(worldserver, blockposition); // CraftBukkit - extinguished by rain } else { int j = Math.min(15, i + randomsource.nextInt(3) / 2); @@ -164,14 +189,14 @@ BlockPosition blockposition1 = blockposition.below(); if (!worldserver.getBlockState(blockposition1).isFaceSturdy(worldserver, blockposition1, EnumDirection.UP) || i > 3) { - worldserver.removeBlock(blockposition, false); + fireExtinguished(worldserver, blockposition); // CraftBukkit } return; } if (i == 15 && randomsource.nextInt(4) == 0 && !this.canBurn(worldserver.getBlockState(blockposition.below()))) { - worldserver.removeBlock(blockposition, false); + fireExtinguished(worldserver, blockposition); // CraftBukkit return; } } @@ -179,12 +204,14 @@ boolean flag1 = worldserver.getBiome(blockposition).is(BiomeTags.INCREASED_FIRE_BURNOUT); int k = flag1 ? -50 : 0; - this.checkBurnOut(worldserver, blockposition.east(), 300 + k, randomsource, i); - this.checkBurnOut(worldserver, blockposition.west(), 300 + k, randomsource, i); - this.checkBurnOut(worldserver, blockposition.below(), 250 + k, randomsource, i); - this.checkBurnOut(worldserver, blockposition.above(), 250 + k, randomsource, i); - this.checkBurnOut(worldserver, blockposition.north(), 300 + k, randomsource, i); - this.checkBurnOut(worldserver, blockposition.south(), 300 + k, randomsource, i); + // CraftBukkit start - add source blockposition to burn calls + this.trySpread(worldserver, blockposition.east(), 300 + k, randomsource, i, blockposition); + this.trySpread(worldserver, blockposition.west(), 300 + k, randomsource, i, blockposition); + this.trySpread(worldserver, blockposition.below(), 250 + k, randomsource, i, blockposition); + this.trySpread(worldserver, blockposition.above(), 250 + k, randomsource, i, blockposition); + this.trySpread(worldserver, blockposition.north(), 300 + k, randomsource, i, blockposition); + this.trySpread(worldserver, blockposition.south(), 300 + k, randomsource, i, blockposition); + // CraftBukkit end BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); for (int l = -1; l <= 1; ++l) { @@ -210,7 +237,15 @@ if (i2 > 0 && randomsource.nextInt(k1) <= i2 && (!worldserver.isRaining() || !this.isNearRain(worldserver, blockposition_mutableblockposition))) { int j2 = Math.min(15, i + randomsource.nextInt(5) / 4); - worldserver.setBlock(blockposition_mutableblockposition, this.getStateWithAge(worldserver, blockposition_mutableblockposition, j2), 3); + // CraftBukkit start - Call to stop spread of fire + if (worldserver.getBlockState(blockposition_mutableblockposition).getBlock() != Blocks.FIRE) { + if (CraftEventFactory.callBlockIgniteEvent(worldserver, blockposition_mutableblockposition, blockposition).isCancelled()) { + continue; + } + + CraftEventFactory.handleBlockSpreadEvent(worldserver, blockposition, blockposition_mutableblockposition, this.getStateWithAge(worldserver, blockposition_mutableblockposition, j2), 3); // CraftBukkit + } + // CraftBukkit end } } } @@ -234,12 +269,24 @@ return iblockdata.hasProperty(BlockProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(iblockdata.getBlock()); } - private void checkBurnOut(World world, BlockPosition blockposition, int i, RandomSource randomsource, int j) { + private void trySpread(World world, BlockPosition blockposition, int i, RandomSource randomsource, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition int k = this.getBurnOdds(world.getBlockState(blockposition)); if (randomsource.nextInt(i) < k) { IBlockData iblockdata = world.getBlockState(blockposition); + // CraftBukkit start + org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); + org.bukkit.block.Block sourceBlock = world.getWorld().getBlockAt(sourceposition.getX(), sourceposition.getY(), sourceposition.getZ()); + + BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); + world.getCraftServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return; + } + // CraftBukkit end + if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) { int l = Math.min(j + randomsource.nextInt(5) / 4, 15);