Best method of creating titles without an API in 1.8?

Discussion in 'Spigot Plugin Development' started by Cervinakuy, May 22, 2016.

  1. Hey guys!

    So I want a title to be shown on a player's screen when they join my server.. but I don't know the best method of doing so. Do you guys mind sharing your methods of creating titles?

    Thanks,
    - Cervinakuy
     
  2. There is a rather limited form of sending titles in Spigot currently (I've got a PR in to improve it). But if you don't want to use it then you could always go the reflection path
     
  3. An elaboration would be appreciated. :)

    I've tried Packets but they don't work for me.. this is the reason I'm creating this thread.. maybe the method I used isn't supported anymore.
     
  4. Player#sendTitle() exists
     
  5. Oh I see what you're saying.
     
  6. NMS is the easiest way to do this. It's easy fast and quite simple.
     

  7. Easiest method: player.sendTitle(title, subtitle)

    Harder but can do timings: Packets (There's buncha tutorials I don't wanna type 6 lines down for an answer)
     
  8. I use this class I made, but it's version specific, so it won't work on anything except 1.9, you would have to re-do the imports to make it work on another version.

    Code (Text):
    import net.minecraft.server.v1_9_R1.IChatBaseComponent;
    import net.minecraft.server.v1_9_R1.PacketPlayOutChat;
    import net.minecraft.server.v1_9_R1.PacketPlayOutTitle;
    import org.bukkit.Bukkit;
    import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer;
    import org.bukkit.entity.Player;

    public enum ChatUtil {
        TITLE,
        SUBTITLE,
        ACTION_BAR;

        public void send(Player p, String message){
            IChatBaseComponent comp = IChatBaseComponent.ChatSerializer.a("{\"text\":\"" + message + "\"}");
            CraftPlayer cp = (CraftPlayer) p;

            switch (this){
                case ACTION_BAR:
                    PacketPlayOutChat packet = new PacketPlayOutChat(comp, (byte) 2);
                    cp.getHandle().playerConnection.sendPacket(packet);
                    break;
                case TITLE:
                    PacketPlayOutTitle title = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, comp);
                    cp.getHandle().playerConnection.sendPacket(title);
                    break;
                case SUBTITLE:
                    PacketPlayOutTitle title2 = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, comp);
                    cp.getHandle().playerConnection.sendPacket(title2);
                    break;
            }
        }

        public void sendAll(String message){
            IChatBaseComponent comp = IChatBaseComponent.ChatSerializer.a("{\"text\":\"" + message + "\"}");

            switch (this){
                case ACTION_BAR:
                    PacketPlayOutChat packet = new PacketPlayOutChat(comp, (byte) 2);
                    for (Player p : Bukkit.getOnlinePlayers()){
                        ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
                    }
                    break;
                case TITLE:
                    PacketPlayOutTitle title = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, comp);
                    for (Player p : Bukkit.getOnlinePlayers()){
                        ((CraftPlayer) p).getHandle().playerConnection.sendPacket(title);
                    }
                    break;
                case SUBTITLE:
                    PacketPlayOutTitle title2 = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, comp);
                    for (Player p : Bukkit.getOnlinePlayers()){
                        ((CraftPlayer) p).getHandle().playerConnection.sendPacket(title2);
                    }
                    break;
            }
        }
    }
     
    ChatUtil.TITLE.send(Player varPlayer, String varMessage);
    ChatUtil.TITLE.sendAll(String varMessage);
     
    • Useful Useful x 1
  9. I forgot to mention this is for 1.8, sorry for the misinformation.
     
  10. @Cervinakuy changing imports should be fine. Nothing title-related has changed in 1.9. I do recommend reflection though
     
  11. Thank you for your help, I'll see what I can do. :)
     
  12. JustisR

    Supporter

    If you're worried about versions, you can always get the path to the NMS class dynamically using something like this:

    Code (Text):
    public static Class<?> getNMSClass(String name) {
            String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
            try {
                return Class.forName("net.minecraft.server." + version + "." + name);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                return null;
            }
        }
     
  13. His help? I gave you the class and even mentioned that if you want it for another version you need to re-do the imports
     
  14. Sorry for the confusion. I'll use your method and see how things go. :)
     
  15. I made this class, much more simpler:

    Code (Text):
    package us.universalpvp.te.utils;

    import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
    import org.bukkit.entity.Player;

    import net.minecraft.server.v1_8_R3.IChatBaseComponent;
    import net.minecraft.server.v1_8_R3.IChatBaseComponent.ChatSerializer;
    import net.minecraft.server.v1_8_R3.PacketPlayOutTitle;
    import net.minecraft.server.v1_8_R3.PacketPlayOutTitle.EnumTitleAction;

    public class TitleManager {

        public void sendTitle(Player player, String text) {
            IChatBaseComponent chatTitle = ChatSerializer.a("{\"text\":\"" + text + "\"}");
            PacketPlayOutTitle title = new PacketPlayOutTitle(EnumTitleAction.TITLE, chatTitle);
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(title);
        }

        public void sendTimedTitle(Player player, String text, int fadeInTime, int stayOnScreenTime, int fadeOutTime) {
            IChatBaseComponent chatTitle = ChatSerializer.a("{\"text\":\"" + text + "\"}");
            PacketPlayOutTitle title = new PacketPlayOutTitle(EnumTitleAction.TIMES, chatTitle, fadeInTime,
                    stayOnScreenTime, fadeOutTime);
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(title);

        }

        public void sendTitleAndSubtitle(Player player, String titleText, String subtitleText) {

            IChatBaseComponent chatTitle = ChatSerializer.a("{\"text\": \"" + titleText + "\"}");
            IChatBaseComponent chatSubTitle = ChatSerializer.a("{\"text\": \"" + subtitleText + "\"}");

            PacketPlayOutTitle title = new PacketPlayOutTitle(EnumTitleAction.TITLE, chatTitle);
            PacketPlayOutTitle subTitle = new PacketPlayOutTitle(EnumTitleAction.SUBTITLE, chatSubTitle);

            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(title);
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(subTitle);
        }

        public void sendTimedTitleAndSubtitle(Player player, String titleText, String subtitleText, int fadeIn, int stay,
                int fadeOut) {

            IChatBaseComponent chatTitle = ChatSerializer.a("{\"text\": \"" + titleText + "\"}");
            IChatBaseComponent chatSubTitle = ChatSerializer.a("{\"text\": \"" + subtitleText + "\"}");

            PacketPlayOutTitle title = new PacketPlayOutTitle(EnumTitleAction.TITLE, chatTitle);
            PacketPlayOutTitle subTitle = new PacketPlayOutTitle(EnumTitleAction.SUBTITLE, chatSubTitle);
            PacketPlayOutTitle length = new PacketPlayOutTitle(fadeIn, stay, fadeOut);

            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(title);
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(subTitle);
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(length);

        }

    }
     
  16. Just use an api like title manager and have it be a required dependancy. Then the end user can pick what version is right for their server.
     
  17. Thanks for the post. I will try this also.

    Why no Spigot Support? :(

    I know having an API would be a lot easier, but as said in the title, I'm looking to create a title without a dependency.
     
  18. It works for Spigot, not with the API but the server jar.