Betonquest: Command for backpack of a player

Created on 18 Jul 2016  路  5Comments  路  Source: BetonQuest/BetonQuest

Hi Co0sh,

is there any way to look into the backpack of a player, similar to looking in the inventory of a player?
That would be really helpful for supporting players.

Feature Request

All 5 comments

It would just be another argument to the /backpack command, with its own separate permission, I would presume.

And async data loading in case of offline players. Modifying other's backpacks would also be possible.

That would be great.
And of course with separate permission :D

I coded a little workaround for solving that problem. It麓s simply your Backpack class modified but it works fine as long as the backpack owner is online. Feel free to use it!

public class BetonQuestBackpackHelper implements Listener {

    private final String playerID;
    private final Player player;
    private final BetonQuest instance;
    private final PlayerData playerData;
    private final String ownerID;
    private final Player owner;
    private Inventory inv;
    private Display display;
    private String lang;
    private BetonQuestBackpackHelper backpack;

    public enum DisplayType {
        DEFAULT, CANCEL, COMPASS
    }

    public BetonQuestBackpackHelper(String playerID, String ownerID, DisplayType type) {
        // fill required fields
        this.playerID = playerID;
        this.ownerID = ownerID;
        lang = BetonQuest.getInstance().getPlayerData(playerID).getLanguage();
        player = PlayerConverter.getPlayer(playerID);
        owner = PlayerConverter.getPlayer(ownerID);
        instance = BetonQuest.getInstance();
        playerData = instance.getPlayerData(ownerID);
        backpack = this;
        // create display
        switch (type) {
            case DEFAULT:
                display = new Page(0);
                break;
            case CANCEL:
                display = new Cancelers();
                break;
            case COMPASS:
                display = new Compass();
                break;
        }
    }

    /**
     * Creates new backpack GUI.
     *
     * @param playerID
     *            ID of the player
     */
    public BetonQuestBackpackHelper(String playerID, String openToId) {
        this(playerID, openToId, DisplayType.DEFAULT);
    }

    @EventHandler
    public void onClick(InventoryClickEvent event) {
        if (event.getWhoClicked().equals(player)) {
            // if the player clicked, then cancel this event
            event.setCancelled(true);
            // if the click was outside of the inventory, do nothing
            if (event.getRawSlot() < 0) {
                return;
            }

            // do nothing if owner is offline or you will get nullpointers
            if (!owner.isOnline())
                return;

            // pass the click to the Display
            display.click(event.getRawSlot(), event.getSlot(), event.getClick());
        }
    }

    @EventHandler
    public void onInventoryClosing(InventoryCloseEvent event) {
        if (event.getPlayer().equals(player)) {
            HandlerList.unregisterAll(this);
        }
    }

    /**
     * Represents a display that can be shown as the backpack.
     *
     * @author Jakub Sapalski
     */
    private abstract class Display {

        abstract void click(int slot, int playerSlot, ClickType click);

    }

    /**
     * Standard page with quest items.
     *
     * @author Jakub Sapalski
     */
    private class Page extends Display {

        private final int page;

