Solved How can I check if a player has enough items?

Discussion in 'Plugin Development' started by ErzLegendZero, Dec 30, 2018.

  1. Offline

    ErzLegendZero

    Hey there I have a problem I want to make a kind of shop-/tradingsystem plugin.
    so I want that players can trade Items

    For example:
    p1 created a shop and want to tread one Diamond_Sword and 2 Iron Ingots against
    10 Cobblestone and 3 Diamonds

    now p2 wands to buy the Sword and the Ingots.

    I Already have 2 list with items:
    1. List<ItemStack> shopItems ... (10 Cobblestone, 3 Diamonds)
    2. List<ItemStack> invItems ... (inv of the p2: 30 Cobblestone, 10 Diamons, 3 Iron ingots...)

    How can I check if p2 has all and enougth items (10 Cobblestone, 3 Diamonds) and when he has to many how can I check how much items he has left?

    I apologize for spelling mistakes and thank you in advance in advance!
     
  2. Offline

    knokko

    @ErzLegendZero

    If I remember well, you can get all itemstacks player1 has by calling p1.getInventory().getContents()
    Then you can create a (Hash)Map that maps Material's to Integer's. Then, for every Material that is relevant for the trade, you go over all itemstacks the player has and put the total amount in the map.

    Then you have a map that has the total amount of every Material the player has and you can use that to determine how many items the player has (and thus if he has enough and what he should have left after the trade).
     
  3. Offline

    ErzLegendZero

    Hey I never worked with hashmaps befor but I think this is like you said but why it dose not work?


    My Code: (open)
    Code:
    Inventory inv = player.getInventory();
    List<ItemStack> shopItems = shops.getShop(target.getName());
    List<ItemStack> shopItemsClone = shopItems;
    HashMap<Material, Integer>invMap = new HashMap<>();
    for (int i = 0; i < inv.getSize(); i++) {
        ItemStack item = inv.getItem(i);
        if (item != null && !item.getType().equals(Material.AIR)) {
            invMap.put(item.getType(), item.getAmount());
        }
    }
    
    Bukkit.broadcastMessage("My Inv:" + invMap.toString());
    
    if(!invMap.isEmpty()) {
        for (ItemStack i : shopItems) {    // l 65
            ItemStack item = i.clone();
            if(invMap.containsKey(item.getType())) {
                int difference = item.getAmount() - invMap.get(item.getType());
                if (difference <= 0) {
                    if(shopItemsClone.contains(item)) {
                        shopItemsClone.remove(item);
                    }
                } else {
                    shopItemsClone.remove(item);
                    item.setAmount(difference);
                    shopItemsClone.add(item);
                }
            }
        }
        shopItems = shopItemsClone;
        Bukkit.broadcastMessage("ShopInv: " + shopItems.toString());
    }


    The Error: (open)
    Code:
    [16:02:24] [Server thread/INFO]: [0;37;22m[[0;35;1mCityBuild[0;37;22m]: [0;35;1mMr_Nice1107[0;32;1m Cleared the chat[m
    [16:02:27] [Server thread/INFO]: {IRON_ORE=64}[m
    [16:02:27] [Server thread/ERROR]: Could not pass event PlayerInteractEntityEvent to TotalBrutal_Quest v0.2
    org.bukkit.event.EventException
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:1315) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.PacketPlayInUseEntity.a(SourceFile:52) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.PacketPlayInUseEntity.a(SourceFile:11) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_191]
        at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_191]
        at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:715) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_191]
    Caused by: java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(Unknown Source) ~[?:1.8.0_191]
        at java.util.ArrayList$Itr.next(Unknown Source) ~[?:1.8.0_191]
        at de.totalbrutal.erzlegendzero.listener.listenerQuest.onClick(listenerQuest.java:56) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_191]
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_191]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_191]
        at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_191]
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot-1.8.8.jar:git-Spigot-db6de12-18fbb24]
        ... 15 more


    If I hold nothing in my inv It workes of corse but it dose nothing
    If I hold just items in inv (a item that is not in the shoplist)
    it sends me:
    My inv: {GRAVLE=1}
    ShopInv:[ItemStack{COAL x 32},ItemStack{IRON_ORE x 16}]
    But if I have Coal or IronOre in inv it sends me:
    Mr inv: {COAL=1}
    and then the Error "Could not passevent PlayerInteractEntityEvent..."
    and it said the error is at
    de.totalbrutal.erzlegendzero.listener.listenerQuest.onClick(listenerQuest.java:56) ~[?:?]
    thats at line 56:
    Code:
    for (ItemStack i : questItems) {
    so where is the problem? Why this yust down't work if I have an item from the shoplist in inv?

    Ok I tryed a bit and that confused me xD
    When I have 1-15 iron_ore in inv it works
    But if I have more the same error at line 56
    And if I have 1-64 coal : same error at l 56
     
    Last edited: Dec 31, 2018
  4. Offline

    Elytes

    Player player;
    if (player.getInventory().containsAtLeast(/* ItemStack */, /* How much he needs */))
    {
    // do something
    }
     
  5. Offline

    knokko

    @ErzLegendZero

    The error occurs because the line
    Code:
    List<ItemStack> shopItemsClone = shopItems;
    should be
    Code:
    List<ItemStack> shopItemsClone = shopItems.clone();
    Unlike ints, using shopItemsClone = shopItems doesn't clone shopItems because shopItems is no boolean, byte, char, short, int, float, double or long. For any variable that is not one of the types I just listed, you need to clone them explicitly.

    And another mistake I found:
    Code:
    if (item != null && !item.getType().equals(Material.AIR)) {
            invMap.put(item.getType(), item.getAmount());
        }
    . Here, you are replacing the previous amount of the Material instead of summing it with the size of item. You should instead use
    Code:
    if (item != null && !item.getType().equals(Material.AIR)) {
        Integer old = invMap.get(item.getType());
        if (old != null){
            invMap.put(item.getType(), old + item.getAmount());
        } else {
            invMap.put(item.getType(), item.getAmount());
        }
    }
    You need that old != null part to avoid a NullPointerException if there is no old value. That is one of the annoying part of using Integer over int, but you don't have much choise here.
     
  6. Offline

    ErzLegendZero

    Thx that worked for me!


    Somehow there is no shopItems.clone(); but already solved the problem!

    Thank you all for help!
     

Share This Page