Solved [FAWE] Get Dispenser contents

Discussion in 'Spigot Plugin Development' started by TerZer, Sep 11, 2019.

  1. So I am trying to get dispensers contents from AsyncBlock. I find out that I can't cast block Dispenser to AsyncBlock state, because it trows errors. What I can do is read NBT. I managed to print out some kind of object:

    Code (Java):
    List<Tag> inventory = ((AsyncBlockState)block.getState()).getNbtData().getList("Items");
            for(Tag tag : inventory) {
                System.out.println(tag.getValue());
            }
    OUTPUT:
    Code (Java):
    {Slot=TAG_Byte(0), id=TAG_String(minecraft:coal), Count=TAG_Byte(64), Damage=TAG_Short(0)}
    But I need to covert it in something like ItemStack. How to do so?
     
  2. It looks like FAWE uses jnbt for the nbt access, so according to the JNBT source, it looks like you'd want to cast the Tag to a CompoundTag, then call getByte("Count") and getString("id") and optionally getShort("Damage") on it, then create an item stack from those. Make sure to remove the Minecraft: part from the id before you use Material.parseMaterial() or whatever.
     
    • Winner Winner x 1
    • Useful Useful x 1
  3. @AlanZ That worked, but how to set new size value for example?
     
  4. It looks like you would create a map of values to change, and use compoundTag.setValue(Map<String,Tag>) which returns a copy of the original compound tag with the new values set, then you'd simply write it back to the AsyncBlockState with setNbtData(CompoundTag)

    NBT source: https://github.com/IntellectualSite...main/java/com/sk89q/jnbt/CompoundTag.java#L65
     
    • Useful Useful x 1
  5. @AlanZ am I doing it wrong?

    Code (Java):
    List<Tag> inventory = ((AsyncBlockState)block.getState()).getNbtData().getList("Items");
            for(int i = 0;i < inventory.size();i++) {
                CompoundTag tag = (CompoundTag)inventory.get(i);
                int size = tag.getByte("Count");
                Material material = Material.matchMaterial(tag.getString("id").replace("minecraft:", ""));
                if(material != null && fuelMap.containsKey(material)) {
                    Map<String, Tag> map = tag.getValue();
                    ByteTag bt = new ByteTag((byte)(size-1));
                    map.replace("Count", bt);
                    CompoundTag item = new CompoundTag(map);
                    List<Tag> list = new ArrayList<Tag>(inventory);
                    list.set(i, item);
                    System.out.println(list.toString());
                    Map<String, Tag> dispenser = ((AsyncBlockState)block.getState()).getNbtData().getValue();
                    dispenser.replace("Items", new ListTag<Tag>(Tag.class, list));
                    CompoundTag newDispenser = new CompoundTag(dispenser);
                    System.out.println(((AsyncBlockState)block.getState()).getNbtData().getList("Items").toString());
                    ((AsyncBlockState)block.getState()).setNbtData(newDispenser);
                    System.out.println(((AsyncBlockState)block.getState()).getNbtData().getList("Items").toString());
                    ((AsyncBlockState)block.getState()).update(true);
                    block.queue.flush();
                    BreakerData.access$3(data, fuelMap.get(material));
                    break;
                }
            }
    I get this in console:

    Code (Java):
    [00:06:38 INFO]: [Slot, id, Count, Damage]
    [00:06:38 INFO]: [TAG_Compound: 4 entries
    [00:06:38 INFO]: {
    [00:06:38 INFO]:    TAG_Byte(0)
    [00:06:38 INFO]:    TAG_String(minecraft:coal)
    [00:06:38 INFO]:    TAG_Byte(63)
    [00:06:38 INFO]:    TAG_Short(0)
    [00:06:38 INFO]: }]
    [00:06:38 INFO]: [TAG_Compound: 4 entries
    [00:06:38 INFO]: {
    [00:06:38 INFO]:    TAG_Byte(0)
    [00:06:38 INFO]:    TAG_String(minecraft:coal)
    [00:06:38 INFO]:    TAG_Byte(64)
    [00:06:38 INFO]:    TAG_Short(0)
    [00:06:38 INFO]: }]
    [00:06:38 INFO]: [TAG_Compound: 4 entries
    [00:06:38 INFO]: {
    [00:06:38 INFO]:    TAG_Byte(0)
    [00:06:38 INFO]:    TAG_String(minecraft:coal)
    [00:06:38 INFO]:    TAG_Byte(64)
    [00:06:38 INFO]:    TAG_Short(0)
    [00:06:38 INFO]: }]
    Basically it resets to 64 again or I just doing something wrong :/
     
  6. I'm not sure. It looks right to me, so I would try debugging a little more, like printing what exactly is in your map before / after you set your Items list, what your items list contains, etc.
     
    • Agree Agree x 1
  7. Everything works with this code:

    Code (Java):
    //Get block state
            AsyncBlockState state = (AsyncBlockState)block.getState();
            //Get inventory items
            List<Tag> inventory = state.getNbtData().getList("Items");
            for(int i = 0;i < inventory.size();i++) {
                //get item
                CompoundTag tag = (CompoundTag)inventory.get(i);
                //get item size
                int size = tag.getByte("Count");
                //parse id to Material
                Material material = Material.matchMaterial(tag.getString("id").replace("minecraft:", ""));
                //check if Material parsed correctly and if fuel map contains this type of material
                if(material != null && fuelMap.containsKey(material)) {
                    //--- REPLACE SIZE ---
                    Map<String, Tag> map = tag.getValue();
                    ByteTag bt = new ByteTag((byte)(size-1));
                    map.replace("Count", bt);
                    CompoundTag item = new CompoundTag(map);
                    //------
                    //Create new inventory list
                    List<Tag> list = new ArrayList<Tag>(inventory);
                    //Replace old item with new one
                    list.set(i, item);
                    //--- REPLACE INVENTORY ---
                    Map<String, Tag> dispenser = state.getNbtData().getValue();
                    dispenser.replace("Items", new ListTag<Tag>(Tag.class, list));
                    CompoundTag newDispenser = new CompoundTag(dispenser);
                    //------
                    //update block
                    block.queue.setTile(block.getX(), block.getY(), block.getZ(), newDispenser);
                    //update fuel level
                    BreakerData.access$3(data, fuelMap.get(material));
                    break;
                }
            }