Jump to content
  • Home
  • Files
  • Docs
Topics
  • All Content

  • This Topic
  • This Forum

  • Advanced Search
  • Existing user? Sign In  

    Sign In



    • Not recommended on shared computers


    • Forgot your password?

  • Sign Up
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [1.15.2] Change player name in Tab List (Player List)
Currently Supported: 1.16.X (Latest) and 1.15.X (LTS)
Sign in to follow this  
Followers 1
Babatunde

[1.15.2] Change player name in Tab List (Player List)

By Babatunde, January 14 in Modder Support

  • Reply to this topic
  • Start new topic

Recommended Posts

Babatunde    0

Babatunde

Babatunde    0

  • Tree Puncher
  • Babatunde
  • Members
  • 0
  • 15 posts
Posted January 14

Hi everyone,

 

I want to add a suffix to every players name, but I cant get it to work.

I'm doing it like this:

 

@SubscribeEvent
public void onNameFormat(PlayerEvent.NameFormat event) {
    if (event.getEntity() instanceof PlayerEntity) {
        event.setDisplayname(event.getUsername() + " test");
    }
}

 

If I use

event.getDisplayname()

it shows the name + test, but it doesn't change on the tab list. 

Do I need to somehow update the tab list for it to work or am I doing it completely wrong?

 

Thanks!

  • Quote

Share this post


Link to post
Share on other sites

ChampionAsh5357    163

ChampionAsh5357

ChampionAsh5357    163

  • World Shaper
  • ChampionAsh5357
  • Members
  • 163
  • 1025 posts
Posted January 14

That grabs the name from the NetworkPlayerInfo which is separate. You would need to set it from the ClientPlayerEntity in a sided-safe manner.

  • Like 1
  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7621

diesieben07

diesieben07    7621

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7621
  • 55263 posts
Posted January 14

You can also do it from the server, by sending a SPlayerListItemPacket with Action.UPDATE_DISPLAY_NAME. Minecraft never does this, because in vanilla the display name never changes.

  • Like 1
  • Quote

Share this post


Link to post
Share on other sites

Babatunde    0

Babatunde

Babatunde    0

  • Tree Puncher
  • Babatunde
  • Members
  • 0
  • 15 posts
Posted January 14
47 minutes ago, diesieben07 said:

by sending a SPlayerListItemPacket with Action.UPDATE_DISPLAY_NAME

How would I do this? I've never worked with packets before.

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7621

diesieben07

diesieben07    7621

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7621
  • 55263 posts
Posted January 14
17 minutes ago, Babatunde said:

How would I do this? I've never worked with packets before.

PlayerList#sendPacketToAllPlayers

  • Quote

Share this post


Link to post
Share on other sites

Babatunde    0

Babatunde

Babatunde    0

  • Tree Puncher
  • Babatunde
  • Members
  • 0
  • 15 posts
Posted January 14

 That doesn't seem to work for me 🤔

 

This is what I got rn:

public class ChangeTabListEvents {

    @SubscribeEvent
    public void onNameFormat(PlayerEvent.NameFormat event) {
        if (event.getEntity() instanceof PlayerEntity) {
            event.setDisplayname(event.getUsername() + " (" + event.getPlayer().getMaxHealth() + ")");
            event.getEntity().sendMessage(new KeybindTextComponent("NameFormat event fired."));
        }
    }

    @SubscribeEvent
    public void onPlayerLogin(EntityJoinWorldEvent event) {
        if (event.getEntity() instanceof PlayerEntity) {
            PlayerEntity player = (PlayerEntity) event.getEntity();
            if (player.getServer() != null) {
                ForgeEventFactory.getPlayerDisplayName(player, player.getGameProfile().getName());
                player.getServer().getPlayerList().sendPacketToAllPlayers(new SPlayerListItemPacket(SPlayerListItemPacket.Action.UPDATE_DISPLAY_NAME));
                player.sendMessage(new KeybindTextComponent("Display name updated."));
            }
        }
    }
}

 

image.png.9e57ad8165bcfa5a3b89acb8f04a8111.png

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7621

diesieben07

diesieben07    7621

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7621
  • 55263 posts
Posted January 14
  1. Do not call the method in ForgeEventFactory. Use the normal getDisplayName method.
  2. You won't be able to use the normal SPlayerListItemPacket constructors, you'll need to hack it a bit. By default it always uses ServerPlayerEntity#getTabListDisplayName, which always returns null. You need to get the entries list using reflection and set the displayName field also using reflection.
  3. You did not give any players to the packet, so it will do absolutely nothing.
  • Quote

Share this post


Link to post
Share on other sites

Babatunde    0

Babatunde

Babatunde    0

  • Tree Puncher
  • Babatunde
  • Members
  • 0
  • 15 posts
Posted January 14 (edited)

So, I've looked at reflection together with a friend of mine, but we could get it to work. 

 

We now have this:
 

    @SubscribeEvent
    public void onPlayerLogin(EntityJoinWorldEvent event) {
        if (event.getEntity() instanceof PlayerEntity) {
            PlayerEntity player = (PlayerEntity) event.getEntity();
            if (player.getServer() != null) {
                ForgeEventFactory.getPlayerDisplayName(player, player.getGameProfile().getName());
                try {
                    Field field = ObfuscationReflectionHelper.findField(SPlayerListItemPacket.class, "field_179769_b");
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                player.getServer().getPlayerList().sendPacketToAllPlayers(new SPlayerListItemPacket(SPlayerListItemPacket.Action.UPDATE_DISPLAY_NAME, (ServerPlayerEntity) player));
                player.sendMessage(new KeybindTextComponent("Display name updated."));
            }
        }
    }

 

field_179769_b = players from:

private final List<SPlayerListItemPacket.AddPlayerData> players = Lists.newArrayList();
  

from the SPlayerListItemPacket class. That is the entries you were talking about right?

 

But we don't know wat to do now.

 

P.S. I'm still using the ForgeEventFactory because getDisplayname() wouldn't fire the even for some reason...

 

Help would be much apriciated, thanks.

Edited January 14 by Babatunde
  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7621

diesieben07

diesieben07    7621

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7621
  • 55263 posts
Posted January 14
  • You need to call refreshDisplayName if you want the event to be fired again when calling getDisplayName again. This is explained in the event's documentation.
  • Probably better to use PlayerLoggedInEvent.
  • 7 minutes ago, Babatunde said:

    But we don't know wat to do now.

    You need to get the entries from the packet you create and forcibly set the display name property inside there. As vanilla will always set it to null.

  • Quote

Share this post


Link to post
Share on other sites

coalbricks    1

coalbricks

coalbricks    1

  • Tree Puncher
  • coalbricks
  • Members
  • 1
  • 8 posts
Posted January 15

It looks like you will need to use reflection twice.

After you create the packet object, you will need to access SPlayerListItemPacket#players. SPlayerListItem#getEntries() only exists on the client, so you won't be able to use this.

The elements of the list (of type SPlayerListItemPacket.AddPlayerData) contain a private 'displayName' member, which you will also need access to. (I would advise creating the Field objects in a static context instead of every EntityJoinWorldEvent, to save performance).

Iterate through all the objects in the list and set their display names accordingly - although from your code it looks like there should only be one object in the list.

 

 

  • Quote

Share this post


Link to post
Share on other sites

Babatunde    0

Babatunde

Babatunde    0

  • Tree Puncher
  • Babatunde
  • Members
  • 0
  • 15 posts
Posted January 15
20 hours ago, diesieben07 said:

You need to call refreshDisplayName if you want the event to be fired again when calling getDisplayName again. This is explained in the event's documentation.

refreshDisplayName is from 1.12.2. A lot is the documentation is outdated.

20 hours ago, diesieben07 said:

Probably better to use PlayerLoggedInEvent.

Thanks, I forgot that existed.

 

20 hours ago, diesieben07 said:

You need to get the entries from the packet you create and forcibly set the display name property inside there.

I'm sorry, I've never worked with packets before. is there a tutorial or documentation on how to create packets?

  • Quote

Share this post


Link to post
Share on other sites

Babatunde    0

Babatunde

Babatunde    0

  • Tree Puncher
  • Babatunde
  • Members
  • 0
  • 15 posts
Posted January 15
17 hours ago, coalbricks said:

(I would advise creating the Field objects in a static context instead of every EntityJoinWorldEvent, to save performance)

Thanks for the tip.

 

17 hours ago, coalbricks said:

After you create the packet object

How do I do this tho?

  • Quote

Share this post


Link to post
Share on other sites

coalbricks    1

coalbricks

coalbricks    1

  • Tree Puncher
  • coalbricks
  • Members
  • 1
  • 8 posts
Posted January 16 (edited)
8 hours ago, Babatunde said:

How do I do this tho?

You've already done it, here:

new SPlayerListItemPacket(SPlayerListItemPacket.Action.UPDATE_DISPLAY_NAME, (ServerPlayerEntity) player)

A packet is just a bit of data that is sent between two or more computers over a network. Usually you don't have to manually send packets because Minecraft takes care of this for you for standard vanilla gameplay, but in this case I think it's the best solution. You can dig around the 'net.minecraft.network' or 'net.minecraft.network.play' packages to look at some example packet implementations; AFAIK there isn't any documentation on them. What IDE are you using?

Edited January 16 by coalbricks
  • Quote

Share this post


Link to post
Share on other sites

Babatunde    0

Babatunde

Babatunde    0

  • Tree Puncher
  • Babatunde
  • Members
  • 0
  • 15 posts
Posted January 16 (edited)
6 hours ago, coalbricks said:

What IDE are you using?

Intellij IDEA Ultimate.

 

6 hours ago, coalbricks said:

You've already done it, here:

Oh nice! completely forgot about that line lmao.

 

This is what I've got so far, I'm kinda stuck because I have no idea what to do:

public class ChangeTabListEvents {

    private final Field fieldPlayers = ObfuscationReflectionHelper.findField(SPlayerListItemPacket.class, "field_179769_b");
    private final Field fieldDisplayName = ObfuscationReflectionHelper.findField(SPlayerListItemPacket.AddPlayerData.class, "field_179965_e");

    @SubscribeEvent
    public void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
        PlayerEntity player = event.getPlayer();
        if (player.getServer() != null) {
            try {
                
            } catch (Throwable e) {
                e.printStackTrace();
            }
            player.getServer().getPlayerList().sendPacketToAllPlayers(new SPlayerListItemPacket(SPlayerListItemPacket.Action.UPDATE_DISPLAY_NAME, (ServerPlayerEntity) player));
            player.sendMessage(new KeybindTextComponent("Display name updated."));
        }
    }
}

