Ways to remove an item from inventory

Discussion in 'Plugin Development' started by Darkwater, Aug 31, 2012.

Thread Status:
Not open for further replies.
  1. I'm developing a plugin similar to AuthMe, blocking every action until a player logs in.

    It's almost complete, but I'm not sure if I've blocked every action.
    I'm worried about the inventory.

    AuthMe stores the inventory and removes it when a player joins, then returns it when he logs in or leaves. This can cause some problems, like entire inventories being lost. I want to block all ways to alter the inventory. Is this possible, or is there a way to remove an item from the inv without the server approving it?
    Also, is it possible to prevent moving items around?
     
  2. Offline

    sternmin8or

    cancel all InventoryOpenEvents, and if you really want for an extra layer of security you can also cancel all InventoryClickEvents

    edit:(before the player has authenticated lol)
     
  3. Thanks, but is it possible to open the inventory with a hacked client, ignoring InventoryOpenEvent?
     
  4. Offline

    sternmin8or

    No, because in order to open an inventory the server needs to send the player the inventory. If the server decides that it "doesnt want" to send the player the inventory, there is nothing the player can do.
     
  5. Okay awesome, thanks.

    Code:
        @EventHandler(priority = EventPriority.LOWEST)
        public void inventoryOpen(InventoryOpenEvent event) {
            if(event.isCancelled()) {
                return;
            }
     
            Entity player = event.getPlayer();
            if(player == null) {
                return;
            }
     
            if(main.isAuthed(event.getPlayer().getName())) {
                return;
            }
         
            event.setCancelled(true);
        }
    I can still open the inventory when unauthed. Did I miss something?

    Edit: Sorry for the doublepost, I'm used to Facepunch' auto-merge.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 28, 2016
  6. Offline

    sternmin8or

    I dont think doubleposts are really that frowned upon here. Anyways that event looks correct to me. Try putting it on a higher priority if you have other plugins that could interfere. Also check that your isAuthed method doesnt always return true. Also, instead of if (event.isCancelled())...etc, you can use use:
    @EventHandler(priority = EventPriority.LOWEST,ignoreCancelled=true)

    edit: also you can use Player player = event.getPlayer() if you dont have any specific reason for using Entity
     
  7. Code:
        @EventHandler(priority = EventPriority.HIGHEST,ignoreCancelled=true)
        public void inventoryOpen(InventoryOpenEvent event) {
            Player player = event.getPlayer();
            if(player == null) {
                return;
            }
     
            if(main.isAuthed(event.getPlayer().getName())) {
                return;
            }
           
            event.setCancelled(true);
        }
     
        @EventHandler(priority = EventPriority.HIGHEST,ignoreCancelled=true)
        public void inventoryClick(InventoryClickEvent event) {
            Player player = event.getWhoClicked();
            if(player == null) {
                return;
            }
     
            if(main.isAuthed(event.getWhoClicked().getName())) {
                return;
            }
           
            event.setCancelled(true);
        }
    I can open my inv and even move things around. Any ideas?
    Btw, I don't really care about viewing the inv, it's the altering that needs to be blocked.
     
  8. Offline

    sternmin8or

    it looks like you either didnt register your events or your isAuthed method always returns true. Try this:
    Code:
    if(main.isAuthed(event.getWhoClicked().getName())) {
        System.out.println("test");
        return;
    }
    
    and tell me if test prints when a NON-authorized person tries to open their inventory
     
  9. When adding this, it suddenly worked. Probably forgot to save before building last time.

    Thanks, I've got everything then.
     
  10. Offline

    sternmin8or

    You can prevent a player from opening their own inventory. The one they open if the event is canceled is not theirs.
     
  11. How am I supposed to understand that? What do you mean, "it's not theirs"? How is seeing your inventory screen with everything in it not "your" inventory? Whether your own inventory is displayed or not is completely client-side, packets are only sent when you click and close it, but not when you open it.
     
  12. Offline

    sternmin8or

    I could be wrong, as I have never actually tried this myself, but in order for a player to open their inventory, their computer needs a copy of it. Even though the server cant deny the openinventory screen, it CAN deny the client access to their actual inventory file. I assume that cancelling the InventoryOpenEvent means that the server doesnt send the client their info. So what the client sees must be a cached version of it, that isnt actually theirs. Unless bukkit has a broken feature or the setCancelled() method does something else. I doubt bukkit has broken features that they haven't marked.
     
  13. Okay, I think your imagination what the Minecraft protocol and bukkit's role in it looks like is a bit off.
    Everything that is sent to the client or to the server is done through so-called packets. These simply contain data which the processing side does something with it. Nothing fancy so far.

    You are right about what is happening for any block inventory (chests, furnaces, etc.).
    Let's assume you right click a chest. The important packets being sent are:
    1. client --> server: Player Block Placement (0x0F) - the client informs the server that the block was right-clicked
    2. server --> client: Open Window (0x64) - the server tells the client to view the inventory window of size X labeled Y
    3. server --> client: Set Window Items (0x68) - the server sends the client information about all the items in the chest that should be displayed

    With bukkit, the InventoryOpenEvent is called before the 2nd packet is sent (to open the window). You cancel that one, and these packets won't happen. Fine.
    The problem with player inventories, like I was trying to explain in my other post, is that none of these packets happen upon opening of the inventory. You're right, of course the client needs to receive the contents of its inventory somehow, but it gets that when the player logs in (and when something changes in there, obviously).

    Don't ask me why, but as a matter of fact, the client always has information about the contents of the own player inventory (most likely because it made integration of the always visible hotbar easier). That makes it unnecessary for the client to send any packet to the server when the player opens his own inventory - because it already has all the data it needs.
    Thus, because there's no packet, neither the server nor bukkit will be able to do anything. You don't even get an event. Just nothing.

    If your desire is actually to hide the items from the player, stopping him from opening his inventory is not the way to go, but rather sending him information that there are actually no items.
    The easiest way to do it is to actually REALLY empty the inventory, but the OP said he doesn't want that ;)

    This is kind of getting off topic, though, I hope you got the gist of the problem.
     
  14. Offline

    sternmin8or

    I think your idea is wrong. The server has to tell the client what is in their inventory every time they open it, because it could have changed whenever. Why is it so "obvious" that the player inventory is updated on the client when they get a new item? That just means dozens of needless packets are sent every time the player picks something up. I'm pretty sure that the player only gets sent inventory contents packets when they open their inventory.

    I understand how packets work. I do not need that explanation for you. In fact, you are overlooking the fact that 0x68 is used for player inventories. This means that if the server doesnt send those packets: no inventory. The window might open, but the player doesnt get their inventory.

    Also... why would bukkit have a cancellable InventoryOpenEvent? the rest of this is debatable, but seriously, bukkit doesnt make mistakes this large. If a feature is deprecated or broken they mark it as so.
     
  15. It's not an idea, it's a fact. This site states that Open Window "is not sent anywhere for clients opening their own inventory".
    If that's not enough for you: Go on a server with high latency; right click a chest --> you get the usual delay between your right click and the inventory actually showing up. Then press your inventory key and see how your inventory is instantly there without any delay, with the contents. No packets involved here.

    If you need code reference:

    1. CraftBukkit: method when a player logs in - at the end, you see "entityplayer.syncInventory()" is being called, if you track what that does, it eventually leads to this method sending all items to the client - using Packet104WindowItems (0x68). Yes, it is used for player inventories, but not when they open their inventory.

    2. An item being picked up: You say it's unnecessary packets? It's one 0x67 packet (setting the single changed slot) per pickup. As a matter of fact, it needs to be sent anyways for items in the hotbar (because that's visible even with a closed inventory), and the server simply doesn't differentiate between the hotbar and the rest of the inventory.
    This method is called when an item is picked up by the player. It calls "this.activeContainer.b()", which checks for changed slots and then calls this method of the player, which sends the packet to update the slot.

    InventoryOpenEvent is working properly for any inventory except for player ones. Cancelling it for chests, furnaces, ... works as it should.
    However, as I am trying to point out, opening your inventory is simply nothing that affects the server at all. It sent you the items beforehand - you need them for the hotbar after all - and it doesn't care whether the client decides to render the window displaying them or not.

    There is no InventoryOpenEvent triggered for player inventories, it's not bukkit's fault, it's the way the game works. It doesn't change anything server-side whether it's visible or not, so there's no notification when that changes. I don't see what makes it broken, then.
    (well, the close window packet is sent as stated here, supposedly to make the item that you have on your cursor drop the ground when closing)
     
  16. Offline

    sternmin8or

    Bone008
    There is no InventoryOpenEvent triggered for player inventories
    ...thats all you needed to say. I thought you were saying that it was triggered, it just didnt work. lol my bad.... sorry about that
     
  17. Lol okay :D
    I said that in my other post (the very first one I linked), though. I could have stressed that a bit more, though, yeah :D
    I thought that saying that "no packets are sent" makes it clear that there also isn't an event. Well, whatever, yet another thread cluttered with off topic ;D
     
Thread Status:
Not open for further replies.

Share This Page