Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 2stinkysocks <zmehall@gmail.com>
Date: Mon, 29 Jan 2024 02:36:33 -0700
Subject: [PATCH] Add player kill credit to beds/respawn anchors


diff --git a/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java b/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java
index 7dcbb75170296c1dd1d784a032bf369602328b29..151807d64c6d973d0ba1e8955a5a3ed8381d7a8b 100644
--- a/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java
+++ b/src/main/java/org/bukkit/event/block/BlockExplodeEvent.java
@@ -21,6 +21,7 @@ public class BlockExplodeEvent extends BlockEvent implements Cancellable {
private final List<Block> blocks;
private float yield;
private final org.bukkit.block.BlockState explodedBlockState; // Paper
+ private final org.bukkit.entity.LivingEntity igniter; // Paper - add player kill credit

@Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
public BlockExplodeEvent(@NotNull final Block what, @NotNull final List<Block> blocks, final float yield) {
@@ -28,15 +29,22 @@ public class BlockExplodeEvent extends BlockEvent implements Cancellable {
this(what, blocks, yield, null);
}
@org.jetbrains.annotations.ApiStatus.Internal
- public BlockExplodeEvent(@NotNull final Block what, @NotNull final List<Block> blocks, final float yield, @org.jetbrains.annotations.Nullable org.bukkit.block.BlockState explodedBlockState) {
+ public BlockExplodeEvent(@NotNull final Block what, @NotNull final List<Block> blocks, final float yield, @org.jetbrains.annotations.Nullable org.bukkit.block.BlockState explodedBlockState, org.bukkit.entity.LivingEntity igniter) { // Paper - add player kill credit
// Paper end
super(what);
this.blocks = blocks;
this.yield = yield;
this.cancel = false;
this.explodedBlockState = explodedBlockState; // Paper
+ this.igniter = igniter; // Paper - add player kill credit
}

+ // Paper start - add player kill credit
+ public BlockExplodeEvent(@NotNull final Block what, @NotNull final List<Block> blocks, final float yield, @org.jetbrains.annotations.Nullable org.bukkit.block.BlockState explodedBlockState) {
+ this(what, blocks, yield, explodedBlockState, null);
+ }
+ // Paper end - add player kill credit
+
@Override
public boolean isCancelled() {
return cancel;
@@ -92,6 +100,17 @@ public class BlockExplodeEvent extends BlockEvent implements Cancellable {
this.yield = yield;
}

+ // Paper start - add player kill credit
+ /**
+ * Returns the {@link org.bukkit.entity.LivingEntity} that ignited the block
+ *
+ * @return The {@link org.bukkit.entity.LivingEntity} who ignited the block
+ */
+ public @org.jetbrains.annotations.Nullable org.bukkit.entity.LivingEntity getIgniter() {
+ return this.igniter;
+ }
+ // Paper end - add player kill credit
+
@NotNull
@Override
public HandlerList getHandlers() {
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: 2stinkysocks <zmehall@gmail.com>
Date: Mon, 29 Jan 2024 00:30:34 -0700
Subject: [PATCH] Add player kill credit to beds/respawn anchors


diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index fc6903b20a6e084729306fc960a6fc80e094f76c..f6f1920d2fe3676b71fad187dfc488aa1689ed9f 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -81,6 +81,15 @@ public class DamageSource {
this(type, (Entity) null, (Entity) null, position);
}

+ // Paper start - add player kill credit
+ public DamageSource(Holder<DamageType> type, Vec3 position, @Nullable Entity attacker) {
+ this.type = type;
+ this.causingEntity = attacker;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unsure how happy I am with hijacking this field.
Given neither paper nor spigot have a damage source API yet it might be fine, but this is changing vanilla behaviour and spigot behaviour.

Does anything stop us from going down the same path as the critical damage API and add a field + getter/setter for the "igniter" entity ref ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes more sense to just add a setter for the causingEntity field, since this is already used in LivingEntity's hurt method to determine kill credit, I can verify that this works later.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more referring to the fact that other things might use the causingEntity field.
Changing that might break things we are not aware of and testing that everything still works fine is kind of hard.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's more the fact that "causingEntity" generally has a very explict meaning within the servers code and reusing this field is likely to cause some issues, if not now, maybe in the future; would much rather just add a field this rather than trying to hijack th emeaning of an exisitng one

Copy link
Copy Markdown
Author

@2stinkysocks 2stinkysocks Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this just require more changes to hurt() in LivingEntity? It seems like all the existing logic in there would just have to be implemented twice, since the entity "causing" the event is still the person who ignited the block. I know that this avoids having unintended side effects with other parts of the code but I don't see a way it could be implemented cleanly without just mostly duplicating the logic. I'll do it if everyone thinks it's the best way, but I just want to put that out there.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that is exactly the point tho.

Vanilla does not consider the "igniting entity" the causing entity of the damage.
This PR should not change this. The logic in LivingEntity#hurt acts on the causingEntity of the damage source, which should remain null for explosions from e.g. respawn anchors.

You are merely supposed to hijack the DamageSource to pass through the entity that ignited the block so that the API event can expose it.
Changing what vanilla considers the actual causingEntity is not a good idea, which is why cat and I suggested this to be moved to its own field so existing logic does not change.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see how I was misunderstanding, it's definitely better for plugin developers to implement this themselves, sorry for the confusion. I'm starting to think this change would be better to make upstream, so I might create a similar pr to spigot that only changes the API. I'll close this pr and will come back to it if I run into problems with spigot.

+ this.directEntity = null;
+ this.damageSourcePosition = position;
+ }
+ // Paper end - add player kill credit
+
public DamageSource(Holder<DamageType> type, @Nullable Entity attacker) {
this(type, attacker, attacker);
}
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSources.java b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
index f339475185645f7be30963e4f980ce81a6f7e536..b41235c47f1e03c25983cb25ff032248609c5bf7 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSources.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
@@ -253,8 +253,14 @@ public class DamageSources {
return this.badRespawnPointExplosion(position, null);
}

+ // Paper start - add player kill credit
public DamageSource badRespawnPointExplosion(Vec3 position, @Nullable org.bukkit.block.BlockState explodedBlockState) {
- DamageSource source = new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position);
+ return this.badRespawnPointExplosion(position, null, explodedBlockState);
+ }
+
+ public DamageSource badRespawnPointExplosion(Vec3 position, @Nullable Player player, @Nullable org.bukkit.block.BlockState explodedBlockState) {
+ DamageSource source = new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position, player);
+ // Paper end - add player kill credit
source.explodedBlockState = explodedBlockState;
return source;
// Paper end - add exploded state
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index 28ef910885dbd48965fba6f08cec412697b1b7f0..f20e32048b335979d3d2d132800a3a213af5b0e2 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -549,7 +549,7 @@ public class Explosion {
int i1 = Mth.floor(this.y + (double) f2 + 1.0D);
int j1 = Mth.floor(this.z - (double) f2 - 1.0D);
int k1 = Mth.floor(this.z + (double) f2 + 1.0D);
- List<Entity> list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate<Entity>) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities
+ List<Entity> list = this.level.getEntities(this.damageSource.is(net.minecraft.world.damagesource.DamageTypes.BAD_RESPAWN_POINT) ? null : this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate<Entity>) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities, add player kill credit
Vec3 vec3d = new Vec3(this.x, this.y, this.z);
Iterator iterator = list.iterator();

@@ -680,14 +680,14 @@ public class Explosion {

List<org.bukkit.block.Block> bukkitBlocks;

- if (explode != null) {
+ if (!this.damageSource.is(net.minecraft.world.damagesource.DamageTypes.BAD_RESPAWN_POINT) && explode != null) { // Paper - add player kill credit
EntityExplodeEvent event = new EntityExplodeEvent(explode, location, blockList, this.yield);
this.level.getCraftServer().getPluginManager().callEvent(event);
this.wasCanceled = event.isCancelled();
bukkitBlocks = event.blockList();
this.yield = event.getYield();
} else {
- BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield, this.damageSource.explodedBlockState); // Paper - add exploded state
+ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield, this.damageSource.explodedBlockState, (org.bukkit.entity.LivingEntity) (source != null && source instanceof net.minecraft.world.entity.LivingEntity ? source.getBukkitEntity() : null)); // Paper - add exploded state, add player kill credit
this.level.getCraftServer().getPluginManager().callEvent(event);
this.wasCanceled = event.isCancelled();
bukkitBlocks = event.blockList();
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
index 8677dc684bd2e0bb3cf5f77b659ce02b79627e76..2902a92ba22bb87bf05d85f73f34bf7f956d116e 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -106,10 +106,10 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock

Vec3 vec3d = pos.getCenter();

- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
+ world.explode(player, world.damageSources().badRespawnPointExplosion(vec3d, player, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state, add player kill credit
return InteractionResult.SUCCESS;
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
- if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos); // Paper - check explode first
+ if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos, player); // Paper - check explode first, add player kill credit
if (!this.kickVillagerOutOfBed(world, pos)) {
player.displayClientMessage(Component.translatable("block.minecraft.bed.occupied"), true);
}
@@ -130,7 +130,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
// Paper end - PlayerBedFailEnterEvent
// CraftBukkit start - handling bed explosion from below here
if (event.getWillExplode()) { // Paper - PlayerBedFailEnterEvent
- this.explodeBed(finaliblockdata, world, finalblockposition);
+ this.explodeBed(finaliblockdata, world, finalblockposition, player); // Paper - add player kill credit
} else
// CraftBukkit end
if (entityhuman_enumbedresult.getMessage() != null) {
@@ -146,7 +146,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
}

// CraftBukkit start
- private InteractionResult explodeBed(BlockState iblockdata, Level world, BlockPos blockposition) {
+ private InteractionResult explodeBed(BlockState iblockdata, Level world, BlockPos blockposition, Player player) { // Paper - add player kill credit
{
{
final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getUnplacedBlockState(world, blockposition, iblockdata); // Paper - add exploded state
@@ -159,7 +159,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock

Vec3 vec3d = blockposition.getCenter();

- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
+ world.explode(player, world.damageSources().badRespawnPointExplosion(vec3d, player, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state, add player kill credit
return InteractionResult.SUCCESS;
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
index 088262f306755a9cb785c7a0cf0a9c66ed0965a8..ef1b454ad825702251e097f118eb3589f33d18eb 100644
--- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -78,7 +78,7 @@ public class RespawnAnchorBlock extends Block {
return InteractionResult.PASS;
} else if (!RespawnAnchorBlock.canSetSpawn(world)) {
if (!world.isClientSide) {
- this.explode(state, world, pos);
+ this.explode(state, world, pos, player); // Paper - add player kill credit
}

return InteractionResult.sidedSuccess(world.isClientSide);
@@ -130,7 +130,7 @@ public class RespawnAnchorBlock extends Block {
}
}

- private void explode(BlockState state, Level world, final BlockPos explodedPos) {
+ private void explode(BlockState state, Level world, final BlockPos explodedPos, Player player) { // Paper - add player kill credit
final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(explodedPos, state, null); // Paper - add exploded state
world.removeBlock(explodedPos, false);
Stream<Direction> stream = Direction.Plane.HORIZONTAL.stream(); // CraftBukkit - decompile error
@@ -148,7 +148,7 @@ public class RespawnAnchorBlock extends Block {
};
Vec3 vec3d = explodedPos.getCenter();

- world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state
+ world.explode(player, world.damageSources().badRespawnPointExplosion(vec3d, player, explodedBlockState), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state, add player kill credit
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the benefit of passing the player as the source here ?
You are already forwarding the "causing" player via the damage source.

Setting the source for the explosion to not null is what is responsible for the pretty ugly checks you have to do in Explosion now.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I totally glossed over this when I was writing it, I'll fix it in my next commit and just pass the entity through the DamageSource.

}

public static boolean canSetSpawn(Level world) {