Do I need to get the list somehow, or do I need to make my own and set my list as the players list? 

And why do I need the 'displayName'?

 

Thanks for the help so far, I appreciate it!

Edited January 16 by Babatunde
  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7621

diesieben07

diesieben07    7621

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7621
  • 55263 posts
Posted January 16
15 hours ago, Babatunde said:

refreshDisplayName is from 1.12.2. A lot is the documentation is outdated.

No, it exists in 1.16.4 and also 1.15.2.

 

32 minutes ago, Babatunde said:

his is what I've got so far, I'm kinda stuck because I have no idea what to do:

  • Make those Field fields static.
  • You need to create the packet first and store it in a variable, so you can work with it. Don't immediately send it.
  • You need to then get the list of AddPlayerData instances from the packet. For this you get the "players" field, using the reflection Field you have already. Then for those AddPlayerData instances you need to set their displayName field, again using reflection.
34 minutes ago, Babatunde said:

And why do I need the 'displayName'?

You need to set it, because Minecraft never sends any custom display name to the client - even though it has the network infrastructure to do so (SPlayerListItemPacket). It always just sends null for the display name, even if a custom display name is set.

  • Quote

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

    • Insert image from URL
×
  • Desktop
  • Tablet
  • Phone
Sign in to follow this  
Followers 1
Go To Topic Listing



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • domi0908
      fix hitbox red baby mobs version forge

      By domi0908 · Posted 10 minutes ago

      fix baby mobs hitboxes red raised up          no villager baby no villager zombie baby strider baby wolf baby sheep baby pig baby ozelot llama baby chicken baby cow
    • diesieben07
      "Reflections" Documentation?

      By diesieben07 · Posted 23 minutes ago

      A good way to do this is to simply store a RegistryObject in a static final field using its of factory method.
    • diesieben07
      [1.15.2] Recipes don't work

      By diesieben07 · Posted 28 minutes ago

      Post debug.log and a Git repo of your mod.
    • diesieben07
      Modded server loading as vanilla server.

      By diesieben07 · Posted 29 minutes ago

    • diesieben07
      'Shutting down internal server'

      By diesieben07 · Posted 30 minutes ago

      1.12 is no longer supported on this forum. Please update to a modern version of Minecraft to receive support.
  • Topics

    • domi0908
      4
      fix hitbox red baby mobs version forge

      By domi0908
      Started Tuesday at 03:04 PM

    • SleepyCatGuy
      2
      "Reflections" Documentation?

      By SleepyCatGuy
      Started 7 hours ago

    • sixze
      1
      [1.15.2] Recipes don't work

      By sixze
      Started 1 hour ago

    • huskies709
      14
      Modded server loading as vanilla server.

      By huskies709
      Started November 26, 2018

    • aryagon
      1
      'Shutting down internal server'

      By aryagon
      Started 10 hours ago

  • Who's Online (See full list)

    • Sterling00
    • Kapibara1
    • DavidQF555
    • davidsks09
    • diesieben07
    • WildZora
    • Rinowie
    • xd_Tim_dx
    • QWERTY 52 38
    • Zemelua
    • Yuqera
    • zOnlyKroks
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [1.15.2] Change player name in Tab List (Player List)
  • Theme

Copyright © 2019 ForgeDevelopment LLC · Ads by Longitude Ads LLC Powered by Invision Community