        /**
         * Creates and displays to the player a given page.
         *
         * @param page
         *            number of the page to display, starting from 0
         */
        public Page(int page) {
            this.page = page;
            List<ItemStack> backpackItems = playerData.getBackpack();
            // amount of pages, considering that the first contains 44
            // items and all others 45
            int pages = (backpackItems.size() < 45 ? 1
                    : (backpackItems.size() + 1 % 45 == 0 ? (int) (backpackItems.size() + 1) / 45
                    : (int) Math.floor((backpackItems.size() + 1) / 45) + 1));
            // prepare the inventory
            inv = Bukkit.createInventory(null, 54, Config.getMessage(lang, "backpack_title")
                    + (pages == 1 ? "" : " (" + (page + 1) + "/" + pages + ")"));
            ItemStack[] content = new ItemStack[54];
            int i = 0;
            // insert the journal if the player doesn't have it in his inventory
            if (page == 0) {
                if (!Journal.hasJournal(playerID)) {
                    content[0] = playerData.getJournal().getAsItem();
                } else {
                    content[0] = null;
                }
                i++;
            } else {
            }
            // set all the items
            while (i < 45 && i + (page * 45) <= backpackItems.size()) {
                ItemStack item = backpackItems.get(i + (page * 45) - 1);
                content[i] = item;
                i++;
            }
            // if there are other pages, place the buttons
            if (page > 0) {
                ItemStack previous = null;
                try {
                    previous = new QuestItem(new ItemID(Config.getPackages().get("default"), "previous_button")).generate(1);
                } catch (ObjectNotFoundException e) {
                    previous = new ItemStack(Material.GLOWSTONE_DUST);
                } catch (InstructionParseException e) {
                    Debug.error("Could not load previous button: " + e.getMessage());
                    player.closeInventory();
                    return;
                }
                ItemMeta meta = previous.getItemMeta();
                meta.setDisplayName(Config.getMessage(lang, "previous").replaceAll("&", "搂"));
                previous.setItemMeta(meta);
                content[48] = previous;
            }
            if (backpackItems.size() > (page + 1) * 45 - 1) {
                ItemStack next;
                try {
                    next = new QuestItem(new ItemID(Config.getPackages().get("default"), "next_button")).generate(1);
                } catch (ObjectNotFoundException e) {
                    next = new ItemStack(Material.REDSTONE);
                } catch (InstructionParseException e) {
                    Debug.error("Could not load next button: " + e.getMessage());
                    player.closeInventory();
                    return;
                }
                ItemMeta meta = next.getItemMeta();
                meta.setDisplayName(Config.getMessage(lang, "next").replaceAll("&", "搂"));
                next.setItemMeta(meta);
                content[50] = next;
            }
            // set "cancel quest" button
            ItemStack cancel;
            try {
                cancel = new QuestItem(new ItemID(Config.getPackages().get("default"), "cancel_button")).generate(1);
            } catch (ObjectNotFoundException e) {
                cancel = new ItemStack(Material.BONE);
            } catch (InstructionParseException e) {
                Debug.error("Could not load cancel button: " + e.getMessage());
                player.closeInventory();
                return;
            }
            ItemMeta meta = cancel.getItemMeta();
            meta.setDisplayName(Config.getMessage(lang, "cancel").replaceAll("&", "搂"));
            cancel.setItemMeta(meta);
            content[45] = cancel;
            // set "compass targets" button
            ItemStack compassItem;
            try {
                compassItem = new QuestItem(new ItemID(Config.getPackages().get("default"), "compass_button")).generate(1);
            } catch (ObjectNotFoundException e) {
                compassItem = new ItemStack(Material.COMPASS);
            } catch (InstructionParseException e) {
                Debug.error("Could not load compass button: " + e.getMessage());
                player.closeInventory();
                return;
            }
            ItemMeta compassMeta = compassItem.getItemMeta();
            compassMeta.setDisplayName(Config.getMessage(lang, "compass").replace('&', '&'));
            compassItem.setItemMeta(compassMeta);
            content[46] = compassItem;
            // set the inventory and display it
            inv.setContents(content);
            player.openInventory(inv);
            Bukkit.getPluginManager().registerEvents(backpack, instance);
        }

        @Override
        void click(int slot, int playerSlot, ClickType click) {
            if (page == 0 && slot == 0) {
                // first page on first slot should contain the journal
                ItemStack journal = playerData.getJournal().getAsItem();
                player.getInventory().addItem(journal);
                //playerData.getJournal().addToInv(Integer.parseInt(Config.getString("config.default_journal_slot")));
                display = new Page(page);
            } else if (slot < 45) {
                // raw slot lower than 45 is a quest item
                // read the id of the item from clicked slot
                int id = page * 45 + slot - 1;
                ItemStack item = null;
                // get the item if it exists
                if (playerData.getBackpack().size() > id) {
                    item = playerData.getBackpack().get(id);
                }
                if (item != null) {
                    // if the item exists, put it in player's inventory
                    int backpackAmount = item.getAmount();
                    int getAmount = 0;
                    // left click is one item, right is the whole stack
                    switch (click) {
                        case LEFT:
                            getAmount = 1;
                            break;
                        case RIGHT:
                            getAmount = backpackAmount;
                            break;
                        default:
                            break;
                    }
                    if (getAmount != 0) {
                        // add desired amount of items to player's inventory
                        ItemStack newItem = item.clone();
                        newItem.setAmount(getAmount);
                        ItemStack leftItems = player.getInventory().addItem(newItem).get(0);
                        // remove from backpack only those items that were
                        // actually added to player's inventory
                        int leftAmount = 0;
                        if (leftItems != null) {
                            leftAmount = leftItems.getAmount();
                        }
                        item.setAmount(backpackAmount - getAmount + leftAmount);
                        if (backpackAmount - getAmount + leftAmount == 0) {
                            List<ItemStack> backpackItems = playerData.getBackpack();
                            backpackItems.remove(id);
                            playerData.setBackpack(backpackItems);
                        }
                    }
                    display = new Page(page);
                }
            } else if (slot > 53) {
                // slot above 53 is player's inventory, so handle item storing
                ItemStack item = player.getInventory().getItem(playerSlot);
                if (item != null) {
                    // if the item exists continue
                    if (Utils.isQuestItem(item)) {
                        // if it is a quest item, add it to the backpack
                        int amount = 0;
                        // left click is one item, right is all items
                        switch (click) {
                            case LEFT:
                                amount = 1;
                                break;
                            case RIGHT:
                                amount = item.getAmount();
                                break;
                            default:
                                break;
                        }
                        // add item to backpack and remove it from player's
                        // inventory
                        playerData.addItem(item.clone(), amount);
                        if (item.getAmount() - amount == 0) {
                            player.getInventory().setItem(playerSlot, null);
                        } else {
                            item.setAmount(item.getAmount() - amount);
                            player.getInventory().setItem(playerSlot, item);
                        }
                    } else if (Journal.isJournal(playerID, item)) {
                        // if it's a journal, remove it so it appears in
                        // backpack again
                        playerData.getJournal().removeFromInv();
                    }
                    display = new Page(page);
                }
            } else if (slot == 48 && page > 0) {
                // if it was a previous/next button turn the pages
                display = new Page(page - 1);
            } else if (slot == 50 && playerData.getBackpack().size() > (page + 1) * 45 - 1) {
                display = new Page(page + 1);
            } else if (slot == 45) {
                // slot 45 is a slot with quest cancelers
                display = new Cancelers();
            } else if (slot == 46) {
                // slot 46 is a slot with compass pointers
                display = new Compass();
            }
        }

    }

    /**
     * The page with quest cancelers.
     *
     * @author Jakub Sapalski
     */
    private class Cancelers extends Display {

        private HashMap<Integer, QuestCanceler> map = new HashMap<>();

        /**
         * Creates a page with quest cancelers and displays it to the player.
         */
        public Cancelers() {
            HashMap<String, QuestCanceler> cancelers = new HashMap<>();
            // get all quest cancelers that can be shown to the player
            for (String name : Config.getCancelers().keySet()) {
                QuestCanceler canceler = Config.getCancelers().get(name);
                if (canceler.show(playerID))
                    cancelers.put(name, canceler);
            }
            // generate the inventory view
            int size = cancelers.size();
            int numberOfRows = ((size - size % 9) / 9) + 1;
            if (numberOfRows > 6) {
                numberOfRows = 6;
                Debug.error("Player " + player.getName() + " has too many active quests, please"
                        + " don't allow for so many of them. It slows down your server!");
            }
            inv = Bukkit.createInventory(null, numberOfRows * 9, Config.getMessage(lang, "cancel_page"));
            ItemStack[] content = new ItemStack[numberOfRows * 9];
            int i = 0;
            for (String name : cancelers.keySet()) {
                QuestCanceler canceler = cancelers.get(name);
                content[i] = canceler.getItem(playerID);
                map.put(i, canceler);
                i++;
            }
            inv.setContents(content);
            player.openInventory(inv);
            Bukkit.getPluginManager().registerEvents(backpack, instance);
        }

        @Override
        void click(int slot, int playerSlot, ClickType click) {
            QuestCanceler cancel = map.get(slot);
            if (cancel == null) {
                return;
            }
            // cancel the chosen quests
            cancel.cancel(playerID);
            player.closeInventory();
        }
    }

    private class Compass extends Display {

        private HashMap<Integer, Location> locations = new HashMap<>();
        private HashMap<Integer, String> names = new HashMap<>();
        private HashMap<Integer, String> items = new HashMap<>();

