1.15.2 Protocol API Entitymeta help

Discussion in 'Spigot Plugin Development' started by LukeEff, Jan 22, 2020.

  1. Hi, I'm quite new to NMS/Protocol API and giving it my best shot to learn, but am having some difficulty with Entitymeta. I do not have much knowledge of the API yet and don't know what I'm doing too well yet, so try to give me a bit of patience :) (I've watched a tutorial and read through the introduction, it just hasn't entirely "clicked" per-say.)

    What I'm trying to do: The goal here is to set a player to glowing through packets, for X amount of time, visible to any player I specify

    With some googling and a bit of mental power, I was able to get a player to glow, but as soon as the player sprinted, they stopped glowing. I believe this might be because the metadata of the player is changing? I did so with this code (Pretty much copy pasted from https://www.spigotmc.org/threads/simulating-potion-effect-glowing-with-protocollib.218828/):

    Code (Java):
        private void setGlowing() {

            pm.addPacketListener(new PacketAdapter(this, ListenerPriority.NORMAL, PacketType.Play.Server.UPDATE_HEALTH) {

                @Override
                public void onPacketSending(PacketEvent event) {
                    Player player = event.getPlayer();
                    PacketContainer packet = pm.createPacket(PacketType.Play.Server.ENTITY_METADATA);
                    packet.getIntegers().write(0, player.getEntityId()); // Set packet's entity id
                    WrappedDataWatcher watcher = new WrappedDataWatcher(); // Create data watcher, the Entity Metadata
                                                                            // packet requires this
                    Serializer serializer = Registry.get(Byte.class); // Found this through google, needed for some stupid
                                                                        // reason
                    watcher.setEntity(player); // Set the new data watcher's target
                    watcher.setObject(0, serializer, (byte) (0x40)); // Set status to glowing, found on protocol page
                    packet.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects()); // Make the packet's //
                                                                                                        // one we created
                    watcher.getWatchableObject(0);
                    try {
                        for (Player p : Bukkit.getOnlinePlayers()) {
                            pm.sendServerPacket(p, packet);
                        }

                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }

                }
            });
        }

    I tried changing the packet listener to PacketType.Play.Server.ENTITY_METADATA... big mistake as it must be looking for the metadata of every entity on this server. Aka it lags the server, and it doesn't even fully fix the problem! Sprinting will cause it to flicker, and it actually pretty much makes sprinting unusable as it cancels the player sprint or something.

    I'm not looking to be spoon fed--I just need some guidance on how I SHOULD be doing this correctly so that no action the player does causes the packet's effect to go away.

    Thanks in advance :)
     
  2. bump. really could use some help. Spent several hours trying to figure this out with no satisfactory solution
     
  3. Your code seems a bit off, why are you adding the glow inside a listener for an update health packet? Why do you have a listener at all?
     
    • Useful Useful x 1
  4. You don't need a packet listener, just send the right packet. And why using ProtocolLib at first place? Absraction and raw NMS is much faster than ProtocolLib and in fact you won't depend on it on every plugin you do.
     
    • Useful Useful x 1
  5. Thanks for the feedback guys!
    I took a look at my code and realized how garbage it was lol, and scrapped it, ditched the ProtocolLib, gave NMS a shot and came up with this:

    Code (Text):

    package io.github.lukeeff;



    import java.lang.reflect.Field;



    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
    import com.mojang.authlib.GameProfile;
    import net.minecraft.server.v1_15_R1.DataWatcherObject;
    import net.minecraft.server.v1_15_R1.EntityHuman;
    import net.minecraft.server.v1_15_R1.World;
    public class PlayerGlow extends EntityHuman {

    public PlayerGlow(World world, GameProfile gameprofile, CraftPlayer player) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
    super(world, gameprofile);
    Field field = EntityHuman.class.getDeclaredField("bq");
    field.setAccessible(true);
    final DataWatcherObject<Byte> bq = (DataWatcherObject<Byte>) field.get(0);
    this.getDataWatcher().set(bq, (byte) 0x40);
    Bukkit.getConsoleSender().sendMessage(ChatColor.GREEN+"Finished PlayerGlow block.");
    }

    @Override
    public boolean isCreative() {
    // TODO Auto-generated method stub
    return false;
    }
    @Override
    public boolean isSpectator() {
    // TODO Auto-generated method stub
    return false;
    }
    }
     

    The good is the entirety of the code will run without any errors in console. Unfortunately, I'm missing something and I'm not sure what that is. Should I be sending packets or something? Is there a certain packet I'm supposed to be sending?

    Edit: Really doubt this is the culprit, but just in case, here's my main class:
    Code (Text):
    package io.github.lukeeff;

    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.plugin.java.JavaPlugin;

    import net.minecraft.server.v1_15_R1.EntityHuman;

    public class NMSPractice extends JavaPlugin implements Listener {

        @Override
        public void onEnable() {
     
            this.getServer().getPluginManager().registerEvents(this, this);
        }
     
        @Override
        public void onDisable() {
     
     
     
        }
     
        @EventHandler
        public void onJoin(PlayerJoinEvent e) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException  {
            CraftPlayer player = (CraftPlayer) e.getPlayer();
            EntityHuman p = (EntityHuman) player.getHandle();
            Bukkit.getConsoleSender().sendMessage(ChatColor.GREEN+"onJoin event called!");
                new PlayerGlow(p.getWorld(),p.getProfile());
        }
     
     
    }
     

    ****
    Okay, did some more editing. I updated the code above with my new stuff.


    Thanks :)
     
    #5 LukeEff, Jan 23, 2020
    Last edited: Jan 23, 2020