Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scoreboard objective number format api #10036

Merged
merged 25 commits into from
Feb 17, 2024

Conversation

davidmayr
Copy link
Contributor

@davidmayr davidmayr commented Dec 16, 2023

This PR introduces an easily accessible number format API (using adventure styles and components) for scoreboard objectives for a feature introduced in 1.20.3.

Setting a number format can be as easy as this:

//Remove numbers
objective.numberFormat(NumberFormat.blank());

// Style numbers in green and bold
objective.numberFormat(NumberFormat.styled(NamedTextColor.GREEN, TextDecoration.BOLD));

//Replace numbers
objective.numberFormat(NumberFormat.fixed(Component.text("Lol")));

As for the implementation: The conversion between the Adventure style and Mojangs implementation is a bit messy. The only other way I can think of to implement this is manually converting every style property. As paper doesn't even do that with chat components either, I have decided to just serialize and deserialize again.

Copy link
Contributor

@yannicklamprecht yannicklamprecht left a comment

Choose a reason for hiding this comment

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

Like that. Yes, we're sealed know. 🥳

@456dev
Copy link
Contributor

456dev commented Dec 16, 2023

In vanilla, you can set it per each score holder, right? How is that done here?

Unless I'm misunderstanding what the "objective" is

@davidmayr
Copy link
Contributor Author

In vanilla, you can set it per each score holder, right? How is that done here?

Unless I'm misunderstanding what the "objective" is

I totally missed that that's possible in vanilla. You can set it for the entire objective (e.g. your entire sidebar) or apparently per entry as well (which I missed)

I will add that asap

@davidmayr
Copy link
Contributor Author

That's implemented now. With the latest commit, you can change the formatting of individual scores or the whole objective

patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
@jpenilla
Copy link
Member

jpenilla commented Dec 16, 2023

Should use our codecs for conversions, not the GsonComponentSerializer, see the minecraft round trip style test in AdventureCodecsTest for an example. Also put the conversion methods at PaperAdventure.asVanilla/asMinecraft to be consistent.

Copy link
Member

@Machine-Maker Machine-Maker left a comment

Choose a reason for hiding this comment

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

All there records should be package-private and not exposed to the API. Instead, have interfaces with a method for each record parameter. The field for the blank format can be on the NumberFormat interface.

patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
@davidmayr
Copy link
Contributor Author

Should use our codecs for conversions, not the GsonComponentSerializer, see the minecraft round trip style test in AdventureCodecsTest for an example. Also put the conversion methods at PaperAdventure.asVanilla/asMinecraft to be consistent.

So just we are on the same path: I should add a asVanilla method for the style conversion to PaperAdventure? Or do you mean the entire number formatting? (Probably not, but just making sure)

Aaaand should I update the adventure patch? Because as far as I can tell, everything inside that class comes from that patch and if I would put it in this one it could break multiple patches if this one would be removed (e.g. temporarily while upgrading), right?

@davidmayr
Copy link
Contributor Author

davidmayr commented Dec 16, 2023

All there records should be package-private and not exposed to the API. Instead, have interfaces with a method for each record parameter. The field for the blank format can be on the NumberFormat interface.

Sorry, but I don't think I really get what you are asking me to do. 😅

As far as I can tell, you want me to either:
Package private the entire number format implementations and add static methods to the base interface for creation. But that would be an issue for accessing the number format value, wouldn't it?

You could theoretically also have meant to only package private the constructors, but I don't think that's the case because private constructors don't exist in records, if I recall correctly? - sorry if I'm wrong, I'm using Kotlin most of the time 😅

Or you want me to:
Create interfaces for every type and make the implementations private (but still in the API because I don't know of any provider service to construct it?) But I don't really get the point of that? Wouldn't that just be useless class clutter?

@Machine-Maker
Copy link
Member

Aaaand should I update the adventure patch? Because as far as I can tell, everything inside that class comes from that patch and if I would put it in this one it could break multiple patches if this one would be removed (e.g. temporarily while upgrading), right?

Yeah, you can make asVanilla/asAdventure methods inside PaperAdventure that use the codec's and they should be in the adventure patch.

Or you want me to:
Create interfaces for every type and make the implementations private (but still in the API because I don't know of any provider service to construct it?) But I don't really get the point of that? Wouldn't that just be useless class clutter?

Yes, exactly this. interfaces for NumberFormat, StyledFormat, FixedFormat (no need for blank format, should just use an equality check to know that). And then package-private records that implement those interfaces with static methods on NumberFormat to create instances of each one.

There are a couple reasons for this. 1) javadocs. can have better, separated javadocs for the fluent getters and factory methods and types if you separate out the record from the API interface. 2) future changes. Changing records and making them maintain compat is super ugly if something changes in the future. If the constructor is public, you have to always keep the old one and make new ones and you have to have old components... its just not fun. Look at StructuresLocateEvent$Result and observe the reason why its not good to do that. Better to have static methods to deprecate and we can just change whatever we want in the record.

@yannicklamprecht
Copy link
Contributor

After some thoughts I probably would be against the nullability in the setter and just add a Reset record that is also sealed.
What do you think of @Machine-Maker, @jpenilla, @MenschenToaster ?

@Machine-Maker
Copy link
Member

If we didn't want to have nullability in the setter, I would prefer a clear method instead. I don't think adding a type for resetting is a good idea.

@davidmayr
Copy link
Contributor Author

davidmayr commented Dec 16, 2023

no need for blank format, should just use an equality check to know that

Internally it makes sense, but for accessibility when querying the current format it can get confusing and just more difficult to check, right?

If somebody wants to know if it's a blank format, they would have to do:
if(!(format instanceof StyledFormat) && !(format instanceof FixedFormat)) {}
to know if it's a blank format or not. And if there would be a new format in the future, their code would be broken

@Machine-Maker
Copy link
Member

By "equality check" I meant you can do

if (NumberFormat.blank().equals(format)) {}

@davidmayr
Copy link
Contributor Author

By "equality check" I meant you can do

if (NumberFormat.blank().equals(format)) {}

That makes way more sense. Sure, then I'll do that

patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/server/0010-Adventure.patch Outdated Show resolved Hide resolved
patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/api/0449-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
patches/server/1052-add-number-format-api.patch Outdated Show resolved Hide resolved
Copy link
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.

Requires testing and javadoc addition regarding the creation of the score on the numberFormat setter, otherwise LGTM.

Given upstream has yet to release even a PR for this, I think it is fine to move forwards with this sooner than later 👍

@davidmayr
Copy link
Contributor Author

Requires testing

Did some basic testing. I only tested the number format on the score and not on objectives. But the original code in my first commit was tested on the objective in another plugin as well. (Because that code is used in a paper fork of mine as of right now) I would assume that works.

Getting (and therefor converting the format back) works as well (which can be sen by the output in the console)
Some further testing might be required but as far as I can see everything works as intended

grafik

@davidmayr
Copy link
Contributor Author

Any updates?

davidmayr and others added 20 commits February 17, 2024 11:43
Signed-off-by: David Mayr <[email protected]>
Signed-off-by: David Mayr <[email protected]>
@Machine-Maker Machine-Maker force-pushed the dev/scoreboard-format-api branch from 29c4f51 to a07c2c6 Compare February 17, 2024 19:58
@Machine-Maker Machine-Maker merged commit 1964b22 into PaperMC:master Feb 17, 2024
3 checks passed
@Cryptite
Copy link
Contributor

Might be nice to update the OP which provides examples of the API.

For example, fixed number format is now objective.numberFormat(NumberFormat.fixed(Component.text("Lol"));

@lynxplay
Copy link
Contributor

Done 👍

@davidmayr
Copy link
Contributor Author

davidmayr commented Feb 19, 2024

Done 👍

We both edited the description at the same time 🙃
Didn't even know maintainers could edit the PR's description 😅

lynxplay pushed a commit to lynxplay/paper that referenced this pull request Feb 23, 2024
* feat: number format api

Signed-off-by: David Mayr <[email protected]>

* feat: make each individual score customizable

Signed-off-by: David Mayr <[email protected]>

* docs: fix incorrect descriptions

Signed-off-by: David Mayr <[email protected]>

* feat: use access transformers

Signed-off-by: David Mayr <[email protected]>

* feat: use adventure codecs

Signed-off-by: David Mayr <[email protected]>

* test: test for matching styles

Signed-off-by: David Mayr <[email protected]>

* feat: convert number formats to interfaces

Signed-off-by: David Mayr <[email protected]>

* feat: add style conversion to adventure patch

Signed-off-by: David Mayr <[email protected]>

* feat: use paper adventure method in PaperScoreboardFormat

Signed-off-by: David Mayr <[email protected]>

* chore: rename methods to avoid a method in records

Signed-off-by: David Mayr <[email protected]>

* fix: check if objective is still registered

Signed-off-by: David Mayr <[email protected]>

* feat: improve style conversion

Signed-off-by: David Mayr <[email protected]>

* feat: modify how the getter behaves in score

Signed-off-by: David Mayr <[email protected]>

* feat: use fluent naming

Signed-off-by: David Mayr <[email protected]>

* docs: add spaces before the paper comments

Signed-off-by: David Mayr <[email protected]>

* chore: styling changes

Signed-off-by: David Mayr <[email protected]>

* chore: make constant final

Signed-off-by: David Mayr <[email protected]>

* feat: add methods for styled format instead of constants

Signed-off-by: David Mayr <[email protected]>

* fix: remove incorrect getTrackedPlayers check

Signed-off-by: David Mayr <[email protected]>

* docs: add . at the end of sentences

Signed-off-by: David Mayr <[email protected]>

* docs: explain null behaviour

Signed-off-by: David Mayr <[email protected]>

* docs: mention score creation

Signed-off-by: David Mayr <[email protected]>

* rebase and fix javadoc comments

* remove server implementation defaults

* fix format for PaperScoreboardFormat

---------

Signed-off-by: David Mayr <[email protected]>
Co-authored-by: Jake Potrebic <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.

10 participants