Search code examples
javaminecraftbukkit

Changing player names above head


I have been trying to create my own plugin with allows people to change their name that is displayed above their head, but I can't get it working.

My code:

public void NickPlayer(Player player) {
    try {
        String name = (String) main.getConfig().get("Nick" + player.getUniqueId());
        GameProfile playerProfile = ((CraftPlayer) player).getHandle().getProfile();
        Field ff = playerProfile.getClass().getDeclaredField("name");
        ff.setAccessible(true);
        ff.set(playerProfile, name);
        player.sendMessage(name);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Solution

  • After editing the EntityPlayer and it's GameProfile, you should use PacketPlayOutPlayerInfo. This packet should be sent to everyone who should show the name change.

    For example :

    EntityPlayer ep = ((CraftPlayer) player).getHandle();
    String name = (String) main.getConfig().get("Nick" + player.getUniqueId());
    GameProfile playerProfile = ep.getProfile();
    Field ff = playerProfile.getClass().getDeclaredField("name");
    ff.setAccessible(true);
    ff.set(playerProfile, name);
    // now the name is changed
    
    for(Player all : Bukkit.getOnlinePlayers()) {
       PlayerConnection connection = ((CraftPlayer) p).getHandle().playerConnection;
       connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, ep));
       connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, ep));
    }
    

    We could hope that the EnumPlayerInfoAction.UPDATE_DISPLAYNAME works but it's only the entity.setDisplayName() so it will not.

    If this have issues, you can :

    1. Just use Bukkit's method :
    for(Player all : Bukkit.getOnlinePlayers()) {
       all.hidePlayer(p);
       all.showPlayer(p);
    }
    
    1. Try the hard way, by completly remove the player and make it respawn (only for players!) :
    for(Player all : Bukkit.getOnlinePlayers()) {
       PlayerConnection connection = ((CraftPlayer) p).getHandle().playerConnection;
       connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, ep));
       connection.sendPacket(PacketPlayOutEntityDestroy(ep.entityId));
       connection.sendPacket(PacketPlayOutNamedEntitySpawn(ep));
       connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, ep));
    }
    

    PS: You can add something like Bukkit.getScheduler().runTaskLater() after removing and before adding, just to be sure everyone has removed the player.