net/minecraft/world/level/block/a-r

This commit is contained in:
Owen1212055
2024-12-14 21:31:05 -05:00
parent 11b1877545
commit b16f6f533a
177 changed files with 3259 additions and 3980 deletions

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/AbstractCandleBlock.java
+++ b/net/minecraft/world/level/block/AbstractCandleBlock.java
@@ -47,6 +47,11 @@
@Override
protected void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) {
if (!world.isClientSide && projectile.isOnFire() && this.canBeLit(state)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, hit.getBlockPos(), projectile).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
AbstractCandleBlock.setLit(world, state, hit.getBlockPos(), true);
}

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/AbstractCauldronBlock.java
+++ b/net/minecraft/world/level/block/AbstractCauldronBlock.java
@@ -56,7 +56,7 @@
@Override
protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
CauldronInteraction cauldronInteraction = this.interactions.map().get(stack.getItem());
- return cauldronInteraction.interact(state, world, pos, player, hand, stack);
+ return cauldronInteraction.interact(state, world, pos, player, hand, stack, hit.getDirection()); // Paper - pass hit direction
}
@Override

View File

@@ -1,13 +0,0 @@
--- a/net/minecraft/world/level/block/AnvilBlock.java
+++ b/net/minecraft/world/level/block/AnvilBlock.java
@@ -62,8 +62,9 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!world.isClientSide) {
- player.openMenu(state.getMenuProvider(world, pos));
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_ANVIL);
+ } // Paper - Fix InventoryOpenEvent cancellation
}
return InteractionResult.SUCCESS;

View File

@@ -1,19 +0,0 @@
--- a/net/minecraft/world/level/block/BambooSaplingBlock.java
+++ b/net/minecraft/world/level/block/BambooSaplingBlock.java
@@ -45,7 +45,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- if (random.nextInt(3) == 0 && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) {
+ if (random.nextFloat() < (world.spigotConfig.bambooModifier / (100.0f * 3)) && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
this.growBamboo(world, pos);
}
@@ -87,6 +87,6 @@
}
protected void growBamboo(Level world, BlockPos pos) {
- world.setBlock(pos.above(), (BlockState) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) Blocks.BAMBOO.defaultBlockState().setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3); // CraftBukkit - BlockSpreadEvent
}
}

View File

@@ -1,89 +0,0 @@
--- a/net/minecraft/world/level/block/BambooStalkBlock.java
+++ b/net/minecraft/world/level/block/BambooStalkBlock.java
@@ -134,10 +134,10 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if ((Integer) state.getValue(BambooStalkBlock.STAGE) == 0) {
- if (random.nextInt(3) == 0 && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) {
+ if (random.nextFloat() < (world.spigotConfig.bambooModifier / (100.0f * 3)) && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
int i = this.getHeightBelowUpToMax(world, pos) + 1;
- if (i < 16) {
+ if (i < world.paperConfig().maxGrowthHeight.bamboo.max) { // Paper - Configurable cactus/bamboo/reed growth height
this.growBamboo(state, world, pos, random, i);
}
}
@@ -164,7 +164,7 @@
int i = this.getHeightAboveUpToMax(world, pos);
int j = this.getHeightBelowUpToMax(world, pos);
- return i + j + 1 < 16 && (Integer) world.getBlockState(pos.above(i)).getValue(BambooStalkBlock.STAGE) != 1;
+ return i + j + 1 < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && (Integer) world.getBlockState(pos.above(i)).getValue(BambooStalkBlock.STAGE) != 1; // Paper - Configurable cactus/bamboo/reed growth height
}
@Override
@@ -183,7 +183,7 @@
BlockPos blockposition1 = pos.above(i);
BlockState iblockdata1 = world.getBlockState(blockposition1);
- if (k >= 16 || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) {
+ if (k >= world.paperConfig().maxGrowthHeight.bamboo.max || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooStalkBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus/bamboo/reed growth height
return;
}
@@ -204,14 +204,18 @@
BlockPos blockposition1 = pos.below(2);
BlockState iblockdata2 = world.getBlockState(blockposition1);
BambooLeaves blockpropertybamboosize = BambooLeaves.NONE;
+ boolean shouldUpdateOthers = false; // CraftBukkit
if (height >= 1) {
if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) {
if (iblockdata1.is(Blocks.BAMBOO) && iblockdata1.getValue(BambooStalkBlock.LEAVES) != BambooLeaves.NONE) {
blockpropertybamboosize = BambooLeaves.LARGE;
if (iblockdata2.is(Blocks.BAMBOO)) {
- world.setBlock(pos.below(), (BlockState) iblockdata1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3);
- world.setBlock(blockposition1, (BlockState) iblockdata2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3);
+ // CraftBukkit start - moved down
+ // world.setBlock(blockposition.below(), (IBlockData) iblockdata1.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.SMALL), 3);
+ // world.setBlock(blockposition1, (IBlockData) iblockdata2.setValue(BlockBamboo.LEAVES, BlockPropertyBambooSize.NONE), 3);
+ shouldUpdateOthers = true;
+ // CraftBukkit end
}
}
} else {
@@ -220,15 +224,22 @@
}
int j = (Integer) state.getValue(BambooStalkBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1;
- int k = (height < 11 || random.nextFloat() >= 0.25F) && height != 15 ? 0 : 1;
+ int k = (height < world.paperConfig().maxGrowthHeight.bamboo.min || random.nextFloat() >= 0.25F) && height != (world.paperConfig().maxGrowthHeight.bamboo.max - 1) ? 0 : 1; // Paper - Configurable cactus/bamboo/reed growth height
- world.setBlock(pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooStalkBlock.AGE, j)).setValue(BambooStalkBlock.LEAVES, blockpropertybamboosize)).setValue(BambooStalkBlock.STAGE, k), 3)) {
+ if (shouldUpdateOthers) {
+ world.setBlock(pos.below(), (BlockState) iblockdata1.setValue(BambooStalkBlock.LEAVES, BambooLeaves.SMALL), 3);
+ world.setBlock(blockposition1, (BlockState) iblockdata2.setValue(BambooStalkBlock.LEAVES, BambooLeaves.NONE), 3);
+ }
+ }
+ // CraftBukkit end
}
protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) {
int i;
- for (i = 0; i < 16 && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) {
+ for (i = 0; i < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper - Configurable cactus/bamboo/reed growth height
;
}
@@ -238,7 +249,7 @@
protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) {
int i;
- for (i = 0; i < 16 && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) {
+ for (i = 0; i < ((Level) world).paperConfig().maxGrowthHeight.bamboo.max && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper - Configurable cactus/bamboo/reed growth height
;
}

View File

@@ -1,12 +0,0 @@
--- a/net/minecraft/world/level/block/BarrelBlock.java
+++ b/net/minecraft/world/level/block/BarrelBlock.java
@@ -41,8 +41,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
- if (world instanceof ServerLevel serverLevel && world.getBlockEntity(pos) instanceof BarrelBlockEntity barrelBlockEntity) {
- player.openMenu(barrelBlockEntity);
+ if (world instanceof ServerLevel serverLevel && world.getBlockEntity(pos) instanceof BarrelBlockEntity barrelBlockEntity && player.openMenu(barrelBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.OPEN_BARREL);
PiglinAi.angerNearbyPiglins(serverLevel, player, true);
}

View File

@@ -1,85 +0,0 @@
--- a/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/net/minecraft/world/level/block/BaseFireBlock.java
@@ -12,6 +12,7 @@
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockBehaviour;
@@ -127,6 +128,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!entity.fireImmune()) {
if (entity.getRemainingFireTicks() < 0) {
entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1);
@@ -137,7 +139,18 @@
}
if (entity.getRemainingFireTicks() >= 0) {
- entity.igniteForSeconds(8.0F);
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityCombustEvent event = new org.bukkit.event.entity.EntityCombustByBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), entity.getBukkitEntity(), 8.0F);
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ entity.igniteForSeconds(event.getDuration(), false);
+ // Paper start - fix EntityCombustEvent cancellation
+ } else {
+ entity.setRemainingFireTicks(entity.getRemainingFireTicks() - 1);
+ // Paper end - fix EntityCombustEvent cancellation
+ }
+ // CraftBukkit end
}
}
@@ -146,26 +159,26 @@
}
@Override
- protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
- if (!oldState.is(state.getBlock())) {
+ protected void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext context) { // CraftBukkit - context
+ if (!iblockdata1.is(iblockdata.getBlock())) {
if (BaseFireBlock.inPortalDimension(world)) {
- Optional<PortalShape> optional = PortalShape.findEmptyPortalShape(world, pos, Direction.Axis.X);
+ Optional<PortalShape> optional = PortalShape.findEmptyPortalShape(world, blockposition, Direction.Axis.X);
if (optional.isPresent()) {
- ((PortalShape) optional.get()).createPortalBlocks(world);
+ ((PortalShape) optional.get()).createPortalBlocks(world, (context == null) ? null : context.getPlayer()); // CraftBukkit - player
return;
}
}
- if (!state.canSurvive(world, pos)) {
- world.removeBlock(pos, false);
+ if (!iblockdata.canSurvive(world, blockposition)) {
+ this.fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke
}
}
}
private static boolean inPortalDimension(Level world) {
- return world.dimension() == Level.OVERWORLD || world.dimension() == Level.NETHER;
+ return world.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.OVERWORLD || world.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER; // CraftBukkit - getTypeKey()
}
@Override
@@ -213,4 +226,12 @@
}
}
}
+
+ // CraftBukkit start
+ protected void fireExtinguished(net.minecraft.world.level.LevelAccessor world, BlockPos position) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, position, Blocks.AIR.defaultBlockState()).isCancelled()) {
+ world.removeBlock(position, false);
+ }
+ }
+ // CraftBukkit end
}

View File

@@ -1,56 +0,0 @@
--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java
+++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java
@@ -22,6 +22,7 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
public abstract class BasePressurePlateBlock extends Block {
@@ -76,6 +77,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide) {
int i = this.getSignalForState(state);
@@ -91,6 +93,19 @@
boolean flag = output > 0;
boolean flag1 = j > 0;
+ // CraftBukkit start - Interact Pressure Plate
+ org.bukkit.World bworld = world.getWorld();
+ org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager();
+
+ if (flag != flag1) {
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), output, j);
+ manager.callEvent(eventRedstone);
+
+ flag1 = eventRedstone.getNewCurrent() > 0;
+ j = eventRedstone.getNewCurrent();
+ }
+ // CraftBukkit end
+
if (output != j) {
BlockState iblockdata1 = this.setSignalForState(state, j);
@@ -145,9 +160,15 @@
}
protected static int getEntityCount(Level world, AABB box, Class<? extends Entity> entityClass) {
- return world.getEntitiesOfClass(entityClass, box, EntitySelector.NO_SPECTATORS.and((entity) -> {
+ // CraftBukkit start
+ return BasePressurePlateBlock.getEntities(world, box, entityClass).size();
+ }
+
+ protected static <T extends Entity> java.util.List<T> getEntities(Level world, AABB axisalignedbb, Class<T> oclass) {
+ // CraftBukkit end
+ return world.getEntitiesOfClass(oclass, axisalignedbb, EntitySelector.NO_SPECTATORS.and((entity) -> {
return !entity.isIgnoringBlockTriggers();
- })).size();
+ })); // CraftBukkit
}
protected abstract int getSignalStrength(Level world, BlockPos pos);

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/block/BaseRailBlock.java
+++ b/net/minecraft/world/level/block/BaseRailBlock.java
@@ -71,6 +71,7 @@
state = this.updateDir(world, pos, state, true);
if (this.isStraight) {
world.neighborChanged(state, pos, this, null, notify);
+ state = world.getBlockState(pos); // Paper - Fix some rails connecting improperly
}
return state;

View File

@@ -1,12 +0,0 @@
--- a/net/minecraft/world/level/block/BeaconBlock.java
+++ b/net/minecraft/world/level/block/BeaconBlock.java
@@ -46,8 +46,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
- if (!world.isClientSide && world.getBlockEntity(pos) instanceof BeaconBlockEntity beaconBlockEntity) {
- player.openMenu(beaconBlockEntity);
+ if (!world.isClientSide && world.getBlockEntity(pos) instanceof BeaconBlockEntity beaconBlockEntity && player.openMenu(beaconBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_BEACON);
}

View File

@@ -1,92 +0,0 @@
--- a/net/minecraft/world/level/block/BedBlock.java
+++ b/net/minecraft/world/level/block/BedBlock.java
@@ -95,7 +95,8 @@
}
}
- if (!BedBlock.canSetSpawn(world)) {
+ // CraftBukkit - moved world and biome check into EntityHuman
+ if (false && !BedBlock.canSetSpawn(world)) {
world.removeBlock(pos, false);
BlockPos blockposition1 = pos.relative(((Direction) state.getValue(BedBlock.FACING)).getOpposite());
@@ -108,25 +109,65 @@
world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
return InteractionResult.SUCCESS_SERVER;
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
+ if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos); // Paper - check explode first
if (!this.kickVillagerOutOfBed(world, pos)) {
player.displayClientMessage(Component.translatable("block.minecraft.bed.occupied"), true);
}
return InteractionResult.SUCCESS_SERVER;
} else {
+ // CraftBukkit start
+ BlockState finaliblockdata = state;
+ BlockPos finalblockposition = pos;
+ // CraftBukkit end
player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> {
+ // Paper start - PlayerBedFailEnterEvent
+ if (entityhuman_enumbedresult != null) {
+ io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.values()[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), !world.dimensionType().bedWorks(), io.papermc.paper.adventure.PaperAdventure.asAdventure(entityhuman_enumbedresult.getMessage()));
+ if (!event.callEvent()) {
+ return;
+ }
+ // Paper end - PlayerBedFailEnterEvent
+ // CraftBukkit start - handling bed explosion from below here
+ if (event.getWillExplode()) { // Paper - PlayerBedFailEnterEvent
+ this.explodeBed(finaliblockdata, world, finalblockposition);
+ } else
+ // CraftBukkit end
if (entityhuman_enumbedresult.getMessage() != null) {
- player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true);
+ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper - PlayerBedFailEnterEvent
+ if (message != null) player.displayClientMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), true); // Paper - PlayerBedFailEnterEvent
}
+ } // Paper - PlayerBedFailEnterEvent
});
return InteractionResult.SUCCESS_SERVER;
+ }
+ }
+ }
+
+ // CraftBukkit start
+ private InteractionResult explodeBed(BlockState iblockdata, Level world, BlockPos blockposition) {
+ {
+ {
+ org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition).getState(); // CraftBukkit - capture BlockState before remove block
+ world.removeBlock(blockposition, false);
+ BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite());
+
+ if (world.getBlockState(blockposition1).getBlock() == this) {
+ world.removeBlock(blockposition1, false);
+ }
+
+ Vec3 vec3d = blockposition.getCenter();
+
+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, blockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ return InteractionResult.SUCCESS;
}
}
}
+ // CraftBukkit end
public static boolean canSetSpawn(Level world) {
- return world.dimensionType().bedWorks();
+ return world.dimensionType().bedWorks(); // Paper - actually check if the bed works
}
private boolean kickVillagerOutOfBed(Level world, BlockPos pos) {
@@ -320,6 +361,11 @@
BlockPos blockposition1 = pos.relative((Direction) state.getValue(BedBlock.FACING));
world.setBlock(blockposition1, (BlockState) state.setValue(BedBlock.PART, BedPart.HEAD), 3);
+ // CraftBukkit start - SPIGOT-7315: Don't updated if we capture block states
+ if (world.captureBlockStates) {
+ return;
+ }
+ // CraftBukkit end
world.blockUpdated(pos, Blocks.AIR);
state.updateNeighbourShapes(world, pos, 3);
}

View File

@@ -1,79 +0,0 @@
--- a/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/net/minecraft/world/level/block/BeehiveBlock.java
@@ -94,8 +94,8 @@
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
if (!world.isClientSide && blockEntity instanceof BeehiveBlockEntity tileentitybeehive) {
if (!EnchantmentHelper.hasTag(tool, EnchantmentTags.PREVENTS_BEE_SPAWNS_WHEN_MINING)) {
tileentitybeehive.emptyAllLivingFromHive(player, state, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
@@ -103,7 +103,7 @@
this.angerNearbyBees(world, pos);
}
- CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer) player, state, tool, tileentitybeehive.getOccupantCount());
+ // CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer) player, state, tool, tileentitybeehive.getOccupantCount()); // Paper - Trigger bee_nest_destroyed trigger in the correct place; moved until after items are dropped
}
}
@@ -133,7 +133,7 @@
if (entitybee.getTarget() == null) {
Player entityhuman = (Player) Util.getRandom(list1, world.random);
- entitybee.setTarget(entityhuman);
+ entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit
}
}
}
@@ -141,7 +141,7 @@
}
public static void dropHoneycomb(Level world, BlockPos pos) {
- popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3));
+ popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); // Paper - Add PlayerShearBlockEvent; conflict on change, item needs to be set below
}
@Override
@@ -153,8 +153,19 @@
Item item = stack.getItem();
if (stack.is(Items.SHEARS)) {
+ // Paper start - Add PlayerShearBlockEvent
+ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), new java.util.ArrayList<>());
+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3)));
+ if (!event.callEvent()) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F);
- BeehiveBlock.dropHoneycomb(world, pos);
+ // Paper start - Add PlayerShearBlockEvent
+ for (org.bukkit.inventory.ItemStack itemDrop : event.getDrops()) {
+ popResource(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemDrop));
+ }
+ // Paper end - Add PlayerShearBlockEvent
stack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
flag = true;
world.gameEvent((Entity) player, (Holder) GameEvent.SHEAR, pos);
@@ -297,7 +308,7 @@
ItemStack itemstack = new ItemStack(this);
itemstack.applyComponents(tileentitybeehive.collectComponents());
- itemstack.set(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY.with(BeehiveBlock.HONEY_LEVEL, (Comparable) i));
+ itemstack.set(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY.with(BeehiveBlock.HONEY_LEVEL, i)); // CraftBukkit - decompile error
ItemEntity entityitem = new ItemEntity(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack);
entityitem.setDefaultPickUpDelay();
@@ -332,7 +343,7 @@
ItemStack itemstack = super.getCloneItemStack(world, pos, state, includeData);
if (includeData) {
- itemstack.set(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY.with(BeehiveBlock.HONEY_LEVEL, (Comparable) ((Integer) state.getValue(BeehiveBlock.HONEY_LEVEL))));
+ itemstack.set(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY.with(BeehiveBlock.HONEY_LEVEL, ((Integer) state.getValue(BeehiveBlock.HONEY_LEVEL)))); // CraftBukkit - decompile error
}
return itemstack;

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/BellBlock.java
+++ b/net/minecraft/world/level/block/BellBlock.java
@@ -148,6 +148,11 @@
if (direction == null) {
direction = (Direction) world.getBlockState(pos).getValue(BellBlock.FACING);
}
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBellRingEvent(world, pos, direction, entity)) {
+ return false;
+ }
+ // CraftBukkit end
((BellBlockEntity) tileentity).onHit(direction);
world.playSound((Player) null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F);

View File

