GUI | Prevent players from editing it

Discussion in 'Spigot Plugin Development' started by Qruet, Jun 8, 2017.

  1. I'm having problem having players potentially editing the gui that opens up with a certain command. Although you can't necessarily permanently remove any items in the gui you can still place items into the gui if you just click and drop the item into the gui (fixed the issue with shift+click the item into the gui) however players can also (shift + click) the two items by default in the gui into their own inventory. Although when they reopen the gui the items they stole disappear the can always drop the item that they stole from the gui onto the ground and then pick it up and then reopen the gui without those items being removed. I'm not sure if that made any sense but my code is provided below, I'm sure it's simply a little basic flaw in the code, however I've had some trouble finding exactly where I'm doing it wrong.

    Code (Text):
    @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
        Player player = (Player) event.getWhoClicked();
        ItemStack clicked = event.getCurrentItem();
        Inventory inventory = event.getInventory();
        if (inventory.getName().equals(plugin.myInventory.getName())) {
                if (clicked.getType() == Material.SNOW_BALL) {
                    if(event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP ||
                            event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP)
                    {
                        event.setCancelled(true);
                    }
                        if(plugin.withdraw(player, 100) == true){
                            Cloud.createPet(player);
                            player.sendMessage(ChatColor.GREEN + "Successfully purchased pixie pet, Cloudy!");
                    }
                        else{
                            player.sendMessage(ChatColor.RED + "You can't afford that!");
                        }
                        event.setCancelled(true);
                        player.closeInventory();
                }
                else if(clicked.getType() == Material.COAL)
                {
                    if(event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP ||
                            event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP)
                    {
                        event.setCancelled(true);
                    }
                   
                    if(plugin.withdraw(player, 100) == true){
                        Smoke.createPet(player);
                        player.sendMessage(ChatColor.GREEN + "Successfully purchased pixie pet, Smokey!");
                    }
                    else{
                        player.sendMessage(ChatColor.RED + "You can't afford that!");
                    }
                    event.setCancelled(true);
                    player.closeInventory();
            }
            }
        }
       
     
  2. Try updating inventories. Also try Player#getOpenInventory and check to see if it's the inventory you're viewing, if it is (in PlayerDropItemEvent) then cancel


    Sent from my iPhone using Tapatalk
     
  3. I can give that a try but I'm pretty sure that there's a way to prevent them from stealing any items from within the gui into their inventory from the start.
    ~Geekles
     
  4. Well I have a problem, it seems that the item sort of acts like a ghost item (when checking to see if the player's inventory contains a specific item it doesn't turn up as true however the item is visible in the inventory.) However when the player drops the item then picks it up it then is recognized as an actual item and since I'm checking their inventory onInventoryClose it will only remove when the inventory closes. I don't recall in the past having such a complex setup just to see if they stole an item. I hoping someone can explain what I'm doing here before I have to go in and add a bunch of event listeners (pickup item, drop item etc.) to the GUI class.

    Code (Text):
        @EventHandler
        public void onInventoryEvent(InventoryCloseEvent event) {
            Bukkit.broadcastMessage(ChatColor.GREEN + "Called!");
            Player player = (Player) event.getPlayer();
            Inventory inventory = player.getInventory();
         
            ItemStack coal = new ItemStack(Material.COAL);
            ItemStack snow_ball = new ItemStack(Material.SNOW_BALL);
         
            ItemMeta coal_meta = coal.getItemMeta();
            ItemMeta snow_ball_meta = snow_ball.getItemMeta();
         
            coal_meta.setDisplayName("Smokey");
            snow_ball_meta.setDisplayName("Cloudy");
         
            ArrayList<String> coal_Lore = new ArrayList<String>();
            ArrayList<String> snow_ball_Lore = new ArrayList<String>();
         
            coal_Lore.add("- $100");
            snow_ball_Lore.add("- $100");
         
            coal_meta.setLore(coal_Lore);
            snow_ball_meta.setLore(snow_ball_Lore);
         
            coal.setItemMeta(coal_meta);
            snow_ball.setItemMeta(snow_ball_meta);
         
            if(inventory.contains(snow_ball)){
                inventory.remove(snow_ball);
                Bukkit.broadcastMessage("Removed Snow Ball!");
            }
            else if(inventory.contains(coal)){
                inventory.remove(coal);
                Bukkit.broadcastMessage("Removed Coal!");
            }
         
        }
       

    The part where in chat is shows "qqqq" is simply me showing that I'm pressing 'q' to attempt to drop the item in my hand.


    ~Geekles
     
    #4 Qruet, Jun 9, 2017
    Last edited: Jun 9, 2017
  5. Instead of checking if they are taking the item check if they are trying to interact with the inventory and cancel the event.
     
  6. That event is InventoryClickEvent from what I know.
     
  7. Firestar311

    Supporter

    Correct

    You need to listing for the click event, do a few null checks and checks to see if the inventory is the one you want and if they clicked on a item with in it, then cancel the event.
     
    • Like Like x 1
  8. I did that as well :p
    Here's code from my other listener, I probably should've posted it as well.
    Code (Text):
        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
        Player player = (Player) event.getWhoClicked(); // The player that clicked the item
        ItemStack clicked = event.getCurrentItem(); // The item that was clicked
        Inventory inventory = event.getInventory(); // The inventory that was clicked in
        if (inventory.getName().equals(plugin.myInventory.getName())) {
                if (clicked.getType() == Material.SNOW_BALL) {
                    event.setCancelled(true);
                    player.closeInventory();

                        if(plugin.withdraw(player, 100) == true){
                            Cloud.createPet(player);
                            player.sendMessage(ChatColor.GREEN + "Successfully purchased pixie pet, Cloudy!");
                    }
                        else{
                            player.sendMessage(ChatColor.RED + "You can't afford that!");
                        }
                }
                else if(clicked.getType() == Material.COAL)
                {
                    if(event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP ||
                            event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD || event.getAction() == InventoryAction.HOTBAR_SWAP)
                    {
                        event.setCancelled(true);
                    }
               
                    if(plugin.withdraw(player, 100) == true){
                        Smoke.createPet(player);
                        player.sendMessage(ChatColor.GREEN + "Successfully purchased pixie pet, Smokey!");
                    }
                    else{
                        player.sendMessage(ChatColor.RED + "You can't afford that!");
                    }
                    player.closeInventory();
            }
            }
        }
    I tried to test two different things for both snow ball and coal see which one may have worked. None seemed to really do anything :/

    Also I'd like to bring up though, if I collect the item from the gui and then without dropping the item run the /pixie shop command again to pull up the gui, the item in my inventory that I stole is then removed as well.
     
    • Like Like x 1
  9. Did you debug the event? Is it firing(registered?!) to where is the event going?
     
  10. Firestar311

    Supporter

    I agree with NormalBart, the code looks fine and should be working. Add debug statements to see where it is stopping, also make sure the event is registered.
     
  11. The video shows it all, when I click the item it shows that I don't have any money therefore doesn't spawn the entity. However to simply answer your question everything functions. The listener is fired when I click on either the coal or snow ball, no errors in console. If I were to give myself $100 and then clicked on either one of those items, it'd spawn the entity as well.
    ~Geekles
     
  12. *Bump* Still need help with this.
     
  13. Have you tried using getClickedInventory() instead? Or checking if the inventory you have set to inventory is the correct one?
     
  14. Everything is fired correctly in the event. The correct inventory, the correct item clicked is all checked correctly. When I click the snowball in the inventory it generates the snowball pet. If I click the coal it creates a coal pet etc. So it checks everything correctly however the event.setCancelled(true) doesn't appear to do anything.
    ~Geekles
     
  15. The best way to handle this issue is to cancel the ClickEvent, but in order
    to do so without interfering with other GUIs is to check the title of your custom GUI
    like so:

    Code (Text):

    if(player.getOpenInventory().getTopInventory().getTitle().equalsIgnorecase("GUI Title"))
    {
        //Cancel Click Event
        //Respond To Click Event
    }