partial: net.minecraft.world.level.block

This commit is contained in:
Jake Potrebic
2024-12-14 18:16:46 -08:00
parent b16f6f533a
commit e9680a5afe
59 changed files with 1165 additions and 1452 deletions

View File

@@ -0,0 +1,54 @@
--- a/net/minecraft/world/level/block/SaplingBlock.java
+++ b/net/minecraft/world/level/block/SaplingBlock.java
@@ -26,6 +_,7 @@
protected static final float AABB_OFFSET = 6.0F;
protected static final VoxelShape SHAPE = Block.box(2.0, 0.0, 2.0, 14.0, 12.0, 14.0);
protected final TreeGrower treeGrower;
+ public static org.bukkit.TreeType treeType; // CraftBukkit
@Override
public MapCodec<? extends SaplingBlock> codec() {
@@ -45,7 +_,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
- if (level.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextInt(7) == 0) {
+ if (level.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextFloat() < (level.spigotConfig.saplingModifier / (100.0f * 7))) { // Spigot - SPIGOT-7159: Better modifier resolution
this.advanceTree(level, pos, state, random);
}
}
@@ -54,7 +_,33 @@
if (state.getValue(STAGE) == 0) {
level.setBlock(pos, state.cycle(STAGE), 4);
} else {
- this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random);
+ // CraftBukkit start
+ if (level.captureTreeGeneration) {
+ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random);
+ } else {
+ level.captureTreeGeneration = true;
+ this.treeGrower.growTree(level, level.getChunkSource().getGenerator(), pos, state, random);
+ level.captureTreeGeneration = false;
+ if (level.capturedBlockStates.size() > 0) {
+ org.bukkit.TreeType treeType = SaplingBlock.treeType;
+ SaplingBlock.treeType = null;
+ org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(pos, level.getWorld());
+ java.util.List<org.bukkit.block.BlockState> blocks = new java.util.ArrayList<>(level.capturedBlockStates.values());
+ level.capturedBlockStates.clear();
+ org.bukkit.event.world.StructureGrowEvent event = null;
+ if (treeType != null) {
+ event = new org.bukkit.event.world.StructureGrowEvent(location, treeType, false, null, blocks);
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
+ }
+ if (event == null || !event.isCancelled()) {
+ for (org.bukkit.block.BlockState blockstate : blocks) {
+ org.bukkit.craftbukkit.block.CapturedBlockState.setBlockState(blockstate);
+ level.checkCapturedTreeStateForObserverNotify(pos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
+ }
+ }
+ }
+ }
+ // CraftBukkit end
}
}

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/level/block/ScaffoldingBlock.java
+++ b/net/minecraft/world/level/block/ScaffoldingBlock.java
@@ -119,7 +_,7 @@
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
int distance = getDistance(level, pos);
BlockState blockState = state.setValue(DISTANCE, Integer.valueOf(distance)).setValue(BOTTOM, Boolean.valueOf(this.isBottom(level, pos, distance)));
- if (blockState.getValue(DISTANCE) == 7) {
+ if (blockState.getValue(DISTANCE) == 7&& !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, blockState.getFluidState().createLegacyBlock()).isCancelled()) { // CraftBukkit - BlockFadeEvent // Paper - fix wrong block state
if (state.getValue(DISTANCE) == 7) {
FallingBlockEntity.fall(level, pos, blockState);
} else {

View File

@@ -0,0 +1,16 @@
--- a/net/minecraft/world/level/block/SculkBlock.java
+++ b/net/minecraft/world/level/block/SculkBlock.java
@@ -37,8 +_,11 @@
if (random.nextInt(growthSpawnCost) < charge) {
BlockPos blockPos = pos1.above();
BlockState randomGrowthState = this.getRandomGrowthState(level, blockPos, random, spreader.isWorldGeneration());
- level.setBlock(blockPos, randomGrowthState, 3);
- level.playSound(null, pos1, randomGrowthState.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F);
+ // CraftBukkit start - Call BlockSpreadEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, randomGrowthState, 3)) {
+ level.playSound(null, pos1, randomGrowthState.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F);
+ }
+ // CraftBukkit end
}
return Math.max(0, charge - growthSpawnCost);

View File

@@ -0,0 +1,21 @@
--- a/net/minecraft/world/level/block/SculkCatalystBlock.java
+++ b/net/minecraft/world/level/block/SculkCatalystBlock.java
@@ -61,8 +_,16 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);
+ // CraftBukkit start - Delegate to getExpDrop
+ }
+
+ @Override
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
if (dropExperience) {
- this.tryDropExperience(level, pos, stack, this.xpRange);
+ return this.tryDropExperience(level, pos, stack, this.xpRange);
}
- }
+
+ return 0;
+ // CraftBukkit end
+ }
}

View File

@@ -0,0 +1,77 @@
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -108,6 +_,18 @@
&& level.getBlockEntity(pos) instanceof SculkSensorBlockEntity sculkSensorBlockEntity
&& level instanceof ServerLevel serverLevel
&& sculkSensorBlockEntity.getVibrationUser().canReceiveVibration(serverLevel, pos, GameEvent.STEP, GameEvent.Context.of(state))) {
+ // CraftBukkit start
+ org.bukkit.event.Cancellable cancellable;
+ if (entity instanceof net.minecraft.world.entity.player.Player player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else {
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+ if (cancellable.isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
sculkSensorBlockEntity.getListener().forceScheduleVibration(serverLevel, GameEvent.STEP, GameEvent.Context.of(entity), entity.position());
}
@@ -200,10 +_,19 @@
}
public static boolean canActivate(BlockState state) {
- return getPhase(state) == SculkSensorPhase.INACTIVE;
+ return state.getBlock() instanceof SculkSensorBlock && getPhase(state) == SculkSensorPhase.INACTIVE; // Paper - Check for a valid type
}
public static void deactivate(Level level, BlockPos pos, BlockState state) {
+ // CraftBukkit start
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), 0);
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() > 0) {
+ level.setBlock(pos, state.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3);
+ return;
+ }
+ // CraftBukkit end
level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.COOLDOWN).setValue(POWER, Integer.valueOf(0)), 3);
level.scheduleTick(pos, state.getBlock(), 10);
updateNeighbours(level, pos, state);
@@ -215,6 +_,15 @@
}
public void activate(@Nullable Entity entity, Level level, BlockPos pos, BlockState state, int power, int frequency) {
+ // CraftBukkit start
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), power);
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() <= 0) {
+ return;
+ }
+ power = eventRedstone.getNewCurrent();
+ // CraftBukkit end
level.setBlock(pos, state.setValue(PHASE, SculkSensorPhase.ACTIVE).setValue(POWER, Integer.valueOf(power)), 3);
level.scheduleTick(pos, state.getBlock(), this.getActiveTicks());
updateNeighbours(level, pos, state);
@@ -292,8 +_,16 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);
+ // CraftBukkit start - Delegate to getExpDrop
+ }
+
+ @Override
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
if (dropExperience) {
- this.tryDropExperience(level, pos, stack, ConstantInt.of(5));
+ return this.tryDropExperience(level, pos, stack, ConstantInt.of(5));
}
- }
+
+ return 0;
+ // CraftBukkit end
+ }
}

