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
No known key found for this signature in database
GPG key ID: ECE0B3C133C016C5
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

@ -1,48 +1,48 @@
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -98,8 +98,8 @@
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
if (world instanceof ServerLevel serverLevel
&& world.getBlockEntity(pos) instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity
- && canOpen(state, world, pos, shulkerBoxBlockEntity)) {
@@ -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, world, pos, shulkerBoxBlockEntity) // Paper - Fix InventoryOpenEvent cancellation - expand if for belows check
+ && player.openMenu(shulkerBoxBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
+ && 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);
}
@@ -137,7 +137,7 @@
@@ -139,7 +_,7 @@
itemEntity.setDefaultPickUpDelay();
world.addFreshEntity(itemEntity);
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
}
}
@@ -147,7 +147,15 @@
@@ -149,7 +_,15 @@
@Override
protected List<ItemStack> getDrops(BlockState state, LootParams.Builder builder) {
BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
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 || !builder.getLevel().paperConfig().lootables.retainUnlootedShulkerBoxLootTableOnNonPlayerBreak) {
+ 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
builder = builder.withDynamicDrop(CONTENTS, lootConsumer -> {
params = params.withDynamicDrop(CONTENTS, output -> {
for (int i = 0; i < shulkerBoxBlockEntity.getContainerSize(); i++) {
lootConsumer.accept(shulkerBoxBlockEntity.getItem(i));
@@ -155,7 +163,13 @@
output.accept(shulkerBoxBlockEntity.getItem(i));
@@ -157,7 +_,13 @@
});
}
+ // Paper start - re-set loot table if it was cleared
+ try {
return super.getDrops(state, builder);
return super.getDrops(state, params);
+ } finally {
+ if (reAdd != null) reAdd.run();
+ }

View file

@ -1,33 +1,31 @@
--- a/net/minecraft/world/level/block/SignBlock.java
+++ b/net/minecraft/world/level/block/SignBlock.java
@@ -140,7 +140,7 @@
} else if (flag1) {
return InteractionResult.SUCCESS_SERVER;
} else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag)) {
- this.openTextEdit(player, tileentitysign, flag);
+ this.openTextEdit(player, tileentitysign, flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper - Add PlayerOpenSignEvent
@@ -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;
@@ -185,10 +185,36 @@
return blockpropertywood;
@@ -176,7 +_,33 @@
return woodType;
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - Add PlayerOpenSignEvent
public void openTextEdit(Player player, SignBlockEntity blockEntity, boolean front) {
- blockEntity.setAllowedPlayerEditor(player.getUUID());
- player.openTextEdit(blockEntity, front);
public void openTextEdit(Player player, SignBlockEntity signEntity, boolean isFrontText) {
+ // Paper start - Add PlayerOpenSignEvent
+ this.openTextEdit(player, blockEntity, front, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.UNKNOWN);
}
+ public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause cause) {
+ org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) entityhuman.getBukkitEntity();
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(tileentitysign.getLevel(), tileentitysign.getBlockPos());
+ 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,
+ flag ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
+ 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) {
@ -37,22 +35,19 @@
+ 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(entityhuman, tileentitysign, flag, legacyCause)) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(player, signEntity, isFrontText, legacyCause)) {
+ // Paper end - Add PlayerOpenSignEvent
+ return;
+ }
+ } // Paper - Add PlayerOpenSignEvent
+ tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID());
+ entityhuman.openTextEdit(tileentitysign, flag);
+ }
private boolean otherPlayerIsEditingSign(Player player, SignBlockEntity blockEntity) {
UUID uuid = blockEntity.getPlayerWhoMayEdit();
@@ -199,6 +225,6 @@
signEntity.setAllowedPlayerEditor(player.getUUID());
player.openTextEdit(signEntity, isFrontText);
}
@@ -189,6 +_,6 @@
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level world, BlockState state, BlockEntityType<T> type) {
- return createTickerHelper(type, BlockEntityType.SIGN, SignBlockEntity::tick);
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

@ -1,11 +1,11 @@
--- a/net/minecraft/world/level/block/SmithingTableBlock.java
+++ b/net/minecraft/world/level/block/SmithingTableBlock.java
@@ -38,8 +38,9 @@
@@ -38,8 +_,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
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
}

View file

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

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/SnifferEggBlock.java
+++ b/net/minecraft/world/level/block/SnifferEggBlock.java
@@ -61,12 +61,31 @@
@@ -61,12 +_,31 @@
return this.getHatchLevel(state) == 2;
}
@ -13,41 +13,41 @@
+ // Paper end - Call BlockFadeEvent
+
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!this.isReadyToHatch(state)) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2)) {
+ this.rescheduleTick(world, pos);
+ 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
world.playSound(null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
- world.setBlock(pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2);
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(world, pos, state.getFluidState().createLegacyBlock()).isCancelled()) {
+ this.rescheduleTick(world, pos);
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(level, pos, state.getFluidState().createLegacyBlock()).isCancelled()) {
+ this.rescheduleTick(level, pos);
+ return;
+ }
+ // Paper end - Call BlockFadeEvent
world.playSound(null, pos, SoundEvents.SNIFFER_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
world.destroyBlock(pos, false);
Sniffer sniffer = EntityType.SNIFFER.create(world, EntitySpawnReason.BREEDING);
@@ -74,7 +93,7 @@
Vec3 vec3 = pos.getCenter();
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(vec3.x(), vec3.y(), vec3.z(), Mth.wrapDegrees(world.random.nextFloat() * 360.0F), 0.0F);
- world.addFreshEntity(sniffer);
+ world.addFreshEntity(sniffer, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason
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 +105,7 @@
world.levelEvent(3009, pos, 0);
@@ -86,7 +_,7 @@
level.levelEvent(3009, pos, 0);
}
- int i = bl ? 12000 : 24000;
+ int i = bl ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper
int j = i / 3;
world.gameEvent(GameEvent.BLOCK_PLACE, pos, GameEvent.Context.of(state));
world.scheduleTick(pos, this, j + world.random.nextInt(300));
- 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

@ -1,11 +1,11 @@
--- a/net/minecraft/world/level/block/StonecutterBlock.java
+++ b/net/minecraft/world/level/block/StonecutterBlock.java
@@ -48,8 +48,9 @@
@@ -48,8 +_,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
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
}

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

@ -1,9 +1,9 @@
--- a/net/minecraft/world/level/block/TargetBlock.java
+++ b/net/minecraft/world/level/block/TargetBlock.java
@@ -42,6 +42,10 @@
@@ -42,6 +_,10 @@
@Override
protected void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) {
int i = updateRedstoneOutput(world, state, hit, projectile);
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) {
@ -11,16 +11,15 @@
if (projectile.getOwner() instanceof ServerPlayer serverPlayer) {
serverPlayer.awardStat(Stats.TARGET_HIT);
CriteriaTriggers.TARGET_BLOCK_HIT.trigger(serverPlayer, projectile, hit.getLocation(), i);
@@ -51,10 +55,31 @@
private static int updateRedstoneOutput(LevelAccessor world, BlockState state, BlockHitResult hitResult, Entity entity) {
int i = getRedstoneStrength(hitResult, hitResult.getLocation());
int j = entity instanceof AbstractArrow ? 20 : 8;
@@ -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 (entity instanceof Projectile) {
+ final Projectile projectile = (Projectile) entity;
+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, hitResult.getBlockPos());
+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(hitResult.getDirection());
+ 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();
@ -30,16 +29,15 @@
+ }
+ }
+ // Paper end - Add TargetHitEvent
if (!world.getBlockTicks().hasScheduledTick(hitResult.getBlockPos(), state.getBlock())) {
setOutputPower(world, state, i, hitResult.getBlockPos(), j);
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) entity, hitResult, i);
+ awardTargetHitCriteria((Projectile) projectile, hit, i);
+ }
+ // Paper end - Award Hit Criteria after Block Update
+
return i;
}
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

