Skip to content

Add player kill credit to beds/respawn anchors#10200

Closed
2stinkysocks wants to merge 6 commits into
PaperMC:masterfrom
2stinkysocks:feature/anchor-bed-kill-credit
Closed

Add player kill credit to beds/respawn anchors#10200
2stinkysocks wants to merge 6 commits into
PaperMC:masterfrom
2stinkysocks:feature/anchor-bed-kill-credit

Conversation

@2stinkysocks
Copy link
Copy Markdown

Tracks the player who blew up a bed/respawn anchor so PlayerDeathEvent can be used to get the player who caused the death from the explosion.

@2stinkysocks 2stinkysocks requested a review from a team as a code owner January 29, 2024 08:40
@dawon
Copy link
Copy Markdown
Contributor

dawon commented Jan 29, 2024

Maybe a suggestion for improvement: how about adding the "igniter" into BlockExplodeEvent as well?

@2stinkysocks
Copy link
Copy Markdown
Author

This pr currently breaks BlockExplodeEvent since it only gets called when the entity in the explosion is null, I'll fix this soon.

@dawon
Copy link
Copy Markdown
Contributor

dawon commented Jan 29, 2024

This pr currently breaks BlockExplodeEvent since it only gets called when the entity in the explosion is null, I'll fix this soon.

Are you sure? I did not look too much into the code, but aren't you mixing up the entity that exploded with the entity that caused the entity/block to explode? I think the one you have added is in the DamageSource...

@2stinkysocks
Copy link
Copy Markdown
Author

This pr currently breaks BlockExplodeEvent since it only gets called when the entity in the explosion is null, I'll fix this soon.

Are you sure? I did not look too much into the code, but aren't you mixing up the entity that exploded with the entity that caused the entity/block to explode? I think the one you have added is in the DamageSource...

No, prior to the commit I just made, to differentiate whether to call an EntityExplodeEvent or BlockExplodeEvent, Explosion.java would just check if the source field is null, which doesn't work because it's getting set to the source of the explosion now (for beds and anchors). The source is the entity that caused the block to explode, which could probably be implemented differently but I think this is the cleanest.

@dawon
Copy link
Copy Markdown
Contributor

dawon commented Jan 29, 2024

This pr currently breaks BlockExplodeEvent since it only gets called when the entity in the explosion is null, I'll fix this soon.

Are you sure? I did not look too much into the code, but aren't you mixing up the entity that exploded with the entity that caused the entity/block to explode? I think the one you have added is in the DamageSource...

No, prior to the commit I just made, to differentiate whether to call an EntityExplodeEvent or BlockExplodeEvent, Explosion.java would just check if the source field is null, which doesn't work because it's getting set to the source of the explosion now (for beds and anchors). The source is the entity that caused the block to explode, which could probably be implemented differently but I think this is the cleanest.

Ah you are right... The entity exploding (tnt/creeper) in that case is the entity that caused the explosion... Thank you!

private final List<Block> blocks;
private float yield;
private final org.bukkit.block.BlockState explodedBlockState; // Paper
+ private final org.bukkit.entity.LivingEntity igniter;
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.

// Paper - add player kill credit

this.yield = yield;
this.cancel = false;
this.explodedBlockState = explodedBlockState; // Paper
+ this.igniter = igniter;
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.

// Paper - add player kill credit

@2stinkysocks
Copy link
Copy Markdown
Author

Currently testing everything to make sure I can't find anything broken

Beds now work properly
Fixed the wrong type of LivingEntity in a check
Copy link
Copy Markdown
Contributor

@lynxplay lynxplay left a comment

Choose a reason for hiding this comment

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

🎉 Welcome to paper, thank you for your first PR!

I have yet had time to test this or go through the rest of the affected code, but I added some general questions that popped into my mind on the first read-through.

The diff you need in Explosion is kind of ugly, depending on your answers to the questions we might have to look for a better way to implement this.
Manually checking for the damage source being bad_respawn_point seems not too future proof.

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.

+ // 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants