Jump to content

[1.15.2] How would I beable to add/remove items from an Item without the GUI needing to be opened?


NindyBun

Recommended Posts

package com.nindybun.miningtool.test_item;

import com.nindybun.miningtool.MiningTool;
import net.minecraft.client.renderer.texture.ITickable;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ItemTestItem extends Item {
    private static final int MAX_ITEM_STACK = 1;

    public ItemTestItem(Properties properties) {
        super(properties);
    }

    @Nonnull
    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {

        ItemStack stack = playerIn.getHeldItem(handIn);
        if (!worldIn.isRemote){
            if (playerIn.isSneaking()){
                //Add a piece of coal to this items inventory
            }else{
                INamedContainerProvider containerProviderTestItem = new ContainerProviderTestItem(this, stack);
                final int NUMBER_OF_SLOTS = 1;
                NetworkHooks.openGui((ServerPlayerEntity) playerIn, containerProviderTestItem, (packetBuffer)->{packetBuffer.writeInt(NUMBER_OF_SLOTS); });
            }


        }


        return ActionResult.resultSuccess(stack);
    }



    private static class ContainerProviderTestItem implements INamedContainerProvider{

        public ContainerProviderTestItem(ItemTestItem itemTestItem, ItemStack itemStackTestItem){
            this.itemStackTestItem = itemStackTestItem;
            this.itemTestItem = itemTestItem;
        }

        @Override
        public ITextComponent getDisplayName() {
            return itemStackTestItem.getDisplayName();
        }

        @Nullable
        @Override
        public ContainerTestItem createMenu(int windowID_, PlayerInventory playerInventory, PlayerEntity playerEntity) {
            ContainerTestItem newContainerServerSide =
                    ContainerTestItem.createContainerServerSide(windowID_, playerInventory,
                            itemTestItem.getItemStackHandlerTestItem(itemStackTestItem),
                            itemStackTestItem);

            return newContainerServerSide;
        }

        private ItemTestItem itemTestItem;
        private ItemStack itemStackTestItem;
    }

    @Nonnull
    @Override
    public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT oldCapNbt) {

        return new CapabilityProviderTestItem();
    }

    private static ItemStackHandlerTestItem getItemStackHandlerTestItem(ItemStack itemStack) {
        IItemHandler testItem = itemStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
        if (testItem == null || !(testItem instanceof ItemStackHandlerTestItem)) {
            LOGGER.error("ItemTestItem did not have the expected ITEM_HANDLER_CAPABILITY");
            return new ItemStackHandlerTestItem(1);
        }
        return (ItemStackHandlerTestItem) testItem;
    }

    private final String BASE_NBT_TAG = "base";
    private final String CAPABILITY_NBT_TAG = "cap";


    @Nullable
    @Override
    public CompoundNBT getShareTag(ItemStack stack) {
        CompoundNBT baseTag = stack.getTag();
        ItemStackHandlerTestItem itemStackHandlerTestItem = getItemStackHandlerTestItem(stack);
        CompoundNBT capabilityTag = itemStackHandlerTestItem.serializeNBT();
        CompoundNBT combinedTag = new CompoundNBT();
        if (baseTag != null) {
            combinedTag.put(BASE_NBT_TAG, baseTag);
        }
        if (capabilityTag != null) {
            combinedTag.put(CAPABILITY_NBT_TAG, capabilityTag);
        }
        return combinedTag;
    }

    @Override
    public void readShareTag(ItemStack stack, @Nullable CompoundNBT nbt) {
        if (nbt == null) {
            stack.setTag(null);
            return;
        }
        CompoundNBT baseTag = nbt.getCompound(BASE_NBT_TAG);              // empty if not found
        CompoundNBT capabilityTag = nbt.getCompound(CAPABILITY_NBT_TAG); // empty if not found
        stack.setTag(baseTag);
        ItemStackHandlerTestItem itemStackHandlerTestItem = getItemStackHandlerTestItem(stack);
        itemStackHandlerTestItem.deserializeNBT(capabilityTag);
    }


    public static float getFullnessPropertyOverride(ItemStack itemStack, @Nullable World world, @Nullable LivingEntity livingEntity) {
        ItemStackHandlerTestItem testItem = getItemStackHandlerTestItem(itemStack);
        float fractionEmpty = testItem.getNumberOfEmptySlots() / (float)testItem.getSlots();
        return 1.0F - fractionEmpty;
    }

    private static final Logger LOGGER = LogManager.getLogger();

}

Basically I have an Item GUI that acts as a storage bag right now, and I want to be able to remove/add items to it whenever I shift-right clicked. Problem is I don't know how to make it so it can add or remove an item from the items inventory.

Link to comment
Share on other sites

22 minutes ago, NindyBun said:

IItemHandler testItem = itemStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)

You're already basically doing the thing you need to do, just in a different place.

Once you have an IItemHandler you can get, set, insert, and remove items.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

On 3/4/2021 at 10:54 AM, Draco18s said:

You're already basically doing the thing you need to do, just in a different place.

Once you have an IItemHandler you can get, set, insert, and remove items.

Uh, so I've ran into a problem. I can insert items fine and my item will store them, but when I try to extract an item it still stays there unless I call the extract function twice. Does it have to do with my ItemHandler?

package com.nindybun.miningtool.test_item;

import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraftforge.items.ItemStackHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Nonnull;

public class ItemStackHandlerTestItem extends ItemStackHandler {
    public static final int MIN_SLOTS = 1;
    public static final int MAX_SLOTS = 1;

    public ItemStackHandlerTestItem(int numberOfSlots){
        super(numberOfSlots);
    }

    public static boolean isFuel(ItemStack stack) {
        return net.minecraftforge.common.ForgeHooks.getBurnTime(stack) > 0;
    }

    public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
        if (slot < 0 || slot >= MAX_SLOTS) {
            throw new IllegalArgumentException("Invalid slot number: " + slot);
        }
        if (stack.isEmpty()) {
            return false;
        }
        if (isFuel(stack)) {
            return true;
        }
        return false;
    }

    public boolean isDirty() {
        boolean currentState = isDirty;
        isDirty = false;
        return currentState;
    }

    protected void onContentsChanged(int slot) {
        super.onContentsChanged(slot);
        isDirty = true;
    }


    private boolean isDirty = true;
    private final Logger LOGGER = LogManager.getLogger();

}

 

My item class:

package com.nindybun.miningtool.test_item;

import com.google.common.collect.Sets;
import com.nindybun.miningtool.MiningTool;
import com.nindybun.miningtool.init.ItemInit;
import com.nindybun.miningtool.util.WorldUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.ITickable;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.*;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tags.BlockTags;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.LazyValue;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.ToolType;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;

public class ItemTestItem extends ToolItem{
    private static final int MAX_ITEM_STACK = 1;
    private static final Set<Block> EFFECTIVE_ON = Sets.newHashSet();
    private static int fuelValue;
    private static int use = 100;

    public ItemTestItem(Properties properties) {
        super(15, 15, ModItemTier.TESTITEM, EFFECTIVE_ON,
                properties
                        .addToolType(ToolType.get("pickaxe"), 4)
                        .addToolType(ToolType.get("axe"), 4)
                        .addToolType(ToolType.get("shovel"), 4)
                );

    }
    @Override
    public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
        tooltip.add(new StringTextComponent("IDK"));
        super.addInformation(stack, worldIn, tooltip, flagIn);
    }

    /*@Override
    public boolean onBlockStartBreak(ItemStack stack, BlockPos pos, PlayerEntity player) {
        IItemHandler item = getItemStackHandlerTestItem(stack);
        RayTraceResult ray = WorldUtil.getMovingObjectPosWithReachDistance(player.world, player, pos, player.world.getBlockState(pos));
        if (ray != null){
            if (fuelValue >= use){
                LOGGER.info("Fuel Value Before >> " + fuelValue);
                //BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(player.world, pos, player.world.getBlockState(pos), player);
                //event.getState().getBlock().harvestBlock(player.world, player, pos, player.world.getBlockState(pos), player.world.getTileEntity(pos), stack);
                //player.world.destroyBlock(pos, false);
                fuelValue -= use;
                LOGGER.info("Fuel Value After >> " + fuelValue);
            }else {
                player.world.destroyBlock(pos, false);
            }

        }
        return true;
    }*/

    @Override
    public boolean onBlockDestroyed(ItemStack stack, World worldIn, BlockState state, BlockPos pos, LivingEntity entityLiving) {
        IItemHandler item = getItemStackHandlerTestItem(stack);

        if (fuelValue >= use) {
            LOGGER.info("Fuel Value Before >> " + fuelValue);
            fuelValue -= use;
            LOGGER.info("Fuel Value After >> " + fuelValue);
            //entityLiving.world.destroyBlock(pos, true);
            state.getBlock().harvestBlock(worldIn, (PlayerEntity) entityLiving, pos, state, worldIn.getTileEntity(pos), stack);
        }else{
            entityLiving.world.destroyBlock(pos, false);
        }

        return super.onBlockDestroyed(stack, worldIn, state, pos, entityLiving);
    }

    /*public void refuel(ItemStack stack){
        IItemHandler item = getItemStackHandlerTestItem(stack);
    }*/

    public float getDestroySpeed(ItemStack stack, BlockState state) {
        IItemHandler item = getItemStackHandlerTestItem(stack);

        if (!EFFECTIVE_ON.contains(state.getBlock())){
            EFFECTIVE_ON.add(state.getBlock());
        }
        if (fuelValue >= use){
            return super.getDestroySpeed(stack, state);
        }else{
            if (item.getStackInSlot(0).getCount() > 0){

                fuelValue = net.minecraftforge.common.ForgeHooks.getBurnTime(item.getStackInSlot(0));
                LOGGER.info("Fuel Value >> " + fuelValue);
                item.extractItem(0, 1, false);

                return super.getDestroySpeed(stack, state);
            }
            return 0.2f;
        }



    }

    public enum ModItemTier implements IItemTier
    {
        TESTITEM(4, 0, 20.0f, 7.0f, 250, null);


        public final int harvestlevel;
        private final int maxUses;
        private final float efficiency;
        private final float attackDamage;
        private final int enchantability;
        private final LazyValue<Ingredient> repairMaterial;

        ModItemTier(int harvestLevel, int maxUses, float efficiency, float attackDamage, int enchantability, Supplier<Ingredient> repairMaterial)
        {
            this.maxUses = maxUses;
            this.efficiency = efficiency;
            this.attackDamage = attackDamage;
            this.enchantability = enchantability;
            this.repairMaterial = new LazyValue<>(repairMaterial);
            this.harvestlevel = harvestLevel;
        }

        @Override
        public int getMaxUses() {
            return this.maxUses;
        }

        @Override
        public float getEfficiency() {
            return this.efficiency;
        }

        @Override
        public float getAttackDamage() {
            return this.attackDamage;
        }

        @Override
        public int getHarvestLevel() {
            return this.harvestlevel;
        }

        @Override
        public int getEnchantability() {
            return this.enchantability;
        }

        @Override
        public Ingredient getRepairMaterial() {
            return this.repairMaterial.getValue();
        }
    }



    @Nonnull
    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {

        ItemStack stack = playerIn.getHeldItem(handIn);
        IItemHandler item = getItemStackHandlerTestItem(stack);
        if (!worldIn.isRemote){
            if (playerIn.isSneaking()){
                item.insertItem(0, new ItemStack(Items.COAL, 1), false);

            }else{
                INamedContainerProvider containerProviderTestItem = new ContainerProviderTestItem(this, stack);
                final int NUMBER_OF_SLOTS = 1;
                NetworkHooks.openGui((ServerPlayerEntity) playerIn, containerProviderTestItem, (packetBuffer)->{packetBuffer.writeInt(NUMBER_OF_SLOTS); });
            }
        }


        return ActionResult.resultSuccess(stack);
    }


    private static class ContainerProviderTestItem implements INamedContainerProvider{

        public ContainerProviderTestItem(ItemTestItem itemTestItem, ItemStack itemStackTestItem){
            this.itemStackTestItem = itemStackTestItem;
            this.itemTestItem = itemTestItem;
        }

        @Override
        public ITextComponent getDisplayName() {
            return itemStackTestItem.getDisplayName();
        }

        @Nullable
        @Override
        public ContainerTestItem createMenu(int windowID_, PlayerInventory playerInventory, PlayerEntity playerEntity) {
            ContainerTestItem newContainerServerSide =
                    ContainerTestItem.createContainerServerSide(windowID_, playerInventory,
                            itemTestItem.getItemStackHandlerTestItem(itemStackTestItem),
                            itemStackTestItem);

            return newContainerServerSide;
        }

        private ItemTestItem itemTestItem;
        private ItemStack itemStackTestItem;
    }

    @Nonnull
    @Override
    public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT oldCapNbt) {

        return new CapabilityProviderTestItem();
    }

    private static ItemStackHandlerTestItem getItemStackHandlerTestItem(ItemStack itemStack) {
        IItemHandler testItem = itemStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
        if (testItem == null || !(testItem instanceof ItemStackHandlerTestItem)) {
            LOGGER.error("ItemTestItem did not have the expected ITEM_HANDLER_CAPABILITY");
            return new ItemStackHandlerTestItem(1);
        }
        return (ItemStackHandlerTestItem) testItem;
    }

    private final String BASE_NBT_TAG = "base";
    private final String CAPABILITY_NBT_TAG = "cap";


    @Nullable
    @Override
    public CompoundNBT getShareTag(ItemStack stack) {
        CompoundNBT baseTag = stack.getTag();
        ItemStackHandlerTestItem itemStackHandlerTestItem = getItemStackHandlerTestItem(stack);
        CompoundNBT capabilityTag = itemStackHandlerTestItem.serializeNBT();
        CompoundNBT combinedTag = new CompoundNBT();
        if (baseTag != null) {
            combinedTag.put(BASE_NBT_TAG, baseTag);
        }
        if (capabilityTag != null) {
            combinedTag.put(CAPABILITY_NBT_TAG, capabilityTag);
        }
        return combinedTag;
    }

    @Override
    public void readShareTag(ItemStack stack, @Nullable CompoundNBT nbt) {
        if (nbt == null) {
            stack.setTag(null);
            return;
        }
        CompoundNBT baseTag = nbt.getCompound(BASE_NBT_TAG);
        CompoundNBT capabilityTag = nbt.getCompound(CAPABILITY_NBT_TAG);
        stack.setTag(baseTag);
        ItemStackHandlerTestItem itemStackHandlerTestItem = getItemStackHandlerTestItem(stack);
        itemStackHandlerTestItem.deserializeNBT(capabilityTag);
    }


    private static final Logger LOGGER = LogManager.getLogger();

}

 

Link to comment
Share on other sites

15 minutes ago, NindyBun said:

private static int fuelValue;

private static int use = 100;

This does not do what you want it to do, unless you want all copies of your item to share fuel values.

You need to store this data in a Capability.

15 minutes ago, NindyBun said:

when I try to extract an item it still stays there unless I call the extract function twice.

Your code is only calling extract once, so I don't know what the problem is. Your stack handler class is fine, but you should override initCapabilities on your item class and attach the capability there, rather than...whatever nonsense you're doing with getItemStackHandlerTestItem.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

1 hour ago, Draco18s said:

Your code is only calling extract once, so I don't know what the problem is. Your stack handler class is fine, but you should override initCapabilities on your item class and attach the capability there, rather than...whatever nonsense you're doing with getItemStackHandlerTestItem.

I call the extract every time my fuelValue is below 0. When it extracts the first time it makes the fuelValue = 1600 but doesn't remove the item, then it extracts again when the fuelValue is at 0 again, this time the item is actually removed from it's inventory.

 

1 hour ago, Draco18s said:

This does not do what you want it to do, unless you want all copies of your item to share fuel values.

You need to store this data in a Capability.

Is there a tutorial that you can recommend for capabilities? I've been looking all over the place but I don't think I understand the concept.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.