• 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!

Erledigt Item aus Inventar abfragen

Mr_Redstone19

Kuhfänger
Osterei Experte
Mitglied seit
31 Januar 2018
Beiträge
91
Alter
43
Hallo,
Ja ich weiß.. Ich hab eine ähnliche Frage schon gestellt, aber irgendwie ging es noch nie so wirklich mit dem Item Abfragen..
Was soll passieren: Wenn man ein Item anklickt, soll überprüft werden, ob der Spieler das Item im Inventar hat. Wenn ja, sollen ihm 2 Items abgezogen werden, oder halt der ganze ItemStack entfernt werden, wenn nur noch 2 Items übrig sind.

Das hab ich dazu programmiert:
Code:
for(ItemStack itemStack : player.getInventory().getContents()){
    if(itemStack.getType() == Material.CLAY_BRICK){
        if(itemStack.getAmount() >= 2){
            player.sendMessage("Du hast mehr als 2");
        }else{
            player.sendMessage("Du hast weniger als 2");
        }
    }else{
        player.sendMessage("Du hast dieses Item nicht");
    }
}
Das ganze hab ich gemacht, um das Item überhaupt erstmal zu überprüfen.
Die Nachricht "Du hast mehr als 2"/"Du hast weniger als 2" gibt er mir tatsächlich aus, wenn das Item auf dem 1. Slot in der Schnellzugriffsleiste liegt.
Ansonsten kommt der Fehler:

Error:
[11:02:40] [Server thread/ERROR]: Could not pass event InventoryClickEvent to BedWars v1.0
org.bukkit.event.EventException
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310) ~[spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.PlayerConnection.a(PlayerConnection.java:1630) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.PacketPlayInWindowClick.a(SourceFile:31) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.PacketPlayInWindowClick.a(SourceFile:9) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.PlayerConnectionUtils$1.run(SourceFile:13) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_222]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_222]
    at net.minecraft.server.v1_8_R3.SystemUtils.a(SourceFile:44) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:715) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:374) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_222]
Caused by: java.lang.NullPointerException
    at me.madebyproxxy.spigot.bedwars.listeners.ingame.VillagerInteract.onShop2(VillagerInteract.java:119) ~[?:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_222]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_222]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_222]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_222]
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot.jar:git-Spigot-db6de12-18fbb24]
    ... 15 more
Hat jemand eine Idee, woran es liegt/kennt jemand eine andere Möglichkeit?

LG
 

LapisMC