@@ -1,116 +0,0 @@
--- a/net/minecraft/world/level/block/BigDripleafBlock.java
+++ b/net/minecraft/world/level/block/BigDripleafBlock.java
@@ -44,6 +44,10 @@
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityInteractEvent;
+// CraftBukkit end
public class BigDripleafBlock extends HorizontalDirectionalBlock implements BonemealableBlock, SimpleWaterloggedBlock {
@@ -119,7 +123,7 @@
@Override
protected void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) {
- this.setTiltAndScheduleTick(state, world, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN);
+ this.setTiltAndScheduleTick(state, world, hit.getBlockPos(), Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, projectile); // CraftBukkit
}
@Override
@@ -176,9 +180,23 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide) {
if (state.getValue(BigDripleafBlock.TILT) == Tilt.NONE && BigDripleafBlock.canEntityTilt(pos, entity) && !world.hasNeighborSignal(pos)) {
- this.setTiltAndScheduleTick(state, world, pos, Tilt.UNSTABLE, (SoundEvent) null);
+ // CraftBukkit start - tilt dripleaf
+ org.bukkit.event.Cancellable cancellable;
+ if (entity instanceof Player) {
+ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else {
+ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ world.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable);
+ }
+
+ if (cancellable.isCancelled()) {
+ return;
+ }
+ this.setTiltAndScheduleTick(state, world, pos, Tilt.UNSTABLE, (SoundEvent) null, entity);
+ // CraftBukkit end
}
}
@@ -192,9 +210,9 @@
Tilt tilt = (Tilt) state.getValue(BigDripleafBlock.TILT);
if (tilt == Tilt.UNSTABLE) {
- this.setTiltAndScheduleTick(state, world, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN);
+ this.setTiltAndScheduleTick(state, world, pos, Tilt.PARTIAL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit
} else if (tilt == Tilt.PARTIAL) {
- this.setTiltAndScheduleTick(state, world, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN);
+ this.setTiltAndScheduleTick(state, world, pos, Tilt.FULL, SoundEvents.BIG_DRIPLEAF_TILT_DOWN, null); // CraftBukkit
} else if (tilt == Tilt.FULL) {
BigDripleafBlock.resetTilt(state, world, pos);
}
@@ -220,36 +238,46 @@
return entity.onGround() && entity.position().y > (double) ((float) pos.getY() + 0.6875F);
}
- private void setTiltAndScheduleTick(BlockState state, Level world, BlockPos pos, Tilt tilt, @Nullable SoundEvent sound) {
- BigDripleafBlock.setTilt(state, world, pos, tilt);
- if (sound != null) {
- BigDripleafBlock.playTiltSound(world, pos, sound);
+ // CraftBukkit start
+ private void setTiltAndScheduleTick(BlockState iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable SoundEvent soundeffect, @Nullable Entity entity) {
+ if (!BigDripleafBlock.setTilt(iblockdata, world, blockposition, tilt, entity)) return;
+ // CraftBukkit end
+ if (soundeffect != null) {
+ BigDripleafBlock.playTiltSound(world, blockposition, soundeffect);
}
int i = BigDripleafBlock.DELAY_UNTIL_NEXT_TILT_STATE.getInt(tilt);
if (i != -1) {
- world.scheduleTick(pos, (Block) this, i);
+ world.scheduleTick(blockposition, (Block) this, i);
}
}
private static void resetTilt(BlockState state, Level world, BlockPos pos) {
- BigDripleafBlock.setTilt(state, world, pos, Tilt.NONE);
+ BigDripleafBlock.setTilt(state, world, pos, Tilt.NONE, null); // CraftBukkit
if (state.getValue(BigDripleafBlock.TILT) != Tilt.NONE) {
BigDripleafBlock.playTiltSound(world, pos, SoundEvents.BIG_DRIPLEAF_TILT_UP);
}
}
- private static void setTilt(BlockState state, Level world, BlockPos pos, Tilt tilt) {
- Tilt tilt1 = (Tilt) state.getValue(BigDripleafBlock.TILT);
+ // CraftBukkit start
+ private static boolean setTilt(BlockState iblockdata, Level world, BlockPos blockposition, Tilt tilt, @Nullable Entity entity) {
+ if (entity != null) {
+ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata.setValue(BigDripleafBlock.TILT, tilt))) {
+ return false;
+ }
+ }
+ // CraftBukkit end
+ Tilt tilt1 = (Tilt) iblockdata.getValue(BigDripleafBlock.TILT);
- world.setBlock(pos, (BlockState) state.setValue(BigDripleafBlock.TILT, tilt), 2);
+ world.setBlock(blockposition, (BlockState) iblockdata.setValue(BigDripleafBlock.TILT, tilt), 2);
if (tilt.causesVibration() && tilt != tilt1) {
- world.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_CHANGE, pos);
+ world.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_CHANGE, blockposition);
}
+ return true; // CraftBukkit
}
@Override

View File

@@ -1,12 +0,0 @@
--- a/net/minecraft/world/level/block/BlastFurnaceBlock.java
+++ b/net/minecraft/world/level/block/BlastFurnaceBlock.java
@@ -45,8 +45,7 @@
@Override
protected void openContainer(Level world, BlockPos pos, Player player) {
BlockEntity blockEntity = world.getBlockEntity(pos);
- if (blockEntity instanceof BlastFurnaceBlockEntity) {
- player.openMenu((MenuProvider)blockEntity);
+ if (blockEntity instanceof BlastFurnaceBlockEntity && player.openMenu((MenuProvider)blockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_BLAST_FURNACE);
}
}

View File

@@ -1,154 +0,0 @@
--- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java
@@ -88,6 +88,21 @@
public static final int UPDATE_LIMIT = 512;
protected final StateDefinition<Block, BlockState> stateDefinition;
private BlockState defaultBlockState;
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
+ public final boolean isDestroyable() {
+ return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
+ this != Blocks.BARRIER &&
+ this != Blocks.BEDROCK &&
+ this != Blocks.END_PORTAL_FRAME &&
+ this != Blocks.END_PORTAL &&
+ this != Blocks.END_GATEWAY &&
+ this != Blocks.COMMAND_BLOCK &&
+ this != Blocks.REPEATING_COMMAND_BLOCK &&
+ this != Blocks.CHAIN_COMMAND_BLOCK &&
+ this != Blocks.STRUCTURE_BLOCK &&
+ this != Blocks.JIGSAW;
+ }
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
@Nullable
private Item item;
private static final int CACHE_SIZE = 256;
@@ -295,12 +310,38 @@
}
+ // Paper start - Add BlockBreakBlockEvent
+ public static boolean dropResources(BlockState state, LevelAccessor levelAccessor, BlockPos pos, @Nullable BlockEntity blockEntity, BlockPos source) {
+ if (levelAccessor instanceof ServerLevel serverLevel) {
+ List<org.bukkit.inventory.ItemStack> items = new java.util.ArrayList<>();
+ for (ItemStack drop : Block.getDrops(state, serverLevel, pos, blockEntity)) {
+ items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
+ }
+ Block block = state.getBlock(); // Paper - Properly handle xp dropping
+ io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, pos), org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, source), items);
+ event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
+ event.callEvent();
+ for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
+ popResource(serverLevel, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
+ }
+ state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
+ block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
+ }
+ return true;
+ }
+ // Paper end - Add BlockBreakBlockEvent
+
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
+ // Paper start - Properly handle xp dropping
+ dropResources(state, world, pos, blockEntity, entity, tool, true);
+ }
+ public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool, boolean dropExperience) {
+ // Paper end - Properly handle xp dropping
if (world instanceof ServerLevel) {
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
Block.popResource(world, pos, itemstack1);
});
- state.spawnAfterBreak((ServerLevel) world, pos, tool, true);
+ state.spawnAfterBreak((ServerLevel) world, pos, tool, dropExperience); // Paper - Properly handle xp dropping
}
}
@@ -340,7 +381,13 @@
ItemEntity entityitem = (ItemEntity) itemEntitySupplier.get();
entityitem.setDefaultPickUpDelay();
- world.addFreshEntity(entityitem);
+ // CraftBukkit start
+ if (world.captureDrops != null) {
+ world.captureDrops.add(entityitem);
+ } else {
+ world.addFreshEntity(entityitem);
+ }
+ // CraftBukkit end
return;
}
}
@@ -348,8 +395,13 @@
}
public void popExperience(ServerLevel world, BlockPos pos, int size) {
+ // Paper start - add entity parameter
+ popExperience(world, pos, size, null);
+ }
+ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.world.entity.Entity entity) {
+ // Paper end - add entity parameter
if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
- ExperienceOrb.award(world, Vec3.atCenterOf(pos), size);
+ ExperienceOrb.award(world, Vec3.atCenterOf(pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, entity); // Paper
}
}
@@ -367,10 +419,18 @@
return this.defaultBlockState();
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - fix drops not preventing stats/food exhaustion
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
+ // Paper start - fix drops not preventing stats/food exhaustion
+ this.playerDestroy(world, player, pos, state, blockEntity, tool, true, true);
+ }
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) {
+ // Paper end - fix drops not preventing stats/food exhaustion
player.awardStat(Stats.BLOCK_MINED.get(this));
- player.causeFoodExhaustion(0.005F);
- Block.dropResources(state, world, pos, blockEntity, player, tool);
+ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
+ if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion
+ Block.dropResources(state, world, pos, blockEntity, player, tool, dropExp); // Paper - Properly handle xp dropping
+ } // Paper - fix drops not preventing stats/food exhaustion
}
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
@@ -490,15 +550,35 @@
return this.builtInRegistryHolder;
}
- protected void tryDropExperience(ServerLevel world, BlockPos pos, ItemStack tool, IntProvider experience) {
- int i = EnchantmentHelper.processBlockExperience(world, tool, experience.sample(world.getRandom()));
+ // CraftBukkit start
+ protected int tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) {
+ int i = EnchantmentHelper.processBlockExperience(worldserver, itemstack, intprovider.sample(worldserver.getRandom()));
if (i > 0) {
- this.popExperience(world, pos, i);
+ // this.popExperience(worldserver, blockposition, i);
+ return i;
}
+ return 0;
}
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+ return 0;
+ }
+ // CraftBukkit end
+
+ // Spigot start
+ public static float range(float min, float value, float max) {
+ if (value < min) {
+ return min;
+ }
+ if (value > max) {
+ return max;
+ }
+ return value;
+ }
+ // Spigot end
+
private static record ShapePairKey(VoxelShape first, VoxelShape second) {
public boolean equals(Object object) {

View File

@@ -1,12 +0,0 @@
--- a/net/minecraft/world/level/block/BrewingStandBlock.java
+++ b/net/minecraft/world/level/block/BrewingStandBlock.java
@@ -68,8 +68,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
- if (!world.isClientSide && world.getBlockEntity(pos) instanceof BrewingStandBlockEntity brewingStandBlockEntity) {
- player.openMenu(brewingStandBlockEntity);
+ if (!world.isClientSide && world.getBlockEntity(pos) instanceof BrewingStandBlockEntity brewingStandBlockEntity && player.openMenu(brewingStandBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_BREWINGSTAND);
}

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/block/BubbleColumnBlock.java
+++ b/net/minecraft/world/level/block/BubbleColumnBlock.java
@@ -48,6 +48,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
BlockState blockState = world.getBlockState(pos.above());
if (blockState.isAir()) {
entity.onAboveBubbleCol(state.getValue(DRAG_DOWN));

View File

@@ -1,17 +0,0 @@
--- a/net/minecraft/world/level/block/BuddingAmethystBlock.java
+++ b/net/minecraft/world/level/block/BuddingAmethystBlock.java
@@ -45,7 +45,13 @@
if (block != null) {
BlockState iblockdata2 = (BlockState) ((BlockState) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, enumdirection)).setValue(AmethystClusterBlock.WATERLOGGED, iblockdata1.getFluidState().getType() == Fluids.WATER);
- world.setBlockAndUpdate(blockposition1, iblockdata2);
+ // Paper start - Have Amethyst throw both spread and grow events
+ if (block == Blocks.SMALL_AMETHYST_BUD) {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, iblockdata2); // CraftBukkit
+ } else {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, blockposition1, iblockdata2);
+ }
+ // Paper end - Have Amethyst throw both spread and grow events
}
}

View File

@@ -1,27 +0,0 @@
--- a/net/minecraft/world/level/block/BushBlock.java
+++ b/net/minecraft/world/level/block/BushBlock.java
@@ -6,6 +6,7 @@
import net.minecraft.tags.BlockTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.ScheduledTickAccess;
import net.minecraft.world.level.block.state.BlockBehaviour;
@@ -27,7 +28,15 @@
@Override
protected BlockState updateShape(BlockState state, LevelReader world, ScheduledTickAccess tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random) {
- return !state.canSurvive(world, pos) ? Blocks.AIR.defaultBlockState() : super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
+ // CraftBukkit start
+ if (!state.canSurvive(world, pos)) {
+ // Suppress during worldgen
+ if (!(world instanceof net.minecraft.server.level.ServerLevel world1 && world1.hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world1, pos).isCancelled()) { // Paper
+ return Blocks.AIR.defaultBlockState();
+ }
+ }
+ return super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
+ // CraftBukkit end
}
@Override

View File

@@ -1,78 +0,0 @@
--- a/net/minecraft/world/level/block/ButtonBlock.java
+++ b/net/minecraft/world/level/block/ButtonBlock.java
@@ -34,6 +34,10 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.event.block.BlockRedstoneEvent;
+import org.bukkit.event.entity.EntityInteractEvent;
+// CraftBukkit end
public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
@@ -126,6 +130,19 @@
if ((Boolean) state.getValue(ButtonBlock.POWERED)) {
return InteractionResult.CONSUME;
} else {
+ // CraftBukkit start
+ boolean powered = ((Boolean) state.getValue(ButtonBlock.POWERED));
+ org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ int old = (powered) ? 15 : 0;
+ int current = (!powered) ? 15 : 0;
+
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) {
+ return InteractionResult.SUCCESS;
+ }
+ // CraftBukkit end
this.press(state, world, pos, player);
return InteractionResult.SUCCESS;
}
@@ -191,17 +208,43 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide && this.type.canButtonBeActivatedByArrows() && !(Boolean) state.getValue(ButtonBlock.POWERED)) {
this.checkPressed(state, world, pos);
}
}
protected void checkPressed(BlockState state, Level world, BlockPos pos) {
- AbstractArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (AbstractArrow) world.getEntitiesOfClass(AbstractArrow.class, state.getShape(world, pos).bounds().move(pos)).stream().findFirst().orElse((Object) null) : null;
+ AbstractArrow entityarrow = this.type.canButtonBeActivatedByArrows() ? (AbstractArrow) world.getEntitiesOfClass(AbstractArrow.class, state.getShape(world, pos).bounds().move(pos)).stream().findFirst().orElse(null) : null; // CraftBukkit - decompile error
boolean flag = entityarrow != null;
boolean flag1 = (Boolean) state.getValue(ButtonBlock.POWERED);
+ // CraftBukkit start - Call interact event when arrows turn on wooden buttons
+ if (flag1 != flag && flag) {
+ org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ EntityInteractEvent event = new EntityInteractEvent(entityarrow.getBukkitEntity(), block);
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return;
+ }
+ }
+ // CraftBukkit end
+
if (flag != flag1) {
+ // CraftBukkit start
+ boolean powered = flag1;
+ org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ int old = (powered) ? 15 : 0;
+ int current = (!powered) ? 15 : 0;
+
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if ((flag && eventRedstone.getNewCurrent() <= 0) || (!flag && eventRedstone.getNewCurrent() > 0)) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(ButtonBlock.POWERED, flag), 3);
this.updateNeighbours(state, world, pos);
this.playSound((Player) null, world, pos, flag);

View File

@@ -1,42 +0,0 @@
--- a/net/minecraft/world/level/block/CactusBlock.java
+++ b/net/minecraft/world/level/block/CactusBlock.java
@@ -22,6 +22,7 @@
import net.minecraft.world.level.redstone.Orientation;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
public class CactusBlock extends Block {
@@ -61,16 +62,17 @@
;
}
- if (i < 3) {
+ if (i < world.paperConfig().maxGrowthHeight.cactus) { // Paper - Configurable cactus/bamboo/reed growth height
int j = (Integer) state.getValue(CactusBlock.AGE);
- if (j == 15) {
- world.setBlockAndUpdate(blockposition1, this.defaultBlockState());
+ int modifier = world.spigotConfig.cactusModifier; // Spigot - SPIGOT-7159: Better modifier resolution
+ if (j >= 15 || (modifier != 100 && random.nextFloat() < (modifier / (100.0f * 16)))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ CraftEventFactory.handleBlockGrowEvent(world, blockposition1, this.defaultBlockState()); // CraftBukkit
BlockState iblockdata1 = (BlockState) state.setValue(CactusBlock.AGE, 0);
world.setBlock(pos, iblockdata1, 4);
world.neighborChanged(iblockdata1, blockposition1, this, (Orientation) null, false);
- } else {
+ } else if (modifier == 100 || random.nextFloat() < (modifier / (100.0f * 16))) { // Spigot - SPIGOT-7159: Better modifier resolution
world.setBlock(pos, (BlockState) state.setValue(CactusBlock.AGE, j + 1), 4);
}
@@ -120,7 +122,8 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
- entity.hurt(world.damageSources().cactus(), 1.0F);
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
+ entity.hurt(world.damageSources().cactus().directBlock(world, pos), 1.0F); // CraftBukkit
}
@Override

View File

@@ -1,47 +0,0 @@
--- a/net/minecraft/world/level/block/CakeBlock.java
+++ b/net/minecraft/world/level/block/CakeBlock.java
@@ -66,6 +66,12 @@
if (block instanceof CandleBlock) {
CandleBlock candleblock = (CandleBlock) block;
+ // Paper start - call change block event
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, CandleCakeBlock.byCandle(candleblock))) {
+ player.containerMenu.sendAllDataToRemote(); // update inv because candle could decrease
+ return InteractionResult.TRY_WITH_EMPTY_HAND;
+ }
+ // Paper end - call change block event
stack.consume(1, player);
world.playSound((Player) null, pos, SoundEvents.CAKE_ADD_CANDLE, SoundSource.BLOCKS, 1.0F, 1.0F);
world.setBlockAndUpdate(pos, CandleCakeBlock.byCandle(candleblock));
@@ -97,10 +103,29 @@
if (!player.canEat(false)) {
return InteractionResult.PASS;
} else {
+ // Paper start - call change block event
+ int i = state.getValue(CakeBlock.BITES);
+ final BlockState newState = i < MAX_BITES ? state.setValue(CakeBlock.BITES, i + 1) : world.getFluidState(pos).createLegacyBlock();
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, pos, newState)) {
+ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate();
+ return InteractionResult.PASS; // return a non-consume result to cake blocks don't drop their candles
+ }
+ // Paper end - call change block event
player.awardStat(Stats.EAT_CAKE_SLICE);
- player.getFoodData().eat(2, 0.1F);
- int i = (Integer) state.getValue(CakeBlock.BITES);
+ // CraftBukkit start
+ // entityhuman.getFoodData().eat(2, 0.1F);
+ int oldFoodLevel = player.getFoodData().foodLevel;
+ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);
+
+ if (!event.isCancelled()) {
+ player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F);
+ }
+
+ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().sendHealthUpdate();
+ // CraftBukkit end
+ // Paper - move up
+
world.gameEvent((Entity) player, (Holder) GameEvent.EAT, pos);
if (i < 6) {
world.setBlock(pos, (BlockState) state.setValue(CakeBlock.BITES, i + 1), 3);

View File

@@ -1,25 +0,0 @@
--- a/net/minecraft/world/level/block/CampfireBlock.java
+++ b/net/minecraft/world/level/block/CampfireBlock.java
@@ -112,8 +112,9 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if ((Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity) {
- entity.hurt(world.damageSources().campfire(), (float) this.fireDamage);
+ entity.hurt(world.damageSources().campfire().directBlock(world, pos), (float) this.fireDamage); // CraftBukkit
}
super.entityInside(state, world, pos, entity);
@@ -219,6 +220,11 @@
if (world instanceof ServerLevel worldserver) {
if (projectile.isOnFire() && projectile.mayInteract(worldserver, blockposition) && !(Boolean) state.getValue(CampfireBlock.LIT) && !(Boolean) state.getValue(CampfireBlock.WATERLOGGED)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, projectile).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(blockposition, (BlockState) state.setValue(BlockStateProperties.LIT, true), 11);
}
}

View File

@@ -1,13 +0,0 @@
--- a/net/minecraft/world/level/block/CartographyTableBlock.java
+++ b/net/minecraft/world/level/block/CartographyTableBlock.java
@@ -32,8 +32,9 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!world.isClientSide) {
- player.openMenu(state.getMenuProvider(world, pos));
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_CARTOGRAPHY_TABLE);
+ } // Paper - Fix InventoryOpenEvent cancellation
}
return InteractionResult.SUCCESS;

View File

@@ -1,29 +0,0 @@
--- a/net/minecraft/world/level/block/CarvedPumpkinBlock.java
+++ b/net/minecraft/world/level/block/CarvedPumpkinBlock.java
@@ -24,6 +24,9 @@
import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder;
import net.minecraft.world.level.block.state.predicate.BlockStatePredicate;
import net.minecraft.world.level.block.state.properties.EnumProperty;
+// CraftBukkit start
+import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
+// CraftBukkit end
public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
@@ -87,9 +90,14 @@
}
private static void spawnGolemInWorld(Level world, BlockPattern.BlockPatternMatch patternResult, Entity entity, BlockPos pos) {
- CarvedPumpkinBlock.clearPatternBlocks(world, patternResult);
+ // clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - moved down
entity.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + 0.05D, (double) pos.getZ() + 0.5D, 0.0F, 0.0F);
- world.addFreshEntity(entity);
+ // CraftBukkit start
+ if (!world.addFreshEntity(entity, (entity.getType() == EntityType.SNOW_GOLEM) ? SpawnReason.BUILD_SNOWMAN : SpawnReason.BUILD_IRONGOLEM)) {
+ return;
+ }
+ CarvedPumpkinBlock.clearPatternBlocks(world, patternResult); // CraftBukkit - from above
+ // CraftBukkit end
Iterator iterator = world.getEntitiesOfClass(ServerPlayer.class, entity.getBoundingBox().inflate(5.0D)).iterator();
while (iterator.hasNext()) {

View File

@@ -1,56 +0,0 @@
--- a/net/minecraft/world/level/block/CauldronBlock.java
+++ b/net/minecraft/world/level/block/CauldronBlock.java
@@ -12,6 +12,9 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
+// CraftBukkit start
+import org.bukkit.event.block.CauldronLevelChangeEvent;
+// CraftBukkit end
public class CauldronBlock extends AbstractCauldronBlock {
@@ -41,9 +44,19 @@
public void handlePrecipitation(BlockState state, Level world, BlockPos pos, Biome.Precipitation precipitation) {
if (CauldronBlock.shouldHandlePrecipitation(world, precipitation)) {
if (precipitation == Biome.Precipitation.RAIN) {
+ // Paper start - Call CauldronLevelChangeEvent
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, Blocks.WATER_CAULDRON.defaultBlockState(), null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL, false)) { // avoid duplicate game event
+ return;
+ }
+ // Paper end - Call CauldronLevelChangeEvent
world.setBlockAndUpdate(pos, Blocks.WATER_CAULDRON.defaultBlockState());
world.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_CHANGE, pos);
} else if (precipitation == Biome.Precipitation.SNOW) {
+ // Paper start - Call CauldronLevelChangeEvent
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, Blocks.POWDER_SNOW_CAULDRON.defaultBlockState(), null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL, false)) { // avoid duplicate game event
+ return;
+ }
+ // Paper end - Call CauldronLevelChangeEvent
world.setBlockAndUpdate(pos, Blocks.POWDER_SNOW_CAULDRON.defaultBlockState());
world.gameEvent((Entity) null, (Holder) GameEvent.BLOCK_CHANGE, pos);
}
@@ -62,13 +75,19 @@
if (fluid == Fluids.WATER) {
iblockdata1 = Blocks.WATER_CAULDRON.defaultBlockState();
- world.setBlockAndUpdate(pos, iblockdata1);
- world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1));
+ // Paper start - Call CauldronLevelChangeEvent; don't send level event or game event if cancelled
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { // CraftBukkit
+ return;
+ }
+ // Paper end - Call CauldronLevelChangeEvent
world.levelEvent(1047, pos, 0);
} else if (fluid == Fluids.LAVA) {
iblockdata1 = Blocks.LAVA_CAULDRON.defaultBlockState();
- world.setBlockAndUpdate(pos, iblockdata1);
- world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1));
+ // Paper start - Call CauldronLevelChangeEvent; don't send level event or game event if cancelled
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) { // CraftBukkit
+ return;
+ }
+ // Paper end - Call CauldronLevelChangeEvent
world.levelEvent(1046, pos, 0);
}