View File

@@ -0,0 +1,28 @@
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -66,6 +_,7 @@
if (level instanceof ServerLevel serverLevel) {
ServerPlayer serverPlayer = SculkShriekerBlockEntity.tryGetPlayer(entity);
if (serverPlayer != null) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(serverPlayer, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null).isCancelled()) return; // CraftBukkit
serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryShriek(serverLevel, serverPlayer));
}
}
@@ -144,9 +_,16 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);
+ // CraftBukkit start - Delegate to getExpDrop
+ }
+
+ @Override
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
if (dropExperience) {
- this.tryDropExperience(level, pos, stack, ConstantInt.of(5));
+ return this.tryDropExperience(level, pos, stack, ConstantInt.of(5));
}
+ return 0;
+ // CraftBukkit end
}
@Nullable

View File

@@ -0,0 +1,55 @@
--- a/net/minecraft/world/level/block/SculkSpreader.java
+++ b/net/minecraft/world/level/block/SculkSpreader.java
@@ -25,6 +_,7 @@
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
+import net.minecraft.nbt.Tag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
@@ -50,6 +_,7 @@
private final int additionalDecayRate;
private List<SculkSpreader.ChargeCursor> cursors = new ArrayList<>();
private static final Logger LOGGER = LogUtils.getLogger();
+ public net.minecraft.world.level.Level level; // CraftBukkit
public SculkSpreader(
boolean isWorldGeneration, TagKey<Block> replaceableBlocks, int growthSpawnCoat, int noGrowthRadius, int chargeDecayRate, int additionalDecayRate
@@ -114,7 +_,7 @@
int min = Math.min(list.size(), 32);
for (int i = 0; i < min; i++) {
- this.addCursor(list.get(i));
+ this.addCursor(list.get(i), false); // Paper - don't fire event for block entity loading
}
}
}
@@ -130,13 +_,25 @@
public void addCursors(BlockPos pos, int charge) {
while (charge > 0) {
int min = Math.min(charge, 1000);
- this.addCursor(new SculkSpreader.ChargeCursor(pos, min));
+ this.addCursor(new SculkSpreader.ChargeCursor(pos, min), true); // Paper - allow firing event for other causes
charge -= min;
}
}
- private void addCursor(SculkSpreader.ChargeCursor cursor) {
+ private void addCursor(SculkSpreader.ChargeCursor cursor, boolean fireEvent) { // Paper - add boolean to conditionally fire SculkBloomEvent
if (this.cursors.size() < 32) {
+ // CraftBukkit start
+ if (!this.isWorldGeneration() && fireEvent) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation // Paper - add boolean to conditionally fire SculkBloomEvent
+ org.bukkit.craftbukkit.block.CraftBlock bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, cursor.pos);
+ org.bukkit.event.block.SculkBloomEvent event = new org.bukkit.event.block.SculkBloomEvent(bukkitBlock, cursor.getCharge());
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return;
+ }
+
+ cursor.charge = event.getCharge();
+ }
+ // CraftBukkit end
this.cursors.add(cursor);
}
}

View File

@@ -0,0 +1,31 @@
--- a/net/minecraft/world/level/block/SculkVeinBlock.java
+++ b/net/minecraft/world/level/block/SculkVeinBlock.java
@@ -90,14 +_,14 @@
public int attemptUseCharge(
SculkSpreader.ChargeCursor cursor, LevelAccessor level, BlockPos pos, RandomSource random, SculkSpreader spreader, boolean shouldConvertBlocks
) {
- if (shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random)) {
+ if (shouldConvertBlocks && this.attemptPlaceSculk(spreader, level, cursor.getPos(), random, pos)) { // CraftBukkit - add source block
return cursor.getCharge() - 1;
} else {
return random.nextInt(spreader.chargeDecayRate()) == 0 ? Mth.floor(cursor.getCharge() * 0.5F) : cursor.getCharge();
}
}
- private boolean attemptPlaceSculk(SculkSpreader spreader, LevelAccessor level, BlockPos pos, RandomSource random) {
+ private boolean attemptPlaceSculk(SculkSpreader spreader, LevelAccessor level, BlockPos pos, RandomSource random, BlockPos sourceBlock) { // CraftBukkit
BlockState blockState = level.getBlockState(pos);
TagKey<Block> tagKey = spreader.replaceableBlocks();
@@ -108,6 +_,11 @@
if (blockState1.is(tagKey)) {
BlockState blockState2 = Blocks.SCULK.defaultBlockState();
level.setBlock(blockPos, blockState2, 3);
+ // CraftBukkit start - Call BlockSpreadEvent
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, sourceBlock, blockPos, blockState2, 3)) {
+ return false;
+ }
+ // CraftBukkit end
Block.pushEntitiesUp(blockState1, blockState2, level, blockPos);
level.playSound(null, blockPos, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F);
this.veinSpreader.spreadAll(blockState2, level, blockPos, spreader.isWorldGeneration());

View File

@@ -0,0 +1,52 @@
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -100,8 +_,8 @@
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (level instanceof ServerLevel serverLevel
&& level.getBlockEntity(pos) instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity
- && canOpen(state, level, pos, shulkerBoxBlockEntity)) {
- player.openMenu(shulkerBoxBlockEntity);
+ && canOpen(state, level, pos, shulkerBoxBlockEntity) // Paper - Fix InventoryOpenEvent cancellation - expand if for belows check
+ && player.openMenu(shulkerBoxBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation) {
player.awardStat(Stats.OPEN_SHULKER_BOX);
PiglinAi.angerNearbyPiglins(serverLevel, player, true);
}
@@ -139,7 +_,7 @@
itemEntity.setDefaultPickUpDelay();
level.addFreshEntity(itemEntity);
} else {
- shulkerBoxBlockEntity.unpackLootTable(player);
+ shulkerBoxBlockEntity.unpackLootTable(player, true); // Paper - force clear loot table so replenish data isn't persisted in the stack
}
}
@@ -149,7 +_,15 @@
@Override
protected List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
BlockEntity blockEntity = params.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
+ Runnable reAdd = null; // Paper
if (blockEntity instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity) {
+ // Paper start - clear loot table if it was already used
+ if (shulkerBoxBlockEntity.lootableData().getLastFill() != -1 || !params.getLevel().paperConfig().lootables.retainUnlootedShulkerBoxLootTableOnNonPlayerBreak) {
+ net.minecraft.resources.ResourceKey<net.minecraft.world.level.storage.loot.LootTable> lootTableResourceKey = shulkerBoxBlockEntity.getLootTable();
+ reAdd = () -> shulkerBoxBlockEntity.setLootTable(lootTableResourceKey);
+ shulkerBoxBlockEntity.setLootTable(null);
+ }
+ // Paper end
params = params.withDynamicDrop(CONTENTS, output -> {
for (int i = 0; i < shulkerBoxBlockEntity.getContainerSize(); i++) {
output.accept(shulkerBoxBlockEntity.getItem(i));
@@ -157,7 +_,13 @@
});
}
+ // Paper start - re-set loot table if it was cleared
+ try {
return super.getDrops(state, params);
+ } finally {
+ if (reAdd != null) reAdd.run();
+ }
+ // Paper end - re-set loot table if it was cleared
}
@Override

