geforkt von Mirrors/Paper
Fix experience & improvements to block events (#8067)
This is a lot but basically adds a method to disable the dropping of experience and drops experience by default. This way things that require XP to be dropped manually (via modification), they can drop XP themselves when needed but without touching anywhere else that may drop xp. It should be noted this causes breakNaturally() to now drop experience.
Dieser Commit ist enthalten in:
Ursprung
635ece80cf
Commit
9940519717
@ -15,6 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.block.BlockEvent;
|
||||
+import org.bukkit.event.block.BlockExpEvent;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
@ -25,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ * <p>
|
||||
+ * Currently called for piston's and liquid flows.
|
||||
+ */
|
||||
+public class BlockBreakBlockEvent extends BlockEvent {
|
||||
+public class BlockBreakBlockEvent extends BlockExpEvent {
|
||||
+
|
||||
+ private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
+
|
||||
@ -33,7 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ private final Block source;
|
||||
+
|
||||
+ public BlockBreakBlockEvent(@NotNull Block block, @NotNull Block source, @NotNull List<ItemStack> drops) {
|
||||
+ super(block);
|
||||
+ super(block, 0);
|
||||
+ this.source = source;
|
||||
+ this.drops = drops;
|
||||
+ }
|
||||
|
@ -23,6 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.block.BlockEvent;
|
||||
+import org.bukkit.event.block.BlockExpEvent;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+/**
|
||||
@ -36,23 +37,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ * Events such as leaves decaying, pistons retracting (where the block is moving), does NOT fire this event.
|
||||
+ *
|
||||
+ */
|
||||
+public class BlockDestroyEvent extends BlockEvent implements Cancellable {
|
||||
+public class BlockDestroyEvent extends BlockExpEvent implements Cancellable {
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ @NotNull private final BlockData newState;
|
||||
+ private boolean willDrop;
|
||||
+ private boolean playEffect = true;
|
||||
+ private BlockData effectBlock;
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ public BlockDestroyEvent(@NotNull Block block, @NotNull BlockData newState, boolean willDrop) {
|
||||
+ super(block);
|
||||
+ super(block, 0);
|
||||
+ this.newState = newState;
|
||||
+ this.willDrop = willDrop;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Get the effect that will be played when the block is broken.
|
||||
+ * @return block break effect
|
||||
+ */
|
||||
+ @NotNull
|
||||
+ public BlockData getEffectBlock() {
|
||||
+ return this.effectBlock;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the effect that will be played when the block is broken.
|
||||
+ * Note: {@link BlockDestroyEvent#playEffect()} must be true in order for this effect to be
|
||||
+ * played.
|
||||
+ *
|
||||
+ * @param effectBlock block effect
|
||||
+ */
|
||||
+ public void setEffectBlock(@NotNull BlockData effectBlock) {
|
||||
+ this.effectBlock = effectBlock;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * @return The new state of this block (Air, or a Fluid type)
|
||||
+ */
|
||||
+ @NotNull
|
||||
|
@ -30,18 +30,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent,
|
||||
+ // it doesn't imply destruction of a block that plays a sound effect / drops an item.
|
||||
+ boolean playEffect = true;
|
||||
+ BlockState effectType = iblockdata;
|
||||
+ int xp = iblockdata.getBlock().getExpDrop(iblockdata, (ServerLevel) this, pos, ItemStack.EMPTY, true);
|
||||
+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ effectType = ((CraftBlockData) event.getEffectBlock()).getState();
|
||||
+ playEffect = event.playEffect();
|
||||
+ drop = event.willDrop();
|
||||
+ xp = event.getExpToDrop();
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) {
|
||||
+ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper
|
||||
this.levelEvent(2001, pos, Block.getId(iblockdata));
|
||||
- this.levelEvent(2001, pos, Block.getId(iblockdata));
|
||||
+ if (playEffect && !(effectType.getBlock() instanceof BaseFireBlock)) { // Paper
|
||||
+ this.levelEvent(2001, pos, Block.getId(effectType)); // Paper
|
||||
}
|
||||
|
||||
if (drop) {
|
||||
|
@ -299,14 +299,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
|
||||
public void popExperience(ServerLevel world, BlockPos pos, int size) {
|
||||
+ // Paper start - add player parameter
|
||||
+ // Paper start - add entity parameter
|
||||
+ popExperience(world, pos, size, null);
|
||||
+ }
|
||||
+ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.server.level.ServerPlayer player) {
|
||||
+ // Paper end - add player parameter
|
||||
+ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.world.entity.Entity entity) {
|
||||
+ // Paper end - add entity parameter
|
||||
if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) {
|
||||
- ExperienceOrb.award(world, Vec3.atCenterOf(pos), size);
|
||||
+ ExperienceOrb.award(world, Vec3.atCenterOf(pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player); // Paper
|
||||
+ ExperienceOrb.award(world, Vec3.atCenterOf(pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, entity); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
- if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items
|
||||
- block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1);
|
||||
+ if (flag && flag1 && event.isDropItems()/* && event.isDropItems() */) { // CraftBukkit - Check if block should drop items // Paper - fix drops not preventing stats/food exhaustion
|
||||
+ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems()); // Paper
|
||||
+ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems(), false); // Paper
|
||||
}
|
||||
|
||||
// return true; // CraftBukkit
|
||||
@ -33,8 +33,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@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) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
|
||||
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper
|
||||
if (!world.isClientSide && blockEntity instanceof BeehiveBlockEntity) {
|
||||
BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) blockEntity;
|
||||
|
||||
@ -49,9 +49,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ @io.papermc.paper.annotation.DoNotUse // Paper - method below allows better control of item drops
|
||||
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
|
||||
+ // Paper start
|
||||
+ this.playerDestroy(world, player, pos, state, blockEntity, tool, true);
|
||||
+ this.playerDestroy(world, player, pos, state, blockEntity, tool, true, true);
|
||||
+ }
|
||||
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) {
|
||||
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) {
|
||||
+ // Paper end
|
||||
player.awardStat(Stats.BLOCK_MINED.get(this));
|
||||
player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
|
||||
@ -71,8 +71,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@Override
|
||||
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
|
||||
- super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool);
|
||||
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops); // Paper
|
||||
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper
|
||||
}
|
||||
|
||||
protected static void preventDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) {
|
||||
@ -86,8 +86,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@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) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
|
||||
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper
|
||||
// Paper start
|
||||
this.afterDestroy(world, pos, tool);
|
||||
}
|
||||
@ -101,8 +101,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@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) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
|
||||
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper
|
||||
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper
|
||||
this.decreaseEggs(world, pos, state);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Sat, 30 Dec 2023 15:00:06 -0500
|
||||
Subject: [PATCH] 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
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (drop) {
|
||||
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); // Don't drop xp
|
||||
+ iblockdata.getBlock().popExperience((ServerLevel) this, pos, xp, breakingEntity); // Paper - handle drop experience logic, custom amount
|
||||
}
|
||||
|
||||
boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
@@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
for (net.minecraft.world.item.ItemStack drop : net.minecraft.world.level.block.Block.getDrops(state, world.getMinecraftWorld(), pos, blockEntity)) {
|
||||
items.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(drop));
|
||||
}
|
||||
+ Block block = state.getBlock();
|
||||
io.papermc.paper.event.block.BlockBreakBlockEvent event = new io.papermc.paper.event.block.BlockBreakBlockEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, pos), org.bukkit.craftbukkit.block.CraftBlock.at(world, source), items);
|
||||
+ event.setExpToDrop(block.getExpDrop(state, (ServerLevel) world, pos, net.minecraft.world.item.ItemStack.EMPTY, true));
|
||||
event.callEvent();
|
||||
for (var drop : event.getDrops()) {
|
||||
popResource(world.getMinecraftWorld(), pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
|
||||
}
|
||||
- state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, true);
|
||||
+ state.spawnAfterBreak(world.getMinecraftWorld(), pos, ItemStack.EMPTY, false);
|
||||
+ block.popExperience((ServerLevel) world, pos, event.getExpToDrop());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Paper end
|
||||
|
||||
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
|
||||
+ // Paper start
|
||||
+ 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
|
||||
if (world instanceof ServerLevel) {
|
||||
Block.getDrops(state, (ServerLevel) world, pos, blockEntity, entity, tool).forEach((itemstack1) -> {
|
||||
Block.popResource(world, pos, itemstack1);
|
||||
});
|
||||
- state.spawnAfterBreak((ServerLevel) world, pos, tool, true);
|
||||
+ state.spawnAfterBreak((ServerLevel) world, pos, tool, dropExperience); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
player.awardStat(Stats.BLOCK_MINED.get(this));
|
||||
player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
|
||||
if (includeDrops) { // Paper
|
||||
- Block.dropResources(state, world, pos, blockEntity, player, tool);
|
||||
+ Block.dropResources(state, world, pos, blockEntity, player, tool, dropExp); // Paper
|
||||
} // Paper
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
|
||||
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 - spawn experience
|
||||
}
|
||||
|
||||
public List<ItemStack> getDrops(LootParams.Builder builder) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
|
||||
@@ -0,0 +0,0 @@ public class CraftBlock implements Block {
|
||||
|
||||
// Modelled off EntityHuman#hasBlock
|
||||
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
|
||||
// Paper start - improve Block#breanNaturally
|
||||
if (triggerEffect) {
|
||||
if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.BaseFireBlock) {
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren