Solved Hiding names on tab

Discussion in 'Plugin Development' started by Fhbgsdhkfbl, Feb 23, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    Fhbgsdhkfbl

    Hey bukkit forums, I'm currently trying to hide names on tab with a command, and I can't seem to get it working, and it's throwing a massive error I can't figure out. If y'all can help me, I'd appreciate it!

    Main class:
    Code:
    package me.Fhbgsdhkfbl.HideTabList;
    
    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    import org.bukkit.event.Listener;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Main extends JavaPlugin implements Listener {
        private PlayerItemList playerList;
        public void onEnable() {
            saveDefaultConfig();
            playerList = new PlayerItemList(this);
        }
        public void onDisable() {
    
        }
    
        public boolean onCommand(CommandSender sender, Command cmd, String label, String args[]) {
            Player p = (Player) sender;
            if(cmd.getName().equalsIgnoreCase("ht")) {
                if(p.hasPermission("ht.hide")) {
                    if(args.length == 0) {
                        p.sendMessage(ChatColor.RED + "Please insert 'hide' to complete the args");
                        return true;
                    }
                    if(args.length == 1) {
                        if(args[0].equalsIgnoreCase("hide")) {
                            if(playerList.isVisible(p)) {
                                playerList.hidePlayer(p);
                                p.sendMessage(this.getConfig().getString(ChatColor.translateAlternateColorCodes('&', "hidemessage")));
                            } else {
                                if(!(playerList.isVisible(p))) {
                                    playerList.showPlayer(p);
                                    p.sendMessage(this.getConfig().getString(ChatColor.translateAlternateColorCodes('&', "showmessage")));
                                }
                            }
                        }
                    }
                }
            }
            return false;
        }
    
    }
    
    PlayerItemList Class:
    Code:
    package me.Fhbgsdhkfbl.HideTabList;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;
    
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.Plugin;
    
    import com.comphenix.protocol.PacketType;
    import com.comphenix.protocol.ProtocolLibrary;
    import com.comphenix.protocol.ProtocolManager;
    import com.comphenix.protocol.events.ListenerPriority;
    import com.comphenix.protocol.events.PacketAdapter;
    import com.comphenix.protocol.events.PacketContainer;
    import com.comphenix.protocol.events.PacketEvent;
    import com.comphenix.protocol.events.PacketListener;
    import com.comphenix.protocol.injector.BukkitUnwrapper;
    import com.comphenix.protocol.injector.PacketConstructor;
    import com.comphenix.protocol.reflect.FieldAccessException;
    import com.comphenix.protocol.reflect.FieldUtils;
    import com.comphenix.protocol.reflect.FuzzyReflection;
    public class PlayerItemList  {
        // Copy of the player list packet
        private class PlayerListItem {
            public String name;
            public boolean online;
        }
       
        private PacketListener overrideListener;
        private ProtocolManager manager;
       
        // Used to construct packets
        private PacketConstructor playerListConstructor;
       
        // Players to hide
        private Set<String> hiddenPlayers = new HashSet<String>();
       
        // The current list of visible players
        private Set<String> visiblePlayers = new HashSet<String>();
       
        // To get the ping
        private Field pingField;
       
        /**
         * Start the player list hook.
         * @param plugin - owner plugin.
         */
        public PlayerItemList (Plugin plugin) {
            this.overrideListener = new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.PLAYER_INFO) {
                @Override
                public void onPacketSending(PacketEvent event) {
                    try {
                        PlayerListItem item = getPlayerListInfo(event);
                       
                        // Overridden player list?
                        if (hiddenPlayers.contains(item.name) && item.online) {
                            // Tell the client to remove this player instead
                            event.getPacket().getSpecificModifier(boolean.class).write(0, false);
                            item.online = false;
                        }
                       
                        // Update list
                        if (item.online)
                            visiblePlayers.add(item.name);
                        else
                            visiblePlayers.remove(item.name);
                       
                    } catch (FieldAccessException e) {
                        e.printStackTrace();
                    }
                }
            };
            this.manager = ProtocolLibrary.getProtocolManager();
           
            // Add every current player
            for (Player player : plugin.getServer().getOnlinePlayers()) {
                visiblePlayers.add(player.getPlayerListName());
            }
        }
        // Read the player list information
        private PlayerListItem getPlayerListInfo(PacketEvent event) throws FieldAccessException {
            PacketContainer packet = event.getPacket();
            PlayerListItem result = new PlayerListItem();
           
            result.name = packet.getSpecificModifier(String.class).read(0);
            result.online = packet.getSpecificModifier(boolean.class).read(0);
            return result;
        }
       
        /**
         * Start the hook.
         */
        public void register() {
            manager.addPacketListener(overrideListener);
        }
       
        /**
         * Hide a player from the list.
         * @param player - the player to hide from the list.
         * @return TRUE if the player was not previously hidden, FALSE otherwise.
         */
        public boolean hidePlayer(Player player) {
            String name = player.getPlayerListName();
            boolean success = hiddenPlayers.add(name);
           
            // Remove it?
            if (visiblePlayers.contains(name)) {
                sendListPacket(player, false);
                visiblePlayers.remove(name);
            }    
            return success;
        }
       
        /**
         * Show a player on the list.
         * @param player - the player to show on the list.
         * @return TRUE if the player was previously hidden, FALSE otherwise.
         */
        public boolean showPlayer(Player player) {
            String name = player.getPlayerListName();
            boolean success = hiddenPlayers.remove(name);
           
            // Add it?
            if (!visiblePlayers.contains(name)) {
                sendListPacket(player, true);
                visiblePlayers.add(name);
            }
            return success;
        }
       
        /**
         * Determine if a given player is visible in the player list.
         * @param player - the player to check.
         * @return TRUE if it is, FALSE otherwise.
         */
        public boolean isVisible(Player player) {
            return visiblePlayers.contains(player.getName());
        }
       
        /**
         * Retrieve the current ping value from a player.
         * @param player - player to retrieve.
         * @return The ping value.
         * @throws IllegalAccessException Unable to read the ping value due to a security limitation.
         */
        public int getPlayerPing(Player player) throws IllegalAccessException {
            BukkitUnwrapper unwrapper = new BukkitUnwrapper();
            Object entity = unwrapper.unwrapItem(player);
           
            // Next, get the "ping" field
            if (pingField == null) {
                pingField = FuzzyReflection.fromObject(entity).getFieldByName("ping");
            }
           
            return (Integer) FieldUtils.readField(pingField, entity);
        }
       
        private void sendListPacket(Player player, boolean visible) {
           
            String name = player.getPlayerListName();
           
            if (playerListConstructor == null) {
                // REQUIRES 1.4.2
                playerListConstructor = manager.createPacketConstructor(PacketType.Play.Server.PLAYER_INFO, "", false, (int) 0);
            }
           
            try {
                PacketContainer packet = playerListConstructor.createPacket(name, visible, getPlayerPing(player));
               
                // Just broadcast it
                for (Player reciever : player.getServer().getOnlinePlayers()) {
                    manager.sendServerPacket(reciever, packet);
                }
               
            } catch (FieldAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
       
        /**
         * Retrieve every hidden player.
         * @return Every hidden player.
         */
        public Set<String> getHiddenPlayers() {
            return Collections.unmodifiableSet(hiddenPlayers);
        }
       
        /**
         * Cleanup this player list hook.
         */
        public void cleanupAll() {
            if (overrideListener != null) {
                manager.removePacketListener(overrideListener);
                overrideListener = null;
            }
        }
    }


    error:
    Code:
    [22:36:32] [Server thread/ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'ht' in plugin HideTabList v1.0
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchCommand(CraftServer.java:645) ~[craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.PlayerConnection.handleCommand(PlayerConnection.java:1115) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.PlayerConnection.a(PlayerConnection.java:950) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(PacketPlayInChat.java:26) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(PacketPlayInChat.java:53) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.PacketHandleTask.run(SourceFile:13) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [?:1.7.0_75]
            at java.util.concurrent.FutureTask.run(FutureTask.java:262) [?:1.7.0_75]
            at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:683) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:316) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:623) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:526) [craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            at java.lang.Thread.run(Thread.java:745) [?:1.7.0_75]
    Caused by: java.lang.IllegalArgumentException: No suitable constructor could be found.
            at com.comphenix.protocol.injector.PacketConstructor.withPacket(PacketConstructor.java:179) ~[?:?]
            at com.comphenix.protocol.injector.PacketFilterManager.createPacketConstructor(PacketFilterManager.java:933) ~[?:?]
            at me.Fhbgsdhkfbl.HideTabList.PlayerItemList.sendListPacket(PlayerItemList.java:169) ~[?:?]
            at me.Fhbgsdhkfbl.HideTabList.PlayerItemList.showPlayer(PlayerItemList.java:130) ~[?:?]
            at me.Fhbgsdhkfbl.HideTabList.Main.onCommand(Main.java:34) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit.jar:git-craftbukkit-13716d9-850a9e0]
            ... 14 more
    Source: https://gist.github.com/aadnk/3928137
     
  2. Offline

    Skionz

    @Fhbgsdhkfbl After looking at ProtocolLib's Javadocs it seems that the PacketManager#createPacket() method take an array of Objects that represent the arguments of the constructor. Then if I were to guess, it uses reflection to try and find a constructor matching the arguments you provided based on their class. Basically, you are using the wrong arguments here and attempting to use a constructor that doesn't exist.
    Code:
    PacketContainer packet = playerListConstructor.createPacket(name, visible, getPlayerPing(player));
    
    I am sure you can find the correct arguments to pass on your own.
     
  3. Offline

    Fhbgsdhkfbl

    I'm decently new to packets, so I don't know exactly what to do.
     
  4. Offline

    Skionz

    Pass the correct arguments to ProtocolLib's PacketConstructor#createPacket() method.
     
Thread Status:
Not open for further replies.

Share This Page