@ -1,10 +1,10 @@
--- a/net/minecraft/world/level/block/WallHangingSignBlock.java
+++ b/net/minecraft/world/level/block/WallHangingSignBlock.java
@@ -179,6 +179,6 @@
@@ -187,6 +_,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);
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

@ -1,10 +1,10 @@
--- a/net/minecraft/world/level/block/WebBlock.java
+++ b/net/minecraft/world/level/block/WebBlock.java
@@ -24,6 +24,7 @@
@@ -24,6 +_,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
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);
}
}

View file

@ -1,117 +0,0 @@
--- a/net/minecraft/world/level/block/SaplingBlock.java
+++ b/net/minecraft/world/level/block/SaplingBlock.java
@@ -10,12 +10,19 @@
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.grower.TreeGrower;
import net.minecraft.world.level.block.state.BlockBehaviour;
-import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.Location;
+import org.bukkit.TreeType;
+import org.bukkit.block.BlockState;
+import org.bukkit.craftbukkit.block.CapturedBlockState;
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.event.world.StructureGrowEvent;
+// CraftBukkit end
public class SaplingBlock extends BushBlock implements BonemealableBlock {
@@ -28,6 +35,7 @@
protected static final float AABB_OFFSET = 6.0F;
protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D);
protected final TreeGrower treeGrower;
+ public static TreeType treeType; // CraftBukkit
@Override
public MapCodec<? extends SaplingBlock> codec() {
@@ -37,48 +45,74 @@
protected SaplingBlock(TreeGrower generator, BlockBehaviour.Properties settings) {
super(settings);
this.treeGrower = generator;
- this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(SaplingBlock.STAGE, 0));
+ this.registerDefaultState((net.minecraft.world.level.block.state.BlockState) ((net.minecraft.world.level.block.state.BlockState) this.stateDefinition.any()).setValue(SaplingBlock.STAGE, 0));
}
@Override
- protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
+ protected VoxelShape getShape(net.minecraft.world.level.block.state.BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
return SaplingBlock.SHAPE;
}
@Override
- protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
- if (world.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextInt(7) == 0) {
+ protected void randomTick(net.minecraft.world.level.block.state.BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (world.getMaxLocalRawBrightness(pos.above()) >= 9 && random.nextFloat() < (world.spigotConfig.saplingModifier / (100.0f * 7))) { // Spigot - SPIGOT-7159: Better modifier resolution
this.advanceTree(world, pos, state, random);
}
}
- public void advanceTree(ServerLevel world, BlockPos pos, BlockState state, RandomSource random) {
+ public void advanceTree(ServerLevel world, BlockPos pos, net.minecraft.world.level.block.state.BlockState state, RandomSource random) {
if ((Integer) state.getValue(SaplingBlock.STAGE) == 0) {
- world.setBlock(pos, (BlockState) state.cycle(SaplingBlock.STAGE), 4);
+ world.setBlock(pos, (net.minecraft.world.level.block.state.BlockState) state.cycle(SaplingBlock.STAGE), 4);
} else {
- this.treeGrower.growTree(world, world.getChunkSource().getGenerator(), pos, state, random);
+ // CraftBukkit start
+ if (world.captureTreeGeneration) {
+ this.treeGrower.growTree(world, world.getChunkSource().getGenerator(), pos, state, random);
+ } else {
+ world.captureTreeGeneration = true;
+ this.treeGrower.growTree(world, world.getChunkSource().getGenerator(), pos, state, random);
+ world.captureTreeGeneration = false;
+ if (world.capturedBlockStates.size() > 0) {
+ TreeType treeType = SaplingBlock.treeType;
+ SaplingBlock.treeType = null;
+ Location location = CraftLocation.toBukkit(pos, world.getWorld());
+ java.util.List<BlockState> blocks = new java.util.ArrayList<>(world.capturedBlockStates.values());
+ world.capturedBlockStates.clear();
+ StructureGrowEvent event = null;
+ if (treeType != null) {
+ event = new StructureGrowEvent(location, treeType, false, null, blocks);
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
+ }
+ if (event == null || !event.isCancelled()) {
+ for (BlockState blockstate : blocks) {
+ CapturedBlockState.setBlockState(blockstate);
+ world.checkCapturedTreeStateForObserverNotify(pos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
+ }
+ }
+ }
+ }
+ // CraftBukkit end
}
}
@Override
- public boolean isValidBonemealTarget(LevelReader world, BlockPos pos, BlockState state) {
+ public boolean isValidBonemealTarget(LevelReader world, BlockPos pos, net.minecraft.world.level.block.state.BlockState state) {
return true;
}
@Override
- public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
+ public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, net.minecraft.world.level.block.state.BlockState state) {
return (double) world.random.nextFloat() < 0.45D;
}
@Override
- public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
+ public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, net.minecraft.world.level.block.state.BlockState state) {
this.advanceTree(world, pos, state, random);
}
@Override
- protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
+ protected void createBlockStateDefinition(StateDefinition.Builder<Block, net.minecraft.world.level.block.state.BlockState> builder) {
builder.add(SaplingBlock.STAGE);
}
}

View file

@ -1,11 +0,0 @@
--- a/net/minecraft/world/level/block/ScaffoldingBlock.java
+++ b/net/minecraft/world/level/block/ScaffoldingBlock.java
@@ -103,7 +103,7 @@
int i = ScaffoldingBlock.getDistance(world, pos);
BlockState iblockdata1 = (BlockState) ((BlockState) state.setValue(ScaffoldingBlock.DISTANCE, i)).setValue(ScaffoldingBlock.BOTTOM, this.isBottom(world, pos, i));
- if ((Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) == 7) {
+ if ((Integer) iblockdata1.getValue(ScaffoldingBlock.DISTANCE) == 7 && !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, iblockdata1.getFluidState().createLegacyBlock()).isCancelled()) { // CraftBukkit - BlockFadeEvent // Paper - fix wrong block state
if ((Integer) state.getValue(ScaffoldingBlock.DISTANCE) == 7) {
FallingBlockEntity.fall(world, pos, iblockdata1);
} else {

View file

@ -1,16 +0,0 @@
--- a/net/minecraft/world/level/block/SculkBlock.java
+++ b/net/minecraft/world/level/block/SculkBlock.java
@@ -43,8 +43,11 @@
BlockPos blockposition2 = blockposition1.above();
BlockState iblockdata = this.getRandomGrowthState(world, blockposition2, random, spreadManager.isWorldGeneration());
- world.setBlock(blockposition2, iblockdata, 3);
- world.playSound((Player) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F);
+ // CraftBukkit start - Call BlockSpreadEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, catalystPos, blockposition2, iblockdata, 3)) {
+ world.playSound((Player) null, blockposition1, iblockdata.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0F, 1.0F);
+ }
+ // CraftBukkit end
}
return Math.max(0, i - j);

View file

@ -1,21 +0,0 @@
--- a/net/minecraft/world/level/block/SculkCatalystBlock.java
+++ b/net/minecraft/world/level/block/SculkCatalystBlock.java
@@ -63,9 +63,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,88 +0,0 @@
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -43,6 +43,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.craftbukkit.block.CraftBlock;
+import org.bukkit.event.block.BlockRedstoneEvent;
+// CraftBukkit end
public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterloggedBlock {
@@ -104,6 +108,18 @@
@Override
public void stepOn(Level world, BlockPos pos, BlockState state, Entity entity) {
if (!world.isClientSide() && SculkSensorBlock.canActivate(state) && entity.getType() != EntityType.WARDEN) {
+ // CraftBukkit start
+ 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(), world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ world.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);
+ }
+ if (cancellable.isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
BlockEntity tileentity = world.getBlockEntity(pos);
if (tileentity instanceof SculkSensorBlockEntity) {
@@ -198,10 +214,19 @@
}
public static boolean canActivate(BlockState state) {
- return SculkSensorBlock.getPhase(state) == SculkSensorPhase.INACTIVE;
+ return state.getBlock() instanceof SculkSensorBlock && SculkSensorBlock.getPhase(state) == SculkSensorPhase.INACTIVE; // Paper - Check for a valid type
}
public static void deactivate(Level world, BlockPos pos, BlockState state) {
+ // CraftBukkit start
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, pos), state.getValue(SculkSensorBlock.POWER), 0);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() > 0) {
+ world.setBlock(pos, state.setValue(SculkSensorBlock.POWER, eventRedstone.getNewCurrent()), 3);
+ return;
+ }
+ // CraftBukkit end
world.setBlock(pos, (BlockState) ((BlockState) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.COOLDOWN)).setValue(SculkSensorBlock.POWER, 0), 3);
world.scheduleTick(pos, state.getBlock(), 10);
SculkSensorBlock.updateNeighbours(world, pos, state);
@@ -213,6 +238,15 @@
}
public void activate(@Nullable Entity sourceEntity, Level world, BlockPos pos, BlockState state, int power, int frequency) {
+ // CraftBukkit start
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, pos), state.getValue(SculkSensorBlock.POWER), power);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() <= 0) {
+ return;
+ }
+ power = eventRedstone.getNewCurrent();
+ // CraftBukkit end
world.setBlock(pos, (BlockState) ((BlockState) state.setValue(SculkSensorBlock.PHASE, SculkSensorPhase.ACTIVE)).setValue(SculkSensorBlock.POWER, power), 3);
world.scheduleTick(pos, state.getBlock(), this.getActiveTicks());
SculkSensorBlock.updateNeighbours(world, pos, state);
@@ -293,9 +327,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, ConstantInt.of(5));
+ // 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, ConstantInt.of(5));
}
+ return 0;
+ // CraftBukkit end
}
}

View file

@ -1,30 +0,0 @@
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -63,6 +63,7 @@
ServerPlayer entityplayer = SculkShriekerBlockEntity.tryGetPlayer(entity);
if (entityplayer != null) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(entityplayer, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null).isCancelled()) return; // CraftBukkit
worldserver.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent((sculkshriekerblockentity) -> {
sculkshriekerblockentity.tryShriek(worldserver, entityplayer);
});
@@ -140,10 +141,17 @@
@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, ConstantInt.of(5));
+ // 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, ConstantInt.of(5));
}
+ return 0;
+ // CraftBukkit end
}
@Nullable

View file

@ -1,98 +0,0 @@
--- a/net/minecraft/world/level/block/SculkSpreader.java
+++ b/net/minecraft/world/level/block/SculkSpreader.java
@@ -30,6 +30,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;
@@ -37,9 +38,14 @@
import net.minecraft.tags.TagKey;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.state.BlockState;
import org.slf4j.Logger;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.event.block.SculkBloomEvent;
+// CraftBukkit end
public class SculkSpreader {
@@ -57,6 +63,7 @@
private final int additionalDecayRate;
private List<SculkSpreader.ChargeCursor> cursors = new ArrayList();
private static final Logger LOGGER = LogUtils.getLogger();
+ public Level level; // CraftBukkit
public SculkSpreader(boolean worldGen, TagKey<Block> replaceableTag, int extraBlockChance, int maxDistance, int spreadChance, int decayChance) {
this.isWorldGeneration = worldGen;
@@ -111,7 +118,7 @@
public void load(CompoundTag nbt) {
if (nbt.contains("cursors", 9)) {
this.cursors.clear();
- DataResult dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().parse(new Dynamic(NbtOps.INSTANCE, nbt.getList("cursors", 10)));
+ DataResult<List<SculkSpreader.ChargeCursor>> dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().parse(new Dynamic<>(NbtOps.INSTANCE, nbt.getList("cursors", 10))); // CraftBukkit - decompile error
Logger logger = SculkSpreader.LOGGER;
Objects.requireNonNull(logger);
@@ -119,14 +126,14 @@
int i = Math.min(list.size(), 32);
for (int j = 0; j < i; ++j) {
- this.addCursor((SculkSpreader.ChargeCursor) list.get(j));
+ this.addCursor((SculkSpreader.ChargeCursor) list.get(j), false); // Paper - don't fire event for block entity loading
}
}
}
public void save(CompoundTag nbt) {
- DataResult dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.cursors);
+ DataResult<Tag> dataresult = SculkSpreader.ChargeCursor.CODEC.listOf().encodeStart(NbtOps.INSTANCE, this.cursors); // CraftBukkit - decompile error
Logger logger = SculkSpreader.LOGGER;
Objects.requireNonNull(logger);
@@ -139,14 +146,27 @@
while (charge > 0) {
int j = Math.min(charge, 1000);
- this.addCursor(new SculkSpreader.ChargeCursor(pos, j));
+ this.addCursor(new SculkSpreader.ChargeCursor(pos, j), true); // Paper - allow firing event for other causes
charge -= j;
}
}
- 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
+ CraftBlock bukkitBlock = CraftBlock.at(this.level, cursor.pos);
+ SculkBloomEvent event = new SculkBloomEvent(bukkitBlock, cursor.getCharge());
+ Bukkit.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return;
+ }
+
+ cursor.charge = event.getCharge();
+ }
+ // CraftBukkit end
+
this.cursors.add(cursor);
}
}
@@ -244,7 +264,7 @@
this.charge = charge;
this.decayDelay = decay;
this.updateDelay = update;
- this.facings = (Set) faces.orElse((Object) null);
+ this.facings = (Set) faces.orElse(null); // CraftBukkit - decompile error
}
public ChargeCursor(BlockPos pos, int charge) {

View file

@ -1,60 +0,0 @@
--- a/net/minecraft/world/level/block/SculkVeinBlock.java
+++ b/net/minecraft/world/level/block/SculkVeinBlock.java
@@ -101,28 +101,33 @@
@Override
public int attemptUseCharge(SculkSpreader.ChargeCursor cursor, LevelAccessor world, BlockPos catalystPos, RandomSource random, SculkSpreader spreadManager, boolean shouldConvertToBlock) {
- return shouldConvertToBlock && this.attemptPlaceSculk(spreadManager, world, cursor.getPos(), random) ? cursor.getCharge() - 1 : (random.nextInt(spreadManager.chargeDecayRate()) == 0 ? Mth.floor((float) cursor.getCharge() * 0.5F) : cursor.getCharge());
+ // CraftBukkit - add source block
+ return shouldConvertToBlock && this.attemptPlaceSculk(spreadManager, world, cursor.getPos(), random, catalystPos) ? cursor.getCharge() - 1 : (random.nextInt(spreadManager.chargeDecayRate()) == 0 ? Mth.floor((float) cursor.getCharge() * 0.5F) : cursor.getCharge());
}
- private boolean attemptPlaceSculk(SculkSpreader spreadManager, LevelAccessor world, BlockPos pos, RandomSource random) {
- BlockState iblockdata = world.getBlockState(pos);
- TagKey<Block> tagkey = spreadManager.replaceableBlocks();
- Iterator iterator = Direction.allShuffled(random).iterator();
+ private boolean attemptPlaceSculk(SculkSpreader sculkspreader, LevelAccessor generatoraccess, BlockPos blockposition, RandomSource randomsource, BlockPos sourceBlock) { // CraftBukkit
+ BlockState iblockdata = generatoraccess.getBlockState(blockposition);
+ TagKey<Block> tagkey = sculkspreader.replaceableBlocks();
+ Iterator iterator = Direction.allShuffled(randomsource).iterator();
while (iterator.hasNext()) {
Direction enumdirection = (Direction) iterator.next();
if (hasFace(iblockdata, enumdirection)) {
- BlockPos blockposition1 = pos.relative(enumdirection);
- BlockState iblockdata1 = world.getBlockState(blockposition1);
+ BlockPos blockposition1 = blockposition.relative(enumdirection);
+ BlockState iblockdata1 = generatoraccess.getBlockState(blockposition1);
if (iblockdata1.is(tagkey)) {
BlockState iblockdata2 = Blocks.SCULK.defaultBlockState();
- world.setBlock(blockposition1, iblockdata2, 3);
- Block.pushEntitiesUp(iblockdata1, iblockdata2, world, blockposition1);
- world.playSound((Player) null, blockposition1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F);
- this.veinSpreader.spreadAll(iblockdata2, world, blockposition1, spreadManager.isWorldGeneration());
+ // CraftBukkit start - Call BlockSpreadEvent
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(generatoraccess, sourceBlock, blockposition1, iblockdata2, 3)) {
+ return false;
+ }
+ // CraftBukkit end
+ Block.pushEntitiesUp(iblockdata1, iblockdata2, generatoraccess, blockposition1);
+ generatoraccess.playSound((Player) null, blockposition1, SoundEvents.SCULK_BLOCK_SPREAD, SoundSource.BLOCKS, 1.0F, 1.0F);
+ this.veinSpreader.spreadAll(iblockdata2, generatoraccess, blockposition1, sculkspreader.isWorldGeneration());
Direction enumdirection1 = enumdirection.getOpposite();
Direction[] aenumdirection = SculkVeinBlock.DIRECTIONS;
int i = aenumdirection.length;
@@ -132,10 +137,10 @@
if (enumdirection2 != enumdirection1) {
BlockPos blockposition2 = blockposition1.relative(enumdirection2);
- BlockState iblockdata3 = world.getBlockState(blockposition2);
+ BlockState iblockdata3 = generatoraccess.getBlockState(blockposition2);
if (iblockdata3.is((Block) this)) {
- this.onDischarged(world, iblockdata3, blockposition2, random);
+ this.onDischarged(generatoraccess, iblockdata3, blockposition2, randomsource);
}
}
}

View file

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

View file

@ -1,26 +0,0 @@
--- a/net/minecraft/world/level/block/SpawnerBlock.java
+++ b/net/minecraft/world/level/block/SpawnerBlock.java
@@ -45,12 +45,20 @@
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) {
super.spawnAfterBreak(state, world, pos, tool, dropExperience);
- if (dropExperience) {
- int i = 15 + world.random.nextInt(15) + world.random.nextInt(15);
+ // CraftBukkit start - Delegate to getExpDrop
+ }
- this.popExperience(world, pos, i);
+ @Override
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) {
+ if (flag) {
+ int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15);
+
+ // this.popExperience(worldserver, blockposition, i);
+ return i;
}
+ return 0;
+ // CraftBukkit end
}
@Override

View file

@ -1,114 +0,0 @@
--- a/net/minecraft/world/level/block/SpongeBlock.java
+++ b/net/minecraft/world/level/block/SpongeBlock.java
@@ -15,6 +15,13 @@
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.redstone.Orientation;
+// CraftBukkit start
+import java.util.List;
+import org.bukkit.craftbukkit.block.CraftBlockState;
+import org.bukkit.craftbukkit.util.BlockStateListPopulator;
+import org.bukkit.event.block.SpongeAbsorbEvent;
+// CraftBukkit end
+
public class SpongeBlock extends Block {
public static final MapCodec<SpongeBlock> CODEC = simpleCodec(SpongeBlock::new);
@@ -53,7 +60,8 @@
}
private boolean removeWaterBreadthFirstSearch(Level world, BlockPos pos) {
- return BlockPos.breadthFirstTraversal(pos, 6, 65, (blockposition1, consumer) -> {
+ BlockStateListPopulator blockList = new BlockStateListPopulator(world); // CraftBukkit - Use BlockStateListPopulator
+ BlockPos.breadthFirstTraversal(pos, 6, 65, (blockposition1, consumer) -> {
Direction[] aenumdirection = SpongeBlock.ALL_DIRECTIONS;
int i = aenumdirection.length;
@@ -67,8 +75,10 @@
if (blockposition1.equals(pos)) {
return BlockPos.TraversalNodeStatus.ACCEPT;
} else {
- BlockState iblockdata = world.getBlockState(blockposition1);
- FluidState fluid = world.getFluidState(blockposition1);
+ // CraftBukkit start
+ BlockState iblockdata = blockList.getBlockState(blockposition1);
+ FluidState fluid = blockList.getFluidState(blockposition1);
+ // CraftBukkit end
if (!fluid.is(FluidTags.WATER)) {
return BlockPos.TraversalNodeStatus.SKIP;
@@ -78,27 +88,68 @@
if (block instanceof BucketPickup) {
BucketPickup ifluidsource = (BucketPickup) block;
- if (!ifluidsource.pickupBlock((Player) null, world, blockposition1, iblockdata).isEmpty()) {
+ if (!ifluidsource.pickupBlock((Player) null, blockList, blockposition1, iblockdata).isEmpty()) { // CraftBukkit
return BlockPos.TraversalNodeStatus.ACCEPT;
}
}
if (iblockdata.getBlock() instanceof LiquidBlock) {
- world.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3);
+ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3); // CraftBukkit
} else {
if (!iblockdata.is(Blocks.KELP) && !iblockdata.is(Blocks.KELP_PLANT) && !iblockdata.is(Blocks.SEAGRASS) && !iblockdata.is(Blocks.TALL_SEAGRASS)) {
return BlockPos.TraversalNodeStatus.SKIP;
}
- BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null;
+ // CraftBukkit start
+ // TileEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition1) : null;
- dropResources(iblockdata, world, blockposition1, tileentity);
- world.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3);
+ // dropResources(iblockdata, world, blockposition1, tileentity);
+ blockList.setBlock(blockposition1, Blocks.AIR.defaultBlockState(), 3);
+ // CraftBukkit end
}
return BlockPos.TraversalNodeStatus.ACCEPT;
}
}
- }) > 1;
+ });
+ // CraftBukkit start
+ List<CraftBlockState> blocks = blockList.getList(); // Is a clone
+ if (!blocks.isEmpty()) {
+ final org.bukkit.block.Block bblock = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+
+ SpongeAbsorbEvent event = new SpongeAbsorbEvent(bblock, (List<org.bukkit.block.BlockState>) (List) blocks);
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return false;
+ }
+
+ for (CraftBlockState block : blocks) {
+ BlockPos blockposition1 = block.getPosition();
+ BlockState iblockdata = world.getBlockState(blockposition1);
+ FluidState fluid = world.getFluidState(blockposition1);
+
+ if (fluid.is(FluidTags.WATER)) {
+ if (iblockdata.getBlock() instanceof BucketPickup && !((BucketPickup) iblockdata.getBlock()).pickupBlock((Player) 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() ? world.getBlockEntity(blockposition1) : null;
+
+ // Paper start - Fix SpongeAbsortEvent handling
+ if (block.getHandle().isAir()) {
+ dropResources(iblockdata, world, blockposition1, tileentity);
+ }
+ // Paper end - Fix SpongeAbsortEvent handling
+ }
+ }
+ world.setBlock(blockposition1, block.getHandle(), block.getFlag());
+ }
+
+ return true;
+ }
+ return false;
+ // CraftBukkit end
}
}

