1.15.2 team glowing effect packets

Discussion in 'Spigot Plugin Development' started by Frivec, Apr 18, 2020.

  1. Hi, I'm making a minigames plugin and I would like to setup a glowing effect for the members of a team.
    Example: a player of the red team will see the others red's members with a red glowing effect.

    The members if the others teams will not see these players with the glowing effect.

    I tried to create this system with the PacketPlayOutScoreboardTeam to apply a color then to apply the glowing effect with the PacketPlayOutEntityMetadata thanks to a post of a member of the forum (I forgot the name sorry).

    Problem: The color doesn't applu every time and all the players will see each glow effect even if they're in another team

    Example:

    screen.jpg

    Here's my code:
    Code (Java):
    public class GlowEffect {
     
        private Map<Color, NMSTeam> teams;
     
        public GlowEffect() {
         
            this.teams = new HashMap<>();
         
        }
     
        @SuppressWarnings("unchecked")
        public void setGlowColor(final Player player, final Color color) {
         
            /*
             *
             * Team Packet
             *
             */

     
            final EntityPlayer entityPlayer = getEntityPlayer(player);
         
            NMSTeam team = this.teams.get(color);
         
            System.out.println("team getted: " + team);
         
            if(team == null) {
             
                team = new NMSTeam(color.getCode(), color, "", "", EnumNameTagVisibility.NEVER, EnumTeamPush.NEVER);
                this.teams.put(color, team);
                team.createPacket(player, true, false, false, false);
             
            }else
             
                team.createPacket(player, false, false, true, false);
         
            try {
             
                /**
                 *
                 * Glow Effect
                 *
                 */

             
                final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
             
                entityPlayer.glowing = true;
         
                final Int2ObjectOpenHashMap<DataWatcher.Item<Byte>> map = (Int2ObjectOpenHashMap<Item<Byte>>) FieldUtils.readDeclaredField(dataWatcher, "entries", true);
             
                DataWatcher.Item<Byte> item = map.get(0);
             
                byte initialBitMask = item.b();
                byte bitMaskIndex = (byte) 0x40;
             
                item.a((byte) (initialBitMask | 1 << bitMaskIndex));
             
                final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(player.getEntityId(), dataWatcher, true);
             
                for(String players : team.getPlayers())
                 
                    getConnection(Bukkit.getPlayer(players)).sendPacket(entityMetadata);
             
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
         
        }
     
        @SuppressWarnings("unchecked")
        public void removeGlowEffect(final Player player) {
         
            final EntityPlayer entityPlayer = getEntityPlayer(player);
            NMSTeam team = null;
         
            /*
             *
             * Team
             *
             */

         
            for(final NMSTeam teams : this.teams.values()) {
             
                System.out.println(teams.getName());
             
                if(teams.getPlayers().contains(player.getName())) {
                 
                    System.out.println(teams);
                    team = teams;
                    break;
                 
                }
             
            }
         
            System.out.println("team: " + team);
         
            try {
             
                /*
                 *
                 * Glow Effect
                 *
                 */

             
                final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
             
                entityPlayer.glowing = false;
         
                final Int2ObjectOpenHashMap<DataWatcher.Item<Byte>> map = (Int2ObjectOpenHashMap<Item<Byte>>) FieldUtils.readDeclaredField(dataWatcher, "entries", true);
             
                DataWatcher.Item<Byte> item = map.get(0);
             
                byte initialBitMask = item.b(); // Gets the initial bitmask/byte value so we don't overwrite anything.
                byte bitMaskIndex = (byte) 0x40; // The index as specified in wiki.vg/Entities
             
                item.a((byte) (initialBitMask & ~(1 << bitMaskIndex))); // Inverts the specified bit from the index.  
             
                final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(player.getEntityId(), dataWatcher, true);
             
                if(team == null)
                 
                    getConnection(player).sendPacket(entityMetadata);
             
                else
             
                    for(String players : team.getPlayers())
                     
                        getConnection(Bukkit.getPlayer(players)).sendPacket(entityMetadata);
             
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
         
            if(team != null)
         
                team.createPacket(player, false, false, false, true);
         
        }
     
        public Map<Color, NMSTeam> getTeams() {
            return teams;
        }
     
        public enum Color {
         
            BLACK("0", EnumChatFormat.BLACK),
            DARK_BLUE("1", EnumChatFormat.DARK_BLUE),
            DARK_GREEN("2", EnumChatFormat.DARK_GREEN),
            DARK_CYAN("3", EnumChatFormat.DARK_AQUA),
            DARK_RED("4", EnumChatFormat.BLACK),
            DARK_PURPLE("5", EnumChatFormat.DARK_PURPLE),
            GOLD("6", EnumChatFormat.GOLD),
            LIGHT_GRAY("7", EnumChatFormat.GRAY),
            DARK_GRAY("8", EnumChatFormat.DARK_GRAY),
            INDIGUO("9", EnumChatFormat.LIGHT_PURPLE),
            LIME_GREEN("a", EnumChatFormat.GREEN),
            CYAN("b", EnumChatFormat.BLUE),
            RED("c", EnumChatFormat.RED),
            PINK("d", null),
            YELLOW("e", EnumChatFormat.YELLOW),
            WHITE("f", EnumChatFormat.WHITE),
            RESET("r", EnumChatFormat.RESET),
            BOLD("l", EnumChatFormat.BOLD),
            STRIKE("m", EnumChatFormat.STRIKETHROUGH),
            UNDERLINE("n", EnumChatFormat.UNDERLINE),
            ITALIC("o", EnumChatFormat.ITALIC);
         
            private String code;
            private EnumChatFormat chatFormat;
         
            private Color(final String code, final EnumChatFormat chatFormat) {
             
                this.code = code;
                this.chatFormat = chatFormat;
             
            }
         
            public EnumChatFormat getChatFormat() {
                return chatFormat;
            }
         
            public String getCode() {
                return code;
            }
         
        }

    }
    Code (Java):
    public class NMSTeam {
     
        private String name;
        private Color color;
        private String prefix,
                        suffix;
        private EnumNameTagVisibility nameTagVisibility;
        private EnumTeamPush collision;
        private List<String> players;
     
        public NMSTeam(String name, Color color, String prefix, String suffix, EnumNameTagVisibility nameTagVisibility, EnumTeamPush collision, List<String> players) {
         
            this.name = name;
            this.color = color;
            this.prefix = prefix;
            this.suffix = suffix;
            this.nameTagVisibility = nameTagVisibility;
            this.collision = collision;
            this.players = players;
         
        }
     
        public NMSTeam(String name, Color color, String prefix, String suffix, EnumNameTagVisibility nameTagVisibility, EnumTeamPush collision) {
         
            this.name = name;
            this.color = color;
            this.prefix = prefix;
            this.suffix = suffix;
            this.nameTagVisibility = nameTagVisibility;
            this.collision = collision;
            this.players = new ArrayList<>();
         
        }
     
        @SuppressWarnings("unchecked")
        public void createPacket(final Player player, final boolean createTeam, final boolean deleteTeam, final boolean addPlayer, final boolean removePlayer) {
         
            final PacketPlayOutScoreboardTeam team = new PacketPlayOutScoreboardTeam();
         
            setField(team, "a", this.name);
            setField(team, "e", this.nameTagVisibility.e);
            setField(team, "f", this.collision.e);
            setField(team, "i", createTeam ? 0 : addPlayer ? 3 : deleteTeam ? 1 :4);
         
            if(createTeam) {
             
                setField(team, "g", this.color.getChatFormat());
                setField(team, "b", new ChatComponentText(this.prefix + " " + this.name + " "));
                setField(team, "c", new ChatComponentText(this.prefix));
                setField(team, "d", new ChatComponentText(this.suffix));
                setField(team, "j", 0);
             
                this.players.add(player.getName());
             
                return;
             
            }else if(deleteTeam) {
             
                sendPacket(player, team);
             
                return;
         
            }else {
             
                try {
                 
                    final Collection<String> entities = (Collection<String>) FieldUtils.readDeclaredField(team, "h", true);
                 
                    if(addPlayer) {
                     
                        entities.add(player.getName());
                        this.players.add(player.getName());
                     
                        sendPacket(player, team);
                     
                        return;
                 
                    }else if(removePlayer) {
                     
                        entities.remove(player.getName());
                        this.players.remove(player.getName());
                     
                        if(this.players.isEmpty()) {
                         
                            createPacket(player, false, true, false, false);
                            return;
                         
                        }
                     
                        sendPacket(player, team);
                 
                        return;
                     
                    }else
                     
                        return;
                 
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
             
            }
         
            System.out.println(this.players);
         
            for(String names : this.players)
             
                sendPacket(Bukkit.getPlayer(names), team);
         
            //TODO Tester les teams
         
        }
     
        public boolean isPlayerInTeam(final Player player) {
         
            if(this.players.contains(player.getName()))
             
                return true;
         
            return false;
         
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Color getColor() {
            return color;
        }

        public void setColor(Color color) {
            this.color = color;
        }

        public String getPrefix() {
            return prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }

        public String getSuffix() {
            return suffix;
        }

        public void setSuffix(String suffix) {
            this.suffix = suffix;
        }

        public EnumNameTagVisibility getNameTagVisibility() {
            return nameTagVisibility;
        }

        public void setNameTagVisibility(EnumNameTagVisibility nameTagVisibility) {
            this.nameTagVisibility = nameTagVisibility;
        }

        public EnumTeamPush getCollision() {
            return collision;
        }

        public void setCollision(EnumTeamPush collision) {
            this.collision = collision;
        }

        public List<String> getPlayers() {
            return players;
        }

        public void setPlayers(List<String> players) {
            this.players = players;
        }

    }
     
    #1 Frivec, Apr 18, 2020
    Last edited: Apr 18, 2020
  2. The reason every player sees the glow effect is because you set entityPlayer.glowing = true. You don't want this for what you're trying to do.

    Code (Java):
    DataWatcher.Item<Byte> item = map.get(0);
         
                byte initialBitMask = item.b();
                byte bitMaskIndex = (byte) 0x40;
         
                item.a((byte) (initialBitMask | 1 << bitMaskIndex));
         
                final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(player.getEntityId(), dataWatcher, true);
     
    Code (Java):
    item.a((byte) (initialBitMask | 1 << bitMaskIndex))
    is incorrect. Instead, try this:

    Code (Java):
    byte bitMaskIndex = (byte) 0x40;

    item.a(bitMaskIndex);
    Now it will set glowing. I have little experience with packets, but I don't think you want to send the target player the packet or it might mess up sprinting for the player or something.
     
  3. Sorry for delay of my answer, I was looking for a way to keep the glowing with your method !

    Your method work perfectly for what I need and I solved the problem of the glowing which stay only for one meta data with a packet listener.
    I am now working on the way to solve the problem of the teams. The two players are on the same team but only one will see the other player in the color of the team. The second player will see the other in white.