Schafhirte
Osterei Experte
Mitglied seit
29 März 2014
Beiträge
114
Alter
21
Minecraft
LapisMC
Das ist aus der Stacktrace eigentlich klar ersichtlich:
Code:
Caused by: java.lang.NullPointerException
at me.madebyproxxy.spigot.bedwars.listeners.ingame.VillagerInteract.onShop2(VillagerInteract.java:119) ~[?:?]
In Zeile 119 der Datei VillagerInteract.java liegt also eine NullPointerException vor, es wird dort also auf eine Variable zugegriffen, die null ist. Anhand deiner Fehlerbeschreibung gehe ich mal davon aus, dass es diese Stelle ist:
if(itemStack.getType() == Material.CLAY_BRICK){
Da du über alle Slots des Spielerinventars iterierst (Rückgabewert von Inventory#getContents()), gehst du auch leere Slots durch; bei diesen ist die Variable itemStack aus der Schleife dann eben null. Bevor du also ItemStack#getType() aufrufst, musst du erst überprüfen, ob dieser nicht null ist.
 

Mr_Redstone19

Kuhfänger
Osterei Experte
Mitglied seit
31 Januar 2018
Beiträge
91
Alter
43
Hallo,
Danke für die schnelle Antwort.. Stimmt, ich hab vergessen, dass der ItemStack auch null sein kann, bzw. keiner vorhanden ist.
Dadurch funktioniert es nun auch endlich.

Vielen Dank
 

Mr_Redstone19

Kuhfänger
Osterei Experte
Mitglied seit
31 Januar 2018
Beiträge
91
Alter
43
Ah, hab doch noch eine Frage. Wie kann ich die Nachricht einbauen, dass kein Item vorhanden ist?
Wenn ich das als else an die Material-Abfrage hänge, kommt nichts und wenn ich es als else an die != null-Abfrage hänge, kommt es logischerweise 36 mal.
 

SirYwell

Vorarbeiter
Osterei Experte
Mitglied seit
30 Juni 2017
Beiträge
255
Alter
20
Minecraft
SirYwell
Auch wenn du so dein Problem lösen kannst, würde ich gerne eine Alternative vorschlagen:
Du kannst die Methode all(material) verwenden, um eine Map mit allen Slots zurückzubekommen, an denen ItemStacks des Typs material sind. Wenn die Map leer ist, hat der Spieler das Item nicht im Inventar.
Ansonsten kannst du über die Map iterieren, bis du (maximal) 2 Items entfernt hast. Das dürfte dir einiges erleichtern.
 

Mr_Redstone19

Kuhfänger
Osterei Experte
Mitglied seit
31 Januar 2018
Beiträge
91
Alter
43
Okay danke. Mal eine neue Methode, da jz aber die "alte" funktioniert und ich mich wenig mit Maps auskenne (Ja, sie sind wichtig, ich lerne sie auch gerade), würde ich lieber bei der Methode bleiben. Wo kann man die Nachricht bei der alten Methode denn einbauen?
Mit alte Methode mein ich die For-Schleife mit dem .getContents()
 

Luki_xx

Minecrafter
Mitglied seit
12 Juni 2019
Beiträge
29
Hallo. Also es gibt aus meiner Sicht zwei Möglichkeiten wie du das machen könntest.
Die erste:
Java:
    public static int getAmount(Inventory inv, ItemStack item)
    {
            int amount = 0;
            for(ItemStack contents : inv.getContents()) {
            if(contents == null || contents.getType() == Material.AIR) continue;
            if(contents.isSimilar(item))amount += contents.getAmount();
            }return amount;
    }
Damit fragst du mal die Anzahl ab, danach kannst du abfragen ob die Zahl größer gleich 2 ist, alle Items dieses Typs aus dem Inventar entfernen und anzahl-2 wieder hinzufügen.


Ist die einfachste aber nicht die beste Möglichkeit (grade wenig Zeit).
 

Mr_Redstone19

Kuhfänger
Osterei Experte
Mitglied seit
31 Januar 2018
Beiträge
91
Alter
43
Ja, das ist um die Items zu entfernen. Das hab ich auch jetzt bereits gemacht. Jetzt gehts erstmal darum, wo kann ich diese "Du hast dieses Item nicht" Nachricht einbauen?
 

SirYwell

Vorarbeiter
Osterei Experte
Mitglied seit
30 Juni 2017
Beiträge
255
Alter
20
Minecraft
SirYwell
Ich geh jetzt mal davon aus, dass die Items auch entfernt werden soll, wenn weniger als 2 Items vorhanden sind. Wenn das zutrifft, dann kannst du auch mit der first-Methode arbeiten:


Remove Items:
Material material = ...; // das gesuchte Item
int toRemve = 2; // Konstante, wie viel entfernt werden soll
int removed = 0;
int index = -1;
while ((index = inventory.first(material)) != -1 && removed < toRemove) {
    if (inventory.getItem(index).getAmount() + removed <= toRemove) {
        removed += inventory.getItem(index).getAmount();
        inventory.setItem(index, null);
    } else { // Stack ist groß genug, dass einfach die Menge reduziert werden kann
        removed = toRemove;
        inventory.getItem(index).setAmount(inventory.getItem(index).getAmount() - toRemove);
    }
}
Wenn der Spieler das Item nicht im Inventar hat, ist removed nach Ablauf des Codes immer noch 0, somit kannst du auch das einfach herausfinden.
 

Mr_Redstone19

Kuhfänger
Osterei Experte
Mitglied seit
31 Januar 2018
Beiträge
91
Alter
43
So. Soweit funktioniert alles, jedoch hab ich noch 2 kleine Probleme.
Ich hab das jetzt so geändert, dass man nur noch 1 Item braucht und keine 2 mehr.

Hier mein Code zum Abfragen der anzahl der Items:
Java:
public int getAmountBronze(Inventory inventory) {
        int amount = 0;
        
        ItemStack itemStack2 = new ItemStack(Material.CLAY_BRICK, 1);
        ItemMeta itemMeta = itemStack2.getItemMeta();
        itemMeta.setDisplayName("§cBronze");
        itemStack2.setItemMeta(itemMeta);
        
        for(ItemStack itemStack : inventory.getContents()) {
            if(itemStack != null) {
                if(itemStack.isSimilar(itemStack2)) {
                    amount += itemStack.getAmount();
                }
            }
        }
        return amount;
    }
und das hier ist der Code, der die Items dann removed:

Java:
int i = getAmountBronze(player.getInventory());
                if(i == 0) {
                    player.sendMessage(main.prefix + "§7Du hast §cnicht genügend §7Ressoucen für dieses Item!");
                    player.playSound(player.getLocation(), Sound.ANVIL_LAND, 1, 1);
                }else if(i >= 1) {
                    if(i == 1) {
                        player.getInventory().addItem(new ItemAPI(Material.SANDSTONE, (byte)0, 2).buildNorm());
                        player.getInventory().remove(itemStack2);
                    }else {
                        player.getInventory().addItem(new ItemAPI(Material.SANDSTONE, (byte)0, 2).buildNorm());
                        for(ItemStack itemStack : player.getInventory().getContents()) {
                            if(itemStack != null) {
                                if(itemStack.isSimilar(itemStack2)) {
                                    itemStack.setAmount(itemStack.getAmount() -1);
                                }
                            }
                        }
                    }
                }
Jedoch gibt es 2 Probleme.
1. Wenn ich 2 Slots habe, wo je nur ein Item drauf ist, removed er kein Item mehr und gibt mir aber immer mehr Sandstein.
2. Wenn ich 2 Stacks habe, dann removed er mir von jedem Stack ein Item und gibt mir aber nur 2 Sandstein. Er soll aber nur ein Item von einem der beiden Stacks entfernen.

ich steh gerade auf dem Schlauch und weiß gerade nicht weiter..
Kennt da jemand die Lösung?
 

Luki_xx

Minecrafter
Mitglied seit
12 Juni 2019
Beiträge
29
Soviel mal zu deinem zweiten Problem. Du musst gehst ja jeden Inventar Slot durch, nach dem du es gefunden hast musst du abbrechen.

Java:
for(ItemStack itemStack : player.getInventory().getContents()) {
    if(itemStack != null) {
        if(itemStack.isSimilar(itemStack2)) {
            itemStack.setAmount(itemStack.getAmount() -1);
            break;
         }
     }
}
Bezüglich Problem 1 habe ich noch nicht gefunden. Allerdings muss ich sagen das du die Namen ja auch net gerade günstig gewählt hast. Ich würde dir heute Abend dafür einen schöneren Code schicken, von mir aus auf deine Art.( mit Erklärung)
 

Mr_Redstone19

Kuhfänger
Osterei Experte
Mitglied seit
31 Januar 2018
Beiträge
91
Alter
43
Danke euch allen :D
Endlich geschafft. Problem 2 hab ich dank Luki_xx's Hilfe gelöst, Problem 1 allein, mit einer Abfrage, die nochmal den Amount eines einzelnen ItemStacks abfragt.
 

Twitter

Allgemein
Hilfe Benutzer
  • ❤️可愛いちゃん️❤️ ❤️可愛いちゃん️❤️:
    Das in der Minecraft Community so üblich
  • Kroseida Kroseida:
    eklig
  • Kroseida Kroseida:
    und auch wenn ich mir den src von forge angucke, bzw. das gesamte Konzept
  • Kroseida Kroseida:
    Keine Wrapper, nutzer wird direkt auf die API geworfen
  • Kroseida Kroseida:
    und jede Model-Datei muss immer wieder neu erstellt werden
  • maybeto maybeto:
    Das Leben ist nun mal kein Ponyhof.....
  • Kroseida Kroseida:
    trozdem kann man das ordentlich machen
  • Kroseida Kroseida:
    z.B steht in der Doku das 3D Model's für Entities gehen, dachte mir da "geil"
  • Kroseida Kroseida:
    suche im Forum, man muss den Renderer.. selber implementieren
  • iTz_Proph3t iTz_Proph3t:
    Sagte doch gestern im Stream, mach n besseres Forge :p
  • Kroseida Kroseida:
    Ich überlege es wirklich
  • Kroseida Kroseida:
    aber als solo-project ist das viel, vorallem wenn ich alles Dokumentieren muss
  • iTz_Proph3t iTz_Proph3t:
    Das wenn du machst und es
    auch läuft und danach auch besser ist, dann respekt :p
  • Kroseida Kroseida:
    näää, da wäre eigene Server Side Software interessanter
  • Kroseida Kroseida:
    oder eigenes Spiel,
  • maybeto maybeto:
    Forge ist eben schon uralt...
  • Kroseida Kroseida:
    Denoch, es ist ein Grundlegend falsches Konzept
  • Kroseida Kroseida:
    API Nutzer in Minecraft kommen zu direkt in Kontakt
  • ❤️可愛いちゃん️❤️ ❤️可愛いちゃん️❤️:
    Modding ist aber auch ne hässliche Sache. Das kann man fast nicht idiotensicher machen.
  • Kroseida Kroseida:
    meh
  • iTz_Proph3t iTz_Proph3t:
    Heute gibts Wochenend-Abend-Live-Support-Stream :p
    Bei Fragen und Problemen einfach im Chat melden ;)
    Vlt. ist Dean ja auch am Start
  • Matthias Matthias:
    Guten Morgen
  • Stern☆ Stern☆:
    Morgen
    Stern☆ Stern☆: Morgen
    Oben