Skip to content

Conversation

Tmpod
Copy link

@Tmpod Tmpod commented Sep 19, 2025

This adds a new event, ScoreboardTagsChangeEvent, which is called when an entity gets their scoreboard tags changed, through plugins calling Entity#addScoreboardTag, /tag, /data, etc.
It is fired before the change happens and can be cancelled. It contains the affected entity, which change it is happening (add, remove or replace), and which tags are part of the change.

I was looking to implement this event, because I'm currently emulating it, on a plugin I'm developing, by doing some complex and brittle handling of commands. However, it can't handle plugins calling addScoreboardTag/addTag and it isn't even complete for vanilla methods (e.g. has issues with execute context changes).
So I thought of adding this small event, it shouldn't impact performance that much. Even though I wasn't originally thinking of doing it, I made it cancellable, because why not?
I do have one concern with the current implementation, which is that it always creates a new list, even for single tag changes (which are likely to be the vast majority of changes). Not sure what the best move here is, suggestions are welcome.


Note: This implementation isn't finalized, it is missing doc comments, possibly some changes to imports, and naturally doesn't need to use feature patches. I threw this together very quickly to understand if the maintainers are okay with adding this event. If it is green-lit, I will finish it. In retrospective, I should have made an issue first, but oh well 🙃

@Tmpod Tmpod requested a review from a team as a code owner September 19, 2025 16:49
@github-project-automation github-project-automation bot moved this to Awaiting review in Paper PR Queue Sep 19, 2025
@Tmpod Tmpod marked this pull request as draft September 19, 2025 17:07
@electronicboy
Copy link
Member

We generally dislike low level zero-contextual events to be cancellable, especially in cases where plugin calls will be involved; These events are okay for notification purposes (assuming they're not too heavy), but, generally, "plugins actions are exposed to everything else" is a pretty niche area due to just not breaking stuff blindly

@Tmpod
Copy link
Author

Tmpod commented Sep 19, 2025

In this case, addTag/removeTag (and their Bukkit Entity counterparts) can already fail and not do anything (and thus return a boolean), so it doesn't seem completely out of place to have them be cancellable. This does implement cancellation for NBT changes (e.g. through /data), which I can see being problematic. In any case, I am okay with removing cancellation altogether, if you prefer it so.

As for "plugins actions are exposed to everything else", I can see the reservations, though tags can be manipulated by means other than plugins.

@electronicboy
Copy link
Member

The only reason an add would currently fail is either that the tag already existed or you hit the size limit;

The concern here is that plugins have 0 real context of why a tag was being mutated, exposing such events for the purposes of notification to allow plugins to update stuff like a cache sounds fair, allowing plugins to blindly prevent a tag from being added to an entity is a bit more iffy

@Tmpod
Copy link
Author

Tmpod commented Sep 19, 2025

Alright, I see, that is indeed iffy. I will completely remove cancellation then.

@Tmpod
Copy link
Author

Tmpod commented Sep 19, 2025

Regarding naming and/or structure, is there any glaring issue? Apart from it being a feature patch.

@Tmpod Tmpod force-pushed the event/scoreboard-tag-change branch from 79c574e to 6ec009f Compare September 19, 2025 18:42
@Tmpod
Copy link
Author

Tmpod commented Sep 19, 2025

There it goes, amended the commits. Do you prefer squashing them both into one?

@electronicboy
Copy link
Member

The merger can deal with that aspect;

Tags should probably not be mutable inside of the event, and the event generally shouldn't fire for loading data

@Tmpod
Copy link
Author

Tmpod commented Sep 19, 2025

Tags should probably not be mutable inside of the event

Good point. Would Collections.unmodifiableList be sufficient here, or do we want to go for a copy (with List.copyOf)?

the event generally shouldn't fire for loading data

Mmm, I see the concern. If we don't include that, modifying through NBT won't be covered. We can either accept that (I'd rather not, but ultimately it is okay if you prefer that) or opt to fire the event in the /data implementation, which would cover pretty much everything, I think.

@electronicboy
Copy link
Member

unmodifiableList would be fine;

firing inside of data is probably going to be the best option here

@Tmpod Tmpod force-pushed the event/scoreboard-tag-change branch from 6ec009f to 7440ccb Compare September 19, 2025 19:45
@Tmpod
Copy link
Author

Tmpod commented Sep 19, 2025

There we go. Just missing documentation on the public stuff.

This adds a new event, `ScoreboardTagsChangeEvent`, which is called when
an entity gets their scoreboard tags changed, through plugins calling
`Entity#addScoreboardTag`, `/tag`, `/data`, etc.

It is fired before the change happens and cannot be cancelled. It
contains the affected entity, which change it is happening (add, remove
or replace), and which tags are part of the change.
@Tmpod Tmpod force-pushed the event/scoreboard-tag-change branch from 7440ccb to ba5904f Compare September 19, 2025 21:13
@Tmpod Tmpod marked this pull request as ready for review September 19, 2025 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Awaiting review

Development

Successfully merging this pull request may close these issues.

2 participants