View file

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

View file

@ -1,47 +0,0 @@
--- a/net/minecraft/world/level/block/StemBlock.java
+++ b/net/minecraft/world/level/block/StemBlock.java
@@ -26,6 +26,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 StemBlock extends BushBlock implements BonemealableBlock {
@@ -74,12 +75,12 @@
if (world.getRawBrightness(pos, 0) >= 9) {
float f = CropBlock.getGrowthSpeed(this, world, pos);
- if (random.nextInt((int) (25.0F / f) + 1) == 0) {
+ if (random.nextFloat() < ((this == Blocks.PUMPKIN_STEM ? world.spigotConfig.pumpkinModifier : world.spigotConfig.melonModifier) / (100.0f * (Math.floor((25.0F / f) + 1))))) { // Spigot - SPIGOT-7159: Better modifier resolution
int i = (Integer) state.getValue(StemBlock.AGE);
if (i < 7) {
state = (BlockState) state.setValue(StemBlock.AGE, i + 1);
- world.setBlock(pos, state, 2);
+ CraftEventFactory.handleBlockGrowEvent(world, pos, state, 2); // CraftBukkit
} else {
Direction enumdirection = Direction.Plane.HORIZONTAL.getRandomDirection(random);
BlockPos blockposition1 = pos.relative(enumdirection);
@@ -91,7 +92,11 @@
Optional<Block> optional1 = iregistry.getOptional(this.attachedStem);
if (optional.isPresent() && optional1.isPresent()) {
- world.setBlockAndUpdate(blockposition1, ((Block) optional.get()).defaultBlockState());
+ // CraftBukkit start
+ if (!CraftEventFactory.handleBlockGrowEvent(world, blockposition1, ((Block) optional.get()).defaultBlockState())) {
+ return;
+ }
+ // CraftBukkit end
world.setBlockAndUpdate(pos, (BlockState) ((Block) optional1.get()).defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, enumdirection));
}
}
@@ -121,7 +126,7 @@
int i = Math.min(7, (Integer) state.getValue(StemBlock.AGE) + Mth.nextInt(world.random, 2, 5));
BlockState iblockdata1 = (BlockState) state.setValue(StemBlock.AGE, i);
- world.setBlock(pos, iblockdata1, 2);
+ CraftEventFactory.handleBlockGrowEvent(world, pos, iblockdata1, 2); // CraftBukkit
if (i == 7) {
iblockdata1.randomTick(world, pos, world.random);
}

View file

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

View file

@ -1,62 +0,0 @@
--- a/net/minecraft/world/level/block/SweetBerryBushBlock.java
+++ b/net/minecraft/world/level/block/SweetBerryBushBlock.java
@@ -28,6 +28,12 @@
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.Collections;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.event.player.PlayerHarvestBlockEvent;
+// CraftBukkit end
public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock {
@@ -67,10 +73,10 @@
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
int i = (Integer) state.getValue(SweetBerryBushBlock.AGE);
- if (i < 3 && random.nextInt(5) == 0 && world.getRawBrightness(pos.above(), 0) >= 9) {
+ if (i < 3 && random.nextFloat() < (world.spigotConfig.sweetBerryModifier / (100.0f * 5)) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot - SPIGOT-7159: Better modifier resolution
BlockState iblockdata1 = (BlockState) state.setValue(SweetBerryBushBlock.AGE, i + 1);
- world.setBlock(pos, iblockdata1, 2);
+ if (!CraftEventFactory.handleBlockGrowEvent(world, pos, iblockdata1, 2)) return; // CraftBukkit
world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(iblockdata1));
}
@@ -78,6 +84,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.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) {
entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D));
if (world instanceof ServerLevel) {
@@ -91,7 +98,7 @@
double d1 = Math.abs(vec3d.z());
if (d0 >= 0.003000000026077032D || d1 >= 0.003000000026077032D) {
- entity.hurtServer(worldserver, world.damageSources().sweetBerryBush(), 1.0F);
+ entity.hurtServer(worldserver, world.damageSources().sweetBerryBush().directBlock(world, pos), 1.0F); // CraftBukkit
}
}
@@ -118,7 +125,15 @@
if (i > 1) {
int j = 1 + world.random.nextInt(2);
- popResource(world, pos, new ItemStack(Items.SWEET_BERRIES, j + (flag ? 1 : 0)));
+ // CraftBukkit start - useWithoutItem is always MAIN_HAND
+ PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(world, pos, player, InteractionHand.MAIN_HAND, Collections.singletonList(new ItemStack(Items.SWEET_BERRIES, j + (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(world, pos, CraftItemStack.asNMSCopy(itemStack));
+ }
+ // CraftBukkit end
world.playSound((Player) null, pos, SoundEvents.SWEET_BERRY_BUSH_PICK_BERRIES, SoundSource.BLOCKS, 1.0F, 0.8F + world.random.nextFloat() * 0.4F);
BlockState iblockdata1 = (BlockState) state.setValue(SweetBerryBushBlock.AGE, 1);

View file

@ -1,102 +0,0 @@
--- a/net/minecraft/world/level/block/TntBlock.java
+++ b/net/minecraft/world/level/block/TntBlock.java
@@ -28,6 +28,10 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.redstone.Orientation;
import net.minecraft.world.phys.BlockHitResult;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.block.TNTPrimeEvent.PrimeCause;
+// CraftBukkit end
public class TntBlock extends Block {
@@ -47,7 +51,13 @@
@Override
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
if (!oldState.is(state.getBlock())) {
- if (world.hasNeighborSignal(pos)) {
+ if (world.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
+ return;
+ }
+ // Paper end - TNTPrimeEvent
TntBlock.explode(world, pos);
world.removeBlock(pos, false);
}
@@ -57,7 +67,13 @@
@Override
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, @Nullable Orientation wireOrientation, boolean notify) {
- if (world.hasNeighborSignal(pos)) {
+ if (world.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.REDSTONE, null, null)) { // CraftBukkit - TNTPrimeEvent
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) {
+ return;
+ }
+ // Paper end - TNTPrimeEvent
TntBlock.explode(world, pos);
world.removeBlock(pos, false);
}
@@ -66,7 +82,7 @@
@Override
public BlockState playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
- if (!world.isClientSide() && !player.isCreative() && (Boolean) state.getValue(TntBlock.UNSTABLE)) {
+ if (!world.isClientSide() && !player.isCreative() && (Boolean) state.getValue(TntBlock.UNSTABLE) && CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.BLOCK_BREAK, player, null)) { // CraftBukkit - TNTPrimeEvent
TntBlock.explode(world, pos);
}
@@ -75,6 +91,13 @@
@Override
public void wasExploded(ServerLevel world, BlockPos pos, Explosion explosion) {
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, 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 entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getIndirectSourceEntity());
int i = entitytntprimed.getFuse();
@@ -101,6 +124,17 @@
if (!stack.is(Items.FLINT_AND_STEEL) && !stack.is(Items.FIRE_CHARGE)) {
return super.useItemOn(stack, state, world, pos, player, hand, hit);
} else {
+ // CraftBukkit start - TNTPrimeEvent
+ if (!CraftEventFactory.callTNTPrimeEvent(world, pos, PrimeCause.PLAYER, player, null)) {
+ return InteractionResult.CONSUME;
+ }
+ // CraftBukkit end
+ // Paper start - TNTPrimeEvent
+ org.bukkit.block.Block tntBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, 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
TntBlock.explode(world, pos, player);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11);
Item item = stack.getItem();
@@ -123,6 +157,17 @@
Entity entity = projectile.getOwner();
if (projectile.isOnFire() && projectile.mayInteract(worldserver, blockposition)) {
+ // CraftBukkit start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(projectile, blockposition, state.getFluidState().createLegacyBlock()) || !CraftEventFactory.callTNTPrimeEvent(world, blockposition, 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(world, blockposition);
+ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) {
+ return;
+ }
+ // Paper end - TNTPrimeEvent
TntBlock.explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null);
world.removeBlock(blockposition, false);
}

View file

@ -1,51 +0,0 @@
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -37,6 +37,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 TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock {
@@ -143,7 +144,39 @@
boolean flag1 = world.hasNeighborSignal(pos);
if (flag1 != (Boolean) state.getValue(TrapDoorBlock.POWERED)) {
- if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) {
+ // CraftBukkit start
+ org.bukkit.World bworld = world.getWorld();
+ org.bukkit.block.Block bblock = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+
+ int power = bblock.getBlockPower();
+ int oldPower = (Boolean) state.getValue(TrapDoorBlock.OPEN) ? 15 : 0;
+
+ if (oldPower == 0 ^ power == 0 || sourceBlock.defaultBlockState().isSignalSource()) {
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bblock, oldPower, power);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+ flag1 = eventRedstone.getNewCurrent() > 0;
+ }
+ // CraftBukkit end
+ // Paper start - break redstone on trapdoors early
+ boolean open = (Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1;
+ // 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 (flag1 && 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 = world.getBlockState(abovePos);
+ if (above.getBlock() instanceof RedStoneWireBlock) {
+ world.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
+ Block.popResource(world, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
+ // now check that this didn't change our state
+ if (world.getBlockState(pos) != state) {
+ // our state was changed, so we cannot propagate this update
+ return;
+ }
+ }
+ }
+ if (open) {
+ // Paper end - break redstone on trapdoors early
state = (BlockState) state.setValue(TrapDoorBlock.OPEN, flag1);
this.playSound((Player) null, world, pos, flag1);
}

View file

@ -1,114 +0,0 @@
--- a/net/minecraft/world/level/block/TripWireBlock.java
+++ b/net/minecraft/world/level/block/TripWireBlock.java
@@ -28,6 +28,7 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.entity.EntityInteractEvent; // CraftBukkit
public class TripWireBlock extends Block {
@@ -67,6 +68,7 @@
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return this.defaultBlockState(); // Paper - place tripwire without updating
Level world = ctx.getLevel();
BlockPos blockposition = ctx.getClickedPos();
@@ -75,11 +77,13 @@
@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.disableTripwireUpdates) return state; // Paper - prevent tripwire from updating
return direction.getAxis().isHorizontal() ? (BlockState) state.setValue((Property) TripWireBlock.PROPERTY_BY_DIRECTION.get(direction), this.shouldConnectTo(neighborState, direction)) : super.updateShape(state, world, tickView, pos, direction, neighborPos, neighborState, random);
}
@Override
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!oldState.is(state.getBlock())) {
this.updateSource(world, pos, state);
}
@@ -87,6 +91,7 @@
@Override
protected void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!moved && !state.is(newState.getBlock())) {
this.updateSource(world, pos, (BlockState) state.setValue(TripWireBlock.POWERED, true));
}
@@ -94,6 +99,7 @@
@Override
public BlockState playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return state; // Paper - prevent disarming tripwires
if (!world.isClientSide && !player.getMainHandItem().isEmpty() && player.getMainHandItem().is(Items.SHEARS)) {
world.setBlock(pos, (BlockState) state.setValue(TripWireBlock.DISARMED, true), 4);
world.gameEvent((Entity) player, (Holder) GameEvent.SHEAR, pos);
@@ -103,6 +109,7 @@
}
private void updateSource(Level world, BlockPos pos, BlockState state) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
Direction[] aenumdirection = new Direction[]{Direction.SOUTH, Direction.WEST};
int i = aenumdirection.length;
int j = 0;
@@ -140,6 +147,8 @@
@Override
protected void entityInside(BlockState state, Level world, 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(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide) {
if (!(Boolean) state.getValue(TripWireBlock.POWERED)) {
this.checkPressed(world, pos, List.of(entity));
@@ -149,6 +158,7 @@
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent tripwire pressed check
if ((Boolean) world.getBlockState(pos).getValue(TripWireBlock.POWERED)) {
this.checkPressed(world, pos);
}
@@ -179,6 +189,40 @@
}
}
+ // CraftBukkit start - Call interact even when triggering connected tripwire
+ if (flag != flag1 && flag1 && (Boolean)iblockdata.getValue(TripWireBlock.ATTACHED)) {
+ org.bukkit.World bworld = world.getWorld();
+ org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager();
+ org.bukkit.block.Block block = bworld.getBlockAt(pos.getX(), pos.getY(), pos.getZ());
+ boolean allowed = false;
+
+ // If all of 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 EntityInteractEvent(((Entity) object).getBukkitEntity(), block);
+ manager.callEvent((EntityInteractEvent) cancellable);
+ } else {
+ continue;
+ }
+
+ if (!cancellable.isCancelled()) {
+ allowed = true;
+ break;
+ }
+ }
+ }
+
+ if (!allowed) {
+ return;
+ }
+ }
+ // CraftBukkit end
+
if (flag1 != flag) {
iblockdata = (BlockState) iblockdata.setValue(TripWireBlock.POWERED, flag1);
world.setBlock(pos, iblockdata, 3);

View file

@ -1,34 +0,0 @@
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -31,6 +31,10 @@
import net.minecraft.world.level.redstone.Orientation;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.event.block.BlockRedstoneEvent;
+// CraftBukkit end
public class TripWireHookBlock extends Block {
@@ -174,10 +178,20 @@
world.setBlock(blockposition1, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection1), 3);
TripWireHookBlock.notifyNeighbors(block, world, blockposition1, enumdirection1);
TripWireHookBlock.emitState(world, blockposition1, flag4, flag5, flag2, flag3);
+ }
+
+ // CraftBukkit start
+ BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(world, pos), 15, 0);
+ world.getCraftServer().getPluginManager().callEvent(eventRedstone);
+
+ if (eventRedstone.getNewCurrent() > 0) {
+ return;
}
+ // CraftBukkit end
TripWireHookBlock.emitState(world, pos, flag4, flag5, flag2, flag3);
if (!flag) {
+ if (world.getBlockState(pos).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - Validate tripwire hook placement before update
world.setBlock(pos, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3);
if (flag1) {
TripWireHookBlock.notifyNeighbors(block, world, pos, enumdirection);

View file

@ -1,76 +0,0 @@
--- a/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -31,6 +31,11 @@
import net.minecraft.world.level.gameevent.GameEvent;
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.block.CraftBlock;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
public class TurtleEggBlock extends Block {
@@ -74,6 +79,19 @@
private void destroyEgg(Level world, BlockState state, BlockPos pos, Entity entity, int inverseChance) {
if (state.is(Blocks.TURTLE_EGG) && world instanceof ServerLevel worldserver) {
if (this.canDestroyEgg(worldserver, entity) && world.random.nextInt(inverseChance) == 0) {
+ // CraftBukkit start - Step on eggs
+ 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(), CraftBlock.at(worldserver, pos));
+ worldserver.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable);
+ }
+
+ if (cancellable.isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
this.decreaseEggs(worldserver, pos, state);
}
}
@@ -100,10 +118,20 @@
int i = (Integer) state.getValue(TurtleEggBlock.HATCH);
if (i < 2) {
+ // CraftBukkit start - Call BlockGrowEvent
+ if (!CraftEventFactory.handleBlockGrowEvent(world, pos, state.setValue(TurtleEggBlock.HATCH, i + 1), 2)) {
+ return;
+ }
+ // CraftBukkit end
world.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
- world.setBlock(pos, (BlockState) state.setValue(TurtleEggBlock.HATCH, i + 1), 2);
+ // worldserver.setBlock(blockposition, (IBlockData) iblockdata.setValue(BlockTurtleEgg.HATCH, i + 1), 2); // CraftBukkit - handled above
world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state));
} else {
+ // CraftBukkit start - Call BlockFadeEvent
+ if (CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.AIR.defaultBlockState()).isCancelled()) {
+ return;
+ }
+ // CraftBukkit end
world.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
world.removeBlock(pos, false);
world.gameEvent((Holder) GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state));
@@ -116,7 +144,7 @@
entityturtle.setAge(-24000);
entityturtle.setHomePos(pos);
entityturtle.moveTo((double) pos.getX() + 0.3D + (double) j * 0.2D, (double) pos.getY(), (double) pos.getZ() + 0.3D, 0.0F, 0.0F);
- world.addFreshEntity(entityturtle);
+ world.addFreshEntity(entityturtle, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // CraftBukkit
}
}
}
@@ -147,8 +175,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
this.decreaseEggs(world, pos, state);
}

View file

@ -1,79 +0,0 @@
--- a/net/minecraft/world/level/block/VineBlock.java
+++ b/net/minecraft/world/level/block/VineBlock.java
@@ -24,6 +24,7 @@
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.event.CraftEventFactory; // CraftBukkit
public class VineBlock extends Block {
@@ -184,7 +185,7 @@
@Override
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (world.getGameRules().getBoolean(GameRules.RULE_DO_VINES_SPREAD)) {
- if (random.nextInt(4) == 0) {
+ if (random.nextFloat() < (world.spigotConfig.vineModifier / (100.0f * 4))) { // Spigot - SPIGOT-7159: Better modifier resolution
Direction enumdirection = Direction.getRandom(random);
BlockPos blockposition1 = pos.above();
BlockPos blockposition2;
@@ -203,30 +204,34 @@
BlockPos blockposition3 = blockposition2.relative(enumdirection1);
BlockPos blockposition4 = blockposition2.relative(enumdirection2);
+ // CraftBukkit start - Call BlockSpreadEvent
+ BlockPos source = pos;
+
if (flag && VineBlock.isAcceptableNeighbour(world, blockposition3, enumdirection1)) {
- world.setBlock(blockposition2, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection1), true), 2);
+ CraftEventFactory.handleBlockSpreadEvent(world, source, blockposition2, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection1), true), 2);
} else if (flag1 && VineBlock.isAcceptableNeighbour(world, blockposition4, enumdirection2)) {
- world.setBlock(blockposition2, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection2), true), 2);
+ CraftEventFactory.handleBlockSpreadEvent(world, source, blockposition2, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection2), true), 2);
} else {
Direction enumdirection3 = enumdirection.getOpposite();
if (flag && world.isEmptyBlock(blockposition3) && VineBlock.isAcceptableNeighbour(world, pos.relative(enumdirection1), enumdirection3)) {
- world.setBlock(blockposition3, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection3), true), 2);
+ CraftEventFactory.handleBlockSpreadEvent(world, source, blockposition3, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection3), true), 2);
} else if (flag1 && world.isEmptyBlock(blockposition4) && VineBlock.isAcceptableNeighbour(world, pos.relative(enumdirection2), enumdirection3)) {
- world.setBlock(blockposition4, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection3), true), 2);
+ CraftEventFactory.handleBlockSpreadEvent(world, source, blockposition4, (BlockState) this.defaultBlockState().setValue(VineBlock.getPropertyForFace(enumdirection3), true), 2);
} else if ((double) random.nextFloat() < 0.05D && VineBlock.isAcceptableNeighbour(world, blockposition2.above(), Direction.UP)) {
- world.setBlock(blockposition2, (BlockState) this.defaultBlockState().setValue(VineBlock.UP, true), 2);
+ CraftEventFactory.handleBlockSpreadEvent(world, source, blockposition2, (BlockState) this.defaultBlockState().setValue(VineBlock.UP, true), 2);
}
+ // CraftBukkit end
}
} else if (VineBlock.isAcceptableNeighbour(world, blockposition2, enumdirection)) {
- world.setBlock(pos, (BlockState) state.setValue(VineBlock.getPropertyForFace(enumdirection), true), 2);
+ CraftEventFactory.handleBlockGrowEvent(world, pos, (BlockState) state.setValue(VineBlock.getPropertyForFace(enumdirection), true), 2); // CraftBukkit
}
}
} else {
if (enumdirection == Direction.UP && pos.getY() < world.getMaxY()) {
if (this.canSupportAtFace(world, pos, enumdirection)) {
- world.setBlock(pos, (BlockState) state.setValue(VineBlock.UP, true), 2);
+ CraftEventFactory.handleBlockGrowEvent(world, pos, (BlockState) state.setValue(VineBlock.UP, true), 2); // CraftBukkit
return;
}
@@ -246,7 +251,7 @@
}
if (this.hasHorizontalConnection(iblockdata2)) {
- world.setBlock(blockposition1, iblockdata2, 2);
+ CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, iblockdata2, 2); // CraftBukkit
}
return;
@@ -261,7 +266,7 @@
BlockState iblockdata4 = this.copyRandomFaces(state, iblockdata3, random);
if (iblockdata3 != iblockdata4 && this.hasHorizontalConnection(iblockdata4)) {
- world.setBlock(blockposition2, iblockdata4, 2);
+ CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition2, iblockdata4, 2); // CraftBukkit
}
}
}

