• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

Spigot Items beim Öffnen eines Inventars unsichtbar

HardSoul

Ehemaliges Teammitglied
Ehem. Teammitglied
Registriert
2 August 2012
Beiträge
759
Diamanten
251
Minecraft
HardS0ul
Moin zusammen,
ich habe mich nach einiger Zeit mal wieder an ein eigenes Bukkit-/Spigot-Plugin gewagt und habe aktuell einen Bug, den ich nicht behoben bekomme.
Im grundlegenden schreibe ich gerade an einem Subsystem, welches es mir ermöglichen soll, Inventory-Menüs mit Seitenumbrüchen zu erzeugen. Der Rest meines Codes läuft absolut rund, nur beim initialen Aufruf des Inventory sind alle Items unsichtbar und erscheinen erst, wenn man irgendwo in das Inventory klickt.

Hier mal mein Code:
Java:
/**
 * Mit dieser Methode kann ich das Inventory für einen
 * Speieler öffnen
 */
public void open(Player player) {
    if(player != null) {
        player.openInventory(_inventory);
        player.updateInventory();
        _holder = player;
    }
}

/**
 * Diese Methode legt die Items ins Inventory
 */
private void renderItems(int page) {
    page = Math.min(_maxPages, page);

    int endIndex = Math.min(_items.size(), _usabledSpace * page);
    int startIndex = _usabledSpace * page - _usabledSpace;
    int maxIndex = endIndex - startIndex;
    List<MenuItem> pageItems = _items.subList(startIndex, endIndex);

    for(int i = 0; i < maxIndex; i++) {

        MenuItem menuItem = pageItems.get(i);

        ItemStack item = new ItemStack(menuItem.getMaterial());
        ItemMeta meta = item.getItemMeta();

        if(menuItem.getName() != null)
            meta.setDisplayName(menuItem.getName());
        if(menuItem.getLore() != null)
            meta = formatLore(menuItem.getLore(), meta);

        item.setItemMeta(meta);
        _inventory.setItem(i, item);
    }
}

/**
 * Der Konstruktor der Manager-Klasse
 */
public PagedItemMenu(String name, int rows, List<MenuItem> items) {
    if(rows < 2)
        rows = 2;

    _rows = rows;
    _usabledSpace = _rows * 9 - 9;
    _inventory = Bukkit.createInventory(null, rows * 9, name);
    _items = items;
    _currentPage = 1;
    _maxPages = (int)Math.ceil((double)_items.size() / (double)_usabledSpace);
    _menus.put(_inventory, this);
    _receiver = new ArrayList<BiConsumer<HumanEntity, ItemStack>>();
}

Ich habe mal die drei wichtigen Methoden hier eingefügt und etwas kommentiert. Wie zu sehen ist hat das Inventory keinen Besitzer bis zu dem Zeitpunkt wo ich es aufrufe.

Nun zur Frage:
Woran kann es liegen, dass die Items beim ersten Aufruf des Menüs über die "open"-Methode unsichtbar sind? Was mache ich falsch?

Ich bin offen für Kritik und Verbesserungen, da ich nun seit knapp 3 Jahren nicht mehr für Bukkit programmiert habe :)
 

HardSoul

Ehemaliges Teammitglied
Ehem. Teammitglied
Registriert
2 August 2012
Beiträge
759
Diamanten
251
Minecraft
HardS0ul
Aber gerne doch:
Java:
@EventHandler(priority = EventPriority.NORMAL)
public void onInventoryClick(InventoryClickEvent event) {
    if(event.getClickedInventory() != null)
        if(PagedItemMenu.isPagedMenu(event.getClickedInventory()))
            PagedItemMenu.triggerButtonClick(event);
}

Hauptklasse:
public static void triggerButtonClick(InventoryClickEvent event) {
    PagedItemMenu menu = _menus.get(event.getClickedInventory());
    menu.onButtonClick(event);
}

public void onButtonClick(InventoryClickEvent event) {
    event.setCancelled(true);

    ItemStack clickedItem = event.getCurrentItem();

    if(clickedItem != null) {
        if(clickedItem.hasItemMeta()) {
            ItemMeta meta = clickedItem.getItemMeta();
            if(meta.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES) && clickedItem.getType() == Material.PLAYER_HEAD && meta.getDisplayName().equals("Next")) {
                nextPage();
            }else if(meta.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES) && clickedItem.getType() == Material.PLAYER_HEAD && meta.getDisplayName().equals("Prev"))                 {
                prevPage();
            }else {
                executeConsumers(event);
            }
        }else {
            executeConsumers(event);
        }
    }

}

Die ist nur dafür da, entweder registrierte Methoden auszuführen oder die Seiten neu zu rendern. Das Rendern der neuen Seiten funktioniert aber und weißt nicht den Bug auf. Nur beim aller ersten öffnen des Inventars
 

moinless

Schafhirte
Registriert
4 Oktober 2013
Beiträge
103
Diamanten
302
Öffnest du eventuell das Inventar, bevor du die Items reinlegst?

