How do I change/color the name above a player's head?

Discussion in 'Plugin Development' started by iceypotatoguy, Apr 2, 2021.

  1. Offline

    iceypotatoguy

    I want to make a minigame with teams, and each player will have their name colored to indicate what team they are on. I am talking about the name that players see on top of their heads. I cannot use a Scoreboard, since each player is already assigned their own scoreboard.

    Edit: I am using Bukkit 1.8.8.
     
    Last edited: Apr 4, 2021
  2. Offline

    davidclue

    I can't remember which method I used but one of these methods changed the color of the nametag and a heads up I don' think it's possible to change a player's actual name but just the color. I've looked for a very long time and the closest I ever got was changing just the color, here are the methods.
    Code:
    private void setPlayerName(Player p, String nick) {
            EntityPlayer changeName = ((CraftPlayer)p).getHandle();
            changeName.displayName = ChatColor.translateAlternateColorCodes('&', nick);
            for (Player all : Bukkit.getServer().getOnlinePlayers()) {
                PlayerConnection connection = ((CraftPlayer)all).getHandle().playerConnection;
                connection.sendPacket(new PacketPlayOutNamedEntitySpawn(changeName));
            }
        }
       
        public void changeName(Player p, String newName){
            for(Player pl : Bukkit.getOnlinePlayers()){
                if(pl == p) continue;
                //REMOVES THE PLAYER
                ((CraftPlayer)pl).getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, ((CraftPlayer)p).getHandle()));
                //CHANGES THE PLAYER'S GAME PROFILE
                GameProfile gp = ((CraftPlayer)p).getProfile();
                try {
                    Field nameField = GameProfile.class.getDeclaredField("name");
                    nameField.setAccessible(true);
    
                    Field modifiersField = Field.class.getDeclaredField("modifiers");
                    modifiersField.setAccessible(true);
                    modifiersField.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);
    
                    nameField.set(gp, ChatColor.translateAlternateColorCodes('&', newName));
                } catch (IllegalAccessException | NoSuchFieldException ex) {
                    throw new IllegalStateException(ex);
                }
                //ADDS THE PLAYER
                ((CraftPlayer)pl).getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, ((CraftPlayer)p).getHandle()));
                ((CraftPlayer)pl).getHandle().playerConnection.sendPacket(new PacketPlayOutEntityDestroy(p.getEntityId()));
                ((CraftPlayer)pl).getHandle().playerConnection.sendPacket(new PacketPlayOutNamedEntitySpawn(((CraftPlayer)p).getHandle()));
            }
        }
     
  3. Offline

    iceypotatoguy

    This unfortunately did not work. I forgot to mention that I am using 1.8. I was thinking if there is a way where I can pass in a singular Team object into each player's scoreboard, so each player's scoreboard references the same Team object. Would I have to use reflection? This is because when I do getTeams from the Scoreboard object, it returns an immutable set.

    Edit:
    So, I was working on my code for a couple of hours, and I figured out, that I can create a new class that houses a new Scoreboard object, which then houses 4 teams. Then, I have a method in that class that uses Reflection to get down to NMS Scoreboard to add the teams to the sets. If anyone has a better solution, please tell me. Otherwise, this works, for now.
    Code:
    public class WallsScoreboardSharedTeams implements ScoreboardSharedTeams {
        Scoreboard scoreboard;
        HashMap<String, Team> teams;
        /**
         * Uses Reflection to add a shared bundle of teams to each player's scoreboard.
         */
        public void addTeamsToScoreboard(Scoreboard scoreboard) {
            for (Team team : teams.values()) {
                Class teamClass = team.getClass();
                Class scoreboardClass = scoreboard.getClass();
                try {
                    //Get the nms ScoreboardTeam object
                    Field teamField = teamClass.getDeclaredField("team");
                    teamField.setAccessible(true);
                    ScoreboardTeam nmsScoreboardTeam = (ScoreboardTeam) teamField.get(team);
                   
                    //Get the nms Scoreboard object
                    Field boardField = scoreboardClass.getDeclaredField("board");
                    boardField.setAccessible(true);
                    net.minecraft.server.v1_8_R3.Scoreboard nmsScoreboard = (net.minecraft.server.v1_8_R3.Scoreboard) boardField.get(scoreboard);
                    Class nmsScoreBoardClass = nmsScoreboard.getClass().getSuperclass();
                    Field nmsScoreboardTeamsbyName = nmsScoreBoardClass.getDeclaredField("teamsByName");
                    nmsScoreboardTeamsbyName.setAccessible(true);
                    HashMap<String, ScoreboardTeam> teams = (HashMap<String, ScoreboardTeam>) nmsScoreboardTeamsbyName.get(nmsScoreboard);
                    teams.put(team.getName(), nmsScoreboardTeam); // Put the nmsScoreboardTeam into the nms Scoreboard
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }...
     
    Last edited: Apr 4, 2021

Share This Page