Changing a player's tablist name only for another player

Discussion in 'Spigot Plugin Development' started by lavabird, Apr 24, 2017.

  1. Hello Spigot community, this is my first post asking for help, so pardon if I miss anything important.

    What I'm trying to do is difficult to explain fully in words, so I will use an example. Player1 and Player2 are in game. Player1 runs a command that changes his tablist, making the color of Player2's name purple. However, Player2 still sees the tablist as he normally would.

    I know that this probably has something to do with packets, but I've been searching for a while, and have yet to come up wit a valid answer. I know how to add/remove players using packets, but I don't think this will help with changing the tablist name completely, or at least from what I tried it doesn't seem to.

    What would be a good starting point for a solution to this issue? I'm really lost and could use at least a push in the right direction.
     
  2. Do you have any preexisting code you have already created on this?
     
  3. sothatsit

    Patron

    You will need to use packets for this. Take a look at wiki.vg, it contains documentation for all of the minecraft packets, you should be able to find the packet/s you need to use there.
     
  4. Well, I tried this today, but it didn't work because adding the player actually adds a whole new player, and giving them a name that long causes the user to get kicked due to too long a String.
    Code (Text):
    EntityPlayer user = ((CraftPlayer) p).getHandle();
                                EntityPlayer player = ((CraftPlayer) pl).getHandle();
                                user.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, player));
                               
                                MinecraftServer server = MinecraftServer.getServer();
                                WorldServer world = server.getWorldServer(0);
                                PlayerInteractManager manager = new PlayerInteractManager(world);
                                GameProfile profile = new GameProfile(pl.getUniqueId(), Tools.getTabName(pl) + ChatColor.GRAY + " (" + ((CraftPlayer) p).getHandle().ping + " ms)");
                                EntityPlayer target = new EntityPlayer(server, world, profile, manager);
                                user.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, target));
    I'm aware of that resource, but the issue is I can't find a packet that's suitable for what I'm doing. The closest things I could find were changing the player list by adding/removing players using packets, but the name that I'm trying to add is too long to fit a full player's name, even though tablist doesn't have any real boundaries. There is also the tablist header/footer, but that doesn't help change the player's names.
     
  5. Alright, I did some digging for you, and I found the code that Player#setPlayerListName(String) uses, which sets your name on tab list visible for all other players, you should just be able to modify a few lines on here so it only executes for the player it's setting to.

    Code (Text):
    @Override
    public void setPlayerListName(String name) {
        if (name == null) {
            name = getName();
        }
        getHandle().listName = name.equals(getName()) ? null : CraftChatMessage.fromString(name)[0];
        for (EntityPlayer player : (List<EntityPlayer>)server.getHandle().players) {
            if (player.getBukkitEntity().canSee(this)) {
                player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle()));
            }
        }
    }
     
    • Winner Winner x 1
    • Informative Informative x 1
  6. EntityPlayer has a listname variable?! This is the key thing I was missing, and that code makes it so much clearer how to implement what I am trying to do. Thank you so much for providing that! And now I know if I have a problem in the future, I should probably dig into the code of the methods, such as setPlayerListName().
     
  7. sothatsit

    Patron

    You will still run into to the length issue and your 2 options to get around it are to trim the player's name with the colour to 16 characters or use scoreboard teams, which is more complicated again.
    if it exists, it's on wiki.vg. Not my fault that you weren't looking hard enough.
     
  8. No problem, if you want to dive into NMS and stuff other people may not have done specifically, I recommend having a project in Intellij/eclipse or whatever IDE you use that's the decompiled spigot code, which is really helpful if you want to see usages of certain classes or variables. Check a tutorial for that here: https://www.spigotmc.org/wiki/cloning-building-and-compiling-the-spigot-source/
     
    • Useful Useful x 1
  9. That's actually incorrect. The list name can be over 16 characters, and that variable stated above accesses just the list name itself (I just did it and it worked as I intended it to with well over 16 characters). What you have to do is change the list name, then use the packet to "update display name" of the player for the user of the command, which ultimately just changes the tablist, as RubbaBoy demonstrated with the Spigot code that sets the list name. Then right after, you need to make sure to change the list name back to whatever it should have been, because if you don't, players that log in will see the new list name :O
     
  10. sothatsit

    Patron

    Unless anything has changed in newer versions, clients will crash upon receiving a tablist name longer than 16 characters.
     
  11. Just did a quick search. Apparently in 1.8+ (which is what I'm using) the tablist name no longer has restrictions, but the display name still does. Any earlier version will have to account for that restriction on the tablist name.
     
    • Useful Useful x 1