View File

@@ -1,42 +0,0 @@
--- a/net/minecraft/world/level/block/CaveVines.java
+++ b/net/minecraft/world/level/block/CaveVines.java
@@ -19,6 +19,13 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import java.util.Collections;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.event.player.PlayerHarvestBlockEvent;
+// CraftBukkit end
+
public interface CaveVines {
VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D);
@@ -26,7 +33,24 @@
static InteractionResult use(@Nullable Entity picker, BlockState state, Level world, BlockPos pos) {
if ((Boolean) state.getValue(CaveVines.BERRIES)) {
- Block.popResource(world, pos, new ItemStack(Items.GLOW_BERRIES, 1));
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(picker, pos, (BlockState) state.setValue(CaveVines.BERRIES, false))) {
+ return InteractionResult.SUCCESS;
+ }
+
+ if (picker instanceof Player) {
+ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(world, pos, (Player) picker, net.minecraft.world.InteractionHand.MAIN_HAND, Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1)));
+ if (event.isCancelled()) {
+ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block
+ }
+ for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) {
+ Block.popResource(world, pos, CraftItemStack.asNMSCopy(itemStack));
+ }
+ } else {
+ Block.popResource(world, pos, new ItemStack(Items.GLOW_BERRIES, 1));
+ }
+ // CraftBukkit end
+
float f = Mth.randomBetween(world.random, 0.8F, 1.2F);
world.playSound((Player) null, pos, SoundEvents.CAVE_VINES_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, f);

View File

@@ -1,22 +0,0 @@
--- a/net/minecraft/world/level/block/CaveVinesBlock.java
+++ b/net/minecraft/world/level/block/CaveVinesBlock.java
@@ -50,9 +50,18 @@
return to.setValue(BERRIES, from.getValue(BERRIES));
}
+ // Paper start - Fix Spigot growth modifiers
@Override
+ protected BlockState getGrowIntoState(BlockState state, RandomSource random, @javax.annotation.Nullable Level level) {
+ final boolean value = random.nextFloat() < (level != null ? (0.11F * (level.spigotConfig.glowBerryModifier / 100.0F)) : 0.11F);
+ return (BlockState) super.getGrowIntoState(state, random).setValue(CaveVinesBlock.BERRIES, value);
+ }
+ // Paper end - Fix Spigot growth modifiers
+
+ @Override
protected BlockState getGrowIntoState(BlockState state, RandomSource random) {
- return super.getGrowIntoState(state, random).setValue(BERRIES, Boolean.valueOf(random.nextFloat() < 0.11F));
+ // Paper start - Fix Spigot growth modifiers
+ return this.getGrowIntoState(state, random, null);
}
@Override

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/block/CeilingHangingSignBlock.java
+++ b/net/minecraft/world/level/block/CeilingHangingSignBlock.java
@@ -159,6 +159,6 @@
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level world, BlockState state, BlockEntityType<T> type) {
- return createTickerHelper(type, BlockEntityType.HANGING_SIGN, SignBlockEntity::tick);
+ return null; // Craftbukkit - remove unnecessary sign ticking
}
}

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/ChangeOverTimeBlock.java
+++ b/net/minecraft/world/level/block/ChangeOverTimeBlock.java
@@ -20,7 +20,7 @@
if (random.nextFloat() < 0.05688889F) {
this.getNextState(state, world, pos, random).ifPresent((iblockdata1) -> {
- world.setBlockAndUpdate(pos, iblockdata1);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, pos, iblockdata1); // CraftBukkit
});
}

View File

@@ -1,118 +0,0 @@
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -91,24 +91,7 @@
public Optional<MenuProvider> acceptDouble(final ChestBlockEntity first, final ChestBlockEntity second) {
final CompoundContainer inventorylargechest = new CompoundContainer(first, second);
- return Optional.of(new MenuProvider(this) {
- @Nullable
- @Override
- public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
- if (first.canOpen(player) && second.canOpen(player)) {
- first.unpackLootTable(playerInventory.player);
- second.unpackLootTable(playerInventory.player);
- return ChestMenu.sixRows(syncId, playerInventory, inventorylargechest);
- } else {
- return null;
- }
- }
-
- @Override
- public Component getDisplayName() {
- return (Component) (first.hasCustomName() ? first.getDisplayName() : (second.hasCustomName() ? second.getDisplayName() : Component.translatable("container.chestDouble")));
- }
- });
+ return Optional.of(new DoubleInventory(first, second, inventorylargechest)); // CraftBukkit // CraftBukkit - decompile error
}
public Optional<MenuProvider> acceptSingle(ChestBlockEntity single) {
@@ -118,8 +101,40 @@
@Override
public Optional<MenuProvider> acceptNone() {
return Optional.empty();
+ }
+ };
+
+ // CraftBukkit start
+ public static class DoubleInventory implements MenuProvider {
+
+ private final ChestBlockEntity tileentitychest;
+ private final ChestBlockEntity tileentitychest1;
+ public final CompoundContainer inventorylargechest;
+
+ public DoubleInventory(ChestBlockEntity tileentitychest, ChestBlockEntity tileentitychest1, CompoundContainer inventorylargechest) {
+ this.tileentitychest = tileentitychest;
+ this.tileentitychest1 = tileentitychest1;
+ this.inventorylargechest = inventorylargechest;
+ }
+
+ @Nullable
+ @Override
+ public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
+ if (this.tileentitychest.canOpen(player) && this.tileentitychest1.canOpen(player)) {
+ this.tileentitychest.unpackLootTable(playerInventory.player);
+ this.tileentitychest1.unpackLootTable(playerInventory.player);
+ return ChestMenu.sixRows(syncId, playerInventory, this.inventorylargechest);
+ } else {
+ return null;
+ }
}
+
+ @Override
+ public Component getDisplayName() {
+ return (Component) (this.tileentitychest.hasCustomName() ? this.tileentitychest.getDisplayName() : (this.tileentitychest1.hasCustomName() ? this.tileentitychest1.getDisplayName() : Component.translatable("container.chestDouble")));
+ }
};
+ // CraftBukkit end
@Override
public MapCodec<? extends ChestBlock> codec() {
@@ -232,8 +247,7 @@
if (world instanceof ServerLevel worldserver) {
MenuProvider itileinventory = this.getMenuProvider(state, world, pos);
- if (itileinventory != null) {
- player.openMenu(itileinventory);
+ if (itileinventory != null && player.openMenu(itileinventory).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(this.getOpenChestStat());
PiglinAi.angerNearbyPiglins(worldserver, player, true);
}
@@ -257,7 +271,7 @@
@Override
public DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> combine(BlockState state, Level world, BlockPos pos, boolean ignoreBlocked) {
- BiPredicate bipredicate;
+ BiPredicate<LevelAccessor, BlockPos> bipredicate; // CraftBukkit - decompile error
if (ignoreBlocked) {
bipredicate = (generatoraccess, blockposition1) -> {
@@ -273,9 +287,16 @@
@Nullable
@Override
public MenuProvider getMenuProvider(BlockState state, Level world, BlockPos pos) {
- return (MenuProvider) ((Optional) this.combine(state, world, pos, false).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null);
+ // CraftBukkit start
+ return this.getMenuProvider(state, world, pos, false);
}
+ @Nullable
+ public MenuProvider getMenuProvider(BlockState iblockdata, Level world, BlockPos blockposition, boolean ignoreObstructions) {
+ return (MenuProvider) ((Optional) this.combine(iblockdata, world, blockposition, ignoreObstructions).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null);
+ // CraftBukkit end
+ }
+
public static DoubleBlockCombiner.Combiner<ChestBlockEntity, Float2FloatFunction> opennessCombiner(final LidBlockEntity progress) {
return new DoubleBlockCombiner.Combiner<ChestBlockEntity, Float2FloatFunction>() {
public Float2FloatFunction acceptDouble(ChestBlockEntity first, ChestBlockEntity second) {
@@ -321,6 +342,11 @@
}
private static boolean isCatSittingOnChest(LevelAccessor world, BlockPos pos) {
+ // Paper start - Option to disable chest cat detection
+ if (world.getMinecraftWorld().paperConfig().entities.behavior.disableChestCatDetection) {
+ return false;
+ }
+ // Paper end - Option to disable chest cat detection
List<Cat> list = world.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1)));
if (!list.isEmpty()) {

View File

@@ -1,73 +0,0 @@
--- a/net/minecraft/world/level/block/ChorusFlowerBlock.java
+++ b/net/minecraft/world/level/block/ChorusFlowerBlock.java
@@ -23,6 +23,8 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+
public class ChorusFlowerBlock extends Block {
public static final MapCodec<ChorusFlowerBlock> CODEC = RecordCodecBuilder.mapCodec((instance) -> {
@@ -103,8 +105,12 @@
}
if (flag && ChorusFlowerBlock.allNeighborsEmpty(world, blockposition1, (Direction) null) && world.isEmptyBlock(pos.above(2))) {
- world.setBlock(pos, ChorusPlantBlock.getStateWithConnections(world, pos, this.plant.defaultBlockState()), 2);
- this.placeGrownFlower(world, blockposition1, i);
+ // CraftBukkit start - add event
+ if (CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i)), 2)) {
+ world.setBlock(pos, ChorusPlantBlock.getStateWithConnections(world, pos, this.plant.defaultBlockState()), 2);
+ this.placeGrownFlower(world, blockposition1, i);
+ }
+ // CraftBukkit end
} else if (i < 4) {
j = random.nextInt(4);
if (flag1) {
@@ -118,18 +124,30 @@
BlockPos blockposition2 = pos.relative(enumdirection);
if (world.isEmptyBlock(blockposition2) && world.isEmptyBlock(blockposition2.below()) && ChorusFlowerBlock.allNeighborsEmpty(world, blockposition2, enumdirection.getOpposite())) {
- this.placeGrownFlower(world, blockposition2, i + 1);
- flag2 = true;
+ // CraftBukkit start - add event
+ if (CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition2, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(i + 1)), 2)) {
+ this.placeGrownFlower(world, blockposition2, i + 1);
+ flag2 = true;
+ }
+ // CraftBukkit end
}
}
if (flag2) {
world.setBlock(pos, ChorusPlantBlock.getStateWithConnections(world, pos, this.plant.defaultBlockState()), 2);
} else {
- this.placeDeadFlower(world, pos);
+ // CraftBukkit start - add event
+ if (CraftEventFactory.handleBlockGrowEvent(world, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) {
+ this.placeDeadFlower(world, pos);
+ }
+ // CraftBukkit end
}
} else {
- this.placeDeadFlower(world, pos);
+ // CraftBukkit start - add event
+ if (CraftEventFactory.handleBlockGrowEvent(world, pos, this.defaultBlockState().setValue(ChorusFlowerBlock.AGE, Integer.valueOf(5)), 2)) {
+ this.placeDeadFlower(world, pos);
+ }
+ // CraftBukkit end
}
}
@@ -267,6 +285,11 @@
if (world instanceof ServerLevel worldserver) {
if (projectile.mayInteract(worldserver, blockposition) && projectile.mayBreak(worldserver)) {
+ // CraftBukkit
+ if (!CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
+ return;
+ }
+ // CraftBukkit end
world.destroyBlock(blockposition, true, projectile);
}
}

View File

@@ -1,34 +0,0 @@
--- a/net/minecraft/world/level/block/ChorusPlantBlock.java
+++ b/net/minecraft/world/level/block/ChorusPlantBlock.java
@@ -38,6 +38,7 @@
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return this.defaultBlockState(); // Paper - add option to disable block updates
return getStateWithConnections(ctx.getLevel(), ctx.getClickedPos(), this.defaultBlockState());
}
@@ -68,6 +69,7 @@
BlockState neighborState,
RandomSource random
) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return state; // Paper - add option to disable block updates
if (!state.canSurvive(world, pos)) {
tickView.scheduleTick(pos, this, 1);
return super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
@@ -79,6 +81,7 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return; // Paper - add option to disable block updates
if (!state.canSurvive(world, pos)) {
world.destroyBlock(pos, true);
}
@@ -86,6 +89,7 @@
@Override
protected boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return true; // Paper - add option to disable block updates
BlockState blockState = world.getBlockState(pos.below());
boolean bl = !world.getBlockState(pos.above()).isAir() && !blockState.isAir();

View File

@@ -1,33 +0,0 @@
--- a/net/minecraft/world/level/block/CocoaBlock.java
+++ b/net/minecraft/world/level/block/CocoaBlock.java
@@ -20,6 +20,7 @@
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
public class CocoaBlock extends HorizontalDirectionalBlock implements BonemealableBlock {
@@ -57,11 +58,11 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- if (world.random.nextInt(5) == 0) {
+ if (world.random.nextFloat() < (world.spigotConfig.cocoaModifier / (100.0f * 5))) { // Spigot - SPIGOT-7159: Better modifier resolution
int i = (Integer) state.getValue(CocoaBlock.AGE);
if (i < 2) {
- world.setBlock(pos, (BlockState) state.setValue(CocoaBlock.AGE, i + 1), 2);
+ CraftEventFactory.handleBlockGrowEvent(world, pos, (BlockState) state.setValue(CocoaBlock.AGE, i + 1), 2); // CraftBukkkit
}
}
@@ -131,7 +132,7 @@
@Override
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
- world.setBlock(pos, (BlockState) state.setValue(CocoaBlock.AGE, (Integer) state.getValue(CocoaBlock.AGE) + 1), 2);
+ CraftEventFactory.handleBlockGrowEvent(world, pos, (BlockState) state.setValue(CocoaBlock.AGE, (Integer) state.getValue(CocoaBlock.AGE) + 1), 2); // CraftBukkit
}
@Override

View File

@@ -1,37 +0,0 @@
--- a/net/minecraft/world/level/block/CommandBlock.java
+++ b/net/minecraft/world/level/block/CommandBlock.java
@@ -31,6 +31,8 @@
import net.minecraft.world.phys.BlockHitResult;
import org.slf4j.Logger;
+import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
+
public class CommandBlock extends BaseEntityBlock implements GameMasterBlock {
public static final MapCodec<CommandBlock> CODEC = RecordCodecBuilder.mapCodec((instance) -> {
@@ -78,7 +80,16 @@
private void setPoweredAndUpdate(Level world, BlockPos pos, CommandBlockEntity blockEntity, boolean powered) {
boolean flag1 = blockEntity.isPowered();
+ // CraftBukkit start
+ org.bukkit.block.Block bukkitBlock = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ int old = flag1 ? 15 : 0;
+ int current = powered ? 15 : 0;
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+ powered = eventRedstone.getNewCurrent() > 0;
+ // CraftBukkit end
+
if (powered != flag1) {
blockEntity.setPowered(powered);
if (powered) {
@@ -141,7 +152,7 @@
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
BlockEntity tileentity = world.getBlockEntity(pos);
- if (tileentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) {
+ if (tileentity instanceof CommandBlockEntity && (player.canUseGameMasterBlocks() || (player.isCreative() && player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission
player.openCommandBlock((CommandBlockEntity) tileentity);
return InteractionResult.SUCCESS;
} else {

View File

@@ -1,39 +0,0 @@
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -27,6 +27,7 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.ticks.TickPriority;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
public class ComparatorBlock extends DiodeBlock implements EntityBlock {
@@ -110,7 +111,8 @@
@Nullable
private ItemFrame getItemFrame(Level world, Direction facing, BlockPos pos) {
- List<ItemFrame> list = world.getEntitiesOfClass(ItemFrame.class, new AABB((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 1), (double) (pos.getZ() + 1)), (entityitemframe) -> {
+ // CraftBukkit - decompile error
+ List<ItemFrame> list = world.getEntitiesOfClass(ItemFrame.class, new AABB((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 1), (double) (pos.getZ() + 1)), (java.util.function.Predicate<ItemFrame>) (entityitemframe) -> {
return entityitemframe != null && entityitemframe.getDirection() == facing;
});
@@ -163,8 +165,18 @@
boolean flag1 = (Boolean) state.getValue(ComparatorBlock.POWERED);
if (flag1 && !flag) {
+ // CraftBukkit start
+ if (CraftEventFactory.callRedstoneChange(world, pos, 15, 0).getNewCurrent() != 0) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(ComparatorBlock.POWERED, false), 2);
} else if (!flag1 && flag) {
+ // CraftBukkit start
+ if (CraftEventFactory.callRedstoneChange(world, pos, 0, 15).getNewCurrent() != 15) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(ComparatorBlock.POWERED, true), 2);
}

View File

@@ -1,184 +0,0 @@
--- a/net/minecraft/world/level/block/ComposterBlock.java
+++ b/net/minecraft/world/level/block/ComposterBlock.java
@@ -41,6 +41,10 @@
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder;
+import org.bukkit.craftbukkit.util.DummyGeneratorAccess;
+// CraftBukkit end
public class ComposterBlock extends Block implements WorldlyContainerHolder {
@@ -241,6 +245,11 @@
if (i < 8 && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem())) {
if (i < 7 && !world.isClientSide) {
BlockState iblockdata1 = ComposterBlock.addItem(player, state, world, pos, stack);
+ // Paper start - handle cancelled events
+ if (iblockdata1 == null) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
world.levelEvent(1500, pos, state != iblockdata1 ? 1 : 0);
player.awardStat(Stats.ITEM_USED.get(stack.getItem()));
@@ -269,7 +278,19 @@
int i = (Integer) state.getValue(ComposterBlock.LEVEL);
if (i < 7 && ComposterBlock.COMPOSTABLES.containsKey(stack.getItem())) {
- BlockState iblockdata1 = ComposterBlock.addItem(user, state, world, pos, stack);
+ // CraftBukkit start
+ double rand = world.getRandom().nextDouble();
+ BlockState iblockdata1 = null; // Paper
+ if (false && (state == iblockdata1 || !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(user, pos, iblockdata1))) { // Paper - move event call into addItem
+ return state;
+ }
+ iblockdata1 = ComposterBlock.addItem(user, state, world, pos, stack, rand);
+ // Paper start - handle cancelled events
+ if (iblockdata1 == null) {
+ return state;
+ }
+ // Paper end
+ // CraftBukkit end
stack.shrink(1);
return iblockdata1;
@@ -279,6 +300,14 @@
}
public static BlockState extractProduce(Entity user, BlockState state, Level world, BlockPos pos) {
+ // CraftBukkit start
+ if (user != null && !(user instanceof Player)) {
+ BlockState iblockdata1 = ComposterBlock.empty(user, state, DummyGeneratorAccess.INSTANCE, pos);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(user, pos, iblockdata1)) {
+ return state;
+ }
+ }
+ // CraftBukkit end
if (!world.isClientSide) {
Vec3 vec3d = Vec3.atLowerCornerWithOffset(pos, 0.5D, 1.01D, 0.5D).offsetRandom(world.random, 0.7F);
ItemEntity entityitem = new ItemEntity(world, vec3d.x(), vec3d.y(), vec3d.z(), new ItemStack(Items.BONE_MEAL));
@@ -301,20 +330,47 @@
return iblockdata1;
}
+ @Nullable // Paper
static BlockState addItem(@Nullable Entity user, BlockState state, LevelAccessor world, BlockPos pos, ItemStack stack) {
- int i = (Integer) state.getValue(ComposterBlock.LEVEL);
- float f = ComposterBlock.COMPOSTABLES.getFloat(stack.getItem());
+ // CraftBukkit start
+ return ComposterBlock.addItem(user, state, world, pos, stack, world.getRandom().nextDouble());
+ }
- if ((i != 0 || f <= 0.0F) && world.getRandom().nextDouble() >= (double) f) {
- return state;
- } else {
- int j = i + 1;
- BlockState iblockdata1 = (BlockState) state.setValue(ComposterBlock.LEVEL, j);
+ @Nullable // Paper - make it nullable
+ static BlockState addItem(@Nullable Entity entity, BlockState iblockdata, LevelAccessor generatoraccess, BlockPos blockposition, ItemStack itemstack, double rand) {
+ // CraftBukkit end
+ int i = (Integer) iblockdata.getValue(ComposterBlock.LEVEL);
+ float f = ComposterBlock.COMPOSTABLES.getFloat(itemstack.getItem());
- world.setBlock(pos, iblockdata1, 3);
- world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(user, iblockdata1));
+ // Paper start - Add CompostItemEvent and EntityCompostItemEvent
+ boolean willRaiseLevel = !((i != 0 || f <= 0.0F) && rand >= (double) f);
+ final io.papermc.paper.event.block.CompostItemEvent event;
+ if (entity == null) {
+ event = new io.papermc.paper.event.block.CompostItemEvent(org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, blockposition), itemstack.getBukkitStack(), willRaiseLevel);
+ } else {
+ event = new io.papermc.paper.event.entity.EntityCompostItemEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, blockposition), itemstack.getBukkitStack(), willRaiseLevel);
+ }
+ if (!event.callEvent()) { // check for cancellation of entity event (non entity event can't be cancelled cause of hoppers)
+ return null;
+ }
+ willRaiseLevel = event.willRaiseLevel();
+
+ if (!willRaiseLevel) {
+ // Paper end - Add CompostItemEvent and EntityCompostItemEvent
+ return iblockdata;
+ } else {
+ int j = i + 1;
+ BlockState iblockdata1 = (BlockState) iblockdata.setValue(ComposterBlock.LEVEL, j);
+ // Paper start - move the EntityChangeBlockEvent here to avoid conflict later for the compost events
+ if (entity != null && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, iblockdata1)) {
+ return null;
+ }
+ // Paper end
+
+ generatoraccess.setBlock(blockposition, iblockdata1, 3);
+ generatoraccess.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, iblockdata1));
if (j == 7) {
- world.scheduleTick(pos, state.getBlock(), 20);
+ generatoraccess.scheduleTick(blockposition, iblockdata.getBlock(), 20);
}
return iblockdata1;
@@ -354,7 +410,8 @@
public WorldlyContainer getContainer(BlockState state, LevelAccessor world, BlockPos pos) {
int i = (Integer) state.getValue(ComposterBlock.LEVEL);
- return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(state, world, pos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(state, world, pos) : new ComposterBlock.EmptyContainer()));
+ // CraftBukkit - empty generatoraccess, blockposition
+ return (WorldlyContainer) (i == 8 ? new ComposterBlock.OutputContainer(state, world, pos, new ItemStack(Items.BONE_MEAL)) : (i < 7 ? new ComposterBlock.InputContainer(state, world, pos) : new ComposterBlock.EmptyContainer(world, pos)));
}
public static class OutputContainer extends SimpleContainer implements WorldlyContainer {
@@ -369,6 +426,7 @@
this.state = state;
this.level = world;
this.pos = pos;
+ this.bukkitOwner = new CraftBlockInventoryHolder(world, pos, this); // CraftBukkit
}
@Override
@@ -393,8 +451,15 @@
@Override
public void setChanged() {
+ // CraftBukkit start - allow putting items back (eg cancelled InventoryMoveItemEvent)
+ if (this.isEmpty()) {
ComposterBlock.empty((Entity) null, this.state, this.level, this.pos);
this.changed = true;
+ } else {
+ this.level.setBlock(this.pos, this.state, 3);
+ this.changed = false;
+ }
+ // CraftBukkit end
}
}
@@ -407,6 +472,7 @@
public InputContainer(BlockState state, LevelAccessor world, BlockPos pos) {
super(1);
+ this.bukkitOwner = new CraftBlockInventoryHolder(world, pos, this); // CraftBukkit
this.state = state;
this.level = world;
this.pos = pos;
@@ -439,6 +505,11 @@
if (!itemstack.isEmpty()) {
this.changed = true;
BlockState iblockdata = ComposterBlock.addItem((Entity) null, this.state, this.level, this.pos, itemstack);
+ // Paper start - Add CompostItemEvent and EntityCompostItemEvent
+ if (iblockdata == null) {
+ return;
+ }
+ // Paper end - Add CompostItemEvent and EntityCompostItemEvent
this.level.levelEvent(1500, this.pos, iblockdata != this.state ? 1 : 0);
this.removeItemNoUpdate(0);
@@ -449,8 +520,9 @@
public static class EmptyContainer extends SimpleContainer implements WorldlyContainer {
- public EmptyContainer() {
+ public EmptyContainer(LevelAccessor generatoraccess, BlockPos blockposition) { // CraftBukkit
super(0);
+ this.bukkitOwner = new CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit
}
@Override

View File

@@ -1,76 +0,0 @@
--- a/net/minecraft/world/level/block/ConcretePowderBlock.java
+++ b/net/minecraft/world/level/block/ConcretePowderBlock.java
@@ -15,6 +15,11 @@
import net.minecraft.world.level.ScheduledTickAccess;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
+// CraftBukkit start
+import org.bukkit.craftbukkit.block.CraftBlockState;
+import org.bukkit.craftbukkit.block.CraftBlockStates;
+import org.bukkit.event.block.BlockFormEvent;
+// CraftBukkit end
public class ConcretePowderBlock extends FallingBlock {
@@ -38,7 +43,7 @@
@Override
public void onLand(Level world, BlockPos pos, BlockState fallingBlockState, BlockState currentStateInPos, FallingBlockEntity fallingBlockEntity) {
if (ConcretePowderBlock.shouldSolidify(world, pos, currentStateInPos)) {
- world.setBlock(pos, this.concrete.defaultBlockState(), 3);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, pos, this.concrete.defaultBlockState(), 3); // CraftBukkit
}
}
@@ -49,7 +54,24 @@
BlockPos blockposition = ctx.getClickedPos();
BlockState iblockdata = world.getBlockState(blockposition);
- return ConcretePowderBlock.shouldSolidify(world, blockposition, iblockdata) ? this.concrete.defaultBlockState() : super.getStateForPlacement(ctx);
+ // CraftBukkit start
+ if (!ConcretePowderBlock.shouldSolidify(world, blockposition, iblockdata)) {
+ return super.getStateForPlacement(ctx);
+ }
+
+ // TODO: An event factory call for methods like this
+ CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockposition);
+ blockState.setData(this.concrete.defaultBlockState());
+
+ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState);
+ world.getServer().server.getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ return blockState.getHandle();
+ }
+
+ return super.getStateForPlacement(ctx);
+ // CraftBukkit end
}
private static boolean shouldSolidify(BlockGetter world, BlockPos pos, BlockState state) {
@@ -85,7 +107,25 @@
@Override
protected BlockState updateShape(BlockState state, LevelReader world, ScheduledTickAccess tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random) {
- return ConcretePowderBlock.touchesLiquid(world, pos) ? this.concrete.defaultBlockState() : super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
+ // CraftBukkit start
+ if (ConcretePowderBlock.touchesLiquid(world, pos)) {
+ // Suppress during worldgen
+ if (!(world instanceof Level world1)) {
+ return this.concrete.defaultBlockState();
+ }
+ CraftBlockState blockState = CraftBlockStates.getBlockState(world1, pos);
+ blockState.setData(this.concrete.defaultBlockState());
+
+ BlockFormEvent event = new BlockFormEvent(blockState.getBlock(), blockState);
+ world1.getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ return blockState.getHandle();
+ }
+ }
+
+ return super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
+ // CraftBukkit end
}
@Override

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/CoralBlock.java
+++ b/net/minecraft/world/level/block/CoralBlock.java
@@ -40,6 +40,11 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!this.scanForWater(world, pos)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, this.deadBlock.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, this.deadBlock.defaultBlockState(), 2);
}

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/CoralFanBlock.java
+++ b/net/minecraft/world/level/block/CoralFanBlock.java
@@ -41,6 +41,11 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!scanForWater(state, world, pos)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false)).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) this.deadBlock.defaultBlockState().setValue(CoralFanBlock.WATERLOGGED, false), 2);
}

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/CoralPlantBlock.java
+++ b/net/minecraft/world/level/block/CoralPlantBlock.java
@@ -46,6 +46,11 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!scanForWater(state, world, pos)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false)).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) this.deadBlock.defaultBlockState().setValue(CoralPlantBlock.WATERLOGGED, false), 2);
}

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/CoralWallFanBlock.java
+++ b/net/minecraft/world/level/block/CoralWallFanBlock.java
@@ -41,6 +41,11 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!scanForWater(state, world, pos)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false).setValue(CoralWallFanBlock.FACING, state.getValue(CoralWallFanBlock.FACING))).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) ((BlockState) this.deadBlock.defaultBlockState().setValue(CoralWallFanBlock.WATERLOGGED, false)).setValue(CoralWallFanBlock.FACING, (Direction) state.getValue(CoralWallFanBlock.FACING)), 2);
}

View File

@@ -1,89 +0,0 @@
--- a/net/minecraft/world/level/block/CrafterBlock.java
+++ b/net/minecraft/world/level/block/CrafterBlock.java
@@ -12,6 +12,7 @@
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
+import net.minecraft.world.CompoundContainer;
import net.minecraft.world.Container;
import net.minecraft.world.Containers;
import net.minecraft.world.InteractionResult;
@@ -39,6 +40,12 @@
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.event.block.CrafterCraftEvent;
+import org.bukkit.event.inventory.InventoryMoveItemEvent;
+import org.bukkit.inventory.Inventory;
+// CraftBukkit end
public class CrafterBlock extends BaseEntityBlock {
@@ -189,6 +196,13 @@
RecipeHolder<CraftingRecipe> recipeholder = (RecipeHolder) optional.get();
ItemStack itemstack = ((CraftingRecipe) recipeholder.value()).assemble(craftinginput, world.registryAccess());
+ // CraftBukkit start
+ CrafterCraftEvent event = CraftEventFactory.callCrafterCraftEvent(pos, world, crafterblockentity, itemstack, recipeholder);
+ if (event.isCancelled()) {
+ return;
+ }
+ itemstack = CraftItemStack.asNMSCopy(event.getResult());
+ // CraftBukkit end
if (itemstack.isEmpty()) {
world.levelEvent(1050, pos, 0);
} else {
@@ -227,7 +241,25 @@
ItemStack itemstack1 = stack.copy();
if (iinventory != null && (iinventory instanceof CrafterBlockEntity || stack.getCount() > iinventory.getMaxStackSize(stack))) {
+ // CraftBukkit start - InventoryMoveItemEvent
+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack1);
+
+ Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (iinventory instanceof CompoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
+ } else {
+ destinationInventory = iinventory.getOwner().getInventory();
+ }
+
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(blockEntity.getOwner().getInventory(), oitemstack, destinationInventory, true);
+ world.getCraftServer().getPluginManager().callEvent(event);
+ itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
while (!itemstack1.isEmpty()) {
+ if (event.isCancelled()) {
+ break;
+ }
+ // CraftBukkit end
ItemStack itemstack2 = itemstack1.copyWithCount(1);
ItemStack itemstack3 = HopperBlockEntity.addItem(blockEntity, iinventory, itemstack2, enumdirection.getOpposite());
@@ -238,7 +270,25 @@
itemstack1.shrink(1);
}
} else if (iinventory != null) {
+ // CraftBukkit start - InventoryMoveItemEvent
+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack1);
+
+ Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (iinventory instanceof CompoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
+ } else {
+ destinationInventory = iinventory.getOwner().getInventory();
+ }
+
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(blockEntity.getOwner().getInventory(), oitemstack, destinationInventory, true);
+ world.getCraftServer().getPluginManager().callEvent(event);
+ itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
while (!itemstack1.isEmpty()) {
+ if (event.isCancelled()) {
+ break;
+ }
+ // CraftBukkit end
int i = itemstack1.getCount();
itemstack1 = HopperBlockEntity.addItem(blockEntity, iinventory, itemstack1, enumdirection.getOpposite());

View File

@@ -1,13 +0,0 @@
--- a/net/minecraft/world/level/block/CraftingTableBlock.java
+++ b/net/minecraft/world/level/block/CraftingTableBlock.java
@@ -31,8 +31,9 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!world.isClientSide) {
- player.openMenu(state.getMenuProvider(world, pos));
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_CRAFTING_TABLE);
+ } // Paper - Fix InventoryOpenEvent cancellation
}
return InteractionResult.SUCCESS;

View File

