Jump to content

[1.16.5] can't set inventory slot content in a TileEntity with inventory size of 1


Recommended Posts

Posted

Hi, I don't really know if my title is correct or appropriate but I don't know how to describe it. I created a TileEntity which you can fill only with one item, and which has an inventory size of 1, so it takes only one item in the inventory. My problem is that when I want to set the item in the slot, with items.set(0, ItemStack) (items is a NonNullList of ItemStacks), it is not setting it, and I don't know why because I did exactly the same thing with my other TileEntities (with more slots) and it works perfectly, so I don't know if it's a problem with NonNullList of size 1 or f I need a container (because I think I don't need a container if I won't add a gui but I may be wrong), or anything else. So please someone help me ?

My TileEntity class:

public class CelestialPowerPedestalTileEntity extends LockableLootTileEntity implements ISidedInventory {

	public static final int                     slots              = 1;
	public              NonNullList <ItemStack> items              = NonNullList.withSize(slots, ItemStack.EMPTY);

	public CelestialPowerPedestalTileEntity() {
		super(ModTileEntities.CELESTIAL_POWER_PEDESTAL_TILE_ENTITY.get());
	}

	@Override
	protected ITextComponent getDefaultName() {
		return new TranslationTextComponent("container." + Alcamod.ModID + ".celestial_power_pedestal");
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TranslationTextComponent("Celestial Power Pedestal");
	}

	@Override
	protected Container createMenu(
		int id,
		PlayerInventory player) {
		return null;
	}

	@Override
	protected NonNullList <ItemStack> getItems() {
		return this.items;
	}

	public Item getItem() {
		return this.items.get(0).getItem();
	}

	public ItemStack getStack() {
		return this.items.get(0);
	}

	@Override
	protected void setItems(
		@Nonnull
			NonNullList <ItemStack> itemsIn) {
		this.items = itemsIn;
	}

	public void setStack(ItemStack stack) {
		this.items.set(0, stack);
	}

	@Override
	public int getSizeInventory() {
		return 1;
	}

	public void read(
		BlockState state,
		CompoundNBT nbt) {
		super.read(
			state,
			nbt);

		this.items = NonNullList.withSize(getSizeInventory(), ItemStack.EMPTY);
		if (!this.checkLootAndRead(nbt)) {
			ItemStackHelper.loadAllItems(nbt, this.items);
		}
	}

	@Nonnull
	@Override
	public CompoundNBT write(
		CompoundNBT compound) {
		super.write(compound);

		if (!checkLootAndWrite(compound)) {
			ItemStackHelper.saveAllItems(compound, this.items);
		}

		return compound;
	}

	@Nonnull
	@Override
	public <T> LazyOptional <T> getCapability(
		Capability <T> cap, Direction side) {
		return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.orEmpty(cap, LazyOptional.of(() -> (IItemHandler) this.items));
	}

	@Nonnull
	@Override
	public int[] getSlotsForFace(
		Direction side) {
		return new int[] {0};
	}

	@Override
	public boolean canInsertItem(
		int index,
		ItemStack stack,
		@Nullable
			Direction direction) {
		return stack.getItem() == ModItems.CELESTIAL_POWER_EYE.get();
	}

	@Override
	public boolean canExtractItem(
		int index,
		ItemStack stack,
		Direction direction) {
		return true;
	}

	public boolean isFillable() {
		return getItem() != ModItems.CELESTIAL_POWER_EYE.get();
	}

}

 

My Block class:

public class CelestialPowerPedestal extends Block {

	public CelestialPowerPedestal() {
		super(Properties.create(Material.IRON)
		     .hardnessAndResistance(40, 80)
		     .sound(SoundType.BASALT)
		     .harvestLevel(3)
		     .harvestTool(ToolType.PICKAXE));
	}

	public VoxelShape getShape(
		BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
		return CelestialPowerPedestalVoxelShapes.SHAPE;
	}

	@Override
	public boolean hasTileEntity(BlockState state) {
		return true;
	}

	@Nullable
	@Override
	public TileEntity createTileEntity(
		BlockState state,
		IBlockReader world) {
		return ModTileEntities.CELESTIAL_POWER_PEDESTAL_TILE_ENTITY.get().create();
	}