View File

@@ -0,0 +1,53 @@
--- a/net/minecraft/world/level/block/SignBlock.java
+++ b/net/minecraft/world/level/block/SignBlock.java
@@ -134,7 +_,7 @@
} else if (!this.otherPlayerIsEditingSign(player, signBlockEntity)
&& player.mayBuild()
&& this.hasEditableText(player, signBlockEntity, isFacingFrontText)) {
- this.openTextEdit(player, signBlockEntity, isFacingFrontText);
+ this.openTextEdit(player, signBlockEntity, isFacingFrontText, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper - Add PlayerOpenSignEvent
return InteractionResult.SUCCESS_SERVER;
} else {
return InteractionResult.PASS;
@@ -176,7 +_,33 @@
return woodType;
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - Add PlayerOpenSignEvent
public void openTextEdit(Player player, SignBlockEntity signEntity, boolean isFrontText) {
+ // Paper start - Add PlayerOpenSignEvent
+ this.openTextEdit(player, signEntity, isFrontText, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.UNKNOWN);
+ }
+ public void openTextEdit(Player player, SignBlockEntity signEntity, boolean isFrontText, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause cause) {
+ org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) player.getBukkitEntity();
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(signEntity.getLevel(), signEntity.getBlockPos());
+ org.bukkit.craftbukkit.block.CraftSign<?> bukkitSign = (org.bukkit.craftbukkit.block.CraftSign<?>) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(bukkitBlock);
+ io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent(
+ bukkitPlayer,
+ bukkitSign,
+ isFrontText ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
+ cause);
+ if (!event.callEvent()) return;
+ if (org.bukkit.event.player.PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ final org.bukkit.event.player.PlayerSignOpenEvent.Cause legacyCause = switch (cause) {
+ case PLACE -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE;
+ case PLUGIN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLUGIN;
+ case INTERACT -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT;
+ case UNKNOWN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN;
+ };
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(player, signEntity, isFrontText, legacyCause)) {
+ // Paper end - Add PlayerOpenSignEvent
+ return;
+ }
+ } // Paper - Add PlayerOpenSignEvent
signEntity.setAllowedPlayerEditor(player.getUUID());
player.openTextEdit(signEntity, isFrontText);
}
@@ -189,6 +_,6 @@
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
- return createTickerHelper(blockEntityType, BlockEntityType.SIGN, SignBlockEntity::tick);
+ return null; // Craftbukkit - remove unnecessary sign ticking
}
}

View File

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

View File

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

View File

@@ -0,0 +1,53 @@
--- a/net/minecraft/world/level/block/SnifferEggBlock.java
+++ b/net/minecraft/world/level/block/SnifferEggBlock.java
@@ -61,12 +_,31 @@
return this.getHatchLevel(state) == 2;
}
+ // Paper start - Call BlockFadeEvent
+ private void rescheduleTick(ServerLevel world, BlockPos pos) {
+ int baseDelay = hatchBoost(world, pos) ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper - Configure sniffer egg hatch time
+ world.scheduleTick(pos, this, (baseDelay / 3) + world.random.nextInt(RANDOM_HATCH_OFFSET_TICKS));
+ // reschedule to avoid being stuck here and behave like the other calls (see #onPlace)
+ }
+ // Paper end - Call BlockFadeEvent
+
@Override
public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!this.isReadyToHatch(state)) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2)) {
+ this.rescheduleTick(level, pos);
+ return;
+ }
+ // Paper end
level.playSound(null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
- level.setBlock(pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2);
} else {
+ // Paper start - Call BlockFadeEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, state.getFluidState().createLegacyBlock()).isCancelled()) {
+ this.rescheduleTick(level, pos);
+ return;
+ }
+ // Paper end - Call BlockFadeEvent
level.playSound(null, pos, SoundEvents.SNIFFER_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
level.destroyBlock(pos, false);
Sniffer sniffer = EntityType.SNIFFER.create(level, EntitySpawnReason.BREEDING);
@@ -74,7 +_,7 @@
Vec3 center = pos.getCenter();
sniffer.setBaby(true);
sniffer.moveTo(center.x(), center.y(), center.z(), Mth.wrapDegrees(level.random.nextFloat() * 360.0F), 0.0F);
- level.addFreshEntity(sniffer);
+ level.addFreshEntity(sniffer, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason
}
}
}
@@ -86,7 +_,7 @@
level.levelEvent(3009, pos, 0);
}
- int i = flag ? 12000 : 24000;
+ int i = flag ? level.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : level.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper
int i1 = i / 3;
level.gameEvent(GameEvent.BLOCK_PLACE, pos, GameEvent.Context.of(state));
level.scheduleTick(pos, this, i1 + level.random.nextInt(300));

View File

@@ -0,0 +1,14 @@
--- a/net/minecraft/world/level/block/SnowLayerBlock.java
+++ b/net/minecraft/world/level/block/SnowLayerBlock.java
@@ -123,6 +_,11 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (level.getBrightness(LightLayer.BLOCK, pos) > 11) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
dropResources(state, level, pos);
level.removeBlock(pos, false);
}

View File