@@ -1,59 +0,0 @@
--- a/net/minecraft/world/level/block/CropBlock.java
+++ b/net/minecraft/world/level/block/CropBlock.java
@@ -21,6 +21,7 @@
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
public class CropBlock extends BushBlock implements BonemealableBlock {
@@ -82,9 +83,26 @@
if (i < this.getMaxAge()) {
float f = CropBlock.getGrowthSpeed(this, world, pos);
- if (random.nextInt((int) (25.0F / f) + 1) == 0) {
- world.setBlock(pos, this.getStateForAge(i + 1), 2);
+ // Spigot start
+ int modifier;
+ if (this == Blocks.BEETROOTS) {
+ modifier = world.spigotConfig.beetrootModifier;
+ } else if (this == Blocks.CARROTS) {
+ modifier = world.spigotConfig.carrotModifier;
+ } else if (this == Blocks.POTATOES) {
+ modifier = world.spigotConfig.potatoModifier;
+ // Paper start - Fix Spigot growth modifiers
+ } else if (this == Blocks.TORCHFLOWER_CROP) {
+ modifier = world.spigotConfig.torchFlowerModifier;
+ // Paper end - Fix Spigot growth modifiers
+ } else {
+ modifier = world.spigotConfig.wheatModifier;
}
+
+ if (random.nextFloat() < (modifier / (100.0f * (Math.floor((25.0F / f) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ // Spigot end
+ CraftEventFactory.handleBlockGrowEvent(world, pos, this.getStateForAge(i + 1), 2); // CraftBukkit
+ }
}
}
@@ -98,7 +116,7 @@
i = j;
}
- world.setBlock(pos, this.getStateForAge(i), 2);
+ CraftEventFactory.handleBlockGrowEvent(world, pos, this.getStateForAge(i), 2); // CraftBukkit
}
protected int getBonemealAgeIncrease(Level world) {
@@ -160,8 +178,9 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (world instanceof ServerLevel worldserver) {
- if (entity instanceof Ravager && worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
+ if (entity instanceof Ravager && CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING))) { // CraftBukkit
worldserver.destroyBlock(pos, true, entity);
}
}

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/block/DaylightDetectorBlock.java
+++ b/net/minecraft/world/level/block/DaylightDetectorBlock.java
@@ -74,6 +74,7 @@
i = Mth.clamp(i, 0, 15);
if ((Integer) state.getValue(DaylightDetectorBlock.POWER) != i) {
+ i = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, pos, ((Integer) state.getValue(DaylightDetectorBlock.POWER)), i).getNewCurrent(); // CraftBukkit - Call BlockRedstoneEvent
world.setBlock(pos, (BlockState) state.setValue(DaylightDetectorBlock.POWER, i), 3);
}

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
@@ -240,6 +240,11 @@
if (world instanceof ServerLevel worldserver) {
if (projectile.mayInteract(worldserver, blockposition) && projectile.mayBreak(worldserver)) {
+ // CraftBukkit start - call EntityChangeBlockEvent
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, this.getFluidState(state).createLegacyBlock())) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(blockposition, (BlockState) state.setValue(DecoratedPotBlock.CRACKED, true), 4);
world.destroyBlock(blockposition, true, projectile);
}

View File

@@ -1,44 +0,0 @@
--- a/net/minecraft/world/level/block/DetectorRailBlock.java
+++ b/net/minecraft/world/level/block/DetectorRailBlock.java
@@ -26,6 +26,7 @@
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.level.redstone.Orientation;
import net.minecraft.world.phys.AABB;
+import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
public class DetectorRailBlock extends BaseRailBlock {
@@ -51,6 +52,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide) {
if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) {
this.checkPressed(world, pos, state);
@@ -77,6 +79,7 @@
private void checkPressed(Level world, BlockPos pos, BlockState state) {
if (this.canSurvive(state, world, pos)) {
+ if (state.getBlock() != this) { return; } // Paper - Fix some rails connecting improperly
boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED);
boolean flag1 = false;
List<AbstractMinecart> list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (entity) -> {
@@ -88,7 +91,17 @@
}
BlockState iblockdata1;
+ // CraftBukkit start
+ if (flag != flag1) {
+ org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, flag ? 15 : 0, flag1 ? 15 : 0);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ flag1 = eventRedstone.getNewCurrent() > 0;
+ }
+ // CraftBukkit end
+
if (flag1 && !flag) {
iblockdata1 = (BlockState) state.setValue(DetectorRailBlock.POWERED, true);
world.setBlock(pos, iblockdata1, 3);

View File

@@ -1,29 +0,0 @@
--- a/net/minecraft/world/level/block/DiodeBlock.java
+++ b/net/minecraft/world/level/block/DiodeBlock.java
@@ -23,6 +23,7 @@
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.ticks.TickPriority;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
public abstract class DiodeBlock extends HorizontalDirectionalBlock {
@@ -59,8 +60,18 @@
boolean flag1 = this.shouldTurnOn(world, pos, state);
if (flag && !flag1) {
+ // CraftBukkit start
+ if (CraftEventFactory.callRedstoneChange(world, pos, 15, 0).getNewCurrent() != 0) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(DiodeBlock.POWERED, false), 2);
} else if (!flag) {
+ // CraftBukkit start
+ if (CraftEventFactory.callRedstoneChange(world, pos, 0, 15).getNewCurrent() != 15) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(DiodeBlock.POWERED, true), 2);
if (!flag1) {
world.scheduleTick(pos, (Block) this, this.getDelay(state), TickPriority.VERY_HIGH);

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/DirtPathBlock.java
+++ b/net/minecraft/world/level/block/DirtPathBlock.java
@@ -51,6 +51,11 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ // CraftBukkit start - do not fade if the block is valid here
+ if (state.canSurvive(world, pos)) {
+ return;
+ }
+ // CraftBukkit end
FarmBlock.turnToDirt((Entity) null, state, world, pos);
}

View File

@@ -1,61 +0,0 @@
--- a/net/minecraft/world/level/block/DispenserBlock.java
+++ b/net/minecraft/world/level/block/DispenserBlock.java
@@ -52,6 +52,7 @@
private static final DefaultDispenseItemBehavior DEFAULT_BEHAVIOR = new DefaultDispenseItemBehavior();
public static final Map<Item, DispenseItemBehavior> DISPENSER_REGISTRY = new IdentityHashMap();
private static final int TRIGGER_DURATION = 4;
+ public static boolean eventFired = false; // CraftBukkit
@Override
public MapCodec<? extends DispenserBlock> codec() {
@@ -79,8 +80,9 @@
if (tileentity instanceof DispenserBlockEntity) {
DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) tileentity;
- player.openMenu(tileentitydispenser);
+ if (player.openMenu(tileentitydispenser).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(tileentitydispenser instanceof DropperBlockEntity ? Stats.INSPECT_DROPPER : Stats.INSPECT_DISPENSER);
+ } // Paper - Fix InventoryOpenEvent cancellation
}
}
@@ -88,7 +90,7 @@
}
public void dispenseFrom(ServerLevel world, BlockState state, BlockPos pos) {
- DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) world.getBlockEntity(pos, BlockEntityType.DISPENSER).orElse((Object) null);
+ DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) world.getBlockEntity(pos, BlockEntityType.DISPENSER).orElse(null); // CraftBukkit - decompile error
if (tileentitydispenser == null) {
DispenserBlock.LOGGER.warn("Ignoring dispensing attempt for Dispenser without matching block entity at {}", pos);
@@ -97,13 +99,17 @@
int i = tileentitydispenser.getRandomSlot(world.random);
if (i < 0) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) { // Paper - Add BlockFailedDispenseEvent
world.levelEvent(1001, pos, 0);
world.gameEvent((Holder) GameEvent.BLOCK_ACTIVATE, pos, GameEvent.Context.of(tileentitydispenser.getBlockState()));
+ } // Paper - Add BlockFailedDispenseEvent
} else {
ItemStack itemstack = tileentitydispenser.getItem(i);
DispenseItemBehavior idispensebehavior = this.getDispenseMethod(world, itemstack);
if (idispensebehavior != DispenseItemBehavior.NOOP) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - Add BlockPreDispenseEvent
+ DispenserBlock.eventFired = false; // CraftBukkit - reset event status
tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack));
}
@@ -111,6 +117,12 @@
}
}
+ // Paper start - Fix NPE with equippable and items without behavior
+ public static DispenseItemBehavior getDispenseBehavior(BlockSource pointer, ItemStack stack) {
+ return ((DispenserBlock) pointer.state().getBlock()).getDispenseMethod(pointer.level(), stack);
+ }
+ // Paper end - Fix NPE with equippable and items without behavior
+
protected DispenseItemBehavior getDispenseMethod(Level world, ItemStack stack) {
if (!stack.isItemEnabled(world.enabledFeatures())) {
return DispenserBlock.DEFAULT_BEHAVIOR;

View File

@@ -1,37 +0,0 @@
--- a/net/minecraft/world/level/block/DoorBlock.java
+++ b/net/minecraft/world/level/block/DoorBlock.java
@@ -38,6 +38,7 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
public class DoorBlock extends Block {
@@ -222,9 +223,24 @@
@Override
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, @Nullable Orientation wireOrientation, boolean notify) {
- boolean flag1 = world.hasNeighborSignal(pos) || world.hasNeighborSignal(pos.relative(state.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN));
+ // CraftBukkit start
+ BlockPos otherHalf = pos.relative(state.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN);
- if (!this.defaultBlockState().is(sourceBlock) && flag1 != (Boolean) state.getValue(DoorBlock.POWERED)) {
+ org.bukkit.World bworld = world.getWorld();
+ org.bukkit.block.Block bukkitBlock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block blockTop = bworld.getBlockAt(otherHalf.getX(), otherHalf.getY(), otherHalf.getZ());
+
+ int power = bukkitBlock.getBlockPower();
+ int powerTop = blockTop.getBlockPower();
+ if (powerTop > power) power = powerTop;
+ int oldPower = (Boolean) state.getValue(DoorBlock.POWERED) ? 15 : 0;
+
+ if (oldPower == 0 ^ power == 0) {
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, oldPower, power);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ boolean flag1 = eventRedstone.getNewCurrent() > 0;
+ // CraftBukkit end
if (flag1 != (Boolean) state.getValue(DoorBlock.OPEN)) {
this.playSound((Entity) null, world, pos, flag1);
world.gameEvent((Entity) null, (Holder) (flag1 ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE), pos);

View File

@@ -1,16 +0,0 @@
--- a/net/minecraft/world/level/block/DoubleBlockCombiner.java
+++ b/net/minecraft/world/level/block/DoubleBlockCombiner.java
@@ -34,7 +34,12 @@
return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity);
} else {
BlockPos blockPos = pos.relative(directionMapper.apply(state));
- BlockState blockState = world.getBlockState(blockPos);
+ // Paper start - Don't load Chunks from Hoppers and other things
+ BlockState blockState = world.getBlockStateIfLoaded(blockPos);
+ if (blockState == null) {
+ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity);
+ }
+ // Paper end - Don't load Chunks from Hoppers and other things
if (blockState.is(state.getBlock())) {
DoubleBlockCombiner.BlockType blockType2 = typeMapper.apply(blockState);
if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE

View File

@@ -1,21 +0,0 @@
--- a/net/minecraft/world/level/block/DoublePlantBlock.java
+++ b/net/minecraft/world/level/block/DoublePlantBlock.java
@@ -98,11 +98,16 @@
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
}
protected static void preventDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) {
+ // CraftBukkit start
+ if (((net.minecraft.server.level.ServerLevel)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper
+ return;
+ }
+ // CraftBukkit end
DoubleBlockHalf blockpropertydoubleblockhalf = (DoubleBlockHalf) state.getValue(DoublePlantBlock.HALF);
if (blockpropertydoubleblockhalf == DoubleBlockHalf.UPPER) {

View File

@@ -1,29 +0,0 @@
--- a/net/minecraft/world/level/block/DragonEggBlock.java
+++ b/net/minecraft/world/level/block/DragonEggBlock.java
@@ -15,6 +15,7 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.block.BlockFromToEvent; // CraftBukkit
public class DragonEggBlock extends FallingBlock {
@@ -53,6 +54,18 @@
BlockPos blockposition1 = pos.offset(world.random.nextInt(16) - world.random.nextInt(16), world.random.nextInt(8) - world.random.nextInt(8), world.random.nextInt(16) - world.random.nextInt(16));
if (world.getBlockState(blockposition1).isAir() && worldborder.isWithinBounds(blockposition1)) {
+ // CraftBukkit start
+ org.bukkit.block.Block from = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ org.bukkit.block.Block to = world.getWorld().getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ());
+ BlockFromToEvent event = new BlockFromToEvent(from, to);
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return;
+ }
+
+ blockposition1 = new BlockPos(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ());
+ // CraftBukkit end
if (world.isClientSide) {
for (int j = 0; j < 128; ++j) {
double d0 = world.random.nextDouble();

View File

@@ -1,21 +0,0 @@
--- a/net/minecraft/world/level/block/DropExperienceBlock.java
+++ b/net/minecraft/world/level/block/DropExperienceBlock.java
@@ -31,9 +31,16 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) {
super.spawnAfterBreak(state, world, pos, tool, dropExperience);
- if (dropExperience) {
- this.tryDropExperience(world, pos, tool, this.xpRange);
+ // CraftBukkit start - Delegate to getExpDrop
+ }
+
+ @Override
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+ if (flag) {
+ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange);
}
+ return 0;
+ // CraftBukkit end
}
}

View File

@@ -1,75 +0,0 @@
--- a/net/minecraft/world/level/block/DropperBlock.java
+++ b/net/minecraft/world/level/block/DropperBlock.java
@@ -8,6 +8,7 @@
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.server.level.ServerLevel;
+import net.minecraft.world.CompoundContainer;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@@ -19,12 +20,15 @@
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.event.inventory.InventoryMoveItemEvent;
+// CraftBukkit end
public class DropperBlock extends DispenserBlock {
private static final Logger LOGGER = LogUtils.getLogger();
public static final MapCodec<DropperBlock> CODEC = simpleCodec(DropperBlock::new);
- private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior();
+ private static final DispenseItemBehavior DISPENSE_BEHAVIOUR = new DefaultDispenseItemBehavior(true); // CraftBukkit
@Override
public MapCodec<DropperBlock> codec() {
@@ -47,7 +51,7 @@
@Override
public void dispenseFrom(ServerLevel world, BlockState state, BlockPos pos) {
- DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) world.getBlockEntity(pos, BlockEntityType.DROPPER).orElse((Object) null);
+ DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) world.getBlockEntity(pos, BlockEntityType.DROPPER).orElse(null); // CraftBukkit - decompile error
if (tileentitydispenser == null) {
DropperBlock.LOGGER.warn("Ignoring dispensing attempt for Dropper without matching block entity at {}", pos);
@@ -56,6 +60,7 @@
int i = tileentitydispenser.getRandomSlot(world.random);
if (i < 0) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) // Paper - Add BlockFailedDispenseEvent
world.levelEvent(1001, pos, 0);
} else {
ItemStack itemstack = tileentitydispenser.getItem(i);
@@ -66,10 +71,28 @@
ItemStack itemstack1;
if (iinventory == null) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - Add BlockPreDispenseEvent
itemstack1 = DropperBlock.DISPENSE_BEHAVIOUR.dispense(sourceblock, itemstack);
} else {
- itemstack1 = HopperBlockEntity.addItem(tileentitydispenser, iinventory, itemstack.copyWithCount(1), enumdirection.getOpposite());
- if (itemstack1.isEmpty()) {
+ // CraftBukkit start - Fire event when pushing items into other inventories
+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(itemstack.copyWithCount(1));
+
+ org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly
+ if (iinventory instanceof CompoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
+ } else {
+ destinationInventory = iinventory.getOwner().getInventory();
+ }
+
+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentitydispenser.getOwner().getInventory(), oitemstack, destinationInventory, true);
+ world.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return;
+ }
+ itemstack1 = HopperBlockEntity.addItem(tileentitydispenser, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection.getOpposite());
+ if (event.getItem().equals(oitemstack) && itemstack1.isEmpty()) {
+ // CraftBukkit end
itemstack1 = itemstack.copy();
itemstack1.shrink(1);
} else {

View File

@@ -1,34 +0,0 @@
--- a/net/minecraft/world/level/block/EndGatewayBlock.java
+++ b/net/minecraft/world/level/block/EndGatewayBlock.java
@@ -22,6 +22,9 @@
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.event.player.PlayerTeleportEvent;
+// CraftBukkit end
public class EndGatewayBlock extends BaseEntityBlock implements Portal {
@@ -89,7 +92,12 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
+ // Paper start - call EntityPortalEnterEvent
+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.END_GATEWAY); // Paper - add portal type
+ if (!event.callEvent()) return;
+ // Paper end - call EntityPortalEnterEvent
BlockEntity tileentity = world.getBlockEntity(pos);
if (!world.isClientSide && tileentity instanceof TheEndGatewayBlockEntity) {
@@ -112,7 +120,7 @@
if (tileentity instanceof TheEndGatewayBlockEntity tileentityendgateway) {
Vec3 vec3d = tileentityendgateway.getPortalPosition(world, pos);
- return vec3d == null ? null : (entity instanceof ThrownEnderpearl ? new TeleportTransition(world, vec3d, Vec3.ZERO, 0.0F, 0.0F, Set.of(), TeleportTransition.PLACE_PORTAL_TICKET) : new TeleportTransition(world, vec3d, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), TeleportTransition.PLACE_PORTAL_TICKET));
+ return vec3d == null ? null : (entity instanceof ThrownEnderpearl ? new TeleportTransition(world, vec3d, Vec3.ZERO, 0.0F, 0.0F, Set.of(), TeleportTransition.PLACE_PORTAL_TICKET, PlayerTeleportEvent.TeleportCause.END_GATEWAY) : new TeleportTransition(world, vec3d, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), TeleportTransition.PLACE_PORTAL_TICKET, PlayerTeleportEvent.TeleportCause.END_GATEWAY)); // CraftBukkit
} else {
return null;
}

View File

@@ -1,91 +0,0 @@
--- a/net/minecraft/world/level/block/EndPortalBlock.java
+++ b/net/minecraft/world/level/block/EndPortalBlock.java
@@ -19,12 +19,23 @@
import net.minecraft.world.level.block.entity.TheEndPortalBlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.feature.EndPlatformFeature;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import java.util.List;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.CraftWorld;
+import org.bukkit.craftbukkit.event.CraftPortalEvent;
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.event.entity.EntityPortalEnterEvent;
+import org.bukkit.event.player.PlayerRespawnEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+// CraftBukkit end
public class EndPortalBlock extends BaseEntityBlock implements Portal {
@@ -57,10 +68,17 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
+ // CraftBukkit start - Entity in portal
+ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.ENDER); // Paper - add portal type
+ world.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) return; // Paper - make cancellable
+ // CraftBukkit end
if (!world.isClientSide && world.dimension() == Level.END && entity instanceof ServerPlayer) {
ServerPlayer entityplayer = (ServerPlayer) entity;
+ if (world.paperConfig().misc.disableEndCredits) entityplayer.seenCredits = true; // Paper - Option to disable end credits
if (!entityplayer.seenCredits) {
entityplayer.showEndCredits();
return;
@@ -74,11 +92,11 @@
@Override
public TeleportTransition getPortalDestination(ServerLevel world, Entity entity, BlockPos pos) {
- ResourceKey<Level> resourcekey = world.dimension() == Level.END ? Level.OVERWORLD : Level.END;
+ ResourceKey<Level> resourcekey = world.getTypeKey() == LevelStem.END ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends
ServerLevel worldserver1 = world.getServer().getLevel(resourcekey);
if (worldserver1 == null) {
- return null;
+ return null; // Paper - keep previous behavior of not firing PlayerTeleportEvent if the target world doesn't exist
} else {
boolean flag = resourcekey == Level.END;
BlockPos blockposition1 = flag ? ServerLevel.END_SPAWN_POINT : worldserver1.getSharedSpawnPos();
@@ -87,7 +105,7 @@
Set set;
if (flag) {
- EndPlatformFeature.createEndPlatform(worldserver1, BlockPos.containing(vec3d).below(), true);
+ EndPlatformFeature.createEndPlatform(worldserver1, BlockPos.containing(vec3d).below(), true, entity); // CraftBukkit
f = Direction.WEST.toYRot();
set = Relative.union(Relative.DELTA, Set.of(Relative.X_ROT));
if (entity instanceof ServerPlayer) {
@@ -99,13 +117,21 @@
if (entity instanceof ServerPlayer) {
ServerPlayer entityplayer = (ServerPlayer) entity;
- return entityplayer.findRespawnPositionAndUseSpawnBlock(false, TeleportTransition.DO_NOTHING);
+ return entityplayer.findRespawnPositionAndUseSpawnBlock(false, TeleportTransition.DO_NOTHING, PlayerRespawnEvent.RespawnReason.END_PORTAL); // CraftBukkit
}
vec3d = entity.adjustSpawnLocation(worldserver1, blockposition1).getBottomCenter();
}
- return new TeleportTransition(worldserver1, vec3d, Vec3.ZERO, f, 0.0F, set, TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET));
+ // CraftBukkit start
+ CraftPortalEvent event = entity.callPortalEvent(entity, CraftLocation.toBukkit(vec3d, worldserver1.getWorld(), f, entity.getXRot()), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0);
+ if (event == null) {
+ return null;
+ }
+ Location to = event.getTo();
+
+ return new TeleportTransition(((CraftWorld) to.getWorld()).getHandle(), CraftLocation.toVec3D(to), entity.getDeltaMovement(), to.getYaw(), to.getPitch(), set, TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET), PlayerTeleportEvent.TeleportCause.END_PORTAL);
+ // CraftBukkit end
}
}

View File

@@ -1,25 +0,0 @@
--- a/net/minecraft/world/level/block/EnderChestBlock.java
+++ b/net/minecraft/world/level/block/EnderChestBlock.java
@@ -78,14 +78,16 @@
PlayerEnderChestContainer playerEnderChestContainer = player.getEnderChestInventory();
if (playerEnderChestContainer != null && world.getBlockEntity(pos) instanceof EnderChestBlockEntity enderChestBlockEntity) {
BlockPos blockPos = pos.above();
- if (world.getBlockState(blockPos).isRedstoneConductor(world, blockPos)) {
+ if (world.getBlockState(blockPos).isRedstoneConductor(world, blockPos)) { // Paper - diff on change; make sure that EnderChest#isBlocked uses the same logic
return InteractionResult.SUCCESS;
} else {
- if (world instanceof ServerLevel serverLevel) {
- playerEnderChestContainer.setActiveChest(enderChestBlockEntity);
- player.openMenu(
- new SimpleMenuProvider((i, inventory, playerx) -> ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE)
- );
+ // Paper start - Fix InventoryOpenEvent cancellation - moved up;
+ playerEnderChestContainer.setActiveChest(enderChestBlockEntity); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
+ if (world instanceof ServerLevel serverLevel && player.openMenu(
+ new SimpleMenuProvider((i, inventory, playerx) -> ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE)
+ ).isPresent()) {
+ // Paper end - Fix InventoryOpenEvent cancellation - moved up;
+ // Paper - Fix InventoryOpenEvent cancellation - moved up;
player.awardStat(Stats.OPEN_ENDERCHEST);
PiglinAi.angerNearbyPiglins(serverLevel, player, true);
}

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/block/EyeblossomBlock.java
+++ b/net/minecraft/world/level/block/EyeblossomBlock.java
@@ -100,6 +100,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide()
&& world.getDifficulty() != Difficulty.PEACEFUL
&& entity instanceof Bee bee

View File

@@ -1,112 +0,0 @@
--- a/net/minecraft/world/level/block/FarmBlock.java
+++ b/net/minecraft/world/level/block/FarmBlock.java
@@ -29,6 +29,10 @@
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.event.entity.EntityInteractEvent;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
public class FarmBlock extends Block {
@@ -89,31 +93,56 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
int i = (Integer) state.getValue(FarmBlock.MOISTURE);
+ if (i > 0 && world.paperConfig().tickRates.wetFarmland != 1 && (world.paperConfig().tickRates.wetFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.wetFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks
+ if (i == 0 && world.paperConfig().tickRates.dryFarmland != 1 && (world.paperConfig().tickRates.dryFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.dryFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks
if (!FarmBlock.isNearWater(world, pos) && !world.isRainingAt(pos.above())) {
if (i > 0) {
- world.setBlock(pos, (BlockState) state.setValue(FarmBlock.MOISTURE, i - 1), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(world, pos, (BlockState) state.setValue(FarmBlock.MOISTURE, i - 1), 2); // CraftBukkit
} else if (!FarmBlock.shouldMaintainFarmland(world, pos)) {
FarmBlock.turnToDirt((Entity) null, state, world, pos);
}
} else if (i < 7) {
- world.setBlock(pos, (BlockState) state.setValue(FarmBlock.MOISTURE, 7), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleMoistureChangeEvent(world, pos, (BlockState) state.setValue(FarmBlock.MOISTURE, 7), 2); // CraftBukkit
}
}
@Override
public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
+ super.fallOn(world, state, pos, entity, fallDistance); // CraftBukkit - moved here as game rules / events shouldn't affect fall damage.
if (world instanceof ServerLevel worldserver) {
if (world.random.nextFloat() < fallDistance - 0.5F && entity instanceof LivingEntity && (entity instanceof Player || worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && entity.getBbWidth() * entity.getBbWidth() * entity.getBbHeight() > 0.512F) {
+ // CraftBukkit start - Interact soil
+ org.bukkit.event.Cancellable cancellable;
+ if (entity instanceof Player) {
+ cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else {
+ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ world.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable);
+ }
+
+ if (cancellable.isCancelled()) {
+ return;
+ }
+
+ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.DIRT.defaultBlockState())) {
+ return;
+ }
+ // CraftBukkit end
FarmBlock.turnToDirt(entity, state, world, pos);
}
}
- super.fallOn(world, state, pos, entity, fallDistance);
+ // super.fallOn(world, iblockdata, blockposition, entity, f); // CraftBukkit - moved up
}
public static void turnToDirt(@Nullable Entity entity, BlockState state, Level world, BlockPos pos) {
+ // CraftBukkit start
+ if (CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
BlockState iblockdata1 = pushEntitiesUp(state, Blocks.DIRT.defaultBlockState(), world, pos);
world.setBlockAndUpdate(pos, iblockdata1);
@@ -125,19 +154,28 @@
}
private static boolean isNearWater(LevelReader world, BlockPos pos) {
- Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 1, 4)).iterator();
+ // Paper start - Perf: remove abstract block iteration
+ int xOff = pos.getX();
+ int yOff = pos.getY();
+ int zOff = pos.getZ();
- BlockPos blockposition1;
-
- do {
- if (!iterator.hasNext()) {
- return false;
+ for (int dz = -4; dz <= 4; ++dz) {
+ int z = dz + zOff;
+ for (int dx = -4; dx <= 4; ++dx) {
+ int x = xOff + dx;
+ for (int dy = 0; dy <= 1; ++dy) {
+ int y = dy + yOff;
+ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)world.getChunk(x >> 4, z >> 4);
+ net.minecraft.world.level.material.FluidState fluid = chunk.getBlockStateFinal(x, y, z).getFluidState();
+ if (fluid.is(FluidTags.WATER)) {
+ return true;
+ }
+ }
}
+ }
- blockposition1 = (BlockPos) iterator.next();
- } while (!world.getFluidState(blockposition1).is(FluidTags.WATER));
-
- return true;
+ return false;
+ // Paper end - Perf: remove abstract block iteration
}
@Override

View File

@@ -1,20 +0,0 @@
--- a/net/minecraft/world/level/block/FenceGateBlock.java
+++ b/net/minecraft/world/level/block/FenceGateBlock.java
@@ -173,6 +173,17 @@
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, @Nullable Orientation wireOrientation, boolean notify) {
if (!world.isClientSide) {
boolean flag1 = world.hasNeighborSignal(pos);
+ // CraftBukkit start
+ boolean oldPowered = state.getValue(FenceGateBlock.POWERED);
+ if (oldPowered != flag1) {
+ int newPower = flag1 ? 15 : 0;
+ int oldPower = oldPowered ? 15 : 0;
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bukkitBlock, oldPower, newPower);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+ flag1 = eventRedstone.getNewCurrent() > 0;
+ }
+ // CraftBukkit end
if ((Boolean) state.getValue(FenceGateBlock.POWERED) != flag1) {
world.setBlock(pos, (BlockState) ((BlockState) state.setValue(FenceGateBlock.POWERED, flag1)).setValue(FenceGateBlock.OPEN, flag1), 2);

View File

@@ -1,205 +0,0 @@
--- a/net/minecraft/world/level/block/FireBlock.java
+++ b/net/minecraft/world/level/block/FireBlock.java
@@ -14,6 +14,7 @@
import net.minecraft.tags.BiomeTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.context.BlockPlaceContext;
+import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
@@ -28,6 +29,12 @@
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
+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 FireBlock extends BaseFireBlock {
@@ -100,7 +107,25 @@
@Override
protected BlockState updateShape(BlockState state, LevelReader world, ScheduledTickAccess tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random) {
- return this.canSurvive(state, world, pos) ? this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState();
+ // CraftBukkit start
+ if (!(world instanceof ServerLevel)) return this.canSurvive(state, world, pos) ? (BlockState) this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); // Paper - don't fire events in world generation
+ if (!this.canSurvive(state, world, pos)) {
+ // Suppress during worldgen
+ if (!(world instanceof Level world1)) {
+ return Blocks.AIR.defaultBlockState();
+ }
+ CraftBlockState blockState = CraftBlockStates.getBlockState(world1, pos);
+ blockState.setData(Blocks.AIR.defaultBlockState());
+
+ BlockFadeEvent event = new BlockFadeEvent(blockState.getBlock(), blockState);
+ world1.getCraftServer().getPluginManager().callEvent(event);
+
+ if (!event.isCancelled()) {
+ return blockState.getHandle();
+ }
+ }
+ return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); // Paper - don't fire events in world generation; diff on change, see "don't fire events in world generation"
+ // CraftBukkit end
}
@Override
@@ -146,10 +171,10 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world.random));
+ world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world)); // Paper - Add fire-tick-delay option
if (world.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
if (!state.canSurvive(world, pos)) {
- world.removeBlock(pos, false);
+ this.fireExtinguished(world, pos); // CraftBukkit - invalid place location
}
BlockState iblockdata1 = world.getBlockState(pos.below());
@@ -157,7 +182,7 @@
int i = (Integer) state.getValue(FireBlock.AGE);
if (!flag && world.isRaining() && this.isNearRain(world, pos) && random.nextFloat() < 0.2F + (float) i * 0.03F) {
- world.removeBlock(pos, false);
+ this.fireExtinguished(world, pos); // CraftBukkit - extinguished by rain
} else {
int j = Math.min(15, i + random.nextInt(3) / 2);
@@ -171,14 +196,14 @@
BlockPos blockposition1 = pos.below();
if (!world.getBlockState(blockposition1).isFaceSturdy(world, blockposition1, Direction.UP) || i > 3) {
- world.removeBlock(pos, false);
+ this.fireExtinguished(world, pos); // CraftBukkit
}
return;
}
if (i == 15 && random.nextInt(4) == 0 && !this.canBurn(world.getBlockState(pos.below()))) {
- world.removeBlock(pos, false);
+ this.fireExtinguished(world, pos); // CraftBukkit
return;
}
}
@@ -186,12 +211,14 @@
boolean flag1 = world.getBiome(pos).is(BiomeTags.INCREASED_FIRE_BURNOUT);
int k = flag1 ? -50 : 0;
- this.checkBurnOut(world, pos.east(), 300 + k, random, i);
- this.checkBurnOut(world, pos.west(), 300 + k, random, i);
- this.checkBurnOut(world, pos.below(), 250 + k, random, i);
- this.checkBurnOut(world, pos.above(), 250 + k, random, i);
- this.checkBurnOut(world, pos.north(), 300 + k, random, i);
- this.checkBurnOut(world, pos.south(), 300 + k, random, i);
+ // CraftBukkit start - add source blockposition to burn calls
+ this.trySpread(world, pos.east(), 300 + k, random, i, pos);
+ this.trySpread(world, pos.west(), 300 + k, random, i, pos);
+ this.trySpread(world, pos.below(), 250 + k, random, i, pos);
+ this.trySpread(world, pos.above(), 250 + k, random, i, pos);
+ this.trySpread(world, pos.north(), 300 + k, random, i, pos);
+ this.trySpread(world, pos.south(), 300 + k, random, i, pos);
+ // CraftBukkit end
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
for (int l = -1; l <= 1; ++l) {
@@ -217,7 +244,15 @@
if (i2 > 0 && random.nextInt(k1) <= i2 && (!world.isRaining() || !this.isNearRain(world, blockposition_mutableblockposition))) {
int j2 = Math.min(15, i + random.nextInt(5) / 4);
- world.setBlock(blockposition_mutableblockposition, this.getStateWithAge(world, blockposition_mutableblockposition, j2), 3);
+ // CraftBukkit start - Call to stop spread of fire
+ if (world.getBlockState(blockposition_mutableblockposition).getBlock() != Blocks.FIRE) {
+ if (CraftEventFactory.callBlockIgniteEvent(world, blockposition_mutableblockposition, pos).isCancelled()) {
+ continue;
+ }
+
+ CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition_mutableblockposition, this.getStateWithAge(world, blockposition_mutableblockposition, j2), 3); // CraftBukkit
+ }
+ // CraftBukkit end
}
}
}
@@ -241,24 +276,47 @@
return state.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) state.getValue(BlockStateProperties.WATERLOGGED) ? 0 : this.igniteOdds.getInt(state.getBlock());
}
- private void checkBurnOut(Level world, BlockPos pos, int spreadFactor, RandomSource random, int currentAge) {
- int k = this.getBurnOdds(world.getBlockState(pos));
+ private void trySpread(Level world, BlockPos blockposition, int i, RandomSource randomsource, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition
+ int k = this.getBurnOdds(world.getBlockState(blockposition));
- if (random.nextInt(spreadFactor) < k) {
- BlockState iblockdata = world.getBlockState(pos);
+ if (randomsource.nextInt(i) < k) {
+ BlockState iblockdata = world.getBlockState(blockposition);
- if (random.nextInt(currentAge + 10) < 5 && !world.isRainingAt(pos)) {
- int l = Math.min(currentAge + random.nextInt(5) / 4, 15);
+ // 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());
- world.setBlock(pos, this.getStateWithAge(world, pos, l), 3);
+ BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock);
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return;
+ }
+
+ if (iblockdata.getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(world, blockposition, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.FIRE, null, sourceposition)) {
+ return;
+ }
+ // CraftBukkit end
+
+ if (randomsource.nextInt(j + 10) < 5 && !world.isRainingAt(blockposition)) {
+ int l = Math.min(j + randomsource.nextInt(5) / 4, 15);
+
+ world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3);
} else {
- world.removeBlock(pos, false);
+ if(iblockdata.getBlock() != Blocks.TNT) world.removeBlock(blockposition, false); // Paper - TNTPrimeEvent; We might be cancelling it below, move the setAir down
}
Block block = iblockdata.getBlock();
if (block instanceof TntBlock) {
- TntBlock.explode(world, pos);
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) {
+ return;
+ }
+ world.removeBlock(blockposition, false);
+ // Paper end - TNTPrimeEvent
+ TntBlock.explode(world, blockposition);
}
}
@@ -310,13 +368,15 @@
}
@Override
- protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
- super.onPlace(state, world, pos, oldState, notify);
- world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world.random));
+ // CraftBukkit start - context
+ protected void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext context) {
+ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, context);
+ // CraftBukkit end
+ world.scheduleTick(blockposition, (Block) this, FireBlock.getFireTickDelay(world)); // Paper - Add fire-tick-delay option
}
- private static int getFireTickDelay(RandomSource random) {
- return 30 + random.nextInt(10);
+ private static int getFireTickDelay(Level world) { // Paper - Add fire-tick-delay option
+ return world.paperConfig().environment.fireTickDelay + world.random.nextInt(10); // Paper - Add fire-tick-delay option
}
@Override

View File

@@ -1,40 +0,0 @@
--- a/net/minecraft/world/level/block/FlowerPotBlock.java
+++ b/net/minecraft/world/level/block/FlowerPotBlock.java
@@ -63,6 +63,18 @@
} else if (!this.isEmpty()) {
return InteractionResult.CONSUME;
} else {
+ // Paper start - Add PlayerFlowerPotManipulateEvent
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ org.bukkit.inventory.ItemStack placedStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack);
+
+ io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent event = new io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent((org.bukkit.entity.Player) player.getBukkitEntity(), block, placedStack, true);
+ if (!event.callEvent()) {
+ // Update client
+ player.containerMenu.sendAllDataToRemote();
+
+ return InteractionResult.CONSUME;
+ }
+ // Paper end - Add PlayerFlowerPotManipulateEvent
world.setBlock(pos, blockState, 3);
world.gameEvent(player, GameEvent.BLOCK_CHANGE, pos);
player.awardStat(Stats.POT_FLOWER);
@@ -77,6 +89,18 @@
return InteractionResult.CONSUME;
} else {
ItemStack itemStack = new ItemStack(this.potted);
+ // Paper start - Add PlayerFlowerPotManipulateEvent
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ org.bukkit.inventory.ItemStack pottedStack = new org.bukkit.inventory.ItemStack(org.bukkit.craftbukkit.block.CraftBlockType.minecraftToBukkit(this.potted));
+
+ io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent event = new io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent((org.bukkit.entity.Player) player.getBukkitEntity(), block, pottedStack, false);
+ if (!event.callEvent()) {
+ // Update client
+ player.containerMenu.sendAllDataToRemote();
+
+ return InteractionResult.PASS;
+ }
+ // Paper end - Add PlayerFlowerPotManipulateEvent
if (!player.addItem(itemStack)) {
player.drop(itemStack, false);
}

View File

@@ -1,31 +0,0 @@
--- a/net/minecraft/world/level/block/FrogspawnBlock.java
+++ b/net/minecraft/world/level/block/FrogspawnBlock.java
@@ -89,6 +89,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.getType().equals(EntityType.FALLING_BLOCK)) {
this.destroyBlock(world, pos);
}
@@ -101,6 +102,11 @@
}
private void hatchFrogspawn(ServerLevel world, BlockPos pos, RandomSource random) {
+ // Paper start - Call BlockFadeEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.AIR.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // Paper end - Call BlockFadeEvent
this.destroyBlock(world, pos);
world.playSound(null, pos, SoundEvents.FROGSPAWN_HATCH, SoundSource.BLOCKS, 1.0F, 1.0F);
this.spawnTadpoles(world, pos, random);
@@ -121,7 +127,7 @@
int k = random.nextInt(1, 361);
tadpole.moveTo(d, (double)pos.getY() - 0.5, e, (float)k, 0.0F);
tadpole.setPersistenceRequired();
- world.addFreshEntity(tadpole);
+ world.addFreshEntity(tadpole, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason
}
}
}