	@Override
	public ActionResultType onBlockActivated(
		BlockState state,
		World worldIn,
		BlockPos pos,
		PlayerEntity player,
		Hand handIn,
		BlockRayTraceResult hit) {
		if (worldIn != null && !worldIn.isRemote()) {
			TileEntity te = worldIn.getTileEntity(pos);
			Item playerItem = player.getHeldItemMainhand()
			                        .getItem();

			if (te instanceof CelestialPowerPedestalTileEntity) {

				if (((CelestialPowerPedestalTileEntity) te).isFillable() && playerItem == ModItems.CELESTIAL_POWER_EYE.get()) {
					ItemStack stack = player.getHeldItemMainhand();

					((CelestialPowerPedestalTileEntity) te).setStack(stack);
					player.getHeldItemMainhand().shrink(1);
					return ActionResultType.SUCCESS;
				}

				if (!((CelestialPowerPedestalTileEntity) te).isFillable()) {

					player.addItemStackToInventory(((CelestialPowerPedestalTileEntity) te).getStack());
					((CelestialPowerPedestalTileEntity) te).setStack(ItemStack.EMPTY);
					return ActionResultType.SUCCESS;
				}
			}

		}
		return ActionResultType.CONSUME;
	}

	@Override
	public void onReplaced(
		BlockState state,
		World worldIn,
		BlockPos pos,
		BlockState newState,
		boolean isMoving) {
		TileEntity tile = worldIn.getTileEntity(pos);
		if (tile instanceof CelestialPowerPedestalTileEntity && state.getBlock() != newState.getBlock()) {
			InventoryHelper.dropInventoryItems(worldIn, pos, (IInventory) tile);
			worldIn.updateComparatorOutputLevel(pos, this);
		}

		if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
			worldIn.removeTileEntity(pos);
		}
	}

}

 

The targeted code block where I put the action when the player right click the block:

@Override
	public ActionResultType onBlockActivated(
		BlockState state,
		World worldIn,
		BlockPos pos,
		PlayerEntity player,
		Hand handIn,
		BlockRayTraceResult hit) {
		if (worldIn != null && !worldIn.isRemote()) {
			TileEntity te = worldIn.getTileEntity(pos);
			Item playerItem = player.getHeldItemMainhand()
			                        .getItem();

			if (te instanceof CelestialPowerPedestalTileEntity) {

				if (((CelestialPowerPedestalTileEntity) te).isFillable() && playerItem == ModItems.CELESTIAL_POWER_EYE.get()) {
					ItemStack stack = player.getHeldItemMainhand();

					((CelestialPowerPedestalTileEntity) te).setStack(stack);
					player.getHeldItemMainhand().shrink(1);
					return ActionResultType.SUCCESS;
				}

				if (!((CelestialPowerPedestalTileEntity) te).isFillable()) {

					player.addItemStackToInventory(((CelestialPowerPedestalTileEntity) te).getStack());
					((CelestialPowerPedestalTileEntity) te).setStack(ItemStack.EMPTY);
					return ActionResultType.SUCCESS;
				}
			}

		}
		return ActionResultType.CONSUME;
	}

 

Posted