@@ -0,0 +1,24 @@
--- a/net/minecraft/world/level/block/SpawnerBlock.java
+++ b/net/minecraft/world/level/block/SpawnerBlock.java
@@ -46,11 +_,19 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience);
+ // CraftBukkit start - Delegate to getExpDrop
+ }
+
+ @Override
+ public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
if (dropExperience) {
int i = 15 + level.random.nextInt(15) + level.random.nextInt(15);
- this.popExperience(level, pos, i);
+ // this.popExperience(level, pos, i);
+ return i;
}
- }
+ return 0;
+ // CraftBukkit end
+ }
@Override
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {

View File

@@ -0,0 +1,98 @@
--- a/net/minecraft/world/level/block/SpongeBlock.java
+++ b/net/minecraft/world/level/block/SpongeBlock.java
@@ -50,7 +_,8 @@
}
private boolean removeWaterBreadthFirstSearch(Level level, BlockPos pos) {
- return BlockPos.breadthFirstTraversal(
+ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(level); // CraftBukkit - Use BlockStateListPopulator
+ BlockPos.breadthFirstTraversal(
pos,
6,
65,
@@ -63,16 +_,18 @@
if (blockPos.equals(pos)) {
return BlockPos.TraversalNodeStatus.ACCEPT;
} else {
- BlockState blockState = level.getBlockState(blockPos);
- FluidState fluidState = level.getFluidState(blockPos);
+ // CraftBukkit start
+ BlockState blockState = blockList.getBlockState(blockPos);
+ FluidState fluidState = blockList.getFluidState(blockPos);
+ // CraftBukkit end
if (!fluidState.is(FluidTags.WATER)) {
return BlockPos.TraversalNodeStatus.SKIP;
} else if (blockState.getBlock() instanceof BucketPickup bucketPickup
- && !bucketPickup.pickupBlock(null, level, blockPos, blockState).isEmpty()) {
+ && !bucketPickup.pickupBlock(null, blockList, blockPos, blockState).isEmpty()) { // CraftBukkit
return BlockPos.TraversalNodeStatus.ACCEPT;
} else {
if (blockState.getBlock() instanceof LiquidBlock) {
- level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3);
+ blockList.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit
} else {
if (!blockState.is(Blocks.KELP)
&& !blockState.is(Blocks.KELP_PLANT)
@@ -81,16 +_,57 @@
return BlockPos.TraversalNodeStatus.SKIP;
}
- BlockEntity blockEntity = blockState.hasBlockEntity() ? level.getBlockEntity(blockPos) : null;
- dropResources(blockState, level, blockPos, blockEntity);
- level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3);
+ // CraftBukkit start
+ // BlockEntity blockEntity = blockState.hasBlockEntity() ? level.getBlockEntity(blockPos) : null;
+ // dropResources(blockState, level, blockPos, blockEntity);
+ // level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3);
+ blockList.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3);
+ // CraftBukkit end
}
return BlockPos.TraversalNodeStatus.ACCEPT;
}
}
}
- )
- > 1;
+ );
+ // CraftBukkit start
+ java.util.List<org.bukkit.craftbukkit.block.CraftBlockState> blocks = blockList.getList(); // Is a clone
+ if (!blocks.isEmpty()) {
+ final org.bukkit.block.Block bblock = level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+
+ org.bukkit.event.block.SpongeAbsorbEvent event = new org.bukkit.event.block.SpongeAbsorbEvent(bblock, (java.util.List<org.bukkit.block.BlockState>) (java.util.List) blocks);
+ level.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return false;
+ }
+
+ for (org.bukkit.craftbukkit.block.CraftBlockState block : blocks) {
+ BlockPos blockposition1 = block.getPosition();
+ BlockState iblockdata = level.getBlockState(blockposition1);
+ FluidState fluid = level.getFluidState(blockposition1);
+
+ if (fluid.is(FluidTags.WATER)) {
+ if (iblockdata.getBlock() instanceof BucketPickup && !((BucketPickup) iblockdata.getBlock()).pickupBlock(null, blockList, blockposition1, iblockdata).isEmpty()) {
+ // NOP
+ } else if (iblockdata.getBlock() instanceof LiquidBlock) {
+ // NOP
+ } else if (iblockdata.is(Blocks.KELP) || iblockdata.is(Blocks.KELP_PLANT) || iblockdata.is(Blocks.SEAGRASS) || iblockdata.is(Blocks.TALL_SEAGRASS)) {
+ BlockEntity tileentity = iblockdata.hasBlockEntity() ? level.getBlockEntity(blockposition1) : null;
+
+ // Paper start - Fix SpongeAbsortEvent handling
+ if (block.getHandle().isAir()) {
+ dropResources(iblockdata, level, blockposition1, tileentity);
+ }
+ // Paper end - Fix SpongeAbsortEvent handling
+ }
+ }
+ level.setBlock(blockposition1, block.getHandle(), block.getFlag());
+ }
+
+ return true;
+ }
+ return false;
+ // CraftBukkit end
}
}

View File