View File

@@ -1,24 +0,0 @@
--- a/net/minecraft/world/level/block/FrostedIceBlock.java
+++ b/net/minecraft/world/level/block/FrostedIceBlock.java
@@ -42,6 +42,7 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (!world.paperConfig().environment.frostedIce.enabled) return; // Paper - Frosted ice options
if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4))
&& world.getMaxLocalRawBrightness(pos) > 11 - state.getValue(AGE) - state.getLightBlock()
&& this.slightlyMelt(state, world, pos)) {
@@ -51,11 +52,11 @@
mutableBlockPos.setWithOffset(pos, direction);
BlockState blockState = world.getBlockState(mutableBlockPos);
if (blockState.is(this) && !this.slightlyMelt(blockState, world, mutableBlockPos)) {
- world.scheduleTick(mutableBlockPos, this, Mth.nextInt(random, 20, 40));
+ world.scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig().environment.frostedIce.delay.min, world.paperConfig().environment.frostedIce.delay.max)); // Paper - Frosted ice options
}
}
} else {
- world.scheduleTick(pos, this, Mth.nextInt(random, 20, 40));
+ world.scheduleTick(pos, this, Mth.nextInt(random, world.paperConfig().environment.frostedIce.delay.min, world.paperConfig().environment.frostedIce.delay.max)); // Paper - Frosted ice options
}
}

View File

@@ -1,16 +0,0 @@
--- a/net/minecraft/world/level/block/FungusBlock.java
+++ b/net/minecraft/world/level/block/FungusBlock.java
@@ -74,6 +74,13 @@
@Override
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
this.getFeature(world).ifPresent((holder) -> {
+ // CraftBukkit start
+ if (this == Blocks.WARPED_FUNGUS) {
+ SaplingBlock.treeType = org.bukkit.TreeType.WARPED_FUNGUS;
+ } else if (this == Blocks.CRIMSON_FUNGUS) {
+ SaplingBlock.treeType = org.bukkit.TreeType.CRIMSON_FUNGUS;
+ }
+ // CraftBukkit end
((ConfiguredFeature) holder.value()).place(world, world.getChunkSource().getGenerator(), random, pos);
});
}

View File

@@ -1,12 +0,0 @@
--- a/net/minecraft/world/level/block/FurnaceBlock.java
+++ b/net/minecraft/world/level/block/FurnaceBlock.java
@@ -45,8 +45,7 @@
@Override
protected void openContainer(Level world, BlockPos pos, Player player) {
BlockEntity blockEntity = world.getBlockEntity(pos);
- if (blockEntity instanceof FurnaceBlockEntity) {
- player.openMenu((MenuProvider)blockEntity);
+ if (blockEntity instanceof FurnaceBlockEntity && player.openMenu((MenuProvider)blockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_FURNACE);
}
}

View File

@@ -1,13 +0,0 @@
--- a/net/minecraft/world/level/block/GrindstoneBlock.java
+++ b/net/minecraft/world/level/block/GrindstoneBlock.java
@@ -152,8 +152,9 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!world.isClientSide) {
- player.openMenu(state.getMenuProvider(world, pos));
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_GRINDSTONE);
+ } // Paper - Fix InventoryOpenEvent cancellation
}
return InteractionResult.SUCCESS;

View File

@@ -1,39 +0,0 @@
--- a/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
+++ b/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
@@ -44,16 +44,34 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- if ((Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25 && random.nextDouble() < this.growPerTickProbability) {
+ // Spigot start
+ int modifier;
+ if (this == Blocks.KELP) {
+ modifier = world.spigotConfig.kelpModifier;
+ } else if (this == Blocks.TWISTING_VINES) {
+ modifier = world.spigotConfig.twistingVinesModifier;
+ } else if (this == Blocks.WEEPING_VINES) {
+ modifier = world.spigotConfig.weepingVinesModifier;
+ } else {
+ modifier = world.spigotConfig.caveVinesModifier;
+ }
+ if ((Integer) state.getValue(GrowingPlantHeadBlock.AGE) < 25 && random.nextDouble() < ((modifier / 100.0D) * this.growPerTickProbability)) { // Spigot - SPIGOT-7159: Better modifier resolution
+ // Spigot end
BlockPos blockposition1 = pos.relative(this.growthDirection);
if (this.canGrowInto(world.getBlockState(blockposition1))) {
- world.setBlockAndUpdate(blockposition1, this.getGrowIntoState(state, world.random));
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, this.getGrowIntoState(state, world.random, world)); // CraftBukkit // Paper - Fix Spigot growth modifiers
}
}
}
+ // Paper start - Fix Spigot growth modifiers
+ protected BlockState getGrowIntoState(BlockState state, RandomSource random, @javax.annotation.Nullable Level level) {
+ return this.getGrowIntoState(state, random);
+ }
+ // Paper end - Fix Spigot growth modifiers
+
protected BlockState getGrowIntoState(BlockState state, RandomSource random) {
return (BlockState) state.cycle(GrowingPlantHeadBlock.AGE);
}

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/block/HoneyBlock.java
+++ b/net/minecraft/world/level/block/HoneyBlock.java
@@ -60,6 +60,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (this.isSlidingDown(pos, entity)) {
this.maybeDoSlideAchievement(entity, pos);
this.doSlideMovement(entity);

View File

@@ -1,20 +0,0 @@
--- a/net/minecraft/world/level/block/HopperBlock.java
+++ b/net/minecraft/world/level/block/HopperBlock.java
@@ -125,8 +125,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
- if (!world.isClientSide && world.getBlockEntity(pos) instanceof HopperBlockEntity hopperBlockEntity) {
- player.openMenu(hopperBlockEntity);
+ if (!world.isClientSide && world.getBlockEntity(pos) instanceof HopperBlockEntity hopperBlockEntity && player.openMenu(hopperBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INSPECT_HOPPER);
}
@@ -178,6 +177,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof HopperBlockEntity) {
HopperBlockEntity.entityInside(world, pos, state, entity, (HopperBlockEntity)blockEntity);

View File

@@ -1,34 +0,0 @@
--- a/net/minecraft/world/level/block/HugeMushroomBlock.java
+++ b/net/minecraft/world/level/block/HugeMushroomBlock.java
@@ -45,6 +45,7 @@
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return this.defaultBlockState(); // Paper - add option to disable block updates
BlockGetter blockGetter = ctx.getLevel();
BlockPos blockPos = ctx.getClickedPos();
return this.defaultBlockState()
@@ -67,6 +68,7 @@
BlockState neighborState,
RandomSource random
) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return neighborState.is(this)
? state.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.valueOf(false))
: super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
@@ -74,6 +76,7 @@
@Override
protected BlockState rotate(BlockState state, Rotation rotation) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.EAST)), state.getValue(EAST))
@@ -84,6 +87,7 @@
@Override
protected BlockState mirror(BlockState state, Mirror mirror) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.EAST)), state.getValue(EAST))

View File

@@ -1,30 +0,0 @@
--- a/net/minecraft/world/level/block/IceBlock.java
+++ b/net/minecraft/world/level/block/IceBlock.java
@@ -34,8 +34,13 @@
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
+ // Paper start - Improve Block#breakNaturally API
+ this.afterDestroy(world, pos, tool);
+ }
+ public void afterDestroy(Level world, BlockPos pos, ItemStack tool) {
+ // Paper end - Improve Block#breakNaturally API
if (!EnchantmentHelper.hasTag(tool, EnchantmentTags.PREVENTS_ICE_MELTING)) {
if (world.dimensionType().ultraWarm()) {
world.removeBlock(pos, false);
@@ -60,6 +65,11 @@
}
protected void melt(BlockState state, Level world, BlockPos pos) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, world.dimensionType().ultraWarm() ? Blocks.AIR.defaultBlockState() : Blocks.WATER.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
if (world.dimensionType().ultraWarm()) {
world.removeBlock(pos, false);
} else {

View File

@@ -1,19 +0,0 @@
--- a/net/minecraft/world/level/block/InfestedBlock.java
+++ b/net/minecraft/world/level/block/InfestedBlock.java
@@ -19,6 +19,7 @@
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Property;
+import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; // CraftBukkit
public class InfestedBlock extends Block {
@@ -54,7 +55,7 @@
if (entitysilverfish != null) {
entitysilverfish.moveTo((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, 0.0F, 0.0F);
- world.addFreshEntity(entitysilverfish);
+ world.addFreshEntity(entitysilverfish, SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason
entitysilverfish.spawnAnim();
}

View File

@@ -1,10 +0,0 @@
--- a/net/minecraft/world/level/block/LavaCauldronBlock.java
+++ b/net/minecraft/world/level/block/LavaCauldronBlock.java
@@ -32,6 +32,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (this.isEntityInsideContent(state, pos, entity)) {
entity.lavaHurt();
}

View File

@@ -1,127 +0,0 @@
--- a/net/minecraft/world/level/block/LayeredCauldronBlock.java
+++ b/net/minecraft/world/level/block/LayeredCauldronBlock.java
@@ -17,6 +17,11 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
+// CraftBukkit start
+import org.bukkit.craftbukkit.block.CraftBlockState;
+import org.bukkit.craftbukkit.block.CraftBlockStates;
+import org.bukkit.event.block.CauldronLevelChangeEvent;
+// CraftBukkit end
public class LayeredCauldronBlock extends AbstractCauldronBlock {
@@ -62,41 +67,86 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (world instanceof ServerLevel worldserver) {
if (entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) {
- entity.clearFire();
- if (entity.mayInteract(worldserver, pos)) {
- this.handleEntityOnFireInside(state, world, pos);
+ // CraftBukkit start - moved down
+ // entity.clearFire();
+ if ((entity instanceof net.minecraft.world.entity.player.Player || worldserver.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING)) && entity.mayInteract(worldserver, pos)) { // Paper - Fixes MC-248588
+ if (this.handleEntityOnFireInsideWithEvent(state, world, pos, entity)) { // Paper - fix powdered snow cauldron extinguishing entities
+ entity.clearFire();
+ }
+ // CraftBukkit end
}
}
}
}
- private void handleEntityOnFireInside(BlockState state, Level world, BlockPos pos) {
+ // CraftBukkit start
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - fix powdered snow cauldron extinguishing entities; use #handleEntityOnFireInsideWithEvent
+ private boolean handleEntityOnFireInside(BlockState iblockdata, Level world, BlockPos blockposition, Entity entity) {
if (this.precipitationType == Biome.Precipitation.SNOW) {
- LayeredCauldronBlock.lowerFillLevel((BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL)), world, pos);
+ return LayeredCauldronBlock.lowerFillLevel((BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL)), world, blockposition, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH);
} else {
- LayeredCauldronBlock.lowerFillLevel(state, world, pos);
+ return LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH);
+ // CraftBukkit end
}
}
+ // Paper start - fix powdered snow cauldron extinguishing entities
+ protected boolean handleEntityOnFireInsideWithEvent(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (this.precipitationType == Biome.Precipitation.SNOW) {
+ return LayeredCauldronBlock.lowerFillLevel((BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL)), world, pos, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH);
+ } else {
+ return LayeredCauldronBlock.lowerFillLevel(state, world, pos, entity, CauldronLevelChangeEvent.ChangeReason.EXTINGUISH);
+ }
+ }
+ // Paper end - fix powdered snow cauldron extinguishing entities
public static void lowerFillLevel(BlockState state, Level world, BlockPos pos) {
- int i = (Integer) state.getValue(LayeredCauldronBlock.LEVEL) - 1;
- BlockState iblockdata1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (BlockState) state.setValue(LayeredCauldronBlock.LEVEL, i);
+ // CraftBukkit start
+ LayeredCauldronBlock.lowerFillLevel(state, world, pos, null, CauldronLevelChangeEvent.ChangeReason.UNKNOWN);
+ }
- world.setBlockAndUpdate(pos, iblockdata1);
- world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1));
+ public static boolean lowerFillLevel(BlockState iblockdata, Level world, BlockPos blockposition, Entity entity, CauldronLevelChangeEvent.ChangeReason reason) {
+ int i = (Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) - 1;
+ BlockState iblockdata1 = i == 0 ? Blocks.CAULDRON.defaultBlockState() : (BlockState) iblockdata.setValue(LayeredCauldronBlock.LEVEL, i);
+
+ return LayeredCauldronBlock.changeLevel(iblockdata, world, blockposition, iblockdata1, entity, reason);
}
+ // CraftBukkit start
+ // Paper start - Call CauldronLevelChangeEvent
+ public static boolean changeLevel(BlockState iblockdata, Level world, BlockPos blockposition, BlockState newBlock, @javax.annotation.Nullable Entity entity, CauldronLevelChangeEvent.ChangeReason reason) { // Paper - entity is nullable
+ return changeLevel(iblockdata, world, blockposition, newBlock, entity, reason, true);
+ }
+
+ public static boolean changeLevel(BlockState iblockdata, Level world, BlockPos blockposition, BlockState newBlock, @javax.annotation.Nullable Entity entity, CauldronLevelChangeEvent.ChangeReason reason, boolean sendGameEvent) { // Paper - entity is nullable
+ // Paper end - Call CauldronLevelChangeEvent
+ CraftBlockState newState = CraftBlockStates.getBlockState(world, blockposition);
+ newState.setData(newBlock);
+
+ CauldronLevelChangeEvent event = new CauldronLevelChangeEvent(
+ world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()),
+ (entity == null) ? null : entity.getBukkitEntity(), reason, newState
+ );
+ world.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return false;
+ }
+ newState.update(true);
+ if (sendGameEvent) world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(newBlock)); // Paper - Call CauldronLevelChangeEvent
+ return true;
+ }
+ // CraftBukkit end
+
@Override
public void handlePrecipitation(BlockState state, Level world, BlockPos pos, Biome.Precipitation precipitation) {
if (CauldronBlock.shouldHandlePrecipitation(world, precipitation) && (Integer) state.getValue(LayeredCauldronBlock.LEVEL) != 3 && precipitation == this.precipitationType) {
BlockState iblockdata1 = (BlockState) state.cycle(LayeredCauldronBlock.LEVEL);
- world.setBlockAndUpdate(pos, iblockdata1);
- world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1));
+ LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL); // CraftBukkit
}
}
@@ -115,8 +165,11 @@
if (!this.isFull(state)) {
BlockState iblockdata1 = (BlockState) state.setValue(LayeredCauldronBlock.LEVEL, (Integer) state.getValue(LayeredCauldronBlock.LEVEL) + 1);
- world.setBlockAndUpdate(pos, iblockdata1);
- world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1));
+ // CraftBukkit start
+ if (!LayeredCauldronBlock.changeLevel(state, world, pos, iblockdata1, null, CauldronLevelChangeEvent.ChangeReason.NATURAL_FILL)) {
+ return;
+ }
+ // CraftBukkit end
world.levelEvent(1047, pos, 0);
}
}

