Resource Titles, ActionBar, & TabTitles

Discussion in 'Spigot Plugin Development' started by ula492, May 14, 2016.

  1. Ive seen so many plugins using this APIs and it makes their plugins looks ugly, no player wants to download a developers plugin that has an API. Unless the plugin is really is awesome. So Im posting a class that everyone should have, this is for Tittles, ActionBar, & Tab. No more of does ugly nasty 3rd party APIs are needed!

    Code (Text):
    package net.thevoidmc.ula.Utils;
    import net.minecraft.server.v1_8_R3.*;
    import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
    import org.bukkit.entity.Player;
    import java.lang.reflect.Field;

    /**
    * Created by Ula on 4/24/16.
    */
    public class PacketUtils {


    public static void sendTitle(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut) {
      CraftPlayer craftplayer = (CraftPlayer) player;
      PlayerConnection connection = craftplayer.getHandle().playerConnection;
      IChatBaseComponent titleJSON = IChatBaseComponent.ChatSerializer.a("{'text': '" + title + "'}");
      IChatBaseComponent subtitleJSON = IChatBaseComponent.ChatSerializer.a("{'text': '" + subtitle + "'}");
      PacketPlayOutTitle titlePacket = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, titleJSON, fadeIn, stay, fadeOut);
      PacketPlayOutTitle subtitlePacket = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, subtitleJSON);
      connection.sendPacket(titlePacket);
      connection.sendPacket(subtitlePacket);
    }


    public static void sendTabHF(Player player, String header, String footer){

      CraftPlayer craftplayer = (CraftPlayer) player;
      PlayerConnection connection = craftplayer.getHandle().playerConnection;
      IChatBaseComponent headerJSON = IChatBaseComponent.ChatSerializer.a("{\"text\": \"" + header + "\"}");
      IChatBaseComponent footerJSON = IChatBaseComponent.ChatSerializer.a("{\"text\": \"" + footer + "\"}");
      PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter();

      try {
       Field headerField = packet.getClass().getDeclaredField("a");
       headerField.setAccessible(true);
       headerField.set(packet, headerJSON);
       headerField.setAccessible(!headerField.isAccessible());

       Field footerField = packet.getClass().getDeclaredField("b");
       footerField.setAccessible(true);
       footerField.set(packet, footerJSON);
       footerField.setAccessible(!footerField.isAccessible());
      } catch (Exception e) {
       e.printStackTrace();
      }

      connection.sendPacket(packet);


    }



    public static void sendActionBar(Player p, String message){
      IChatBaseComponent cbc = IChatBaseComponent.ChatSerializer.a("{\"text\": \"" + message + "\"}");
      PacketPlayOutChat ppoc = new PacketPlayOutChat(cbc,(byte) 2);
      ((CraftPlayer) p).getHandle().playerConnection.sendPacket(ppoc);
    }

    }
     

    Their might be a few people asking how to use it, So here is an Example of how to use with title, its common sense with the others :p.

    Code (Text):
    //PacketUtils.sendTitle(player, Tittle, SubTittle,Fade In, Stay, Fade Out);

    PacketUtils.sendTitle(p,"OOPS!","Looks like you dont have permission!",10, 60, 10);
     
     
    #1 ula492, May 14, 2016
    Last edited: May 14, 2016
    • Agree Agree x 1
    • Useful Useful x 1
  2. I'd tip you with Reflection aswell.
    Create two parts.
    One which is much easier, and one which is harder with reflection.
     
  3. !! NMS && REFLECTION !!

    Made a class for you which will persist through updates and such.
    Code (Java):
    public static final class Packets
    {
        private Class<?> craftPlayer;
        private Method craftHandle;
        private Class<?> iChat;
        private Class<?> chatSer;
        private Method chatSerA;
        private Class<?> packetClass;

        public static String getServerVersion ()
        {
            return Bukkit.getServer ().getClass ().getPackage ().getName ().substring (23);
        }

        public static Class<?> getNMS(String name) throws Exception
        {
            return Class.forName ("net.minecraft.server." + getServerVersion () + "." + name);
        }

        public Packets ()
        {
            try
            {
                craftPlayer = Class.forName("org.bukkit.craftbukkit." + getServerVersion () + ".entity.CraftPlayer");
                craftHandle = craftPlayer.getMethod ("getHandle");
                iChat = getNMS ("IChatBaseComponent");
                chatSer = iChat.getDeclaredClasses ()[0];
                chatSerA = chatSer.getMethod("a", String.class);
                packetClass = getNMS("Packet");
            }
            catch (Exception e)
            {
                e.printStackTrace ();
            }
        }

        public Object getCraftPlayer(Player player)
        {
            try
            {
                return craftHandle.invoke (player);
            }
            catch (IllegalAccessException | InvocationTargetException e)
            {
                e.printStackTrace ();
            }
            return null;
        }

        public Object getConnection(Object craftPlayer)
        {
            try
            {
                return craftPlayer.getClass ().getField ("playerConnection");
            }
            catch (NoSuchFieldException e)
            {
                e.printStackTrace ();
            }
            return null;
        }

        public void sendTitle(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut)
        {
            try
            {
                Object craftPlayer = getCraftPlayer (player);
                Object connection = getConnection (craftPlayer);
                Object titl = chatSerA.invoke (title);
                Object subt = chatSerA.invoke (subtitle);
                Class<?> titlePacket = getNMS ("PacketPlayOutTitle");
                Constructor<?> titlC = ReflectionUtils.getConstructor (titlePacket, titlePacket.getDeclaredClasses ()[0], iChat, int.class, int.class, int.class);
                Constructor<?> subtC = ReflectionUtils.getConstructor (titlePacket, titlePacket.getDeclaredClasses()[0], iChat);
                Object send1 = titlC.newInstance (titlePacket.getDeclaredClasses ()[0].getEnumConstants ()[0], titl, fadeIn, stay, fadeOut);
                Object send2 = subtC.newInstance (titlePacket.getDeclaredClasses ()[0].getEnumConstants ()[1], subt);
                Method send = connection.getClass ().getMethod ("sendPacket", packetClass);
                send.invoke (connection, send1);
                send.invoke (connection, send2);
            }
            catch (Exception e)
            {
                e.printStackTrace ();
            }
        }

        public void sendTabHF(Player player, String header, String footer)
        {
            Object craftPlayer = getCraftPlayer (player);
            Object connection = getConnection (craftPlayer);
            try {
                Object headerJSON = chatSerA.invoke (header);
                Object footerJSON = chatSerA.invoke(footer);
                Object packet = getNMS ("PacketPlayOutPlayerListHeaderFooter").getConstructor ().newInstance ();
                Field headerField = packet.getClass ().getDeclaredField("a");
                headerField.setAccessible(true);
                headerField.set(packet, headerJSON);
                headerField.setAccessible(!headerField.isAccessible());

                Field footerField = packet.getClass().getDeclaredField("b");
                footerField.setAccessible(true);
                footerField.set(packet, footerJSON);
                footerField.setAccessible(!footerField.isAccessible());

                connection.getClass ().getMethod ("sendPacket", packetClass).invoke (player, packet);
            }catch (Exception e)
            {
                e.printStackTrace ();
            }
        }

        public void sendActionBar(Player player, String message)
        {
            Object craftPlayer = getCraftPlayer (player);
            Object connection = getConnection (craftPlayer);
            try {
                Class<?> packet = getNMS ("PacketPlayOutChat");
                connection.getClass ().getMethod ("sendPacket", packetClass).invoke (player, packet.getConstructor (iChat, byte.class).newInstance (chatSerA.invoke ("{\"text\": \"" + message + "\"}"), (byte)2));
            } catch (Exception e)
            {
                e.printStackTrace ();
            }
        }
    }
     
    • Like Like x 2
  4. Why make it harder... Literally just copy and paste that. Import ur version and ur done, that works with 1.8+1.9. Thanks for the tip doe!
     
  5. Nop
    Yours work with the one that they build against, and REQUIRES spigot/craftbukkit jar, and not the spigotapi/bukkit jar.
    So, if they build it with the packages net.minecraft.server.V1_9_2R01, it will only work with that.
    1.9.2R02 won't work with the plugin.
    Mine will.
     
    • Agree Agree x 1
  6. True, My apologies.