@@ -0,0 +1,25 @@
--- a/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
+++ b/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
@@ -39,7 +_,13 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
+ if (this instanceof GrassBlock && level.paperConfig().tickRates.grassSpread != 1 && (level.paperConfig().tickRates.grassSpread < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % level.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - Configurable random tick rates for blocks
if (!canBeGrass(state, level, pos)) {
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
level.setBlockAndUpdate(pos, Blocks.DIRT.defaultBlockState());
} else {
if (level.getMaxLocalRawBrightness(pos.above()) >= 9) {
@@ -48,7 +_,7 @@
for (int i = 0; i < 4; i++) {
BlockPos blockPos = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
if (level.getBlockState(blockPos).is(Blocks.DIRT) && canPropagate(blockState, level, blockPos)) {
- level.setBlockAndUpdate(blockPos, blockState.setValue(SNOWY, Boolean.valueOf(isSnowySetting(level.getBlockState(blockPos.above())))));
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, blockState.setValue(SNOWY, Boolean.valueOf(isSnowySetting(level.getBlockState(blockPos.above()))))); // CraftBukkit
}
}
}

View File

@@ -0,0 +1,38 @@
--- a/net/minecraft/world/level/block/StemBlock.java
+++ b/net/minecraft/world/level/block/StemBlock.java
@@ -80,11 +_,11 @@
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (level.getRawBrightness(pos, 0) >= 9) {
float growthSpeed = CropBlock.getGrowthSpeed(this, level, pos);
- if (random.nextInt((int)(25.0F / growthSpeed) + 1) == 0) {
+ if (random.nextFloat() < ((this == Blocks.PUMPKIN_STEM ? level.spigotConfig.pumpkinModifier : level.spigotConfig.melonModifier) / (100.0f * (Math.floor((25.0F / growthSpeed) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution
int ageValue = state.getValue(AGE);
if (ageValue < 7) {
state = state.setValue(AGE, Integer.valueOf(ageValue + 1));
- level.setBlock(pos, state, 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state, 2); // CraftBukkit
} else {
Direction randomDirection = Direction.Plane.HORIZONTAL.getRandomDirection(random);
BlockPos blockPos = pos.relative(randomDirection);
@@ -94,7 +_,11 @@
Optional<Block> optional = registry.getOptional(this.fruit);
Optional<Block> optional1 = registry.getOptional(this.attachedStem);
if (optional.isPresent() && optional1.isPresent()) {
- level.setBlockAndUpdate(blockPos, optional.get().defaultBlockState());
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, blockPos, optional.get().defaultBlockState())) {
+ return;
+ }
+ // CraftBukkit end
level.setBlockAndUpdate(pos, optional1.get().defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, randomDirection));
}
}
@@ -122,7 +_,7 @@
public void performBonemeal(ServerLevel level, RandomSource random, BlockPos pos, BlockState state) {
int min = Math.min(7, state.getValue(AGE) + Mth.nextInt(level.random, 2, 5));
BlockState blockState = state.setValue(AGE, Integer.valueOf(min));
- level.setBlock(pos, blockState, 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, blockState, 2); // CraftBukkit
if (min == 7) {
blockState.randomTick(level, pos, level.random);
}

View File

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

View File

@@ -0,0 +1,20 @@
--- a/net/minecraft/world/level/block/SugarCaneBlock.java
+++ b/net/minecraft/world/level/block/SugarCaneBlock.java
@@ -56,12 +_,13 @@
i++;
}
- if (i < 3) {
+ if (i < level.paperConfig().maxGrowthHeight.reeds) { // Paper - Configurable cactus/bamboo/reed growth height
int ageValue = state.getValue(AGE);
- if (ageValue == 15) {
- level.setBlockAndUpdate(pos.above(), this.defaultBlockState());
+ int modifier = level.spigotConfig.caneModifier; // Spigot - SPIGOT-7159: Better modifier resolution
+ if (ageValue >= 15 || (modifier != 100 && random.nextFloat() < (modifier / (100.0f * 16)))) { // Spigot - SPIGOT-7159: Better modifier resolution
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos.above(), this.defaultBlockState()); // CraftBukkit
level.setBlock(pos, state.setValue(AGE, Integer.valueOf(0)), 4);
- } else {
+ } else if (modifier == 100 || random.nextFloat() < (modifier / (100.0f * 16))) { // Spigot - SPIGOT-7159: Better modifier resolution
level.setBlock(pos, state.setValue(AGE, Integer.valueOf(ageValue + 1)), 4);
}
}

View File

@@ -0,0 +1,48 @@
--- a/net/minecraft/world/level/block/SweetBerryBushBlock.java
+++ b/net/minecraft/world/level/block/SweetBerryBushBlock.java
@@ -68,15 +_,17 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
int ageValue = state.getValue(AGE);
- if (ageValue < 3 && random.nextInt(5) == 0 && level.getRawBrightness(pos.above(), 0) >= 9) {
+ if (ageValue < 3 && random.nextFloat() < (level.spigotConfig.sweetBerryModifier / (100.0f * 5)) && level.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
BlockState blockState = state.setValue(AGE, Integer.valueOf(ageValue + 1));
- level.setBlock(pos, blockState, 2);
+ // level.setBlock(pos, blockState, 2);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, blockState, 2)) return; // CraftBukkit
level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(blockState));
}
}
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) {
entity.makeStuckInBlock(state, new Vec3(0.8F, 0.75, 0.8F));
if (level instanceof ServerLevel serverLevel && state.getValue(AGE) != 0) {
@@ -85,7 +_,7 @@
double abs = Math.abs(vec3.x());
double abs1 = Math.abs(vec3.z());
if (abs >= 0.003F || abs1 >= 0.003F) {
- entity.hurtServer(serverLevel, level.damageSources().sweetBerryBush(), 1.0F);
+ entity.hurtServer(serverLevel, level.damageSources().sweetBerryBush().directBlock(level, pos), 1.0F); // CraftBukkit
}
}
}
@@ -109,7 +_,15 @@
boolean flag = ageValue == 3;
if (ageValue > 1) {
int i = 1 + level.random.nextInt(2);
- popResource(level, pos, new ItemStack(Items.SWEET_BERRIES, i + (flag ? 1 : 0)));
+ // CraftBukkit start - useWithoutItem is always MAIN_HAND
+ org.bukkit.event.player.PlayerHarvestBlockEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, player, InteractionHand.MAIN_HAND, java.util.Collections.singletonList(new ItemStack(Items.SWEET_BERRIES, i + (flag ? 1 : 0))));
+ 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()) {
+ popResource(level, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemStack));
+ }
+ // CraftBukkit end
level.playSound(null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + level.random.nextFloat() * 0.4F);
BlockState blockState = state.setValue(AGE, Integer.valueOf(1));
level.setBlock(pos, blockState, 2);

View File

@@ -0,0 +1,43 @@
--- a/net/minecraft/world/level/block/TargetBlock.java
+++ b/net/minecraft/world/level/block/TargetBlock.java
@@ -42,6 +_,10 @@
@Override
protected void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) {
int i = updateRedstoneOutput(level, state, hit, projectile);
+ // Paper start - Add TargetHitEvent
+ }
+ private static void awardTargetHitCriteria(Projectile projectile, BlockHitResult hit, int i) {
+ // Paper end - Add TargetHitEvent
if (projectile.getOwner() instanceof ServerPlayer serverPlayer) {
serverPlayer.awardStat(Stats.TARGET_HIT);
CriteriaTriggers.TARGET_BLOCK_HIT.trigger(serverPlayer, projectile, hit.getLocation(), i);
@@ -51,9 +_,29 @@
private static int updateRedstoneOutput(LevelAccessor level, BlockState state, BlockHitResult hit, Entity projectile) {
int redstoneStrength = getRedstoneStrength(hit, hit.getLocation());
int i = projectile instanceof AbstractArrow ? 20 : 8;
+ // Paper start - Add TargetHitEvent
+ boolean shouldAward = false;
+ if (projectile instanceof Projectile) {
+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, hit.getBlockPos());
+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(hit.getDirection());
+ final io.papermc.paper.event.block.TargetHitEvent targetHitEvent = new io.papermc.paper.event.block.TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i);
+ if (targetHitEvent.callEvent()) {
+ i = targetHitEvent.getSignalStrength();
+ shouldAward = true;
+ } else {
+ return i;
+ }
+ }
+ // Paper end - Add TargetHitEvent
if (!level.getBlockTicks().hasScheduledTick(hit.getBlockPos(), state.getBlock())) {
setOutputPower(level, state, redstoneStrength, hit.getBlockPos(), i);
}
+
+ // Paper start - Award Hit Criteria after Block Update
+ if (shouldAward) {
+ awardTargetHitCriteria((Projectile) projectile, hit, i);
+ }
+ // Paper end - Award Hit Criteria after Block Update
return redstoneStrength;
}

View File

@@ -0,0 +1,91 @@
--- a/net/minecraft/world/level/block/TntBlock.java
+++ b/net/minecraft/world/level/block/TntBlock.java
@@ -45,7 +_,13 @@
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
if (!oldState.is(state.getBlock())) {
- if (level.hasNeighborSignal(pos)) {
+ if (level.hasNeighborSignal(pos) && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
+ return;
+ }
+ // Paper end - TNTPrimeEvent
explode(level, pos);
level.removeBlock(pos, false);
}
@@ -54,7 +_,13 @@
@Override
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston) {
- if (level.hasNeighborSignal(pos)) {
+ if (level.hasNeighborSignal(pos) && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
+ return;
+ }
+ // Paper end - TNTPrimeEvent
explode(level, pos);
level.removeBlock(pos, false);
}
@@ -62,7 +_,7 @@
@Override
public BlockState playerWillDestroy(Level level, BlockPos pos, BlockState state, Player player) {
- if (!level.isClientSide() && !player.isCreative() && state.getValue(UNSTABLE)) {
+ if (!level.isClientSide() && !player.isCreative() && state.getValue(UNSTABLE) && org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.BLOCK_BREAK, player, null)) { // CraftBukkit - TNTPrimeEvent
explode(level, pos);
}
@@ -71,6 +_,13 @@
@Override
public void wasExploded(ServerLevel level, BlockPos pos, Explosion explosion) {
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ org.bukkit.entity.Entity source = explosion.getDirectSourceEntity() != null ? explosion.getDirectSourceEntity().getBukkitEntity() : null;
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) {
+ return;
+ }
+ // Paper end - TNTPrimeEvent
PrimedTnt primedTnt = new PrimedTnt(level, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, explosion.getIndirectSourceEntity());
int fuse = primedTnt.getFuse();
primedTnt.setFuse((short)(level.random.nextInt(fuse / 4) + fuse / 8));
@@ -97,6 +_,17 @@
if (!stack.is(Items.FLINT_AND_STEEL) && !stack.is(Items.FIRE_CHARGE)) {
return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
} else {
+ // CraftBukkit start - TNTPrimeEvent
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.PLAYER, player, null)) {
+ return InteractionResult.CONSUME;
+ }
+ // CraftBukkit end
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) {
+ return InteractionResult.FAIL;
+ }
+ // Paper end - TNTPrimeEvent
explode(level, pos, player);
level.setBlock(pos, Blocks.AIR.defaultBlockState(), 11);
Item item = stack.getItem();
@@ -117,6 +_,17 @@
BlockPos blockPos = hit.getBlockPos();
Entity owner = projectile.getOwner();
if (projectile.isOnFire() && projectile.mayInteract(serverLevel, blockPos)) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockPos, state.getFluidState().createLegacyBlock()) || !org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, blockPos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.PROJECTILE, projectile, null)) { // Paper - fix wrong block state
+ return;
+ }
+ // CraftBukkit end
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPos);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) {
+ return;
+ }
+ // Paper end - TNTPrimeEvent
explode(level, blockPos, owner instanceof LivingEntity ? (LivingEntity)owner : null);
level.removeBlock(blockPos, false);
}

