Jump to content

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


Recommended Posts

Posted
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.

Posted
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.

Posted
14 minutes ago, 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.

OMG. I did not know that. Very thanks!

Posted
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();

}

 

Posted
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.

Posted
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.

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • If you’ve lost crypto to a scam, don’t let shame or fear keep you silent. There are real experts out there who know how to fight back. Dexdert Net Recovery did the impossible for me, and they can do it for others too. Contact Dexdet Net Recovery For Help Visa Information Below:    
    • Hi everyone, I'm currently developing a Forge 1.21 mod for Minecraft and I want to display a custom HUD overlay for a minigame. My goal: When the game starts, all players should see an item/block icon (from the base game, not a custom texture) plus its name/text in the HUD – similar to how the bossbar overlay works. The HUD should appear centered above the hotbar (or at a similar prominent spot), and update dynamically (icon and name change as the target item changes). What I've tried: I looked at many online tutorials and several GitHub repos (e.g. SeasonHUD, MiniHUD), but most of them use NeoForge or Forge versions <1.20 that provide the IGuiOverlay API (e.g. implements IGuiOverlay, RegisterGuiOverlaysEvent). In Forge 1.21, it seems that neither IGuiOverlay nor RegisterGuiOverlaysEvent exist anymore – at least, I can't import them and they are missing from the docs and code completion. I tried using RenderLevelStageEvent as a workaround but it is probably not intended for custom HUDs. I am not using NeoForge, and switching the project to NeoForge is currently not an option for me. I tried to look at the original minecraft source code to see how elements like hearts, hotbar etc are drawn on the screen but I am too new to Minecraft modding to understand. What I'm looking for: What is the correct way to add a custom HUD element (icon + text) in Forge 1.21, given that the previous overlay API is missing? Is there a new recommended event, callback, or method in Forge 1.21 for custom HUD overlays, or is everyone just using a workaround? Is there a minimal open-source example repo for Forge 1.21 that demonstrates a working HUD overlay without relying on NeoForge or deprecated Forge APIs? My ideal solution: Centered HUD element with an in-game item/block icon (from the base game's assets, e.g. a diamond or any ItemStack / Item) and its name as text, with a transparent background rectangle. It should be visible to the players when the mini game is running. Easy to update the item (e.g. static variable or other method), so it can change dynamically during the game. Any help, code snippets, or up-to-date references would be really appreciated! If this is simply not possible right now in Forge 1.21, it would also help to know that for sure. Thank you very much in advance!
    • The simple answer is there is not an easy way. You would need to know how to program in Java, as well as at least some familiarity with how Forge works so you could port the differences. You would also need the sourcecode for the original mod, and permission from the author to modify it, if they did not use some sort of open source license. So it's not impossible, but it would take some effort, but doing so would open up a whole new world of possibilities for you!
    • Does it still crash if you remove holdmyitems? Looks like that mod doesn't work on a server as far as I can tell from the error.  
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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