View File

@@ -1,25 +0,0 @@
--- a/net/minecraft/world/level/block/LeavesBlock.java
+++ b/net/minecraft/world/level/block/LeavesBlock.java
@@ -26,6 +26,7 @@
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.block.LeavesDecayEvent; // CraftBukkit
public class LeavesBlock extends Block implements SimpleWaterloggedBlock {
@@ -59,6 +60,14 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (this.decaying(state)) {
+ // CraftBukkit start
+ LeavesDecayEvent event = new LeavesDecayEvent(world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled() || world.getBlockState(pos).getBlock() != this) {
+ return;
+ }
+ // CraftBukkit end
dropResources(state, world, pos);
world.removeBlock(pos, false);
}

View File

@@ -1,69 +0,0 @@
--- a/net/minecraft/world/level/block/LecternBlock.java
+++ b/net/minecraft/world/level/block/LecternBlock.java
@@ -153,7 +153,24 @@
BlockEntity tileentity = world.getBlockEntity(pos);
if (tileentity instanceof LecternBlockEntity tileentitylectern) {
- tileentitylectern.setBook(stack.consumeAndReturn(1, user));
+ // Paper start - Add PlayerInsertLecternBookEvent
+ ItemStack eventSourcedBookStack = null;
+ if (user instanceof final net.minecraft.server.level.ServerPlayer serverPlayer) {
+ final io.papermc.paper.event.player.PlayerInsertLecternBookEvent event = new io.papermc.paper.event.player.PlayerInsertLecternBookEvent(
+ serverPlayer.getBukkitEntity(),
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, pos),
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack.copyWithCount(1))
+ );
+ if (!event.callEvent()) return;
+ eventSourcedBookStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getBook());
+ }
+ if (eventSourcedBookStack == null) {
+ eventSourcedBookStack = stack.consumeAndReturn(1, user);
+ } else {
+ stack.consume(1, user);
+ }
+ tileentitylectern.setBook(eventSourcedBookStack);
+ // Paper end - Add PlayerInsertLecternBookEvent
LecternBlock.resetBookState(user, world, pos, state, true);
world.playSound((Player) null, pos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F);
}
@@ -175,6 +192,16 @@
}
private static void changePowered(Level world, BlockPos pos, BlockState state, boolean powered) {
+ // Paper start - Call BlockRedstoneEvent properly
+ final int currentRedstoneLevel = state.getValue(LecternBlock.POWERED) ? 15 : 0, targetRedstoneLevel = powered ? 15 : 0;
+ if (currentRedstoneLevel != targetRedstoneLevel) {
+ final org.bukkit.event.block.BlockRedstoneEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, pos, currentRedstoneLevel, targetRedstoneLevel);
+
+ if (event.getNewCurrent() != targetRedstoneLevel) {
+ return;
+ }
+ }
+ // Paper end - Call BlockRedstoneEvent properly
world.setBlock(pos, (BlockState) state.setValue(LecternBlock.POWERED, powered), 3);
LecternBlock.updateBelow(world, pos, state);
}
@@ -206,11 +233,12 @@
}
private void popBook(BlockState state, Level world, BlockPos pos) {
- BlockEntity tileentity = world.getBlockEntity(pos);
+ BlockEntity tileentity = world.getBlockEntity(pos, false); // CraftBukkit - don't validate, type may be changed already
if (tileentity instanceof LecternBlockEntity tileentitylectern) {
Direction enumdirection = (Direction) state.getValue(LecternBlock.FACING);
ItemStack itemstack = tileentitylectern.getBook().copy();
+ if (itemstack.isEmpty()) return; // CraftBukkit - SPIGOT-5500
float f = 0.25F * (float) enumdirection.getStepX();
float f1 = 0.25F * (float) enumdirection.getStepZ();
ItemEntity entityitem = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) f, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D + (double) f1, itemstack);
@@ -282,8 +310,7 @@
private void openScreen(Level world, BlockPos pos, Player player) {
BlockEntity tileentity = world.getBlockEntity(pos);
- if (tileentity instanceof LecternBlockEntity) {
- player.openMenu((LecternBlockEntity) tileentity);
+ if (tileentity instanceof LecternBlockEntity && player.openMenu((LecternBlockEntity) tileentity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_LECTERN);
}

View File

@@ -1,31 +0,0 @@
--- a/net/minecraft/world/level/block/LeverBlock.java
+++ b/net/minecraft/world/level/block/LeverBlock.java
@@ -31,6 +31,7 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit
public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
@@ -102,6 +103,20 @@
LeverBlock.makeParticle(iblockdata1, world, pos, 1.0F);
}
} else {
+ // CraftBukkit start - Interact Lever
+ boolean powered = state.getValue(LeverBlock.POWERED); // Old powered state
+ org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ int old = (powered) ? 15 : 0;
+ int current = (!powered) ? 15 : 0;
+
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, old, current);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if ((eventRedstone.getNewCurrent() > 0) != (!powered)) {
+ return InteractionResult.SUCCESS;
+ }
+ // CraftBukkit end
+
this.pull(state, world, pos, (Player) null);
}

View File

@@ -1,18 +0,0 @@
--- a/net/minecraft/world/level/block/LightBlock.java
+++ b/net/minecraft/world/level/block/LightBlock.java
@@ -50,7 +50,15 @@
builder.add(LEVEL, WATERLOGGED);
}
+ // Paper start - prevent unintended light block manipulation
@Override
+ protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, net.minecraft.world.InteractionHand hand, BlockHitResult hit) {
+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || (world instanceof final net.minecraft.server.level.ServerLevel serverLevel && !player.mayInteract(serverLevel, pos)) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return net.minecraft.world.InteractionResult.PASS; } // Paper - Prevent unintended light block manipulation
+ return super.useItemOn(stack, state, world, pos, player, hand, hit);
+ }
+ // Paper end - prevent unintended light block manipulation
+
+ @Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!world.isClientSide && player.canUseGameMasterBlocks()) {
world.setBlock(pos, state.cycle(LEVEL), 2);

View File

@@ -1,33 +0,0 @@
--- a/net/minecraft/world/level/block/LightningRodBlock.java
+++ b/net/minecraft/world/level/block/LightningRodBlock.java
@@ -24,6 +24,11 @@
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils;
+// CraftBukkit start
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.event.block.BlockRedstoneEvent;
+// CraftBukkit end
+
public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBlock {
public static final MapCodec<LightningRodBlock> CODEC = simpleCodec(LightningRodBlock::new);
@@ -76,6 +81,18 @@
}
public void onLightningStrike(BlockState state, Level world, BlockPos pos) {
+ // CraftBukkit start
+ boolean powered = state.getValue(LightningRodBlock.POWERED);
+ int old = (powered) ? 15 : 0;
+ int current = (!powered) ? 15 : 0;
+
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, pos), old, current);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() <= 0) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(LightningRodBlock.POWERED, true), 3);
this.updateNeighbours(state, world, pos);
world.scheduleTick(pos, (Block) this, 8);

View File

@@ -1,78 +0,0 @@
--- a/net/minecraft/world/level/block/LiquidBlock.java
+++ b/net/minecraft/world/level/block/LiquidBlock.java
@@ -42,7 +42,7 @@
public class LiquidBlock extends Block implements BucketPickup {
private static final Codec<FlowingFluid> FLOWING_FLUID = BuiltInRegistries.FLUID.byNameCodec().comapFlatMap((fluidtype) -> {
- DataResult dataresult;
+ DataResult<FlowingFluid> dataresult; // CraftBukkit - decompile error
if (fluidtype instanceof FlowingFluid fluidtypeflowing) {
dataresult = DataResult.success(fluidtypeflowing);
@@ -141,11 +141,31 @@
@Override
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) {
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - Configurable speed for water flowing over lava
}
}
+ // Paper start - Configurable speed for water flowing over lava
+ public int getFlowSpeed(Level world, BlockPos blockposition) {
+ if (net.minecraft.core.registries.BuiltInRegistries.FLUID.wrapAsHolder(this.fluid).is(FluidTags.WATER)) {
+ if (
+ isLava(world, blockposition.north(1)) ||
+ isLava(world, blockposition.south(1)) ||
+ isLava(world, blockposition.west(1)) ||
+ isLava(world, blockposition.east(1))
+ ) {
+ return world.paperConfig().environment.waterOverLavaFlowSpeed;
+ }
+ }
+ return this.fluid.getTickDelay(world);
+ }
+ private static boolean isLava(Level world, BlockPos blockPos) {
+ final FluidState fluidState = world.getFluidIfLoaded(blockPos);
+ return fluidState != null && fluidState.is(FluidTags.LAVA);
+ }
+ // Paper end - Configurable speed for water flowing over lava
+
@Override
protected BlockState updateShape(BlockState state, LevelReader world, ScheduledTickAccess tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random) {
if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) {
@@ -158,7 +178,7 @@
@Override
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, @Nullable Orientation wireOrientation, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) {
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper - Configurable speed for water flowing over lava
}
}
@@ -175,14 +195,20 @@
if (world.getFluidState(blockposition1).is(FluidTags.WATER)) {
Block block = world.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
- world.setBlockAndUpdate(pos, block.defaultBlockState());
- this.fizz(world, pos);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, pos, block.defaultBlockState())) {
+ this.fizz(world, pos);
+ }
+ // CraftBukkit end
return false;
}
if (flag && world.getBlockState(blockposition1).is(Blocks.BLUE_ICE)) {
- world.setBlockAndUpdate(pos, Blocks.BASALT.defaultBlockState());
- this.fizz(world, pos);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, pos, Blocks.BASALT.defaultBlockState())) {
+ this.fizz(world, pos);
+ }
+ // CraftBukkit end
return false;
}
}

View File

@@ -1,13 +0,0 @@
--- a/net/minecraft/world/level/block/LoomBlock.java
+++ b/net/minecraft/world/level/block/LoomBlock.java
@@ -33,8 +33,9 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!world.isClientSide) {
- player.openMenu(state.getMenuProvider(world, pos));
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
player.awardStat(Stats.INTERACT_WITH_LOOM);
+ } // Paper - Fix InventoryOpenEvent cancellation
}
return InteractionResult.SUCCESS;

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/MagmaBlock.java
+++ b/net/minecraft/world/level/block/MagmaBlock.java
@@ -30,7 +30,7 @@
@Override
public void stepOn(Level world, BlockPos pos, BlockState state, Entity entity) {
if (!entity.isSteppingCarefully() && entity instanceof LivingEntity) {
- entity.hurt(world.damageSources().hotFloor(), 1.0F);
+ entity.hurt(world.damageSources().hotFloor().directBlock(world, pos), 1.0F); // CraftBukkit
}
super.stepOn(world, pos, state, entity);

View File

@@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/MangrovePropaguleBlock.java
+++ b/net/minecraft/world/level/block/MangrovePropaguleBlock.java
@@ -123,7 +123,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!isHanging(state)) {
- if (random.nextInt(7) == 0) {
+ if (random.nextFloat() < (world.spigotConfig.saplingModifier / (100.0F * 7))) { // Paper - Fix Spigot growth modifiers
this.advanceTree(world, pos, state, random);
}
} else {

View File

@@ -1,43 +0,0 @@
--- a/net/minecraft/world/level/block/MultifaceSpreader.java
+++ b/net/minecraft/world/level/block/MultifaceSpreader.java
@@ -156,7 +156,7 @@
world.getChunk(growPos.pos()).markPosForPostprocessing(growPos.pos());
}
- return world.setBlock(growPos.pos(), iblockdata1, 2);
+ return org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, growPos.source(), growPos.pos(), iblockdata1, 2); // CraftBukkit
} else {
return false;
}
@@ -174,19 +174,19 @@
SAME_POSITION {
@Override
public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction newDirection, Direction oldDirection) {
- return new MultifaceSpreader.SpreadPos(pos, newDirection);
+ return new MultifaceSpreader.SpreadPos(pos, newDirection, pos); // CraftBukkit
}
},
SAME_PLANE {
@Override
public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction newDirection, Direction oldDirection) {
- return new MultifaceSpreader.SpreadPos(pos.relative(newDirection), oldDirection);
+ return new MultifaceSpreader.SpreadPos(pos.relative(newDirection), oldDirection, pos); // CraftBukkit
}
},
WRAP_AROUND {
@Override
public MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction newDirection, Direction oldDirection) {
- return new MultifaceSpreader.SpreadPos(pos.relative(newDirection).relative(oldDirection), newDirection.getOpposite());
+ return new MultifaceSpreader.SpreadPos(pos.relative(newDirection).relative(oldDirection), newDirection.getOpposite(), pos); // CraftBukkit
}
};
@@ -195,7 +195,7 @@
public abstract MultifaceSpreader.SpreadPos getSpreadPos(BlockPos pos, Direction newDirection, Direction oldDirection);
}
- public static record SpreadPos(BlockPos pos, Direction face) {
+ public static record SpreadPos(BlockPos pos, Direction face, BlockPos source) { // CraftBukkit
}
}

View File

@@ -1,46 +0,0 @@
--- a/net/minecraft/world/level/block/MushroomBlock.java
+++ b/net/minecraft/world/level/block/MushroomBlock.java
@@ -19,6 +19,9 @@
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.TreeType;
+// CraftBukkit end
public class MushroomBlock extends BushBlock implements BonemealableBlock {
@@ -48,7 +51,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- if (random.nextInt(25) == 0) {
+ if (random.nextFloat() < (world.spigotConfig.mushroomModifier / (100.0f * 25))) { // Spigot - SPIGOT-7159: Better modifier resolution
int i = 5;
boolean flag = true;
Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, -1, -4), pos.offset(4, 1, 4)).iterator();
@@ -65,6 +68,7 @@
}
BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
+ final BlockPos sourcePos = pos; // Paper - Use correct source for mushroom block spread event
for (int j = 0; j < 4; ++j) {
if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
@@ -75,7 +79,7 @@
}
if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
- world.setBlock(blockposition2, state, 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, sourcePos, blockposition2, state, 2); // CraftBukkit // Paper - Use correct source for mushroom block spread event
}
}
@@ -101,6 +105,7 @@
return false;
} else {
world.removeBlock(pos, false);
+ SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.RED_MUSHROOM; // CraftBukkit
if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(world, world.getChunkSource().getGenerator(), random, pos)) {
return true;
} else {

View File

@@ -1,163 +0,0 @@
--- a/net/minecraft/world/level/block/NetherPortalBlock.java
+++ b/net/minecraft/world/level/block/NetherPortalBlock.java
@@ -32,12 +32,19 @@
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.dimension.DimensionType;
+import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.portal.PortalShape;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.slf4j.Logger;
+import org.bukkit.craftbukkit.CraftWorld;
+import org.bukkit.craftbukkit.event.CraftPortalEvent;
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.event.entity.EntityPortalEnterEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+// CraftBukkit end
public class NetherPortalBlock extends Block implements Portal {
@@ -71,16 +78,21 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- if (world.dimensionType().natural() && world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && random.nextInt(2000) < world.getDifficulty().getId()) {
+ if (world.spigotConfig.enableZombiePigmenPortalSpawns && world.dimensionType().natural() && world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && random.nextInt(2000) < world.getDifficulty().getId()) { // Spigot
while (world.getBlockState(pos).is((Block) this)) {
pos = pos.below();
}
if (world.getBlockState(pos).isValidSpawn(world, pos, EntityType.ZOMBIFIED_PIGLIN)) {
- Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(world, pos.above(), EntitySpawnReason.STRUCTURE);
+ // CraftBukkit - set spawn reason to NETHER_PORTAL
+ Entity entity = EntityType.ZOMBIFIED_PIGLIN.spawn(world, pos.above(), EntitySpawnReason.STRUCTURE, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL);
if (entity != null) {
entity.setPortalCooldown();
+ // Paper start - Add option to nerf pigmen from nether portals
+ entity.fromNetherPortal = true;
+ if (world.paperConfig().entities.behavior.nerfPigmenFromNetherPortals) ((net.minecraft.world.entity.Mob) entity).aware = false;
+ // Paper end - Add option to nerf pigmen from nether portals
Entity entity1 = entity.getVehicle();
if (entity1 != null) {
@@ -103,7 +115,13 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity.canUsePortal(false)) {
+ // CraftBukkit start - Entity in portal
+ EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()), org.bukkit.PortalType.NETHER); // Paper - add portal type
+ world.getCraftServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) return; // Paper - make cancellable
+ // CraftBukkit end
entity.setAsInsidePortal(this, pos);
}
@@ -121,51 +139,80 @@
@Nullable
@Override
public TeleportTransition getPortalDestination(ServerLevel world, Entity entity, BlockPos pos) {
- ResourceKey<Level> resourcekey = world.dimension() == Level.NETHER ? Level.OVERWORLD : Level.NETHER;
+ // CraftBukkit start
+ ResourceKey<Level> resourcekey = world.getTypeKey() == LevelStem.NETHER ? Level.OVERWORLD : Level.NETHER;
ServerLevel worldserver1 = world.getServer().getLevel(resourcekey);
+ // Paper start - Add EntityPortalReadyEvent
+ io.papermc.paper.event.entity.EntityPortalReadyEvent portalReadyEvent = new io.papermc.paper.event.entity.EntityPortalReadyEvent(entity.getBukkitEntity(), worldserver1 == null ? null : worldserver1.getWorld(), org.bukkit.PortalType.NETHER);
+ if (!portalReadyEvent.callEvent()) {
+ entity.portalProcess = null;
+ return null;
+ }
+ worldserver1 = portalReadyEvent.getTargetWorld() == null ? null : ((org.bukkit.craftbukkit.CraftWorld) portalReadyEvent.getTargetWorld()).getHandle();
+ // Paper end - Add EntityPortalReadyEvent
if (worldserver1 == null) {
- return null;
+ return null; // Paper - keep previous behavior of not firing PlayerTeleportEvent if the target world doesn't exist
} else {
- boolean flag = worldserver1.dimension() == Level.NETHER;
+ boolean flag = worldserver1.getTypeKey() == LevelStem.NETHER;
+ // CraftBukkit end
WorldBorder worldborder = worldserver1.getWorldBorder();
double d0 = DimensionType.getTeleportationScale(world.dimensionType(), worldserver1.dimensionType());
BlockPos blockposition1 = worldborder.clampToBounds(entity.getX() * d0, entity.getY(), entity.getZ() * d0);
+ // Paper start - Configurable portal search radius
+ int portalSearchRadius = worldserver1.paperConfig().environment.portalSearchRadius;
+ if (entity.level().paperConfig().environment.portalSearchVanillaDimensionScaling && flag) { // flag = is going to nether
+ portalSearchRadius = (int) (portalSearchRadius / worldserver1.dimensionType().coordinateScale());
+ }
+ // Paper end - Configurable portal search radius
+ // CraftBukkit start
+ CraftPortalEvent event = entity.callPortalEvent(entity, CraftLocation.toBukkit(blockposition1, worldserver1.getWorld()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, worldserver1.paperConfig().environment.portalCreateRadius); // Paper - use custom portal search radius
+ if (event == null) {
+ return null;
+ }
+ worldserver1 = ((CraftWorld) event.getTo().getWorld()).getHandle();
+ worldborder = worldserver1.getWorldBorder();
+ blockposition1 = worldborder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ());
- return this.getExitPortal(worldserver1, entity, pos, blockposition1, flag, worldborder);
+ return this.getExitPortal(worldserver1, entity, pos, blockposition1, flag, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius());
}
}
@Nullable
- private TeleportTransition getExitPortal(ServerLevel world, Entity entity, BlockPos pos, BlockPos scaledPos, boolean inNether, WorldBorder worldBorder) {
- Optional<BlockPos> optional = world.getPortalForcer().findClosestPortalPosition(scaledPos, inNether, worldBorder);
+ private TeleportTransition getExitPortal(ServerLevel worldserver, Entity entity, BlockPos blockposition, BlockPos blockposition1, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) {
+ Optional<BlockPos> optional = worldserver.getPortalForcer().findClosestPortalPosition(blockposition1, worldborder, searchRadius);
BlockUtil.FoundRectangle blockutil_rectangle;
TeleportTransition.PostTeleportTransition teleporttransition_a;
if (optional.isPresent()) {
BlockPos blockposition2 = (BlockPos) optional.get();
- BlockState iblockdata = world.getBlockState(blockposition2);
+ BlockState iblockdata = worldserver.getBlockState(blockposition2);
blockutil_rectangle = BlockUtil.getLargestRectangleAround(blockposition2, (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockposition3) -> {
- return world.getBlockState(blockposition3) == iblockdata;
+ return worldserver.getBlockState(blockposition3) == iblockdata;
});
teleporttransition_a = TeleportTransition.PLAY_PORTAL_SOUND.then((entity1) -> {
entity1.placePortalTicket(blockposition2);
});
- } else {
- Direction.Axis enumdirection_enumaxis = (Direction.Axis) entity.level().getBlockState(pos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X);
- Optional<BlockUtil.FoundRectangle> optional1 = world.getPortalForcer().createPortal(scaledPos, enumdirection_enumaxis);
+ } else if (canCreatePortal) {
+ Direction.Axis enumdirection_enumaxis = (Direction.Axis) entity.level().getBlockState(blockposition).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X);
+ Optional<BlockUtil.FoundRectangle> optional1 = worldserver.getPortalForcer().createPortal(blockposition1, enumdirection_enumaxis, entity, createRadius);
+ // CraftBukkit end
if (optional1.isEmpty()) {
- NetherPortalBlock.LOGGER.error("Unable to create a portal, likely target out of worldborder");
+ // BlockPortal.LOGGER.error("Unable to create a portal, likely target out of worldborder"); // CraftBukkit
return null;
}
blockutil_rectangle = (BlockUtil.FoundRectangle) optional1.get();
teleporttransition_a = TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET);
+ // CraftBukkit start
+ } else {
+ return null;
+ // CraftBukkit end
}
- return NetherPortalBlock.getDimensionTransitionFromExit(entity, pos, blockutil_rectangle, world, teleporttransition_a);
+ return NetherPortalBlock.getDimensionTransitionFromExit(entity, blockposition, blockutil_rectangle, worldserver, teleporttransition_a);
}
private static TeleportTransition getDimensionTransitionFromExit(Entity entity, BlockPos pos, BlockUtil.FoundRectangle exitPortalRectangle, ServerLevel world, TeleportTransition.PostTeleportTransition postDimensionTransition) {
@@ -203,7 +250,7 @@
Vec3 vec3d1 = new Vec3((double) blockposition.getX() + (flag ? d2 : d4), (double) blockposition.getY() + d3, (double) blockposition.getZ() + (flag ? d4 : d2));
Vec3 vec3d2 = PortalShape.findCollisionFreePosition(vec3d1, world, entity, entitysize);
- return new TeleportTransition(world, vec3d2, Vec3.ZERO, (float) i, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), postDimensionTransition);
+ return new TeleportTransition(world, vec3d2, Vec3.ZERO, (float) i, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), postDimensionTransition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); // CraftBukkit
}
@Override

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/NetherWartBlock.java
+++ b/net/minecraft/world/level/block/NetherWartBlock.java
@@ -52,9 +52,9 @@
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
int i = (Integer) state.getValue(NetherWartBlock.AGE);
- if (i < 3 && random.nextInt(10) == 0) {
+ if (i < 3 && random.nextFloat() < (world.spigotConfig.wartModifier / (100.0f * 10))) { // Spigot - SPIGOT-7159: Better modifier resolution
state = (BlockState) state.setValue(NetherWartBlock.AGE, i + 1);
- world.setBlock(pos, state, 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, state, 2); // CraftBukkit
}
}

