More more more more more more more more work

This commit is contained in:
Josh Roy 2021-11-23 16:40:37 -05:00 committed by MiniDigger | Martin
parent e131aff8ad
commit 11709feb21
6 changed files with 26 additions and 26 deletions

View file

@ -1,148 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Mon, 3 Sep 2018 18:13:53 -0500
Subject: [PATCH] Add ray tracing methods to LivingEntity
diff --git a/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..18a96dbb01d3b34476652264b2d6be3782a154ec
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/block/TargetBlockInfo.java
@@ -0,0 +1,54 @@
+package com.destroystokyo.paper.block;
+
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents information about a targeted block
+ */
+public class TargetBlockInfo {
+ private final Block block;
+ private final BlockFace blockFace;
+
+ public TargetBlockInfo(@NotNull Block block, @NotNull BlockFace blockFace) {
+ this.block = block;
+ this.blockFace = blockFace;
+ }
+
+ /**
+ * Get the block that is targeted
+ *
+ * @return Targeted block
+ */
+ @NotNull
+ public Block getBlock() {
+ return block;
+ }
+
+ /**
+ * Get the targeted BlockFace
+ *
+ * @return Targeted blockface
+ */
+ @NotNull
+ public BlockFace getBlockFace() {
+ return blockFace;
+ }
+
+ /**
+ * Get the relative Block to the targeted block on the side it is targeted at
+ *
+ * @return Block relative to targeted block
+ */
+ @NotNull
+ public Block getRelativeBlock() {
+ return block.getRelative(blockFace);
+ }
+
+ public enum FluidMode {
+ NEVER,
+ SOURCE_ONLY,
+ ALWAYS
+ }
+}
diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java
index 6d8d96976bcef4e176453fede81a529478f11234..ad885a0775b387e3e8ca6bfae80c18465038056c 100644
--- a/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -82,6 +82,77 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
@NotNull
public Block getTargetBlock(@Nullable Set<Material> transparent, int maxDistance);
+ // Paper start
+ /**
+ * Gets the block that the living entity has targeted, ignoring fluids
+ *
+ * @param maxDistance this is the maximum distance to scan
+ * @return block that the living entity has targeted,
+ * or null if no block is within maxDistance
+ */
+ @Nullable
+ public default Block getTargetBlock(int maxDistance) {
+ return getTargetBlock(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER);
+ }
+
+ /**
+ * Gets the block that the living entity has targeted
+ *
+ * @param maxDistance this is the maximum distance to scan
+ * @param fluidMode whether to check fluids or not
+ * @return block that the living entity has targeted,
+ * or null if no block is within maxDistance
+ */
+ @Nullable
+ public Block getTargetBlock(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode);
+
+ /**
+ * Gets the blockface of that block that the living entity has targeted, ignoring fluids
+ *
+ * @param maxDistance this is the maximum distance to scan
+ * @return blockface of the block that the living entity has targeted,
+ * or null if no block is targeted
+ */
+ @Nullable
+ public default org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance) {
+ return getTargetBlockFace(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER);
+ }
+
+ /**
+ * Gets the blockface of that block that the living entity has targeted
+ *
+ * @param maxDistance this is the maximum distance to scan
+ * @param fluidMode whether to check fluids or not
+ * @return blockface of the block that the living entity has targeted,
+ * or null if no block is targeted
+ */
+ @Nullable
+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode);
+
+ /**
+ * Gets information about the block the living entity has targeted, ignoring fluids
+ *
+ * @param maxDistance this is the maximum distance to scan
+ * @return TargetBlockInfo about the block the living entity has targeted,
+ * or null if no block is targeted
+ */
+ @Nullable
+ public default com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance) {
+ return getTargetBlockInfo(maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode.NEVER);
+ }
+
+ /**
+ * Gets information about the block the living entity has targeted
+ *
+ * @param maxDistance this is the maximum distance to scan
+ * @param fluidMode whether to check fluids or not
+ * @return TargetBlockInfo about the block the living entity has targeted,
+ * or null if no block is targeted
+ */
+ @Nullable
+ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, @NotNull com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode);
+ // Paper end
+
/**
* Gets the last two blocks along the living entity's line of sight.
* <p>

View file

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Tue, 4 Sep 2018 15:01:54 -0500
Subject: [PATCH] Expose attack cooldown methods for Player
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index ac529faeb4e4be2e62228cc931a793f2ff0a28af..1bace560fc0632c702ff820a15defa730272ba75 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -2089,6 +2089,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @param profile The new profile to use
*/
void setPlayerProfile(@NotNull PlayerProfile profile);
+
+ /**
+ * Returns the amount of ticks the current cooldown lasts
+ *
+ * @return Amount of ticks cooldown will last
+ */
+ float getCooldownPeriod();
+
+ /**
+ * Returns the percentage of attack power available based on the cooldown (zero to one).
+ *
+ * @param adjustTicks Amount of ticks to add to cooldown counter for this calculation
+ * @return Percentage of attack power available
+ */
+ float getCooledAttackStrength(float adjustTicks);
+
+ /**
+ * Reset the cooldown counter to 0, effectively starting the cooldown period.
+ */
+ void resetCooldown();
// Paper end
// Spigot start

View file

@ -1,203 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Phoenix616 <mail@moep.tv>
Date: Tue, 21 Aug 2018 01:32:28 +0100
Subject: [PATCH] Improve death events
This adds the ability to cancel the death events and to modify the sound
an entity makes when dying. (In cases were no sound should it will be
called with shouldPlaySound set to false allowing unsilencing of silent
entities)
It makes handling of entity deaths a lot nicer as you no longer need
to listen on the damage event and calculate if the entity dies yourself
to cancel the death which has the benefit of also receiving the dropped
items and experience which is otherwise only properly possible by using
internal code.
diff --git a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
index a5984ab06cce95d30e70511e125f69339b574c04..e19a3df9aa2204b44c0b029bda141ae6306f60a1 100644
--- a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
@@ -5,14 +5,24 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* Thrown whenever a LivingEntity dies
*/
-public class EntityDeathEvent extends EntityEvent {
+public class EntityDeathEvent extends EntityEvent implements org.bukkit.event.Cancellable { // Paper - make cancellable
private static final HandlerList handlers = new HandlerList();
private final List<ItemStack> drops;
private int dropExp = 0;
+ // Paper start - make cancellable
+ private boolean cancelled;
+ private double reviveHealth = 0;
+ private boolean shouldPlayDeathSound;
+ @Nullable private org.bukkit.Sound deathSound;
+ @Nullable private org.bukkit.SoundCategory deathSoundCategory;
+ private float deathSoundVolume;
+ private float deathSoundPitch;
+ // Paper end
public EntityDeathEvent(@NotNull final LivingEntity entity, @NotNull final List<ItemStack> drops) {
this(entity, drops, 0);
@@ -74,4 +84,134 @@ public class EntityDeathEvent extends EntityEvent {
public static HandlerList getHandlerList() {
return handlers;
}
+
+ // Paper start - make cancellable
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ cancelled = cancel;
+ }
+
+ /**
+ * Get the amount of health that the entity should revive with after cancelling the event.
+ * Set to the entity's max health by default.
+ *
+ * @return The amount of health
+ */
+ public double getReviveHealth() {
+ return reviveHealth;
+ }
+
+ /**
+ * Set the amount of health that the entity should revive with after cancelling the event.
+ * Revive health value must be between 0 (exclusive) and the entity's max health (inclusive).
+ *
+ * @param reviveHealth The amount of health
+ * @throws IllegalArgumentException Thrown if the health is {@literal <= 0 or >} max health
+ */
+ public void setReviveHealth(double reviveHealth) throws IllegalArgumentException {
+ double maxHealth = ((LivingEntity) entity).getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue();
+ if ((maxHealth != 0 && reviveHealth <= 0) || (reviveHealth > maxHealth)) {
+ throw new IllegalArgumentException("Health must be between 0 (exclusive) and " + maxHealth + " (inclusive), but was " + reviveHealth);
+ }
+ this.reviveHealth = reviveHealth;
+ }
+
+
+ /**
+ * Whether or not the death sound should play when the entity dies. If the event is cancelled it does not play!
+ *
+ * @return Whether or not the death sound should play. Event is called with this set to false if the entity is silent.
+ */
+ public boolean shouldPlayDeathSound() {
+ return shouldPlayDeathSound;
+ }
+
+ /**
+ * Set whether or not the death sound should play when the entity dies. If the event is cancelled it does not play!
+ *
+ * @param playDeathSound Enable or disable the death sound
+ */
+ public void setShouldPlayDeathSound(boolean playDeathSound) {
+ this.shouldPlayDeathSound = playDeathSound;
+ }
+
+ /**
+ * Get the sound that the entity makes when dying
+ *
+ * @return The sound that the entity makes
+ */
+ @Nullable
+ public org.bukkit.Sound getDeathSound() {
+ return deathSound;
+ }
+
+ /**
+ * Set the sound that the entity makes when dying
+ *
+ * @param sound The sound that the entity should make when dying
+ */
+ public void setDeathSound(@Nullable org.bukkit.Sound sound) {
+ deathSound = sound;
+ }
+
+ /**
+ * Get the sound category that the death sound should play in
+ *
+ * @return The sound category
+ */
+ @Nullable
+ public org.bukkit.SoundCategory getDeathSoundCategory() {
+ return deathSoundCategory;
+ }
+
+ /**
+ * Set the sound category that the death sound should play in.
+ *
+ * @param soundCategory The sound category
+ */
+ public void setDeathSoundCategory(@Nullable org.bukkit.SoundCategory soundCategory) {
+ this.deathSoundCategory = soundCategory;
+ }
+
+ /**
+ * Get the volume that the death sound will play at.
+ *
+ * @return The volume the death sound will play at
+ */
+ public float getDeathSoundVolume() {
+ return deathSoundVolume;
+ }
+
+ /**
+ * Set the volume the death sound should play at. If the event is cancelled this will not play the sound!
+ *
+ * @param volume The volume the death sound should play at
+ */
+ public void setDeathSoundVolume(float volume) {
+ this.deathSoundVolume = volume;
+ }
+
+ /**
+ * Get the pitch that the death sound will play with.
+ *
+ * @return The pitch the death sound will play with
+ */
+ public float getDeathSoundPitch() {
+ return deathSoundPitch;
+ }
+
+ /**
+ * GSetet the pitch that the death sound should play with.
+ *
+ * @param pitch The pitch the death sound should play with
+ */
+ public void setDeathSoundPitch(float pitch) {
+ this.deathSoundPitch = pitch;
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
index a01d4c21bedc7f1a54f5a330bb4c2909ce3a18e4..48f272747b8d5ab43f79a9d474713aca79f121b7 100644
--- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
@@ -63,6 +63,17 @@ public class PlayerDeathEvent extends EntityDeathEvent {
}
// Paper start
+ /**
+ * Clarity method for getting the player. Not really needed except
+ * for reasons of clarity.
+ *
+ * @return Player who is involved in this event
+ */
+ @NotNull
+ public Player getPlayer() {
+ return getEntity();
+ }
+
/**
* Set the death message that will appear to everyone on the server.
*

View file

@ -1,90 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Mon, 3 Sep 2018 18:20:03 -0500
Subject: [PATCH] Add ray tracing methods to LivingEntity
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 802e0259f660c05afb2b772f0e617d819b19c7cc..1c09656bfed70ead0f0d182be4f84f1a97b3cf1e 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -487,6 +487,18 @@ public final class MCUtil {
return getNMSWorld(entity.getWorld());
}
+ public static ClipContext.Fluid getNMSFluidCollisionOption(com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
+ switch (fluidMode) {
+ case NEVER:
+ return ClipContext.Fluid.NONE;
+ case SOURCE_ONLY:
+ return ClipContext.Fluid.SOURCE_ONLY;
+ case ALWAYS:
+ return ClipContext.Fluid.ANY;
+ }
+ return null;
+ }
+
public static BlockFace toBukkitBlockFace(Direction enumDirection) {
switch (enumDirection) {
case DOWN:
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 85aae87d03219a53e5aec2b9983dac2831aff82e..a44a8856d9f6a71a789a7335501abebfd23635be 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3690,6 +3690,23 @@ public abstract class LivingEntity extends Entity {
}
// Paper start
+ public HitResult getRayTrace(int maxDistance) {
+ return getRayTrace(maxDistance, ClipContext.Fluid.NONE);
+ }
+
+ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) {
+ if (maxDistance < 1 || maxDistance > 120) {
+ throw new IllegalArgumentException("maxDistance must be between 1-120");
+ }
+
+ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ());
+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance);
+ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ());
+ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this);
+
+ return level.clip(raytrace);
+ }
+
public int shieldBlockingDelay = level.paperConfig.shieldBlockingDelay;
public int getShieldBlockingDelay() {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 918f87cc79062602e1db41d9368921c0092b1840..873b70c36d145a14632102c9e92d501745064fa4 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -198,6 +198,28 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
return blocks.get(0);
}
+ // Paper start
+ @Override
+ public Block getTargetBlock(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
+ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode));
+ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos());
+ }
+
+ @Override
+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
+ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode));
+ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection());
+ }
+
+ @Override
+ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) {
+ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode));
+ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null :
+ new com.destroystokyo.paper.block.TargetBlockInfo(org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()),
+ net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection()));
+ }
+ // Paper end
+
@Override
public List<Block> getLastTwoTargetBlocks(Set<Material> transparent, int maxDistance) {
return this.getLineOfSight(transparent, maxDistance, 2);

View file

@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Tue, 4 Sep 2018 15:02:00 -0500
Subject: [PATCH] Expose attack cooldown methods for Player
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 7d87be1eb79045226cad3b7e62ff5d265160b866..3be9882ac1e96441f479f22099b77a25dd7cb8dd 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2296,6 +2296,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return this.adventure$pointers;
}
+
+ @Override
+ public float getCooldownPeriod() {
+ return getHandle().getCurrentItemAttackStrengthDelay();
+ }
+
+ @Override
+ public float getCooledAttackStrength(float adjustTicks) {
+ return getHandle().getAttackStrengthScale(adjustTicks);
+ }
+
+ @Override
+ public void resetCooldown() {
+ getHandle().resetAttackStrengthTicker();
+ }
// Paper end
// Spigot start

View file

@ -1,359 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Phoenix616 <mail@moep.tv>
Date: Tue, 21 Aug 2018 01:39:35 +0100
Subject: [PATCH] Improve death events
This adds the ability to cancel the death events and to modify the sound
an entity makes when dying. (In cases were no sound should it will be
called with shouldPlaySound set to false allowing unsilencing of silent
entities)
It makes handling of entity deaths a lot nicer as you no longer need
to listen on the damage event and calculate if the entity dies yourself
to cancel the death which has the benefit of also receiving the dropped
items and experience which is otherwise only properly possible by using
internal code.
TODO 1.17: this needs to be checked (actually get off your lazy ass and cancel the events) for the following entities,
maybe more (please check patch overrides for drops for more):
- players, armor stands, foxes, chested donkeys/llamas
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 3d5db5ce2e60ca72ad202caebe49f3fc80d1af37..91f8b8e8e2ed15481ceafc8695068c8dc5853b3c 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -219,6 +219,10 @@ public class ServerPlayer extends Player {
public int latency;
public boolean wonGame;
private int containerUpdateDelay; // Paper
+ // Paper start - cancellable death event
+ public boolean queueHealthUpdatePacket = false;
+ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
+ // Paper end
// CraftBukkit start
public String displayName;
@@ -748,6 +752,15 @@ public class ServerPlayer extends Player {
String deathmessage = defaultMessage.getString();
this.keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel
org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure
+ // Paper start - cancellable death event
+ if (event.isCancelled()) {
+ // make compatible with plugins that might have already set the health in an event listener
+ if (this.getHealth() <= 0) {
+ this.setHealth((float) event.getReviveHealth());
+ }
+ return;
+ }
+ // Paper end
// SPIGOT-943 - only call if they have an inventory open
if (this.containerMenu != this.inventoryMenu) {
@@ -895,8 +908,17 @@ public class ServerPlayer extends Player {
}
}
}
-
- return super.hurt(source, amount);
+ // Paper start - cancellable death events
+ //return super.hurt(source, amount);
+ this.queueHealthUpdatePacket = true;
+ boolean damaged = super.hurt(source, amount);
+ this.queueHealthUpdatePacket = false;
+ if (this.queuedHealthUpdatePacket != null) {
+ this.connection.send(this.queuedHealthUpdatePacket);
+ this.queuedHealthUpdatePacket = null;
+ }
+ return damaged;
+ // Paper end
}
}
}
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index db366a5d81dac6748bb0b20188117266aee095d1..f4828c1bdc7d5e67941926f8d772b1bbc83031cf 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -261,6 +261,7 @@ public abstract class LivingEntity extends Entity {
public Set<UUID> collidableExemptions = new HashSet<>();
public boolean bukkitPickUpLoot;
public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper
+ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event
@Override
public float getBukkitYaw() {
@@ -1446,13 +1447,12 @@ public abstract class LivingEntity extends Entity {
if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback
if (this.isDeadOrDying()) {
if (!this.checkTotemDeathProtection(source)) {
- SoundEvent soundeffect = this.getDeathSound();
-
- if (flag1 && soundeffect != null) {
- this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch());
- }
+ // Paper start - moved into CraftEventFactory event caller for cancellable death event
+ this.silentDeath = !flag1; // mark entity as dying silently
+ // Paper end
this.die(source);
+ this.silentDeath = false; // Paper - cancellable death event - reset to default
}
} else if (flag1) {
this.playHurtSound(source);
@@ -1601,7 +1601,7 @@ public abstract class LivingEntity extends Entity {
if (!this.isRemoved() && !this.dead) {
Entity entity = source.getEntity();
LivingEntity entityliving = this.getKillCredit();
-
+ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below
if (this.deathScore >= 0 && entityliving != null) {
entityliving.awardKillScore(this, this.deathScore, source);
}
@@ -1613,20 +1613,46 @@ public abstract class LivingEntity extends Entity {
if (!this.level.isClientSide && this.hasCustomName()) {
if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot
}
+ */ // Paper - move down to make death event cancellable - this is the runKillTrigger below
this.dead = true;
- this.getCombatTracker().recheckStatus();
+ // Paper - moved into if below
if (this.level instanceof ServerLevel) {
if (entity != null) {
- entity.killed((ServerLevel) this.level, this);
+ // Paper - move below into if for onKill
}
- this.dropAllDeathLoot(source);
+ // Paper start
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(source);
+ if (deathEvent == null || !deathEvent.isCancelled()) {
+ if (this.deathScore >= 0 && entityliving != null) {
+ entityliving.awardKillScore(this, this.deathScore, source);
+ }
+
+ if (this.isSleeping()) {
+ this.stopSleeping();
+ }
+
+ if (!this.level.isClientSide && this.hasCustomName()) {
+ if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot
+ }
+
+ this.getCombatTracker().recheckStatus();
+ if (entity != null) {
+ entity.killed((ServerLevel) this.level, this);
+ }
+ } else {
+ this.dead = false;
+ this.setHealth((float) deathEvent.getReviveHealth());
+ }
+ // Paper end
this.createWitherRose(entityliving);
}
+ if (this.dead) { // Paper
this.level.broadcastEntityEvent(this, (byte) 3);
this.setPose(Pose.DYING);
+ } // Paper
}
}
@@ -1634,7 +1660,7 @@ public abstract class LivingEntity extends Entity {
if (!this.level.isClientSide) {
boolean flag = false;
- if (adversary instanceof WitherBoss) {
+ if (this.dead && adversary instanceof WitherBoss) { // Paper
if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
BlockPos blockposition = this.blockPosition();
BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState();
@@ -1663,7 +1689,7 @@ public abstract class LivingEntity extends Entity {
}
}
- protected void dropAllDeathLoot(DamageSource source) {
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { // Paper
Entity entity = source.getEntity();
int i;
@@ -1681,15 +1707,18 @@ public abstract class LivingEntity extends Entity {
this.dropCustomDeathLoot(source, i, flag);
}
// CraftBukkit start - Call death event
- CraftEventFactory.callEntityDeathEvent(this, this.drops);
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper
+ this.postDeathDropItems(deathEvent); // Paper
this.drops = new ArrayList<>();
// CraftBukkit end
// this.dropInventory();// CraftBukkit - moved up
this.dropExperience();
+ return deathEvent; // Paper
}
protected void dropEquipment() {}
+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled
// CraftBukkit start
public int getExpReward() {
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
index 7de3d73232d985ab18d7266371d301c490b79b9f..bfb042f4828e1cd47124939ca3b9caadc7fe1b39 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
@@ -691,15 +691,25 @@ public class Fox extends Animal {
}
@Override
- protected void dropAllDeathLoot(DamageSource source) {
- ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND);
+ // Paper start - Cancellable death event
+ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) {
+ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper - modified by supercall
+
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(source);
+
+ // Below is code to drop
+
+ if (deathEvent == null || deathEvent.isCancelled()) {
+ return deathEvent;
+ }
+ // Paper end
if (!itemstack.isEmpty()) {
this.spawnAtLocation(itemstack);
this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
}
- super.dropAllDeathLoot(source);
+ return deathEvent; // Paper
}
public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) {
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
index 224eca7d20cf4b890a6bc1b314d566e02e716762..7281eb294ddd178ba742088d3c61bf3d529ff0c4 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java
@@ -68,11 +68,19 @@ public abstract class AbstractChestedHorse extends AbstractHorse {
this.spawnAtLocation(Blocks.CHEST);
}
- this.setChest(false);
+ //this.setCarryingChest(false); // Paper - moved to post death logic
}
}
+ // Paper start
+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {
+ if (this.hasChest() && (event == null || !event.isCancelled())) {
+ this.setChest(false);
+ }
+ }
+ // Paper end
+
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
super.addAdditionalSaveData(nbt);
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
index f9375dbbeda6fdc92406fe5d93df0467e6e70672..b41e6fb0b7e02b50e5ad05555ed911d09055d694 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -755,7 +755,8 @@ public class ArmorStand extends LivingEntity {
@Override
public void kill() {
- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event
+ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable
+ if (event.isCancelled()) return; // Paper - make cancellable
this.remove(Entity.RemovalReason.KILLED);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 3be9882ac1e96441f479f22099b77a25dd7cb8dd..7b7ceefbcc1f0be710dd8995f0afaad98f9c044d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1876,7 +1876,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
public void sendHealthUpdate() {
- this.getHandle().connection.send(new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().getSaturationLevel()));
+ // Paper start - cancellable death event
+ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().getSaturationLevel());
+ if (this.getHandle().queueHealthUpdatePacket) {
+ this.getHandle().queuedHealthUpdatePacket = packet;
+ } else {
+ this.getHandle().connection.send(packet);
+ }
+ // Paper end
}
public void injectScaledMaxHealth(Collection<AttributeInstance> collection, boolean force) {
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e094b1b00d5fb73da73abcadb02ffd98b91fb869..3ef52d7705f3c59e19c56aac6250f2e5b5712600 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -807,9 +807,16 @@ public class CraftEventFactory {
public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, List<org.bukkit.inventory.ItemStack> drops) {
CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity();
EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward());
+ populateFields(victim, event); // Paper - make cancellable
CraftWorld world = (CraftWorld) entity.getWorld();
Bukkit.getServer().getPluginManager().callEvent(event);
+ // Paper start - make cancellable
+ if (event.isCancelled()) {
+ return event;
+ }
+ playDeathSound(victim, event);
+ // Paper end
victim.expToDrop = event.getDroppedExp();
for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
@@ -826,8 +833,15 @@ public class CraftEventFactory {
PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure
event.setKeepInventory(keepInventory);
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
+ populateFields(victim, event); // Paper - make cancellable
org.bukkit.World world = entity.getWorld();
Bukkit.getServer().getPluginManager().callEvent(event);
+ // Paper start - make cancellable
+ if (event.isCancelled()) {
+ return event;
+ }
+ playDeathSound(victim, event);
+ // Paper end
victim.keepLevel = event.getKeepLevel();
victim.newLevel = event.getNewLevel();
@@ -844,6 +858,31 @@ public class CraftEventFactory {
return event;
}
+ // Paper start - helper methods for making death event cancellable
+ // Add information to death event
+ private static void populateFields(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) {
+ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue());
+ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent());
+ net.minecraft.sounds.SoundEvent soundEffect = victim.getDeathSound();
+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null);
+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name()));
+ event.setDeathSoundVolume(victim.getSoundVolume());
+ event.setDeathSoundPitch(victim.getVoicePitch());
+ }
+
+ // Play death sound manually
+ private static void playDeathSound(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) {
+ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) {
+ net.minecraft.world.entity.player.Player source = victim instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) victim : null;
+ double x = event.getEntity().getLocation().getX();
+ double y = event.getEntity().getLocation().getY();
+ double z = event.getEntity().getLocation().getZ();
+ net.minecraft.sounds.SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound());
+ net.minecraft.sounds.SoundSource soundCategory = net.minecraft.sounds.SoundSource.valueOf(event.getDeathSoundCategory().name());
+ victim.level.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch());
+ }
+ }
+ // Paper end
/**
* Server methods
*/