Solved Refresh Gui

Discussion in 'Spigot Plugin Development' started by JustDevs_, Apr 6, 2019.

Thread Status:
Not open for further replies.
  1. I created a team selection guide for a minigame I'm doing:
    Code (Java):
     TEAM API CLASS
    public ItemStack getIcon(Player p) {
            ItemStack it = new ItemStack(Material.STAINED_GLASS, getPlayers().size(), colorData);
            ItemMeta m = it.getItemMeta();
            m.setDisplayName(prefix + name + " §7- " + getPlayers().size() + "§7/" + getMaxPlayers());
            m.setLore(players);
            it.setItemMeta(m);
         
            return it;
        }
    Code (Java):
        GUI CLASS
    public gui(Main plugin) {
            this.plugin = plugin;
            red = new TeamApi("Red", "§c", (byte) 14);
            blue = new TeamApi("Blue", "§1", (byte) 11);
            green = new TeamApi("Green", "§2", (byte) 13);
            yellow = new TeamApi("Yellow", "§e", (byte) 4);
            orange = new TeamApi("Orange", "§6", (byte) 1);
            white = new TeamApi("White", "§f", (byte) 0);
            purple = new TeamApi("Purple", "§5", (byte) 10);
            black = new TeamApi("Black", "§0", (byte) 15);
        }
     
        @SuppressWarnings("deprecation")
        @EventHandler
        public void onInvClick(InventoryClickEvent e) {
            if (e.getInventory() != null && e.getCurrentItem() != null && e.getInventory().getTitle().equals("§6§lTeams")) {
                if (e.getCurrentItem().getType() == Material.STAINED_GLASS) {
                    e.setCancelled(true);
                    Player p = (Player) e.getWhoClicked();
                    if (e.getCurrentItem().getData().getData() == (byte) 14) {
                        addToTeam(p, red);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 11) {
                        addToTeam(p, blue);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 13) {
                        addToTeam(p, green);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 4) {
                        addToTeam(p, yellow);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 1) {
                        addToTeam(p, orange);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 0) {
                        addToTeam(p, white);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 15) {
                        addToTeam(p, black);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 10) {
                        addToTeam(p, purple);
                    }
                    openInv(p);
                }
            }

        public void openInv(Player p) {
            Inventory inv = Bukkit.createInventory(null, 9, "§6§lTeams");
            if(plugin.team()) {
                inv.setItem(0, red.getIcon(p));
                inv.setItem(1, yellow.getIcon(p));
                inv.setItem(2, green.getIcon(p));
                inv.setItem(3, blue.getIcon(p));
            } else {
                inv.setItem(0, black.getIcon(p));
                inv.setItem(1, purple.getIcon(p));
                inv.setItem(2, red.getIcon(p));
                inv.setItem(3, orange.getIcon(p));
                inv.setItem(4, yellow.getIcon(p));
                inv.setItem(5, green.getIcon(p));
                inv.setItem(6, blue.getIcon(p));
                inv.setItem(7, white.getIcon(p));
            }
            p.openInventory(inv);
        }
        }
    When I go to open it I select the team and it's fine but at the next opening I lose the team selection, I have to click on a block to redo what appears before was updated.
    I would like this guide to be updated every 2 or 3 seconds and that there is no problem described above.
    Thanks in advance.
     
  2. Hello,

    what's your exact problem? Do you want how to update your GUI, or you have problem with some type of GUI options showing?
     
  3. Yes, I would like to know how to update the gui.
     
  4. If yes, there's the steps how I am doing this and how I'd do this:

    1. When opening inventory, schedule repeating task with delay like you want to update the inventory.
    2. At the beggining of each task check if inventory name corresponds with name of inventory you created.
    2A: If yes, continue with process
    2B: If not, cancel the repeating task and return.
    3. If yes, get Inventory object with HumanEntity#getOpenInventory#getTopInventory.
    4. At this point, use Inventory#setItem to reset the items in inventory.
     
  5. I would like to understand better be sure not to make mistakes: could you send me an example code?
     
  6. Firstly, when I am reading your code I see this:
    Code (Java):
    public gui(Main main)
    In class namings, Java uses CamelCase, what means, your class should be named Gui as your Main class, not gui. This style of naming is suitable for methods, exampleMethod, exampleVoid etc.
    Also, when we are talking about your Main class, if it is the real main class (extends JavaPlugin), then it should be named after your plugin name.

    Anyways, I don't like spoonfeeding, but I think it should be okay when I will comment the code.
    1. Create new void called for example "updateInventory", like this:
    Code (Java):
    private void updateInventory(final Player player) {

    }
    We don't need to make it public, because it will be only for internal class use only.
    2. Add method calling at the end of openInv:
    Code (Java):
    public void openInv(Player p) {
            Inventory inv = Bukkit.createInventory(null, 9, "§6§lTeams");
            if(plugin.team()) {
                inv.setItem(0, red.getIcon(p));
                inv.setItem(1, yellow.getIcon(p));
                inv.setItem(2, green.getIcon(p));
                inv.setItem(3, blue.getIcon(p));
            } else {
                inv.setItem(0, black.getIcon(p));
                inv.setItem(1, purple.getIcon(p));
                inv.setItem(2, red.getIcon(p));
                inv.setItem(3, orange.getIcon(p));
                inv.setItem(4, yellow.getIcon(p));
                inv.setItem(5, green.getIcon(p));
                inv.setItem(6, blue.getIcon(p));
                inv.setItem(7, white.getIcon(p));
            }
            p.openInventory(inv);

            updateInventory(p);
        }
    Simply, add updateInventory(p); at the end of the openInv method.
    3. Create BukkitRunnable in our new method:
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
         
        }
      }.runTaskTimer(Plugin plugin, long delay, long period);
    }
    The task will repeat every X seconds. We will use BukkitRunnable instead of BukkitScheduler, because BukkitRunnable has cancelling method built in. This method will find it's usage in the next steps.
    4. Set parameters as wanted:
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
         
        }
      }.runTaskTimer(this.main, 20L, 20L);
    }
    In my case, the task will start firstly after 1 second (20 ticks) and will repeat every 1 second.
    5. Get the top inventory:
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
            Inventory inv = ((HumanEntity) player).getOpenInventory().getTopInventory();
        }
      }.runTaskTimer(this.main, 20L, 20L);
    }
    Get the opened inventory.
    6. Check for a title:
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
            Inventory inventory = ((HumanEntity) player).getOpenInventory().getTopInventory();

            if (!inventory.getName().equals("§6§lTeams")) {
              cancel();
              return;
            }
        }
      }.runTaskTimer(this.main, 20L, 20L);
    }
    If inventory title doesn't equal to title of previously created inventory in openInv, cancel the task. There we used that method to cancel the task. However, we need to put return after that, because cancel(); only cancels the task - prevents it's further executing. That means, we need it there because after this if there will be upcoming code. I am familiar with this design, but you can also use this:
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
            Inventory inventory = ((HumanEntity) player).getOpenInventory().getTopInventory();

            if (inventory.getName().equals("§6§lTeams")) {
           
            } else {
              cancel();
            }
        }
      }.runTaskTimer(this.main, 20L, 20L);
    }
    * there is no need for brackets in block where is cancel();. I put them there to not make you confused.
    7. Update the inventory:
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
            Inventory inventory = ((HumanEntity) player).getOpenInventory().getTopInventory();

            if (!inventory.getName().equals("§6§lTeams")) {
              cancel();
              return;
            }

            if(plugin.team()) {
                inv.setItem(0, red.getIcon(p));
                inv.setItem(1, yellow.getIcon(p));
                inv.setItem(2, green.getIcon(p));
                inv.setItem(3, blue.getIcon(p));
            } else {
                inv.setItem(0, black.getIcon(p));
                inv.setItem(1, purple.getIcon(p));
                inv.setItem(2, red.getIcon(p));
                inv.setItem(3, orange.getIcon(p));
                inv.setItem(4, yellow.getIcon(p));
                inv.setItem(5, green.getIcon(p));
                inv.setItem(6, blue.getIcon(p));
                inv.setItem(7, white.getIcon(p));
            }
        }
      }.runTaskTimer(this.main, 20L, 20L);
    }
    Just copy the part of code from openInv() and modify by yourself as you wanted.
    * This code has not been tested, might require player.updateInventory() at the end of the task code.
    8. Final editing and shortening (optional):
    Code (Java):
    public void openInv(Player p) {
            Inventory inv = Bukkit.createInventory(null, 9, "§6§lTeams");
            p.openInventory(inv);

            updateInventory(p);
        }
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
            Inventory inventory = ((HumanEntity) player).getOpenInventory().getTopInventory();

            if (!inventory.getName().equals("§6§lTeams")) {
              cancel();
              return;
            }

            if(plugin.team()) {
                inv.setItem(0, red.getIcon(p));
                inv.setItem(1, yellow.getIcon(p));
                inv.setItem(2, green.getIcon(p));
                inv.setItem(3, blue.getIcon(p));
            } else {
                inv.setItem(0, black.getIcon(p));
                inv.setItem(1, purple.getIcon(p));
                inv.setItem(2, red.getIcon(p));
                inv.setItem(3, orange.getIcon(p));
                inv.setItem(4, yellow.getIcon(p));
                inv.setItem(5, green.getIcon(p));
                inv.setItem(6, blue.getIcon(p));
                inv.setItem(7, white.getIcon(p));
            }
        }
      }.runTaskTimer(this.main, 0L, 20L);
    }
    Since we have duplicating code (inv.setItem code block), you can remove it from openInv void. But, don't forget to change delay value in runnable to 0! Otherwise first second players will see only empty inventory.
    9. Final code:
    Code (Java):
    public void openInv(Player p) {
            Inventory inv = Bukkit.createInventory(null, 9, "§6§lTeams");
            p.openInventory(inv);

            updateInventory(p);
        }
    Code (Java):
    private void updateInventory(final Player player) {
      new BukkitRunnable() {
        @Override
        public void run() {
            Inventory inventory = ((HumanEntity) player).getOpenInventory().getTopInventory();

            if (!inventory.getName().equals("§6§lTeams")) {
              cancel();
              return;
            }

            if(plugin.team()) {
                inv.setItem(0, red.getIcon(p));
                inv.setItem(1, yellow.getIcon(p));
                inv.setItem(2, green.getIcon(p));
                inv.setItem(3, blue.getIcon(p));
            } else {
                inv.setItem(0, black.getIcon(p));
                inv.setItem(1, purple.getIcon(p));
                inv.setItem(2, red.getIcon(p));
                inv.setItem(3, orange.getIcon(p));
                inv.setItem(4, yellow.getIcon(p));
                inv.setItem(5, green.getIcon(p));
                inv.setItem(6, blue.getIcon(p));
                inv.setItem(7, white.getIcon(p));
            }
        }
      }.runTaskTimer(this.main, 0L, 20L);
    }
    If I helped you, leave a like! Thanks!
     
    • Like Like x 1
  7. Thank you so much you gave me a great hand. But now I have one last problem:
    The gui when a player clicks us to enter the team correctly enters it and everything works, but when it closes and reopens the gui no longer shows the player / players in the team, only when you do a "physical" update, that is when you click on a other block.
     
  8. What does the plugin.team() do?

    And, please show me your current code.
     
  9. check if the team is enabled
     
    • Like Like x 1
  10. Then please send me your code, when you are creating inventory.

    Also, what's the exact problem right now? Player opens inventory, chooses team and closes it. Then opens it again and there are not some items displayed or?
     
  11. Yes, That's the problem

    Code (Java):
    TeamApi class  
    private String name, prefix;
        public ArrayList<String> players;
        private byte colorData;
        private int maxPlayers;
        private Main plugin = Main.getPlugin(Main.class);

        public TeamApi(String name, String prefix, byte colorData) {
            this.name = name;
            this.prefix = prefix;
            this.colorData = colorData;
            maxPlayers = getMaxPlayers();
            this.players = new ArrayList<>();
        }
       
        public TeamApi(Main main) {
            main = plugin;
        }

        public byte getColorData() {
            return colorData;
        }

        public String getName() {
            return name;
        }

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

        public String getPrefix() {
            return prefix;
        }

        public int getMaxPlayers() {
            if (plugin.getConfig().getBoolean("Game.Teams-enable")) {
                maxPlayers = 2;
            } else {
                maxPlayers = 1;
            }
            return maxPlayers;
        }
       
        public boolean isInTeam(Player p) {
            if (players.contains(p.getName())) {
                return true;
            }
            return false;
        }
       
        public ItemStack getIcon(Player p) {
            ItemStack it = new ItemStack(Material.STAINED_GLASS, getPlayers().size(), colorData);
            ItemMeta m = it.getItemMeta();
            m.setDisplayName(prefix + name + " §7- " + getPlayers().size() + "§7/" + getMaxPlayers());
            //m.setLore(Arrays.asList(new String[] {ChatColor.GRAY + "- " + getPlayers()}));
            m.setLore(players);
            it.setItemMeta(m);
           
            return it;
        }





    Gui Class

        private TeamApi red;
        private TeamApi blue;
        private TeamApi green;
        private TeamApi yellow;
        private TeamApi black;
        private TeamApi purple;
        private TeamApi white;
        private TeamApi orange;
        private Main plugin;
        private Inventory inv;
       
        public Gui(Main plugin) {
            this.plugin = plugin;
            red = new TeamApi("Red", "§c", (byte) 14);
            blue = new TeamApi("Blue", "§1", (byte) 11);
            green = new TeamApi("Green", "§2", (byte) 13);
            yellow = new TeamApi("Yellow", "§e", (byte) 4);
            orange = new TeamApi("Orange", "§6", (byte) 1);
            white = new TeamApi("White", "§f", (byte) 0);
            purple = new TeamApi("Purple", "§5", (byte) 10);
            black = new TeamApi("Black", "§0", (byte) 15);
        }
       
        public void openInv(Player p) {
            inv = Bukkit.createInventory(null, 9, "§6§lTeams");
            p.openInventory(inv);
            p.updateInventory();
            updateInventory(p);
        }
       
        @SuppressWarnings("deprecation")
        @EventHandler
        public void onInvClick(InventoryClickEvent e) {
            if (e.getInventory() != null && e.getCurrentItem() != null && e.getInventory().getTitle().equals("§6§lTeams")) {
                if (e.getCurrentItem().getType() == Material.STAINED_GLASS) {
                    Player p = (Player) e.getWhoClicked();
                    if (e.getCurrentItem().getData().getData() == (byte) 14) {
                        addToTeam(p, red);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 11) {
                        addToTeam(p, blue);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 13) {
                        addToTeam(p, green);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 4) {
                        addToTeam(p, yellow);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 1) {
                        addToTeam(p, orange);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 0) {
                        addToTeam(p, white);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 15) {
                        addToTeam(p, black);
                    } else if (e.getCurrentItem().getData().getData() == (byte) 10) {
                        addToTeam(p, purple);
                    }
                    e.setCancelled(true);
                    openInv(p);
                }
            }
        }
       
        private void updateInventory(final Player p) {
          new BukkitRunnable() {
            @Override
            public void run() {
                Inventory inventory = ((HumanEntity) p).getOpenInventory().getTopInventory();
                if (!inventory.getName().equals(inv.getName())) {
                    cancel();
                    return;
                }
                if(plugin.team()) {
                    inv.setItem(0, red.getIcon(p));
                    inv.setItem(1, yellow.getIcon(p));
                    inv.setItem(2, green.getIcon(p));
                    inv.setItem(3, blue.getIcon(p));
                } else {
                    inv.setItem(0, black.getIcon(p));
                    inv.setItem(1, purple.getIcon(p));
                    inv.setItem(2, red.getIcon(p));
                    inv.setItem(3, orange.getIcon(p));
                    inv.setItem(4, yellow.getIcon(p));
                    inv.setItem(5, green.getIcon(p));
                    inv.setItem(6, blue.getIcon(p));
                    inv.setItem(7, white.getIcon(p));
                }
                p.updateInventory();
            }
          }.runTaskTimer(plugin, 1L, 20L);
        }
     
  12. I don't see many occurences where the problem can be, however, I see thing that may be it.

    Why are you reopening inventory when player clicks some block? Inventory won't close when somebody clicks some of it's contents. Also, by doing that, you will create new thread - running task, for nothing.
     
    • Winner Winner x 1
Thread Status:
Not open for further replies.

Share This Page