View File

@@ -1,78 +0,0 @@
--- a/net/minecraft/world/level/block/NoteBlock.java
+++ b/net/minecraft/world/level/block/NoteBlock.java
@@ -68,11 +68,13 @@
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return this.defaultBlockState(); // Paper - place without considering instrument
return this.setInstrument(ctx.getLevel(), ctx.getClickedPos(), this.defaultBlockState());
}
@Override
protected BlockState updateShape(BlockState state, LevelReader world, ScheduledTickAccess tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return state; // Paper - prevent noteblock instrument from updating
boolean flag = direction.getAxis() == Direction.Axis.Y;
return flag ? this.setInstrument(world, pos, state) : super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
@@ -80,11 +82,13 @@
@Override
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, @Nullable Orientation wireOrientation, boolean notify) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return; // Paper - prevent noteblock powered-state from updating
boolean flag1 = world.hasNeighborSignal(pos);
if (flag1 != (Boolean) state.getValue(NoteBlock.POWERED)) {
if (flag1) {
this.playNote((Entity) null, state, world, pos);
+ state = world.getBlockState(pos); // CraftBukkit - SPIGOT-5617: update in case changed in event
}
world.setBlock(pos, (BlockState) state.setValue(NoteBlock.POWERED, flag1), 3);
@@ -94,6 +98,13 @@
private void playNote(@Nullable Entity entity, BlockState state, Level world, BlockPos pos) {
if (((NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT)).worksAboveNoteBlock() || world.getBlockState(pos.above()).isAir()) {
+ // CraftBukkit start
+ // org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, state.getValue(NoteBlock.INSTRUMENT), state.getValue(NoteBlock.NOTE));
+ // if (event.isCancelled()) {
+ // return;
+ // }
+ // CraftBukkit end
+ // Paper - move NotePlayEvent call to fix instrument/note changes; TODO any way to cancel the game event?
world.blockEvent(pos, this, 0, 0);
world.gameEvent(entity, (Holder) GameEvent.NOTE_BLOCK_PLAY, pos);
}
@@ -108,7 +119,7 @@
@Override
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (!world.isClientSide) {
- state = (BlockState) state.cycle(NoteBlock.NOTE);
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) state = (BlockState) state.cycle(NoteBlock.NOTE); // Paper - prevent noteblock note from updating
world.setBlock(pos, state, 3);
this.playNote(player, state, world, pos);
player.awardStat(Stats.TUNE_NOTEBLOCK);
@@ -132,10 +143,14 @@
@Override
protected boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
NoteBlockInstrument blockpropertyinstrument = (NoteBlockInstrument) state.getValue(NoteBlock.INSTRUMENT);
+ // Paper start - move NotePlayEvent call to fix instrument/note changes
+ org.bukkit.event.block.NotePlayEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callNotePlayEvent(world, pos, blockpropertyinstrument, state.getValue(NOTE));
+ if (event.isCancelled()) return false;
+ // Paper end - move NotePlayEvent call to fix instrument/note changes
float f;
if (blockpropertyinstrument.isTunable()) {
- int k = (Integer) state.getValue(NoteBlock.NOTE);
+ int k = event.getNote().getId(); // Paper - move NotePlayEvent call to fix instrument/note changes
f = NoteBlock.getPitchFromNote(k);
world.addParticle(ParticleTypes.NOTE, (double) pos.getX() + 0.5D, (double) pos.getY() + 1.2D, (double) pos.getZ() + 0.5D, (double) k / 24.0D, 0.0D, 0.0D);
@@ -154,7 +169,7 @@
holder = Holder.direct(SoundEvent.createVariableRangeEvent(minecraftkey));
} else {
- holder = blockpropertyinstrument.getSoundEvent();
+ holder = org.bukkit.craftbukkit.block.data.CraftBlockData.toNMS(event.getInstrument(), NoteBlockInstrument.class).getSoundEvent(); // Paper - move NotePlayEvent call to fix instrument/note changes
}
world.playSeededSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, holder, SoundSource.RECORDS, 3.0F, f, world.random.nextLong());

View File

@@ -1,14 +0,0 @@
--- a/net/minecraft/world/level/block/NyliumBlock.java
+++ b/net/minecraft/world/level/block/NyliumBlock.java
@@ -41,6 +41,11 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!NyliumBlock.canBeNylium(state, world, pos)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.NETHERRACK.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
world.setBlockAndUpdate(pos, Blocks.NETHERRACK.defaultBlockState());
}

View File

@@ -1,30 +0,0 @@
--- a/net/minecraft/world/level/block/ObserverBlock.java
+++ b/net/minecraft/world/level/block/ObserverBlock.java
@@ -18,6 +18,8 @@
import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils;
import net.minecraft.world.level.redstone.Orientation;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+
public class ObserverBlock extends DirectionalBlock {
public static final MapCodec<ObserverBlock> CODEC = simpleCodec(ObserverBlock::new);
@@ -51,8 +53,18 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if ((Boolean) state.getValue(ObserverBlock.POWERED)) {
+ // CraftBukkit start
+ if (CraftEventFactory.callRedstoneChange(world, pos, 15, 0).getNewCurrent() != 0) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(ObserverBlock.POWERED, false), 2);
} else {
+ // CraftBukkit start
+ if (CraftEventFactory.callRedstoneChange(world, pos, 0, 15).getNewCurrent() != 15) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(ObserverBlock.POWERED, true), 2);
world.scheduleTick(pos, (Block) this, 2);
}

View File

@@ -1,28 +0,0 @@
--- a/net/minecraft/world/level/block/PitcherCropBlock.java
+++ b/net/minecraft/world/level/block/PitcherCropBlock.java
@@ -107,6 +107,7 @@
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (world instanceof ServerLevel serverLevel && entity instanceof Ravager && serverLevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
serverLevel.destroyBlock(pos, true, entity);
}
@@ -131,7 +132,7 @@
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
float f = CropBlock.getGrowthSpeed(this, world, pos);
- boolean bl = random.nextInt((int)(25.0F / f) + 1) == 0;
+ boolean bl = random.nextFloat() < (world.spigotConfig.pitcherPlantModifier / (100.0F * (Math.floor(25.0F / f) + 1))); // Paper - Fix Spigot growth modifiers
if (bl) {
this.grow(world, state, pos, 1);
}
@@ -141,7 +142,7 @@
int i = Math.min(state.getValue(AGE) + amount, 4);
if (this.canGrow(world, pos, state, i)) {
BlockState blockState = state.setValue(AGE, Integer.valueOf(i));
- world.setBlock(pos, blockState, 2);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, blockState, 2)) return; // Paper
if (isDouble(i)) {
world.setBlock(pos.above(), blockState.setValue(HALF, DoubleBlockHalf.UPPER), 3);
}

View File

@@ -1,96 +0,0 @@
--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -136,6 +136,11 @@
ServerLevel worldserver = (ServerLevel) world;
if (projectile.mayInteract(worldserver, blockposition) && projectile.mayBreak(worldserver) && projectile instanceof ThrownTrident && projectile.getDeltaMovement().length() > 0.6D) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
+ return;
+ }
+ // CraftBukkit end
world.destroyBlock(blockposition, true);
}
}
@@ -146,7 +151,7 @@
@Override
public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) {
if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) {
- entity.causeFallDamage(fallDistance + 2.0F, 2.0F, world.damageSources().stalagmite());
+ entity.causeFallDamage(fallDistance + 2.0F, 2.0F, world.damageSources().stalagmite().directBlock(world, pos)); // CraftBukkit
} else {
super.fallOn(world, state, pos, entity, fallDistance);
}
@@ -214,10 +219,13 @@
if (((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState.is(Blocks.MUD) && fluidtype == Fluids.WATER) {
BlockState iblockdata1 = Blocks.CLAY.defaultBlockState();
- world.setBlockAndUpdate(((PointedDripstoneBlock.FluidInfo) optional.get()).pos, iblockdata1);
+ // Paper start - Call BlockFormEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos, iblockdata1)) {
Block.pushEntitiesUp(((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState, iblockdata1, world, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos);
world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos, GameEvent.Context.of(iblockdata1));
world.levelEvent(1504, blockposition1, 0);
+ }
+ // Paper end - Call BlockFormEvent
} else {
BlockPos blockposition2 = PointedDripstoneBlock.findFillableCauldronBelowStalactiteTip(world, blockposition1, fluidtype);
@@ -391,15 +399,15 @@
if (PointedDripstoneBlock.isUnmergedTipWithDirection(iblockdata, direction.getOpposite())) {
PointedDripstoneBlock.createMergedTips(iblockdata, world, blockposition1);
} else if (iblockdata.isAir() || iblockdata.is(Blocks.WATER)) {
- PointedDripstoneBlock.createDripstone(world, blockposition1, direction, DripstoneThickness.TIP);
+ PointedDripstoneBlock.createDripstone(world, blockposition1, direction, DripstoneThickness.TIP, pos); // CraftBukkit
}
}
- private static void createDripstone(LevelAccessor world, BlockPos pos, Direction direction, DripstoneThickness thickness) {
- BlockState iblockdata = (BlockState) ((BlockState) ((BlockState) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, direction)).setValue(PointedDripstoneBlock.THICKNESS, thickness)).setValue(PointedDripstoneBlock.WATERLOGGED, world.getFluidState(pos).getType() == Fluids.WATER);
+ private static void createDripstone(LevelAccessor generatoraccess, BlockPos blockposition, Direction enumdirection, DripstoneThickness dripstonethickness, BlockPos source) { // CraftBukkit
+ BlockState iblockdata = (BlockState) ((BlockState) ((BlockState) Blocks.POINTED_DRIPSTONE.defaultBlockState().setValue(PointedDripstoneBlock.TIP_DIRECTION, enumdirection)).setValue(PointedDripstoneBlock.THICKNESS, dripstonethickness)).setValue(PointedDripstoneBlock.WATERLOGGED, generatoraccess.getFluidState(blockposition).getType() == Fluids.WATER);
- world.setBlock(pos, iblockdata, 3);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, source, blockposition, iblockdata, 3); // CraftBukkit
}
private static void createMergedTips(BlockState state, LevelAccessor world, BlockPos pos) {
@@ -414,8 +422,8 @@
blockposition1 = pos.below();
}
- PointedDripstoneBlock.createDripstone(world, blockposition2, Direction.DOWN, DripstoneThickness.TIP_MERGE);
- PointedDripstoneBlock.createDripstone(world, blockposition1, Direction.UP, DripstoneThickness.TIP_MERGE);
+ PointedDripstoneBlock.createDripstone(world, blockposition2, Direction.DOWN, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit
+ PointedDripstoneBlock.createDripstone(world, blockposition1, Direction.UP, DripstoneThickness.TIP_MERGE, pos); // CraftBukkit
}
public static void spawnDripParticle(Level world, BlockPos pos, BlockState state) {
@@ -448,7 +456,7 @@
return (BlockPos) PointedDripstoneBlock.findBlockVertical(world, pos, enumdirection.getAxisDirection(), bipredicate, (iblockdata1) -> {
return PointedDripstoneBlock.isTip(iblockdata1, allowMerged);
- }, range).orElse((Object) null);
+ }, range).orElse(null); // CraftBukkit - decompile error
}
}
@@ -564,7 +572,7 @@
return PointedDripstoneBlock.canDripThrough(world, blockposition1, iblockdata);
};
- return (BlockPos) PointedDripstoneBlock.findBlockVertical(world, pos, Direction.DOWN.getAxisDirection(), bipredicate, predicate, 11).orElse((Object) null);
+ return (BlockPos) PointedDripstoneBlock.findBlockVertical(world, pos, Direction.DOWN.getAxisDirection(), bipredicate, predicate, 11).orElse(null); // CraftBukkit - decompile error
}
@Nullable
@@ -573,7 +581,7 @@
return PointedDripstoneBlock.canDripThrough(world, blockposition1, iblockdata);
};
- return (BlockPos) PointedDripstoneBlock.findBlockVertical(world, pos, Direction.UP.getAxisDirection(), bipredicate, PointedDripstoneBlock::canDrip, 11).orElse((Object) null);
+ return (BlockPos) PointedDripstoneBlock.findBlockVertical(world, pos, Direction.UP.getAxisDirection(), bipredicate, PointedDripstoneBlock::canDrip, 11).orElse(null); // CraftBukkit - decompile error
}
public static Fluid getCauldronFillFluidType(ServerLevel world, BlockPos pos) {

View File

@@ -1,24 +0,0 @@
--- a/net/minecraft/world/level/block/PowderSnowBlock.java
+++ b/net/minecraft/world/level/block/PowderSnowBlock.java
@@ -59,6 +59,7 @@
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!(entity instanceof LivingEntity) || entity.getInBlockState().is((Block) this)) {
entity.makeStuckInBlock(state, new Vec3(0.8999999761581421D, 1.5D, 0.8999999761581421D));
if (world.isClientSide) {
@@ -73,7 +74,12 @@
entity.setIsInPowderSnow(true);
if (world instanceof ServerLevel worldserver) {
- if (entity.isOnFire() && (worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player) && entity.mayInteract(worldserver, pos)) {
+ // CraftBukkit start
+ if (entity.isOnFire() && entity.mayInteract(worldserver, pos)) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !(worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || entity instanceof Player))) {
+ return;
+ }
+ // CraftBukkit end
world.destroyBlock(pos, false);
}

View File

@@ -1,24 +0,0 @@
--- a/net/minecraft/world/level/block/PoweredRailBlock.java
+++ b/net/minecraft/world/level/block/PoweredRailBlock.java
@@ -11,6 +11,7 @@
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.RailShape;
+import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
public class PoweredRailBlock extends BaseRailBlock {
@@ -120,6 +121,13 @@
boolean flag1 = world.hasNeighborSignal(pos) || this.findPoweredRailSignal(world, pos, state, true, 0) || this.findPoweredRailSignal(world, pos, state, false, 0);
if (flag1 != flag) {
+ // CraftBukkit start
+ int power = flag ? 15 : 0;
+ int newPower = CraftEventFactory.callRedstoneChange(world, pos, power, 15 - power).getNewCurrent();
+ if (newPower == power) {
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) state.setValue(PoweredRailBlock.POWERED, flag1), 3);
world.updateNeighborsAt(pos.below(), this);
if (((RailShape) state.getValue(PoweredRailBlock.SHAPE)).isSlope()) {

View File

@@ -1,61 +0,0 @@
--- a/net/minecraft/world/level/block/PressurePlateBlock.java
+++ b/net/minecraft/world/level/block/PressurePlateBlock.java
@@ -5,6 +5,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
@@ -12,6 +13,8 @@
import net.minecraft.world.level.block.state.properties.BlockSetType;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
+import org.bukkit.event.entity.EntityInteractEvent;
+// CraftBukkit end
public class PressurePlateBlock extends BasePressurePlateBlock {
@@ -44,7 +47,7 @@
@Override
protected int getSignalStrength(Level world, BlockPos pos) {
- Class oclass;
+ Class<? extends Entity> oclass; // CraftBukkit
switch (this.type.pressurePlateSensitivity()) {
case EVERYTHING:
@@ -59,7 +62,31 @@
Class<? extends Entity> oclass1 = oclass;
- return getEntityCount(world, PressurePlateBlock.TOUCH_AABB.move(pos), oclass1) > 0 ? 15 : 0;
+ // CraftBukkit start - Call interact event when turning on a pressure plate
+ for (Entity entity : getEntities(world, PressurePlateBlock.TOUCH_AABB.move(pos), oclass)) {
+ if (this.getSignalForState(world.getBlockState(pos)) == 0) {
+ org.bukkit.World bworld = world.getWorld();
+ org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager();
+ org.bukkit.event.Cancellable cancellable;
+
+ if (entity instanceof Player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else {
+ cancellable = new EntityInteractEvent(entity.getBukkitEntity(), bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ manager.callEvent((EntityInteractEvent) cancellable);
+ }
+
+ // We only want to block turning the plate on if all events are cancelled
+ if (cancellable.isCancelled()) {
+ continue;
+ }
+ }
+
+ return 15;
+ }
+
+ return 0;
+ // CraftBukkit end
}
@Override

Some files were not shown because too many files have changed in this diff Show More