        public Compass() {
            Integer counter = 0;
            // for every package
            for (ConfigPackage pack : Config.getPackages().values()) {
                String packName = pack.getName();
                // loop all compass locations
                ConfigurationSection s = pack.getMain().getConfig().getConfigurationSection("compass");
                if (s != null) {
                    for (String key : s.getKeys(false)) {
                        String location = pack.getString("main.compass." + key + ".location");
                        String itemName = pack.getString("main.compass." + key + ".item");
                        String name = null;
                        if (s.isConfigurationSection(key + ".name")) {
                            name = pack.getString("main.compass." + key + ".name." + lang);
                            if (name == null)
                                name = pack.getString("main.compass." + key + ".name." + Config.getLanguage());
                            if (name == null)
                                name = pack.getString("main.compass." + key + ".name.en");
                        } else {
                            name = pack.getString("main.compass." + key + ".name");
                        }
                        if (name == null) {
                            Debug.error("Name not defined in a compass pointer in " + packName + " package: " + key);
                            continue;
                        }
                        if (location == null) {
                            Debug.error(
                                    "Location not defined in a compass pointer in " + packName + " package: " + key);
                            continue;
                        }
                        // check if the player has special compass tag
                        if (!playerData.hasTag(packName + ".compass-" + key)) {
                            continue;
                        }
                        // if the tag is present, continue
                        String[] parts = location.split(";");
                        if (parts.length != 4) {
                            Debug.error("Could not parse location in a compass pointer in " + packName + " package: "
                                    + key);
                            continue;
                        }
                        World world = Bukkit.getWorld(parts[3]);
                        if (world == null) {
                            Debug.error(
                                    "World does not exist in a compass pointer in " + packName + " package: " + key);
                        }
                        int x, y, z;
                        try {
                            x = Integer.parseInt(parts[0]);
                            y = Integer.parseInt(parts[1]);
                            z = Integer.parseInt(parts[2]);
                        } catch (NumberFormatException e) {
                            Debug.error("Could not parse location coordinates in a compass pointer in " + packName
                                    + " package: " + key);
                            player.closeInventory();
                            return;
                        }
                        Location loc = new Location(world, x, y, z);
                        // put location with next number
                        locations.put(counter, loc);
                        names.put(counter, name);
                        if (itemName != null)
                            items.put(counter, packName + "." + itemName);
                        counter++;
                    }
                }
            }
            // solve number of needed rows
            int size = locations.size();
            int numberOfRows = ((size - size % 9) / 9) + 1;
            if (numberOfRows > 6) {
                numberOfRows = 6;
                Debug.error("Player " + player.getName() + " has too many compass pointers, please"
                        + " don't allow for so many of them. It slows down your server!");
                player.closeInventory();
                return;
            }
            inv = Bukkit.createInventory(null, numberOfRows * 9, Config.getMessage(lang, "compass_page"));
            ItemStack[] content = new ItemStack[numberOfRows * 9];
            int i = 0;
            for (Integer slot : locations.keySet()) {
                String name = names.get(slot);
                String item = items.get(slot);
                ItemStack compass = null;
                try {
                    compass = new QuestItem(new ItemID(Config.getPackages().get("default"), item)).generate(1);
                } catch (InstructionParseException e) {
                    Debug.error("Could not load compass button: " + e.getMessage());
                    player.closeInventory();
                    return;
                } catch (NullPointerException e) {
                    if (e.getMessage().equals("Item instruction is null")) {
                        player.closeInventory();
                        return;
                    } else {
                        e.printStackTrace();
                        return;
                    }
                } catch (ObjectNotFoundException e) {
                    compass = new ItemStack(Material.COMPASS);
                }
                ItemMeta meta = compass.getItemMeta();
                meta.setDisplayName(name.replace("_", " ").replace("&", "搂"));
                compass.setItemMeta(meta);
                content[i] = compass;
                i++;
            }
            inv.setContents(content);
            player.openInventory(inv);
            Bukkit.getPluginManager().registerEvents(backpack, instance);
        }

        @Override
        void click(int slot, int layerSlot, ClickType click) {
            Location loc = locations.get(slot);
            if (loc == null) {
                return;
            }
            // set the location of the compass
            player.setCompassTarget(loc);
            player.closeInventory();
        }
    }
}

...and the command:

    public boolean execute(CommandSender sender, String[] args, String label) {
        if (sender.hasPermission("bq.backpack")) {
            if (!(sender instanceof Player)){
                sender.sendMessage(Main.config.messages.prefix + Main.config.messages.notInConsole);
                return true;
            }

            Player owner = null;
            if (args.length > 1 && sender.hasPermission("bq.backpack.other")){
                owner = Bukkit.getServer().getPlayer(args[1]);
                if (owner == null || !owner.hasPlayedBefore() || !owner.isOnline()){
                    sender.sendMessage(Main.config.messages.prefix + Main.config.messages.playerNotFound);
                    return true;
                }
            }

            if (owner == null){
                new Backpack(PlayerConverter.getID((Player) sender));
            } else {
                new BetonQuestBackpackHelper(PlayerConverter.getID((Player) sender), PlayerConverter.getID(owner));
            }
            return true;
        } else
            sender.sendMessage(Main.config.messages.prefix + Main.config.messages.noPermission);

        return true;
    }

Merged into #1356

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HollishKid picture HollishKid  路  6Comments

survetman picture survetman  路  6Comments

digital-r picture digital-r  路  6Comments

SirMittens picture SirMittens  路  4Comments

NotJustPizza picture NotJustPizza  路  3Comments