Setting a nickname? Display Name and DisplayNameData

Hello!

I’m having some difficulties understanding the DisplayNameData data manipulator. To be honest, I don’t understand the data API, it confuses the ever-loving bejesus out of me (I’m honestly at a loss as to what the benefit of the data API is over just storing the values as members and providing standard getter/setter methods. If someone could enlighten me that would be grand).

I am trying to set the players nickname. I don’t know how to do this :\ I want something that is the equivalent of bukkit’s player.setDisplayName(String);

At first I figured I could modify that data by grabbing a DisplayNameData from the player object, however that does not work, as it always seems to throw a no value present exception whenever I try to grab the data. I suspect that it would just be the players standard name if no nickname was set, but I seem to be wrong.

I understand that there is a getOrCreate() method in grabbing data manipulators, but this one in particular doesn’t even have a set method to modify the display name. I found the SpongeDisplayNameData, which does have the ability to set the data in the constructor, but upon offering it to the player object, and then trying to grab the display name data, it is still no value present.

I’m pulling my hair out at the roots here :frowning: Can someone help explain what is going on?

Thanks!

EDIT: After looking into this some more, it looks like the DisplayNameData object should contractually never be null/absent for a player object, so says the documentation. Even so, when getOrCreating, offering it to a player data holder always seems to result in a failure.

OK, so first I’d recommend thoroughly reading the data API docs: https://docs.spongepowered.org/master/en/plugin/data/index.html This is very different from Bukkit’s old system.

Basically, a DataManipulator is a container for, well, data. Display names, furnace time, anything really. The thing to grasp is that it’s not linked to the object you got it from, it’s a copy. So DataHolder#get(Class<DataManipulator>) will only work if that object has pre-existing data of that type - in this case, an existing display name. getOrCreate() will return an existing DataManipulator if one exists, otherwise it will return a new one with default values.

A data manipulator has a set of Values - these are what hold the data you want, and can either be referenced directly, like DisplayNameData#displayName(), or generic-ly using it’s matching key, in this case DataManipulator#getValue(Keys.DISPLAY_NAME). You can get/set your display name through this Value object.

After that you still need to apply this new data to the DataHolder, so you “offer” it to them with DataHolder#offer. Ta-da, you’ve just set a display name!

:\ Unfortunately, i’m still getting “no value present” issues after calling get() on player.getValue(Keys.DISPLAY_NAME).

For reference, the code im using is:

	Player player = event.getPlayer();
	Optional<Value<Text>> dn = player.getValue(Keys.DISPLAY_NAME);
	dn.get().set(suser.getNickname());
	player.offer(dn.get());

Is this not right?

As mentioned, getting the value or data will only work if there was a display name in the first place.

So you just need to do player.offer(Keys.DISPLAY_NAME, super.getNickname()) if you’re only setting the name.

Thank you! I was able to get it to work, but this just seems like an unnecessary headache. Also, I thought that the docs mentioned that player objects would always have DisplayNameData?

There is a big semantic difference between data not being present and the data consisting of default values. While the latter is always possible, there are cases where it is impossible for a DataHolder to support a type of data and then not hold it. Examples of those include:

HealthData is always present on every (vanilla) DataHolder that supports it
DisplayNameData is always present on a Player, but may be absent on other entities

Looks like the docs are inaccurate, the source code here shows that it will return Optional.empty() if the entity does not have a display name.

That’s correct - however, players always have a display name.

Should there be some kind of bug report, then? Because unless i set the display name, the display name always returns back an empty key. :\

Wait, really? Can I see the code you’re using?

Sure.

https://github.com/Blossomforth/SimplyModular-Sponge/blob/fe24a5c9bfdf64fd15ee783a1a9e87104d42dee7/src/me/corriekay/simplymodular/modules/user/SimplyManageable.java#L158

Here is how I set the display name normally.

https://github.com/Blossomforth/SimplyModular-Sponge/blob/fe24a5c9bfdf64fd15ee783a1a9e87104d42dee7/src/me/corriekay/simplymodular/modules/chat/SimpleChannel.java#L143

Here is how I get the display name.

If i comment out the setting name, it returns an exception stating that there is no value when trying to grab the display name.

I also found an interesting issue as well when testing this. I created a brand new server, without any player data, commented out the set display name line, logged into the server, and the exception was thrown when chatting.

Then i uncommented the line, recompiled, reboot, the issue was resolved. Afterwards, i recommented the line, reboot the server, and the data persisted.

The display name does not exist until given to the player, however afterwards, it persists between reboots and does not necessarily need to be set again.

I’ve fixed it in this commit: