Properly handle experience dropping on block break
This causes spawnAfterBreak to spawn xp by default, removing the need to manually add xp wherever this method is used. For classes that use custom xp amounts, they can drop the resources with disabling
This commit is contained in:
@ -303,7 +303,7 @@
|
|||||||
|
|
||||||
+ // Paper start - if loaded
|
+ // Paper start - if loaded
|
||||||
@Nullable
|
@Nullable
|
||||||
+ @Override
|
@Override
|
||||||
+ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) {
|
+ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) {
|
||||||
+ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z);
|
+ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z);
|
||||||
+ }
|
+ }
|
||||||
@ -356,7 +356,7 @@
|
|||||||
+ return getWorldBorder().isWithinBounds(blockposition) ? getBlockStateIfLoaded(blockposition) : null;
|
+ return getWorldBorder().isWithinBounds(blockposition) ? getBlockStateIfLoaded(blockposition) : null;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@Override
|
+ @Override
|
||||||
public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
|
public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create);
|
ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create);
|
||||||
@ -523,7 +523,7 @@
|
|||||||
public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {}
|
public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -270,9 +591,26 @@
|
@@ -270,15 +591,33 @@
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
FluidState fluid = this.getFluidState(pos);
|
FluidState fluid = this.getFluidState(pos);
|
||||||
@ -552,7 +552,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (drop) {
|
if (drop) {
|
||||||
@@ -340,10 +678,18 @@
|
BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
|
||||||
|
|
||||||
|
- Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY);
|
||||||
|
+ Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
|
||||||
|
+ iblockdata.getBlock().popExperience((ServerLevel) this, pos, xp, breakingEntity); // Paper - Properly handle xp dropping; custom amount
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth);
|
||||||
|
@@ -340,10 +679,18 @@
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlockState(BlockPos pos) {
|
public BlockState getBlockState(BlockPos pos) {
|
||||||
@ -572,7 +580,7 @@
|
|||||||
|
|
||||||
return chunk.getBlockState(pos);
|
return chunk.getBlockState(pos);
|
||||||
}
|
}
|
||||||
@@ -446,34 +792,53 @@
|
@@ -446,34 +793,53 @@
|
||||||
this.pendingBlockEntityTickers.clear();
|
this.pendingBlockEntityTickers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,26 +632,26 @@
|
|||||||
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||||
+ // Paper end - Prevent block entity and entity crashes
|
+ // Paper end - Prevent block entity and entity crashes
|
||||||
}
|
}
|
||||||
+ }
|
}
|
||||||
+ // Paper start - Option to prevent armor stands from doing entity lookups
|
+ // Paper start - Option to prevent armor stands from doing entity lookups
|
||||||
+ @Override
|
+ @Override
|
||||||
+ public boolean noCollision(@Nullable Entity entity, AABB box) {
|
+ public boolean noCollision(@Nullable Entity entity, AABB box) {
|
||||||
+ if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return false;
|
+ if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return false;
|
||||||
+ return LevelAccessor.super.noCollision(entity, box);
|
+ return LevelAccessor.super.noCollision(entity, box);
|
||||||
}
|
+ }
|
||||||
+ // Paper end - Option to prevent armor stands from doing entity lookups
|
+ // Paper end - Option to prevent armor stands from doing entity lookups
|
||||||
|
|
||||||
public boolean shouldTickDeath(Entity entity) {
|
public boolean shouldTickDeath(Entity entity) {
|
||||||
return true;
|
return true;
|
||||||
@@ -510,13 +875,32 @@
|
@@ -510,13 +876,32 @@
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockEntity getBlockEntity(BlockPos pos) {
|
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||||
- return this.isOutsideBuildHeight(pos) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE));
|
- return this.isOutsideBuildHeight(pos) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE));
|
||||||
+ // CraftBukkit start
|
+ // CraftBukkit start
|
||||||
+ return this.getBlockEntity(pos, true);
|
+ return this.getBlockEntity(pos, true);
|
||||||
+ }
|
}
|
||||||
+
|
|
||||||
+ @Nullable
|
+ @Nullable
|
||||||
+ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) {
|
+ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) {
|
||||||
+ // Paper start - Perf: Optimize capturedTileEntities lookup
|
+ // Paper start - Perf: Optimize capturedTileEntities lookup
|
||||||
@ -654,8 +662,8 @@
|
|||||||
+ // Paper end - Perf: Optimize capturedTileEntities lookup
|
+ // Paper end - Perf: Optimize capturedTileEntities lookup
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
+ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE));
|
+ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE));
|
||||||
}
|
+ }
|
||||||
|
+
|
||||||
public void setBlockEntity(BlockEntity blockEntity) {
|
public void setBlockEntity(BlockEntity blockEntity) {
|
||||||
BlockPos blockposition = blockEntity.getBlockPos();
|
BlockPos blockposition = blockEntity.getBlockPos();
|
||||||
|
|
||||||
@ -669,7 +677,7 @@
|
|||||||
this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity);
|
this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,7 +1027,7 @@
|
@@ -643,7 +1028,7 @@
|
||||||
|
|
||||||
for (int k = 0; k < j; ++k) {
|
for (int k = 0; k < j; ++k) {
|
||||||
EnderDragonPart entitycomplexpart = aentitycomplexpart[k];
|
EnderDragonPart entitycomplexpart = aentitycomplexpart[k];
|
||||||
@ -678,7 +686,7 @@
|
|||||||
|
|
||||||
if (t0 != null && predicate.test(t0)) {
|
if (t0 != null && predicate.test(t0)) {
|
||||||
result.add(t0);
|
result.add(t0);
|
||||||
@@ -912,7 +1296,7 @@
|
@@ -912,7 +1297,7 @@
|
||||||
|
|
||||||
public static enum ExplosionInteraction implements StringRepresentable {
|
public static enum ExplosionInteraction implements StringRepresentable {
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
--- a/net/minecraft/world/level/block/Block.java
|
--- a/net/minecraft/world/level/block/Block.java
|
||||||
+++ b/net/minecraft/world/level/block/Block.java
|
+++ b/net/minecraft/world/level/block/Block.java
|
||||||
@@ -295,6 +295,24 @@
|
@@ -292,15 +292,41 @@
|
||||||
|
});
|
||||||
|
state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY, true);
|
||||||
}
|
}
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
|
||||||
+ // Paper start - Add BlockBreakBlockEvent
|
+ // Paper start - Add BlockBreakBlockEvent
|
||||||
+ public static boolean dropResources(BlockState state, LevelAccessor levelAccessor, BlockPos pos, @Nullable BlockEntity blockEntity, BlockPos source) {
|
+ public static boolean dropResources(BlockState state, LevelAccessor levelAccessor, BlockPos pos, @Nullable BlockEntity blockEntity, BlockPos source) {
|
||||||
@ -11,21 +14,36 @@
|
|||||||
+ for (ItemStack drop : Block.getDrops(state, serverLevel, pos, blockEntity)) {
|
+ for (ItemStack drop : Block.getDrops(state, serverLevel, pos, blockEntity)) {
|
||||||
+ items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
|
+ items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
|
||||||
+ }
|
+ }
|
||||||
|
+ Block block = state.getBlock(); // Paper - Properly handle xp dropping
|
||||||
+ io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, pos), org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, source), items);
|
+ io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, pos), org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, source), items);
|
||||||
|
+ event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
|
||||||
+ event.callEvent();
|
+ event.callEvent();
|
||||||
+ for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
|
+ for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
|
||||||
+ popResource(serverLevel, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
|
+ popResource(serverLevel, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
|
||||||
+ }
|
+ }
|
||||||
+ state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, true);
|
+ state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
|
||||||
|
+ block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
|
||||||
+ }
|
+ }
|
||||||
+ return true;
|
+ return true;
|
||||||
+ }
|
}
|
||||||
+ // Paper end - Add BlockBreakBlockEvent
|
+ // Paper end - Add BlockBreakBlockEvent
|
||||||
+
|
|
||||||
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
|
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
|
||||||
|
+ // Paper start - Properly handle xp dropping
|
||||||
|
+ dropResources(state, world, pos, blockEntity, entity, tool, true);
|
||||||
|
+ }
|
||||||
|
+ public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool, boolean dropExperience) {
|
||||||
|
+ // Paper end - Properly handle xp dropping
|
||||||
if (world instanceof ServerLevel) {
|
if (world instanceof ServerLevel) {
|
||||||
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
|
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
|
||||||
@@ -340,7 +358,13 @@
|
Block.popResource(world, pos, itemstack1);
|
||||||
|
});
|
||||||
|
- state.spawnAfterBreak((ServerLevel) world, pos, tool, true);
|
||||||
|
+ state.spawnAfterBreak((ServerLevel) world, pos, tool, dropExperience); // Paper - Properly handle xp dropping
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -340,7 +366,13 @@
|
||||||
ItemEntity entityitem = (ItemEntity) itemEntitySupplier.get();
|
ItemEntity entityitem = (ItemEntity) itemEntitySupplier.get();
|
||||||
|
|
||||||
entityitem.setDefaultPickUpDelay();
|
entityitem.setDefaultPickUpDelay();
|
||||||
@ -40,7 +58,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,8 +372,13 @@
|
@@ -348,8 +380,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public void popExperience(ServerLevel world, BlockPos pos, int size) {
|
public void popExperience(ServerLevel world, BlockPos pos, int size) {
|
||||||
@ -55,7 +73,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -367,10 +396,18 @@
|
@@ -367,10 +404,18 @@
|
||||||
return this.defaultBlockState();
|
return this.defaultBlockState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +86,15 @@
|
|||||||
+ // Paper end - fix drops not preventing stats/food exhaustion
|
+ // Paper end - fix drops not preventing stats/food exhaustion
|
||||||
player.awardStat(Stats.BLOCK_MINED.get(this));
|
player.awardStat(Stats.BLOCK_MINED.get(this));
|
||||||
- player.causeFoodExhaustion(0.005F);
|
- player.causeFoodExhaustion(0.005F);
|
||||||
|
- Block.dropResources(state, world, pos, blockEntity, player, tool);
|
||||||
+ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
|
+ player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
|
||||||
+ if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion
|
+ if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion
|
||||||
Block.dropResources(state, world, pos, blockEntity, player, tool);
|
+ Block.dropResources(state, world, pos, blockEntity, player, tool, dropExp); // Paper - Properly handle xp dropping
|
||||||
+ } // Paper - fix drops not preventing stats/food exhaustion
|
+ } // Paper - fix drops not preventing stats/food exhaustion
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
|
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
|
||||||
@@ -490,15 +527,35 @@
|
@@ -490,15 +535,35 @@
|
||||||
return this.builtInRegistryHolder;
|
return this.builtInRegistryHolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -132,7 +132,15 @@
|
|||||||
public void onRemove(Level world, BlockPos pos, BlockState state, boolean moved) {
|
public void onRemove(Level world, BlockPos pos, BlockState state, boolean moved) {
|
||||||
this.getBlock().onRemove(this.asState(), world, pos, state, moved);
|
this.getBlock().onRemove(this.asState(), world, pos, state, moved);
|
||||||
}
|
}
|
||||||
@@ -1250,11 +1280,11 @@
|
@@ -1154,6 +1184,7 @@
|
||||||
|
|
||||||
|
public void spawnAfterBreak(ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) {
|
||||||
|
this.getBlock().spawnAfterBreak(this.asState(), world, pos, tool, dropExperience);
|
||||||
|
+ if (dropExperience) {getBlock().popExperience(world, pos, this.getBlock().getExpDrop(asState(), world, pos, tool, true));} // Paper - Properly handle xp dropping
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemStack> getDrops(LootParams.Builder builder) {
|
||||||
|
@@ -1250,11 +1281,11 @@
|
||||||
return this.getBlock().builtInRegistryHolder().is(key);
|
return this.getBlock().builtInRegistryHolder().is(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -509,7 +509,7 @@ public class CraftBlock implements Block {
|
|||||||
|
|
||||||
// Modelled off EntityHuman#hasBlock
|
// Modelled off EntityHuman#hasBlock
|
||||||
if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) {
|
if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) {
|
||||||
net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem);
|
net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), this.position, this.world.getBlockEntity(this.position), null, nmsItem, false); // Paper - Properly handle xp dropping
|
||||||
// Paper start - improve Block#breanNaturally
|
// Paper start - improve Block#breanNaturally
|
||||||
if (triggerEffect) {
|
if (triggerEffect) {
|
||||||
if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {
|
if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {
|
||||||
|
|||||||
Reference in New Issue
Block a user