View File

@@ -0,0 +1,44 @@
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -146,7 +_,40 @@
if (!level.isClientSide) {
boolean hasNeighborSignal = level.hasNeighborSignal(pos);
if (hasNeighborSignal != state.getValue(POWERED)) {
- if (state.getValue(OPEN) != hasNeighborSignal) {
+ // if (state.getValue(OPEN) != hasNeighborSignal) {
+ // CraftBukkit start
+ org.bukkit.World bworld = level.getWorld();
+ org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+
+ int power = bblock.getBlockPower();
+ int oldPower = state.getValue(TrapDoorBlock.OPEN) ? 15 : 0;
+
+ if (oldPower == 0 ^ power == 0 || neighborBlock.defaultBlockState().isSignalSource()) {
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bblock, oldPower, power);
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
+ hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
+ }
+ // CraftBukkit end
+ // Paper start - break redstone on trapdoors early
+ boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal;
+ // note: this must run before any state for this block/its neighborus are written to the world
+ // we allow the redstone event to fire so that plugins can block
+ if (hasNeighborSignal && open) { // if we are now powered and it caused the trap door to open
+ // in this case, first check for the redstone on top first
+ BlockPos abovePos = pos.above();
+ BlockState above = level.getBlockState(abovePos);
+ if (above.getBlock() instanceof RedStoneWireBlock) {
+ level.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
+ Block.popResource(level, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
+ // now check that this didn't change our state
+ if (level.getBlockState(pos) != state) {
+ // our state was changed, so we cannot propagate this update
+ return;
+ }
+ }
+ }
+ if (open) {
+ // Paper end - break redstone on trapdoors early
state = state.setValue(OPEN, Boolean.valueOf(hasNeighborSignal));
this.playSound(null, level, pos, hasNeighborSignal);
}

View File

@@ -0,0 +1,108 @@
--- a/net/minecraft/world/level/block/TripWireBlock.java
+++ b/net/minecraft/world/level/block/TripWireBlock.java
@@ -72,6 +_,7 @@
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return this.defaultBlockState(); // Paper - place tripwire without updating
BlockGetter level = context.getLevel();
BlockPos clickedPos = context.getClickedPos();
return this.defaultBlockState()
@@ -92,6 +_,7 @@
BlockState neighborState,
RandomSource random
) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return state; // Paper - prevent tripwire from updating
return direction.getAxis().isHorizontal()
? state.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.valueOf(this.shouldConnectTo(neighborState, direction)))
: super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
@@ -99,6 +_,7 @@
@Override
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!oldState.is(state.getBlock())) {
this.updateSource(level, pos, state);
}
@@ -106,6 +_,7 @@
@Override
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!isMoving && !state.is(newState.getBlock())) {
this.updateSource(level, pos, state.setValue(POWERED, Boolean.valueOf(true)));
}
@@ -113,6 +_,7 @@
@Override
public BlockState playerWillDestroy(Level level, BlockPos pos, BlockState state, Player player) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return state; // Paper - prevent disarming tripwires
if (!level.isClientSide && !player.getMainHandItem().isEmpty() && player.getMainHandItem().is(Items.SHEARS)) {
level.setBlock(pos, state.setValue(DISARMED, Boolean.valueOf(true)), 4);
level.gameEvent(player, GameEvent.SHEAR, pos);
@@ -122,6 +_,7 @@
}
private void updateSource(Level level, BlockPos pos, BlockState state) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
for (Direction direction : new Direction[]{Direction.SOUTH, Direction.WEST}) {
for (int i = 1; i < 42; i++) {
BlockPos blockPos = pos.relative(direction, i);
@@ -147,6 +_,8 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent tripwires from detecting collision
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!level.isClientSide) {
if (!state.getValue(POWERED)) {
this.checkPressed(level, pos, List.of(entity));
@@ -156,6 +_,7 @@
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent tripwire pressed check
if (level.getBlockState(pos).getValue(POWERED)) {
this.checkPressed(level, pos);
}
@@ -179,6 +_,40 @@
}
}
}
+
+ // CraftBukkit start - Call interact even when triggering connected tripwire
+ if (flag != poweredValue && poweredValue && blockState.getValue(TripWireBlock.ATTACHED)) {
+ org.bukkit.World bworld = level.getWorld();
+ org.bukkit.plugin.PluginManager manager = level.getCraftServer().getPluginManager();
+ org.bukkit.block.Block block = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ boolean allowed = false;
+
+ // If all the events are cancelled block the tripwire trigger, else allow
+ for (Object object : entities) {
+ if (object != null) {
+ org.bukkit.event.Cancellable cancellable;
+
+ if (object instanceof Player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((Player) object, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else if (object instanceof Entity) {
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(((Entity) object).getBukkitEntity(), block);
+ manager.callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ } else {
+ continue;
+ }
+
+ if (!cancellable.isCancelled()) {
+ allowed = true;
+ break;
+ }
+ }
+ }
+
+ if (!allowed) {
+ return;
+ }
+ }
+ // CraftBukkit end
if (flag != poweredValue) {
blockState = blockState.setValue(POWERED, Boolean.valueOf(flag));

View File

@@ -0,0 +1,21 @@
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -173,9 +_,18 @@
notifyNeighbors(block, level, blockPosx, opposite);
emitState(level, blockPosx, flag2, flag3, flag, flag1);
}
+ // CraftBukkit start
+ org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), 15, 0);
+ level.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() > 0) {
+ return;
+ }
+ // CraftBukkit end
emitState(level, pos, flag2, flag3, flag, flag1);
if (!attaching) {
+ if (level.getBlockState(pos).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - Validate tripwire hook placement before update
level.setBlock(pos, blockState1.setValue(FACING, direction), 3);
if (shouldNotifyNeighbours) {
notifyNeighbors(block, level, pos, direction);

View File

@@ -0,0 +1,64 @@
--- a/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -74,6 +_,19 @@
&& level instanceof ServerLevel serverLevel
&& this.canDestroyEgg(serverLevel, entity)
&& level.random.nextInt(chance) == 0) {
+ // CraftBukkit start - Step on eggs
+ 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 org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+
+ if (cancellable.isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
this.decreaseEggs(serverLevel, pos, state);
}
}
@@ -95,10 +_,20 @@
if (this.shouldUpdateHatchLevel(level) && onSand(level, pos)) {
int hatchValue = state.getValue(HATCH);
if (hatchValue < 2) {
+ // CraftBukkit start - Call BlockGrowEvent
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(TurtleEggBlock.HATCH, hatchValue + 1), 2)) {
+ return;
+ }
+ // CraftBukkit end
level.playSound(null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
- level.setBlock(pos, state.setValue(HATCH, Integer.valueOf(hatchValue + 1)), 2);
+ // level.setBlock(pos, state.setValue(HATCH, Integer.valueOf(hatchValue + 1)), 2); // CraftBukkit - handled above
level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state));
} else {
+ // CraftBukkit start - Call BlockFadeEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, Blocks.AIR.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
level.playSound(null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
level.removeBlock(pos, false);
level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state));
@@ -110,7 +_,7 @@
turtle.setAge(-24000);
turtle.setHomePos(pos);
turtle.moveTo(pos.getX() + 0.3 + i * 0.2, pos.getY(), pos.getZ() + 0.3, 0.0F, 0.0F);
- level.addFreshEntity(turtle);
+ level.addFreshEntity(turtle, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // CraftBukkit
}
}
}
@@ -138,8 +_,8 @@
}
@Override
- public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity te, ItemStack stack) {
- super.playerDestroy(level, player, pos, state, te, stack);
+ public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity te, ItemStack stack, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(level, player, pos, state, te, stack, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
this.decreaseEggs(level, pos, state);
}

View File

@@ -0,0 +1,68 @@
--- a/net/minecraft/world/level/block/VineBlock.java
+++ b/net/minecraft/world/level/block/VineBlock.java
@@ -191,7 +_,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (level.getGameRules().getBoolean(GameRules.RULE_DO_VINES_SPREAD)) {
- if (random.nextInt(4) == 0) {
+ if (random.nextFloat() < (level.spigotConfig.vineModifier / (100.0f * 4))) { // Spigot - SPIGOT-7159: Better modifier resolution
Direction random1 = Direction.getRandom(random);
BlockPos blockPos = pos.above();
if (random1.getAxis().isHorizontal() && !state.getValue(getPropertyForFace(random1))) {
@@ -205,28 +_,31 @@
boolean value1 = state.getValue(getPropertyForFace(counterClockWise));
BlockPos blockPos2 = blockPos1.relative(clockWise);
BlockPos blockPos3 = blockPos1.relative(counterClockWise);
+ // CraftBukkit start - Call BlockSpreadEvent
+ BlockPos source = pos;
if (value && isAcceptableNeighbour(level, blockPos2, clockWise)) {
- level.setBlock(blockPos1, this.defaultBlockState().setValue(getPropertyForFace(clockWise), Boolean.valueOf(true)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, source, blockPos1, this.defaultBlockState().setValue(getPropertyForFace(clockWise), Boolean.valueOf(true)), 2);
} else if (value1 && isAcceptableNeighbour(level, blockPos3, counterClockWise)) {
- level.setBlock(blockPos1, this.defaultBlockState().setValue(getPropertyForFace(counterClockWise), Boolean.valueOf(true)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, source, blockPos1, this.defaultBlockState().setValue(getPropertyForFace(counterClockWise), Boolean.valueOf(true)), 2);
} else {
Direction opposite = random1.getOpposite();
if (value && level.isEmptyBlock(blockPos2) && isAcceptableNeighbour(level, pos.relative(clockWise), opposite)) {
- level.setBlock(blockPos2, this.defaultBlockState().setValue(getPropertyForFace(opposite), Boolean.valueOf(true)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, source, blockPos2, this.defaultBlockState().setValue(getPropertyForFace(opposite), Boolean.valueOf(true)), 2);
} else if (value1 && level.isEmptyBlock(blockPos3) && isAcceptableNeighbour(level, pos.relative(counterClockWise), opposite)) {
- level.setBlock(blockPos3, this.defaultBlockState().setValue(getPropertyForFace(opposite), Boolean.valueOf(true)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, source, blockPos3, this.defaultBlockState().setValue(getPropertyForFace(opposite), Boolean.valueOf(true)), 2);
} else if (random.nextFloat() < 0.05 && isAcceptableNeighbour(level, blockPos1.above(), Direction.UP)) {
- level.setBlock(blockPos1, this.defaultBlockState().setValue(UP, Boolean.valueOf(true)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, source, blockPos1, this.defaultBlockState().setValue(UP, Boolean.valueOf(true)), 2);
}
+ // CraftBukkit end
}
} else if (isAcceptableNeighbour(level, blockPos1, random1)) {
- level.setBlock(pos, state.setValue(getPropertyForFace(random1), Boolean.valueOf(true)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, (BlockState) state.setValue(VineBlock.getPropertyForFace(random1), true), 2); // CraftBukkit
}
}
} else {
if (random1 == Direction.UP && pos.getY() < level.getMaxY()) {
if (this.canSupportAtFace(level, pos, random1)) {
- level.setBlock(pos, state.setValue(UP, Boolean.valueOf(true)), 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(level, pos, state.setValue(UP, Boolean.valueOf(true)), 2); // CraftBukkit
return;
}
@@ -244,7 +_,7 @@
}
if (this.hasHorizontalConnection(blockState1)) {
- level.setBlock(blockPos, blockState1, 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos, blockState1, 2); // CraftBukkit
}
return;
@@ -258,7 +_,7 @@
BlockState blockState2 = blockState.isAir() ? this.defaultBlockState() : blockState;
BlockState blockState3 = this.copyRandomFaces(state, blockState2, random);
if (blockState2 != blockState3 && this.hasHorizontalConnection(blockState3)) {
- level.setBlock(blockPos1, blockState3, 2);
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(level, pos, blockPos1, blockState3, 2); // CraftBukkit
}
}
}

View File

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

View File

@@ -0,0 +1,17 @@
--- a/net/minecraft/world/level/block/WaterlilyBlock.java
+++ b/net/minecraft/world/level/block/WaterlilyBlock.java
@@ -29,8 +_,14 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
super.entityInside(state, level, pos, entity);
if (level instanceof ServerLevel && entity instanceof AbstractBoat) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
+ return;
+ }
+ // CraftBukkit end
level.destroyBlock(new BlockPos(pos), true, entity);
}
}

View File

@@ -0,0 +1,10 @@
--- a/net/minecraft/world/level/block/WebBlock.java
+++ b/net/minecraft/world/level/block/WebBlock.java
@@ -24,6 +_,7 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
Vec3 vec3 = new Vec3(0.25, 0.05F, 0.25);
if (entity instanceof LivingEntity livingEntity && livingEntity.hasEffect(MobEffects.WEAVING)) {
vec3 = new Vec3(0.5, 0.25, 0.5);

View File

@@ -0,0 +1,39 @@
--- a/net/minecraft/world/level/block/WeightedPressurePlateBlock.java
+++ b/net/minecraft/world/level/block/WeightedPressurePlateBlock.java
@@ -6,6 +_,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
+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;
@@ -39,7 +_,27 @@
@Override
protected int getSignalStrength(Level level, BlockPos pos) {
- int min = Math.min(getEntityCount(level, TOUCH_AABB.move(pos), Entity.class), this.maxWeight);
+ // CraftBukkit start
+ // int min = Math.min(getEntityCount(level, TOUCH_AABB.move(pos), Entity.class), this.maxWeight);
+ int min = 0;
+ for (Entity entity : getEntities(level, WeightedPressurePlateBlock.TOUCH_AABB.move(pos), Entity.class)) {
+ 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 org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+
+ // We only want to block turning the plate on if all events are cancelled
+ if (!cancellable.isCancelled()) {
+ min++;
+ }
+ }
+
+ min = Math.min(min, this.maxWeight);
+ // CraftBukkit end
if (min > 0) {
float f = (float)Math.min(this.maxWeight, min) / this.maxWeight;
return Mth.ceil(f * 15.0F);

View File

@@ -0,0 +1,16 @@
--- a/net/minecraft/world/level/block/WitherRoseBlock.java
+++ b/net/minecraft/world/level/block/WitherRoseBlock.java
@@ -63,11 +_,12 @@
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (level instanceof ServerLevel serverLevel
&& level.getDifficulty() != Difficulty.PEACEFUL
&& entity instanceof LivingEntity livingEntity
&& !livingEntity.isInvulnerableTo(serverLevel, level.damageSources().wither())) {
- livingEntity.addEffect(this.getBeeInteractionEffect());
+ livingEntity.addEffect(this.getBeeInteractionEffect(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WITHER_ROSE); // CraftBukkit
}
}

View File

@@ -0,0 +1,39 @@
--- a/net/minecraft/world/level/block/WitherSkullBlock.java
+++ b/net/minecraft/world/level/block/WitherSkullBlock.java
@@ -51,6 +_,7 @@
}
public static void checkSpawn(Level level, BlockPos pos, SkullBlockEntity blockEntity) {
+ if (level.captureBlockStates) return; // CraftBukkit
if (!level.isClientSide) {
BlockState blockState = blockEntity.getBlockState();
boolean flag = blockState.is(Blocks.WITHER_SKELETON_SKULL) || blockState.is(Blocks.WITHER_SKELETON_WALL_SKULL);
@@ -59,7 +_,7 @@
if (blockPatternMatch != null) {
WitherBoss witherBoss = EntityType.WITHER.create(level, EntitySpawnReason.TRIGGERED);
if (witherBoss != null) {
- CarvedPumpkinBlock.clearPatternBlocks(level, blockPatternMatch);
+ // CarvedPumpkinBlock.clearPatternBlocks(level, blockPatternMatch); // CraftBukkit - move down
BlockPos pos1 = blockPatternMatch.getBlock(1, 2, 0).getPos();
witherBoss.moveTo(
pos1.getX() + 0.5,
@@ -70,12 +_,18 @@
);
witherBoss.yBodyRot = blockPatternMatch.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F;
witherBoss.makeInvulnerable();
+ // CraftBukkit start
+ if (!level.addFreshEntity(witherBoss, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_WITHER)) {
+ return;
+ }
+ CarvedPumpkinBlock.clearPatternBlocks(level, blockPatternMatch); // CraftBukkit - from above
+ // CraftBukkit end
for (ServerPlayer serverPlayer : level.getEntitiesOfClass(ServerPlayer.class, witherBoss.getBoundingBox().inflate(50.0))) {
CriteriaTriggers.SUMMONED_ENTITY.trigger(serverPlayer, witherBoss);
}
- level.addFreshEntity(witherBoss);
+ // level.addFreshEntity(witherBoss); // CraftBukkit - moved up
CarvedPumpkinBlock.updatePatternBlocks(level, blockPatternMatch);
}
}