(I don't have a Forge solution so general debugging advice here)

Did you manage to track down where exactly it's not working, or is the "not setting it" just a description of the effects? If you aren't sure where exactly it's not working the way it's supposed to, what I like to do to narrow down the issue is put in debug log lines that echo the status of the variables or code at all the steps of the process that's not working. Echoing your input/output for your set and get methods to console, for example, or checking the status of your items list at each step to see where it changes, or doesn't change, and so on.

Then you can track down exactly which function call(s) aren't working right and try alternatives for them.

Posted
38 minutes ago, diesieben07 said:

Show updated code.

@Override
	public ActionResultType onBlockActivated(
		BlockState state,
		World worldIn,
		BlockPos pos,
		PlayerEntity player,
		Hand handIn,
		BlockRayTraceResult hit) {
		if (worldIn != null && !worldIn.isRemote()) {
			TileEntity te = worldIn.getTileEntity(pos);
			Item playerItem = player.getHeldItemMainhand()
			                        .getItem();

			if (te instanceof CelestialPowerPedestalTileEntity) {

				if (((CelestialPowerPedestalTileEntity) te).isFillable() && playerItem == ModItems.CELESTIAL_POWER_EYE.get()) {
					ItemStack stack = player.getHeldItemMainhand();

					((CelestialPowerPedestalTileEntity) te).insertItem(0, stack, false);
					player.getHeldItemMainhand().shrink(1);
					Alcamod.LOGGER.info(((CelestialPowerPedestalTileEntity) te).getStackInSlot(0));
					return ActionResultType.SUCCESS;
				}

				if (!((CelestialPowerPedestalTileEntity) te).isFillable()) {

					player.addItemStackToInventory(((CelestialPowerPedestalTileEntity) te).getStackInSlot(0));
					((CelestialPowerPedestalTileEntity) te).extractItem(0, 1, false);
					return ActionResultType.SUCCESS;
				}
			}

		}
		return ActionResultType.CONSUME;
	}

 

In the tile entity:

public Item getItem() {
		return getStackInSlot(0).getItem();
	}

	@Override
	public ItemStack getStackInSlot(
		int index) {
		return this.items.get(index);
	}
@Nonnull
	@Override
	public ItemStack insertItem(
		int slot,
		@Nonnull
			ItemStack stack,
		boolean simulate) {
		if (!this.isFillable()) return stack;
		return ItemStack.EMPTY;
	}

	@Nonnull
	@Override
	public ItemStack extractItem(
		int slot,
		int amount,
		boolean simulate) {
		if (this.isFillable()) return ItemStack.EMPTY;
		else return getStackInSlot(0);
	}

	@Override
	public int getSlotLimit(
		int slot) {
		return getStackInSlot(0).getMaxStackSize();
	}

	@Override
	public boolean isItemValid(
		int slot,
		@Nonnull
			ItemStack stack) {
		return true;
	}

 

Posted

I implemented IItemHandler as a capability, but i don't know why it is still not working, the setting part still seems to cause issues.

here is the updated code:

private static      Capability <IItemHandler>   capability             = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
	public              IItemHandler                inv                    = capability.getDefaultInstance();
	private final       LazyOptional <IItemHandler> capabilityLazyOptional = LazyOptional.of(() -> inv);
@Override
	protected NonNullList <ItemStack> getItems() {
		NonNullList<ItemStack> items = NonNullList.withSize(slots, ItemStack.EMPTY);
		for (int i = 0; i < inv.getSlots(); i++) {
			items.set(i, inv.getStackInSlot(i));
		}
		return items;
	}

	@Override
	protected void setItems(
		NonNullList <ItemStack> itemsIn) {
		for (int i = 0; i < itemsIn.size(); i++) {
			inv.insertItem(i, itemsIn.get(i), false);
		}
	}
public Item getItem() {
		return this.inv.getStackInSlot(0)
		               .getItem();
	}

	@Override
	public int getSizeInventory() {
		return slots;
	}

	public boolean isFillable() {
		return inv.getStackInSlot(0).getItem() != ModItems.CELESTIAL_POWER_EYE.get();
	}
@Nonnull
	@Override
	public <T> LazyOptional <T> getCapability(
		Capability <T> cap,
		Direction side) {
		if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
			return capabilityLazyOptional.cast();
		}
		return super.getCapability(cap, side);
	}

	@Override
	protected void invalidateCaps() {
		super.invalidateCaps();
		capabilityLazyOptional.invalidate();
	}
@Override
	public ActionResultType onBlockActivated(
		BlockState state,
		World worldIn,
		BlockPos pos,
		PlayerEntity player,
		Hand handIn,
		BlockRayTraceResult hit) {
		if (worldIn != null && !worldIn.isRemote()) {
			TileEntity te = worldIn.getTileEntity(pos);
			Item playerItem = player.getHeldItemMainhand()
			                        .getItem();

			if (te instanceof CelestialPowerPedestalTileEntity) {

				if (((CelestialPowerPedestalTileEntity) te).isFillable() && playerItem == ModItems.CELESTIAL_POWER_EYE.get()) {
					ItemStack stack = player.getHeldItemMainhand();

					((CelestialPowerPedestalTileEntity) te).inv.insertItem(0, stack, false);
					player.getHeldItemMainhand().shrink(1);
					return ActionResultType.SUCCESS;
				}

				if (!((CelestialPowerPedestalTileEntity) te).isFillable()) {

					player.addItemStackToInventory(((CelestialPowerPedestalTileEntity) te).inv.getStackInSlot(0));
					((CelestialPowerPedestalTileEntity) te).inv.extractItem(0, 1, false);
					return ActionResultType.SUCCESS;
				}
			}

		}
		return ActionResultType.CONSUME;
	}

 

On 7/16/2021 at 7:07 PM, InspectorCaracal said:

