Animated titles bugged

Discussion in 'Spigot Plugin Development' started by SmokingIsBadMkay, May 12, 2017.

  1. Hi, so I'm creating a method to play animated titles and they seem the work. However, I've got 2 bugs;
    1. The title saying "you are the murderer" doesn't show the whole animation.
    2. After the match ends (I use player.resetTitle()) but it only resets the title, not the subtitle so you still see it.

    Video showing the bug:


    My codes:
    Titles class, this is where most things happen
    Code (Text):

    public enum Titles {

        RAN_OUT_OF_TIME(2, 180, "&eThe &fInnocents &ehave won the match", "&c&lGAME OVER", "&6&lG&c&lAME OVER", "&c&lG&6&lA&c&lME OVER", "&c&lGA&6&lM&c&lE OVER", "&c&lGAM&6&lE &c&lOVER", "&c&lGAME &6&lO&c&lVER", "&c&lGAME O&6&lV&c&lER", "&c&lGAME OV&6&lE&c&lR", "&c&lGAME OVE&6&lR", "&c&lGAME OVER"),
        INNOCENT_WIN(2, 180, "&eThe &fInnocents &ehave won the match", "&c&lGAME OVER", "&6&lG&c&lAME OVER", "&c&lG&6&lA&c&lME OVER", "&c&lGA&6&lM&c&lE OVER", "&c&lGAM&6&lE &c&lOVER", "&c&lGAME &6&lO&c&lVER", "&c&lGAME O&6&lV&c&lER", "&c&lGAME OV&6&lE&c&lR", "&c&lGAME OVE&6&lR", "&c&lGAME OVER"),
        MURDERER_WIN(2, 180, "&eThe &cMurderer &ehas won the match", "&c&lGAME OVER", "&6&lG&c&lAME OVER", "&c&lG&6&lA&c&lME OVER", "&c&lGA&6&lM&c&lE OVER", "&c&lGAM&6&lE &c&lOVER", "&c&lGAME &6&lO&c&lVER", "&c&lGAME O&6&lV&c&lER", "&c&lGAME OV&6&lE&c&lR", "&c&lGAME OVE&6&lR", "&c&lGAME OVER"),
        YOU_DIED(5, 20, "&7You are now a spectator", "&c&lYOU DIED", "&4&lYOU DIED", "&c&lYOU DIED", "&4&lYOU DIED", "&c&lYOU DIED", "&4&lYOU DIED", "&c&lYOU DIED"),
        ROLE_MURDERER(2, 20,
                "&7Gotta kill them all :}", "&4&lY&c&lou are the Murderer!", "&4&lYo&c&lu are the Murderer!", "&4&lYou&c&l are the Murderer!", "&4&lYou a&c&lre the Murderer!", "&4&lYou ar&c&le the Murderer!",
                "&4&lYou are&c&l the Murderer!", "&4&lYou are t&c&lhe Murderer!", "&4&lYou are th&c&le Murderer!", "&4&lYou are the&c&l Murderer!", "&4&lYou are the M&c&lurderer!", "&4&lYou are the Mu&c&lrderer!",
                "&4&lYou are the Mur&c&lderer!", "&4&lYou are the Murd&c&lerer!", "&4&lYou are the Murde&c&lrer!", "&4&lYou are the Murder&c&ler!", "&4&lYou are the Murdere&c&lr!", "&4&lYou are the Murderer&c&l!",
                "&4&lYou are the Murderer!"
        ),
        ROLE_GUNNER(2, 20,
                "&7Find and kill the Gunner before they kill you!", "&b&lY&f&lou are the Gunner!", "&b&lYo&f&lu are the Gunner!", "&b&lYou&f&l are the Gunner!", "&b&lYou a&f&lre the Gunner!", "&b&lYou ar&f&le the Gunner!",
                "&b&lYou are&f&l the Gunner!", "&b&lYou are t&f&lhe Gunner!", "&b&lYou are th&f&le Gunner!", "&b&lYou are the&f&l Gunner!", "&b&lYou are the M&f&lurderer!", "&b&lYou are the Mu&f&lrderer!",
                "&b&lYou are the Mur&f&lderer!", "&b&lYou are the Murd&f&lerer!", "&b&lYou are the Murde&f&lrer!", "&b&lYou are the Murder&f&ler!", "&b&lYou are the Murdere&f&lr!", "&b&lYou are the Gunner&f&l!",
                "&b&lYou are the Gunner!"
        ),
        ROLE_INNO(2, 20,
                "&7There is a murderer who wants to kill you, run!", "&f&lY&b&lou are an Innocent!", "&f&lYo&b&lu are an Innocent!", "&f&lYou&b&l are an Innocent!", "&f&lYou a&b&lre an Innocent!", "&f&lYou ar&b&le an Innocent!",
                "&f&lYou are&b&l an Innocent!", "&f&lYou are t&b&lhe Innocent!", "&f&lYou are th&b&le Innocent!", "&f&lYou are an&b&l Innocent!", "&f&lYou are an M&b&lurderer!", "&f&lYou are an Mu&b&lrderer!",
                "&f&lYou are an Mur&b&lderer!", "&f&lYou are an Murd&b&lerer!", "&f&lYou are an Murde&b&lrer!", "&f&lYou are an Murder&b&ler!", "&f&lYou are an Murdere&b&lr!", "&f&lYou are an Innocent&b&l!",
                "&f&lYou are an Innocent!"
        );

        private ArrayList<String> effect = new ArrayList<String>();
        private int playSpeed;
        private int lastStay;
        private String subTitle;

        Titles(int playSpeed, int lastStay, String subTitle, String... lines) {
            this.playSpeed = playSpeed;
            this.lastStay = lastStay;
            this.subTitle = ColorDecoder.msg(subTitle);
     
            for(String i : lines) {
                effect.add(ColorDecoder.msg(i));
            }
        }

        public void play(Player player) {
            DataManager.getPlayerData(player.getUniqueId()).setTitlePlaying(this);
     
            new BukkitRunnable() {
                int index = 0;
                int size = effect.size();
         
                @Override
                public void run() {
                     //This class simply stores the current title so if it doesn't equal the playing title it cancels it to prevent                    //two titles from playing at the same time.
                    Titles t = DataManager.getPlayerData(player.getUniqueId()).getTitlePlaying();
             
                    if(index >= size) {
                        this.cancel();
                        return;
                    }
             
                    if(t != Titles.this) {
                        this.cancel();
                        return;
                    }
             
                    String title = effect.get(index);
             
                    if((index + 1) != size) {
                        PacketHelper.sendTitle(player, title, subTitle, playSpeed, 0, 0);
                    } else {
                        PacketHelper.sendTitle(player, title, subTitle, lastStay, 0, 5);
                    }
             
                    index++;
                }
         
            }.runTaskTimer(Loader.instance, 0, this.playSpeed);
        }
    }
     
    Title send method
    Code (Text):
        public static void sendTitle(Player player, String title, String subtitle, int time , int fadeIn, int fadeOut) {
            PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;

            PacketPlayOutTitle packetPlayOutTimes = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TIMES, null, fadeIn, time, fadeOut);
            connection.sendPacket(packetPlayOutTimes);

            IChatBaseComponent titleSub = IChatBaseComponent.ChatSerializer.a("{\"text\": \"" + subtitle + "\"}");
            PacketPlayOutTitle packetPlayOutSubTitle = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, titleSub);
            connection.sendPacket(packetPlayOutSubTitle);

            IChatBaseComponent titleMain = IChatBaseComponent.ChatSerializer.a("{\"text\": \"" + title + "\"}");
            PacketPlayOutTitle packetPlayOutTitle = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, titleMain);
            connection.sendPacket(packetPlayOutTitle);
        }
    How I execute it
    Code (Text):
    Titles.YOU_DIED.play(player);
    Thank you!

    EDIT: FIXED BUG 2, BUG 1 IS STILL VERY MUCH ALIVE
    player.resetTitle(); was actually causing the subTitle to show (lol).
     
    #1 SmokingIsBadMkay, May 12, 2017
    Last edited: May 12, 2017
  2. Its because the PlaySpeed is the same as the Title Time try to set the Titletime +1 worked for me =)

    EDIT: only fixes flickering :oops:
     
    • Friendly Friendly x 1
  3. Already fixed that earlier. Thanks though! :)
     
  4. So...
    It could either be Server lag or Client lag =/
    Works fine for me (only added 2 ticks to the TitleTime, but I dont think its because of that)
     
  5. I fixed the flickering but the video is not up-to-date. Just need to fix the problem where the title only shows after like 1 second.
     
  6. Try to give the first "frame" of the title a fade-in time.
     
  7. Strange thing is that it works for all animated titles except for that one. So I don't think fading is going to solve it.
     
  8. Any idea what else could be causing this?
     
  9. Change fadeIn/fadeOut time to 0.
     
  10. My fadeIn is set to 0 aready.. :confused:
     
  11. And fadeOut ?
     
  12. Fadeout is on 0 too except for the last frame of the animation where I obviously want to make it fade out. I did just find out something interesting, the only difference between the working and the non-working titles is that the working titles are not being played after another title and the broken ones are. My countdown title which plays right before the "broken" title causes it to break, so I think I should try to reset titles before playing a new animation. Any idea how I remove the title sent to the player using packets?
     
  13. i don't believe you can actually 'cancel' a playing title. only simulating it by sending a new title with blank input.
     
  14. Hmm, you should be able to send a title while another is already playing. I had a similar problem and chaing fadeIn and fadeOut to 0 fixed it.
     
  15. Did some testing, the problem isn't caused by the packets, those do overwrite the older ones. The problem is in my titles class, this is the updated code.
    Code (Text):
    package game;

    import java.util.ArrayList;

    import org.bukkit.entity.Player;
    import org.bukkit.scheduler.BukkitRunnable;

    import database.DataManager;
    import main.Loader;
    import pmcglobal.Tools.ColorDecoder;
    import toolbox.PacketHelper;

    public enum Titles {
     
        RAN_OUT_OF_TIME(2, 180, true, "&e&lThe &fInnocents &e&lhave won the match", "&c&lGAME OVER", "&6&lG&c&lAME OVER", "&c&lG&6&lA&c&lME OVER", "&c&lGA&6&lM&c&lE OVER", "&c&lGAM&6&lE &c&lOVER", "&c&lGAME &6&lO&c&lVER", "&c&lGAME O&6&lV&c&lER", "&c&lGAME OV&6&lE&c&lR", "&c&lGAME OVE&6&lR", "&c&lGAME OVER"),
        INNOCENT_WIN(2, 180, true, "&e&lThe &fInnocents &e&lhave won the match", "&c&lGAME OVER", "&6&lG&c&lAME OVER", "&c&lG&6&lA&c&lME OVER", "&c&lGA&6&lM&c&lE OVER", "&c&lGAM&6&lE &c&lOVER", "&c&lGAME &6&lO&c&lVER", "&c&lGAME O&6&lV&c&lER", "&c&lGAME OV&6&lE&c&lR", "&c&lGAME OVE&6&lR", "&c&lGAME OVER"),
        MURDERER_WIN(2, 180, true, "&e&lThe &cMurderer &e&lhas won the match", "&c&lGAME OVER", "&6&lG&c&lAME OVER", "&c&lG&6&lA&c&lME OVER", "&c&lGA&6&lM&c&lE OVER", "&c&lGAM&6&lE &c&lOVER", "&c&lGAME &6&lO&c&lVER", "&c&lGAME O&6&lV&c&lER", "&c&lGAME OV&6&lE&c&lR", "&c&lGAME OVE&6&lR", "&c&lGAME OVER"),
        YOU_DIED(5, 20, true, "&7You are now a spectator", "&c&lYOU DIED", "&4&lYOU DIED", "&c&lYOU DIED", "&4&lYOU DIED", "&c&lYOU DIED", "&4&lYOU DIED", "&c&lYOU DIED"),
        ROLE_MURDERER(2, 20, true,
                "&7Gotta kill them all :}", "&4&lY&c&lou are the Murderer!", "&4&lYo&c&lu are the Murderer!", "&4&lYou&c&l are the Murderer!", "&4&lYou a&c&lre the Murderer!", "&4&lYou ar&c&le the Murderer!",
                "&4&lYou are&c&l the Murderer!", "&4&lYou are t&c&lhe Murderer!", "&4&lYou are th&c&le Murderer!", "&4&lYou are the&c&l Murderer!", "&4&lYou are the M&c&lurderer!", "&4&lYou are the Mu&c&lrderer!",
                "&4&lYou are the Mur&c&lderer!", "&4&lYou are the Murd&c&lerer!", "&4&lYou are the Murde&c&lrer!", "&4&lYou are the Murder&c&ler!", "&4&lYou are the Murdere&c&lr!", "&4&lYou are the Murderer&c&l!",
                "&4&lYou are the Murderer!"
        ),
        ROLE_GUNNER(2, 20, true,
                "&7Find and kill the Gunner before they kill you!", "&b&lY&f&lou are the Gunner!", "&b&lYo&f&lu are the Gunner!", "&b&lYou&f&l are the Gunner!", "&b&lYou a&f&lre the Gunner!", "&b&lYou ar&f&le the Gunner!",
                "&b&lYou are&f&l the Gunner!", "&b&lYou are t&f&lhe Gunner!", "&b&lYou are th&f&le Gunner!", "&b&lYou are the&f&l Gunner!", "&b&lYou are the M&f&lurderer!", "&b&lYou are the Mu&f&lrderer!",
                "&b&lYou are the Mur&f&lderer!", "&b&lYou are the Murd&f&lerer!", "&b&lYou are the Murde&f&lrer!", "&b&lYou are the Murder&f&ler!", "&b&lYou are the Murdere&f&lr!", "&b&lYou are the Gunner&f&l!",
                "&b&lYou are the Gunner!"
        ),
        ROLE_INNO(2, 20, true,
                "&7There is a murderer who wants to kill you, run!", "&f&lY&b&lou are an Innocent!", "&f&lYo&b&lu are an Innocent!", "&f&lYou&b&l are an Innocent!", "&f&lYou a&b&lre an Innocent!", "&f&lYou ar&b&le an Innocent!",
                "&f&lYou are&b&l an Innocent!", "&f&lYou are t&b&lhe Innocent!", "&f&lYou are th&b&le Innocent!", "&f&lYou are an&b&l Innocent!", "&f&lYou are an M&b&lurderer!", "&f&lYou are an Mu&b&lrderer!",
                "&f&lYou are an Mur&b&lderer!", "&f&lYou are an Murd&b&lerer!", "&f&lYou are an Murde&b&lrer!", "&f&lYou are an Murder&b&ler!", "&f&lYou are an Murdere&b&lr!", "&f&lYou are an Innocent&b&l!",
                "&f&lYou are an Innocent!"
        ),
        COUNT_DOWN(20, 20, false, "&7Get ready to start!", "&e&lSTARTING IN &9&l10 SECONDS", "&e&lSTARTING IN &9&l9 SECONDS", "&e&lSTARTING IN &9&l8 SECONDS", "&e&lSTARTING IN &9&l7 SECONDS", "&e&lSTARTING IN &9&l6 SECONDS", "&e&lSTARTING IN &9&l5 SECONDS", "&e&lSTARTING IN &9&l4 SECONDS", "&e&lSTARTING IN &9&l3 SECONDS", "&e&lSTARTING IN &9&l2 SECONDS", "&e&lSTARTING IN &9&l1 SECOND");
     
        private ArrayList<String> effect = new ArrayList<String>();
        private int playSpeed;
        private int lastStay;
        private String subTitle;
        private boolean fadeOut;
     
        Titles(int playSpeed, int lastStay, boolean fadeOut, String subTitle, String... lines) {
            this.playSpeed = playSpeed;
            this.lastStay = lastStay;
            this.fadeOut = fadeOut;
            this.subTitle = ColorDecoder.msg(subTitle);
         
            for(String i : lines) {
                effect.add(ColorDecoder.msg(i));
            }
        }
     
        public void play(Player player) {  
            DataManager.getPlayerData(player.getUniqueId()).setTitlePlaying(this);
            System.err.println("starting");
         
            new BukkitRunnable() {
                int index = 0;
                int size = effect.size();
             
                @Override
                public void run() {
                    Titles t = DataManager.getPlayerData(player.getUniqueId()).getTitlePlaying();
                 
                    if(index >= size) {
                        this.cancel();
                        return;
                    }
                 
                    if(t != Titles.this) {
                        this.cancel();
                        return;
                    }
                 
                    String title = effect.get(index);
                 
                    if((index + 1) != size) {
                        PacketHelper.sendTitle(player, title, subTitle, (playSpeed + 1), 0, 0);
                        System.err.println("sent case 1");
                    } else {
                        if(fadeOut) {
                            PacketHelper.sendTitle(player, title, subTitle, lastStay, 0, 5);
                            System.err.println("sent case 2");
                        } else {
                            PacketHelper.sendTitle(player, title, subTitle, lastStay, 0, 0);
                            System.err.println("sent case 3");
                        }
                    }
                 
                    index++;
                }
             
            }.runTaskTimer(Loader.instance, 0, this.playSpeed);
        }
    }
     
    I executed the COUNT_DOWN and after that the ROLE_MURDERER message and I got this as result:
    [​IMG]

    As you can see the methods aren't running at the same time, but still they are somehow interfering.
     
  16. Anyone? I kinda need this to work today and I really can't figure out why this wouldn't work.