SamJakob / SpiGUI

A comprehensive GUI API for Spigot with pages support.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Refresh inventory.

iFeliN3x0 opened this issue · comments

Good night, I have a question. Which is the easiest way to refresh the inventory every X seconds? (Items and its lore)
I only want to refresh the contents because it could be that a new item be created or removed with a command that my plugin has.

Greetings.

I have something like this:

                AtomicReference<BukkitTask> borderRunnable = new AtomicReference<>();
		
		borderRunnable.set(new BukkitRunnable(){

			@Override
			public void run() {
				myAwesomeMenu.refreshInventory(p);
				Bukkit.broadcastMessage("a");
			}

		}.runTaskTimer(plugin, 0L, 20L));
		
		myAwesomeMenu.setOnClose(inventory -> {
            if (borderRunnable.get() != null) borderRunnable.get().cancel();
        });
		
		p.openInventory(myAwesomeMenu.getInventory());

The scheduler is executing because it broadcasts the letter "a" but the lore of the items is not updating with the refreshInventory.

Can you share the code you're using to update the lore on the item?

Just some general tips:

  • When you change the lore, make sure you're actually updating the item reference stored in the menu. So try:
    SGButton button = myMenu.getButton(/* slot number */);
    button.getIcon().setLore(/* lore */);
  • If you're only changing the runnable in the same closure as it's defined (i.e. you're not changing the value in a lambda), you don't need the AtomicReference - you can just use a straight up BukkitTask. I used that in the example to pass it into my button listeners and the page change listener.

I thought that "myAwesomeMenu.refreshInventory(p);" refreshed the items and its lore.

I don't know how that could work, because as i said it is possible that the items of the inventory be deleted or new ones be added.

Yeah it should do as everything's passed by reference but I'm not sure how you're updating the inventory. Can you share the snippet of your code where you update the lore?

This is my method, it is supposed that the lore part "Time" updates (00:01, 00:02, etc), but it does not change.
I use myAwesomeMenu.refreshInventory(p); to try to update the inventory including the lore, but it does not.

        @SuppressWarnings("deprecation")
	public static void matchesGUI(Player p) {

		ArrayList<Duel1v1> duels = plugin.getDuels();
		
		SGMenu myAwesomeMenu = Main.spiGUI.create("&bMatches", 1);

		for(Duel1v1 duel : duels) {
			List<String> lore = new ArrayList<>();
			lore.add(ChatColor.translateAlternateColorCodes('&', "&a"+duel.getPlayer1().getPlayer().getName()+" &evs &a"+duel.getPlayer2().getPlayer().getName()));
			lore.add(ChatColor.translateAlternateColorCodes('&', "&fTime: &b"+duel.getMatchTime()));
			lore.add(" ");
			lore.add(ChatColor.translateAlternateColorCodes('&', "&fKit: &b"+duel.getKit().getName()+"."));
			lore.add(ChatColor.translateAlternateColorCodes('&', "&fArena: &b"+duel.getArena().getName()+" &7("+duel.getArena().getKit().getName()+")."));
			
			SGButton myAwesomeButton = new SGButton(
			  new ItemBuilder(new ItemStack(duel.getKit().getId(), 1, (short)duel.getKit().getDatavalue())).name("&d"+duel.getType()+" 1v1").lore(lore).build()
			).withListener((InventoryClickEvent event) -> {
				
			});
			
			myAwesomeMenu.addButton(myAwesomeButton);
		}
		
		AtomicReference<BukkitTask> borderRunnable = new AtomicReference<>();
		
		borderRunnable.set(new BukkitRunnable(){

			@Override
			public void run() {
				myAwesomeMenu.refreshInventory(p);
				Bukkit.broadcastMessage("this");
			}

		}.runTaskTimer(plugin, 0L, 20L));
		
		myAwesomeMenu.setOnClose(inventory -> {
                	if (borderRunnable.get() != null) borderRunnable.get().cancel();
		});
		
		p.openInventory(myAwesomeMenu.getInventory());
	}

Ah - you (initially) create all the buttons and add the lores to them, but then you don't ever update them again.
You're calling refreshInventory every second however you haven't actually updated the lores on any of the items. You'll need to add the code to generate the buttons with their lores to the lambda or alternatively loop over them and update the lores.

Can you give me some code example?

Or make that refreshInventory refreshes the contents and its lore.

Can you add a setTitle call before you refresh the inventory? Doing that updates the inventory a different way and I would be interested to see if that method would refresh the contents and the lore.

Hi, I tried adding a setName as you said but it didn't work (the name of the inventory is changed, but the contents ands its lore are not refreshed. Besides, the scheduler is stopped if I set a different name to the inventory).

On the other hand, I could do a way to refresh the inventory. Simply before refresh the inventory, I used clearAllButStickiedSlots to remove all items and my method to put them again, so now my issue is.... Solved?

Nevertheless, it would be great if in future updates you make that refreshInventory refreshes the contents and its lore instead of.

The SpiGUITest.java file has now been updated to show how to do this.

As you mentioned, re-adding items to the slots is the correct answer.

This is because the code to create the GUI is not re-run when the GUI is refreshed, and without manually having references to each button somehow (i.e., creating a new variable for each SGButton and then adding each into the menu which would be very cumbersome) and updating those, refreshInventory will not work. Changing the inventory name does cause the name to update as the new name is passed into the inventory, but I misunderstood what the issue was here - doing that, of course, would not cause the information to update.

If you wanted a solution to refreshInventory that refreshed the inventory contents and lore in the same way they are generated when the inventory was first opened, I would need to modify the SGMenu API so that all the code to generate buttons for the GUI are placed into a function that can then be re-run when the inventory refreshes.

I hope that somewhat explains the issue and a potential fix -- this is something that warrants its own new feature though, rather than a quick tweak to the existing code. In other words, this is a feature, not a bug 😉.