(I don't have a Forge solution so general debugging advice here)

Did you manage to track down where exactly it's not working, or is the "not setting it" just a description of the effects? If you aren't sure where exactly it's not working the way it's supposed to, what I like to do to narrow down the issue is put in debug log lines that echo the status of the variables or code at all the steps of the process that's not working. Echoing your input/output for your set and get methods to console, for example, or checking the status of your items list at each step to see where it changes, or doesn't change, and so on.

Then you can track down exactly which function call(s) aren't working right and try alternatives for them.

I didn't do that but I saw that the problem was coming from the setting part, since everything works perfectly but this.

Posted

Ok so I found that LockableLootTileEntity extends LockableTileEntity which implements IInventory, and my TileEntity was extending LockableLootTileEntity.

However, even after changing the extends to TileEntity, which does not implements IInventory it is not working, god it will never end XD :((

Posted

I just changes in my TileEntity class the "extends LockableLootTileEntity" with "extends TileEntity", and removed the functionds that were implemented with it

I changed some :

protected NonNullList <ItemStack> getItems() {
		NonNullList<ItemStack> items = NonNullList.withSize(slots, ItemStack.EMPTY);
		for (int i = 0; i < inv.getSlots(); i++) {
			items.set(i, inv.getStackInSlot(i));
		}
		return items;
	}

	protected void setItems(
		NonNullList <ItemStack> itemsIn) {
		for (int i = 0; i < itemsIn.size(); i++) {
			inv.insertItem(i, itemsIn.get(i), false);
		}
	}

	public Item getItem() {
		return this.inv.getStackInSlot(0)
		               .getItem();
	}

	public boolean isFillable() {
		return inv.getStackInSlot(0).getItem() != ModItems.CELESTIAL_POWER_EYE.get();
	}

	public void read(
		BlockState state,
		CompoundNBT nbt) {
		super.read(
			state,
			nbt);

		NonNullList <ItemStack> inv = NonNullList.withSize(this.inv.getSlots(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(nbt, inv);
		setItems(inv);
	}

	@Nonnull
	@Override
	public CompoundNBT write(
		CompoundNBT compound) {
		super.write(compound);

			ItemStackHelper.saveAllItems(compound, this.getItems());

		return compound;
	}

I did not changed the capability and ItemHandler related things:

public static final int                         slots                  = 1;
	private static      Capability <IItemHandler>   capability             = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
	public              IItemHandler                inv                    = capability.getDefaultInstance();
	private final       LazyOptional <IItemHandler> capabilityLazyOptional = LazyOptional.of(() -> inv);

@Nonnull
	@Override
	public <T> LazyOptional <T> getCapability(
		Capability <T> cap,
		Direction side) {
		if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
			return capabilityLazyOptional.cast();
		}
		return super.getCapability(cap, side);
	}

	@Override
	protected void invalidateCaps() {
		super.invalidateCaps();
		capabilityLazyOptional.invalidate();
	}

And retouched the onBlockActivated function:

@Override
	public ActionResultType onBlockActivated(
		BlockState state,
		World worldIn,
		BlockPos pos,
		PlayerEntity player,
		Hand handIn,
		BlockRayTraceResult hit) {
		if (worldIn != null && !worldIn.isRemote()) {
			TileEntity te = worldIn.getTileEntity(pos);
			Item playerItem = player.getHeldItemMainhand()
			                        .getItem();

			if (te instanceof CelestialPowerPedestalTileEntity) {

				if (((CelestialPowerPedestalTileEntity) te).isFillable() && playerItem == ModItems.CELESTIAL_POWER_EYE.get()) {
					ItemStack stack = player.getHeldItemMainhand();

					((CelestialPowerPedestalTileEntity) te).inv.insertItem(0, stack, false);
					player.getHeldItemMainhand().shrink(1);
					return ActionResultType.SUCCESS;
				}

				if (!((CelestialPowerPedestalTileEntity) te).isFillable()) {

					player.addItemStackToInventory(((CelestialPowerPedestalTileEntity) te).inv.getStackInSlot(0));
					((CelestialPowerPedestalTileEntity) te).inv.extractItem(0, 1, false);
					return ActionResultType.SUCCESS;
				}
			}

		}
		return ActionResultType.CONSUME;
	}

 

Posted
10 minutes ago, diesieben07 said:

You cannot modify an ItemStack once you give it to the IItemHandler via insertItem. Here you shrink it afterwards, which will cause undocumented behavior.

Ok, indeed I did not realize this, but putting a copy of the item stack in the tile entity and then shrinking the original seems to work. Was such a stupid thing, thank you !

Posted

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.

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.