Falls nicht, wäre der komplette Code (auch der Teil, in welchem das Inventar zum Einsatz kommen soll) hilfreich, da sich in deinen Ausschnitten doch einige nicht bekannte Methoden finden.
 

HardSoul

Ehemaliges Teammitglied
Ehem. Teammitglied
Registriert
2 August 2012
Beiträge
759
Diamanten
251
Minecraft
HardS0ul
Ich öffne das Inventar erst, nachdem die Items drin sind (außer man wechselt die Seite, dann lasse ich es offen. Aber da kommt auch nicht dieser fehler). Ich liefere den Code leider erst in 1-2 Wochen, da ich im Urlaub bin :)
 

HardSoul

Ehemaliges Teammitglied
Ehem. Teammitglied
Registriert
2 August 2012
Beiträge
759
Diamanten
251
Minecraft
HardS0ul
Raus aus dem Urlaub und back to work!

Hier mein kompletter Code:
PagedItemMenu.java:
package me.HardS0ul.Portal.PagedInventory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiConsumer;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;

import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;

import me.HardS0ul.Portal.Core.Main;

public class PagedItemMenu{

    private static String ARROW_LEFT = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTQyZmRlOGI4MmU4YzFiOGMyMmIyMjY3OTk4M2ZlMzVjYjc2YTc5Nzc4NDI5YmRhZGFiYzM5N2ZkMTUwNjEifX19";
    private static String ARROW_RIGHT = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDA2MjYyYWYxZDVmNDE0YzU5NzA1NWMyMmUzOWNjZTE0OGU1ZWRiZWM0NTU1OWEyZDZiODhjOGQ2N2I5MmVhNiJ9fX0=";
    
    private int _rows;
    private Inventory _inventory;
    private List<MenuItem> _items;
    private int _currentPage;
    private static Map<Inventory, PagedItemMenu> _menus = new HashMap<Inventory, PagedItemMenu>();
    private Player _holder;
    private Integer _maxPages;
    private int _usabledSpace;
    private List<BiConsumer<HumanEntity, ItemStack>> _receiver;
    private boolean _destroyOnClose = false;
    
    public PagedItemMenu(String name, int rows, List<MenuItem> items, boolean destroyOnClose) {
        if(rows < 2)
            rows = 2;
        
        _rows = rows;
        _usabledSpace = _rows * 9 - 9;
        _inventory = Bukkit.createInventory(null, rows * 9, name);
        _items = items;
        _currentPage = 1;
        _maxPages = (int)Math.ceil((double)_items.size() / (double)_usabledSpace);
        _menus.put(_inventory, this);
        _receiver = new ArrayList<BiConsumer<HumanEntity, ItemStack>>();
        _destroyOnClose = destroyOnClose;
    }
    
    public void init() {
        clearInventory();
        renderItems(1);
    }
    
    public void registerConsumer(BiConsumer<HumanEntity, ItemStack> consumer) {
        _receiver.add(consumer);
    }
    
    public boolean unreigsterConsumer(BiConsumer<HumanEntity, ItemStack> consumer) {
        return _receiver.remove(consumer);
    }
    
    
    public void renderPage(int page) {
        if(page > 0 && _holder != null) {
            clearInventory();
            renderItems(page);
            _holder.updateInventory();
        }
    }
    
    public void open(Player player) {
        if(player != null) {
            player.openInventory(_inventory);
            player.updateInventory();
            _holder = player;
        }
    }
    
    public void onButtonClick(InventoryClickEvent event) {
        event.setCancelled(true);

        ItemStack clickedItem = event.getCurrentItem();

        if(clickedItem != null) {
            if(clickedItem.hasItemMeta()) {
                ItemMeta meta = clickedItem.getItemMeta();
                if(meta.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES) && clickedItem.getType() == Material.PLAYER_HEAD && meta.getDisplayName().equals("Next")) {
                    nextPage();
                }else if(meta.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES) && clickedItem.getType() == Material.PLAYER_HEAD && meta.getDisplayName().equals("Prev"))                 {
                    prevPage();
                }else {
                    executeConsumers(event);
                }
            }else {
                executeConsumers(event);
            }
        }
        
    }
    
    public void destroy() {
        _menus.remove(_inventory);
    }
    
    public boolean destroyOnClose() {
        return _destroyOnClose;
    }
    
    public void setItems(List<MenuItem> items) {
        _items = items;
        _maxPages = (int)Math.ceil(_items.size() / _usabledSpace);
    }
    
    public static boolean isPagedMenu(Inventory inventory) {
        return _menus.containsKey(inventory);
    }
    
    public static void triggerButtonClick(InventoryClickEvent event) {
        PagedItemMenu menu = _menus.get(event.getClickedInventory());
        menu.onButtonClick(event);
    }
    
    public static PagedItemMenu getPagedInventory(Inventory inventory) {
        return _menus.get(inventory);
    }
    
    private void renderBottom(Integer currentPage, boolean nextPage, boolean prevPage) {
        
        int middleSlot = _rows * 9 - 4 - 1;
        
        ItemStack pageItem = new ItemStack(Material.PAPER);
        ItemMeta pageItemMeta = pageItem.getItemMeta();
        pageItemMeta.setDisplayName(currentPage.toString() + " / " + _maxPages.toString());
        pageItem.setItemMeta(pageItemMeta);
        _inventory.setItem(middleSlot, pageItem);
        
        
        int nextSlot = _rows * 9 - 1;
        if(nextPage) {
            ItemStack nextItem = getArrowItem(ArrowDirection.Right);
            SkullMeta nextItemMeta = (SkullMeta)nextItem.getItemMeta();
            nextItemMeta.setDisplayName("Next");
            nextItemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
            nextItem.setItemMeta(nextItemMeta);
            _inventory.setItem(nextSlot, nextItem);
        }else {
            ItemStack blank = new ItemStack(Material.AIR);
            _inventory.setItem(nextSlot, blank);
        }
        
        int prevSlot = _rows * 9 - 8 - 1;
        if(prevPage) {
            ItemStack prevItem = getArrowItem(ArrowDirection.Left);
            SkullMeta prevItemMeta = (SkullMeta)prevItem.getItemMeta();
            prevItemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
            prevItemMeta.setDisplayName("Prev");
            prevItem.setItemMeta(prevItemMeta);
            _inventory.setItem(prevSlot, prevItem);
        }else {
            ItemStack blank = new ItemStack(Material.AIR);
            _inventory.setItem(prevSlot, blank);
        }
    }
    
    private void nextPage() {
        _currentPage = Math.min(_maxPages, _currentPage + 1);
        renderPage(_currentPage);
    }
    
    private void prevPage() {
        _currentPage = Math.max(1, _currentPage - 1);
        renderPage(_currentPage);
    }
    
    private void renderItems(int page) {
        page = Math.min(_maxPages, page);
        
        int endIndex = Math.min(_items.size(), _usabledSpace * page);
        int startIndex = _usabledSpace * page - _usabledSpace;
        
        int maxIndex = endIndex - startIndex;
        
        List<MenuItem> pageItems = _items.subList(startIndex, endIndex);
        
        for(int i = 0; i < maxIndex; i++) {
            MenuItem menuItem = pageItems.get(i);
            
            ItemStack item = new ItemStack(menuItem.getMaterial());
            ItemMeta meta = item.getItemMeta();
            
            if(menuItem.getName() != null)
                meta.setDisplayName(menuItem.getName());
            
            if(menuItem.getLore() != null)
                meta = formatLore(menuItem.getLore(), meta);
            
            item.setItemMeta(meta);
            
            _inventory.setItem(i, item);
        }
    }
    
    private void clearInventory() {
        _inventory.clear();
        
        renderBottom(_currentPage, _currentPage != _maxPages, _currentPage != 1);
    }
    
    private ItemMeta formatLore(String lore, ItemMeta meta) {
        for(int i = 0; i < lore.length() / 30; i++) {
            String subString = lore.substring(0, Math.min(lore.length(), i * 30));
            
            if(!subString.isEmpty())
                meta.getLore().add(subString);
        }
        
        return meta;
    }
    
    private ItemStack getArrowItem(ArrowDirection direction) {
        ItemStack item = new ItemStack(Material.PLAYER_HEAD);
        ItemMeta meta = item.getItemMeta();
        GameProfile profile = new GameProfile(UUID.randomUUID(), "");
        
        String skinTexture;
        
        switch(direction) {
        case Left:
            skinTexture = ARROW_LEFT;
            break;
        case Right:
            skinTexture = ARROW_RIGHT;
            break;
        default:
            skinTexture = "";
        }
        
        profile.getProperties().put("textures", new Property("textures", skinTexture));
        
        Field profileField = null;
        
        try {
            profileField = meta.getClass().getDeclaredField("profile");
            profileField.setAccessible(true);
            profileField.set(meta, profile);
        }catch(Exception ex) {
            Main.instance().getLog().error(ex.getMessage(), ExceptionUtils.getStackTrace(ex));
        }
        
        item.setItemMeta(meta);
        
        return item;
    }
    
    private void executeConsumers(InventoryClickEvent event) {
        for(BiConsumer<HumanEntity, ItemStack> consumer : _receiver) {
            if(consumer != null) {
                consumer.accept(event.getWhoClicked(), event.getCurrentItem());
            }
        }
    }
    
}
Ausführende Code:
    private static BiConsumer<CommandSender, String[]> showTicketConsumer = new BiConsumer<CommandSender, String[]>(){
        public void accept(CommandSender sender, String[] args) {
            if(sender instanceof Player) {
                
                List<MenuItem> items = new ArrayList<MenuItem>();
                
                for(Integer i = 0; i < 50; i++) {
                    MenuItem item = new MenuItem(i.toString(), "Test", Material.STONE);
                    items.add(item);
                }
                
                PagedItemMenu menu = new PagedItemMenu("Test", 3, items, true);
                menu.init();
                menu.open((Player)sender);
                
            }else {
                sendMessage(Main.instance().getTranslation().get("dontAcceptConsole"), sender);
            }
        }
    };
Hoffe jetzt sind die zusammenhänge klarer :)
 
Oben