View file

@ -1,27 +0,0 @@
--- a/net/minecraft/world/level/block/WaterlilyBlock.java
+++ b/net/minecraft/world/level/block/WaterlilyBlock.java
@@ -13,6 +13,9 @@
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
public class WaterlilyBlock extends BushBlock {
@@ -30,8 +33,14 @@
@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
super.entityInside(state, world, pos, entity);
if (world instanceof ServerLevel && entity instanceof AbstractBoat) {
+ // CraftBukkit start
+ if (!CraftEventFactory.callEntityChangeBlockEvent(entity, pos, state.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
+ return;
+ }
+ // CraftBukkit end
world.destroyBlock(new BlockPos(pos), true, entity);
}

View file

@ -1,49 +0,0 @@
--- a/net/minecraft/world/level/block/WeightedPressurePlateBlock.java
+++ b/net/minecraft/world/level/block/WeightedPressurePlateBlock.java
@@ -6,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;
@@ -13,6 +14,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.IntegerProperty;
+import org.bukkit.event.entity.EntityInteractEvent;
+// CraftBukkit end
public class WeightedPressurePlateBlock extends BasePressurePlateBlock {
@@ -39,8 +42,28 @@
@Override
protected int getSignalStrength(Level world, BlockPos pos) {
- int i = Math.min(getEntityCount(world, WeightedPressurePlateBlock.TOUCH_AABB.move(pos), Entity.class), this.maxWeight);
+ // CraftBukkit start
+ // int i = Math.min(getEntityCount(world, BlockPressurePlateWeighted.TOUCH_AABB.move(blockposition), Entity.class), this.maxWeight);
+ int i = 0;
+ for (Entity entity : getEntities(world, 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 EntityInteractEvent(entity.getBukkitEntity(), world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ world.getCraftServer().getPluginManager().callEvent((EntityInteractEvent) cancellable);
+ }
+
+ // We only want to block turning the plate on if all events are cancelled
+ if (!cancellable.isCancelled()) {
+ i++;
+ }
+ }
+
+ i = Math.min(i, this.maxWeight);
+ // CraftBukkit end
+
if (i > 0) {
float f = (float) Math.min(this.maxWeight, i) / (float) this.maxWeight;

View file

@ -1,15 +0,0 @@
--- a/net/minecraft/world/level/block/WitherRoseBlock.java
+++ b/net/minecraft/world/level/block/WitherRoseBlock.java
@@ -63,10 +63,11 @@
@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 (world.getDifficulty() != Difficulty.PEACEFUL && entity instanceof LivingEntity entityliving) {
if (!entityliving.isInvulnerableTo(worldserver, world.damageSources().wither())) {
- entityliving.addEffect(this.getBeeInteractionEffect());
+ entityliving.addEffect(this.getBeeInteractionEffect(), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WITHER_ROSE); // CraftBukkit
}
}
}

View file

@ -1,50 +0,0 @@
--- a/net/minecraft/world/level/block/WitherSkullBlock.java
+++ b/net/minecraft/world/level/block/WitherSkullBlock.java
@@ -26,6 +26,10 @@
import net.minecraft.world.level.block.state.pattern.BlockPatternBuilder;
import net.minecraft.world.level.block.state.predicate.BlockStatePredicate;
+// CraftBukkit start
+import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
+// CraftBukkit end
+
public class WitherSkullBlock extends SkullBlock {
public static final MapCodec<WitherSkullBlock> CODEC = simpleCodec(WitherSkullBlock::new);
@@ -58,6 +62,7 @@
}
public static void checkSpawn(Level world, BlockPos pos, SkullBlockEntity blockEntity) {
+ if (world.captureBlockStates) return; // CraftBukkit
if (!world.isClientSide) {
BlockState iblockdata = blockEntity.getBlockState();
boolean flag = iblockdata.is(Blocks.WITHER_SKELETON_SKULL) || iblockdata.is(Blocks.WITHER_SKELETON_WALL_SKULL);
@@ -69,12 +74,18 @@
WitherBoss entitywither = (WitherBoss) EntityType.WITHER.create(world, EntitySpawnReason.TRIGGERED);
if (entitywither != null) {
- CarvedPumpkinBlock.clearPatternBlocks(world, shapedetector_shapedetectorcollection);
+ // BlockPumpkinCarved.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - move down
BlockPos blockposition1 = shapedetector_shapedetectorcollection.getBlock(1, 2, 0).getPos();
entitywither.moveTo((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.55D, (double) blockposition1.getZ() + 0.5D, shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F, 0.0F);
entitywither.yBodyRot = shapedetector_shapedetectorcollection.getForwards().getAxis() == Direction.Axis.X ? 0.0F : 90.0F;
entitywither.makeInvulnerable();
+ // CraftBukkit start
+ if (!world.addFreshEntity(entitywither, SpawnReason.BUILD_WITHER)) {
+ return;
+ }
+ CarvedPumpkinBlock.clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - from above
+ // CraftBukkit end
Iterator iterator = world.getEntitiesOfClass(ServerPlayer.class, entitywither.getBoundingBox().inflate(50.0D)).iterator();
while (iterator.hasNext()) {
@@ -83,7 +94,7 @@
CriteriaTriggers.SUMMONED_ENTITY.trigger(entityplayer, (Entity) entitywither);
}
- world.addFreshEntity(entitywither);
+ // world.addFreshEntity(entitywither); // CraftBukkit - moved up
CarvedPumpkinBlock.updatePatternBlocks(world, shapedetector_shapedetectorcollection);
}