Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Container in Item


frankiecav
 Share

Recommended Posts

Good afternoon,

 

Been working on an item which, on right click, opens an inventory. The inventory opens and everything is alright except instead of creating a new tileentity for each item, it uses the same tileentity. For example, if you have two sheaths in your inventory and put a sword in one, you can open the other and find the same sword. I'm just not sure how to define a new tileentity, the block class has the createTileEntity method but I'm making an item...

 

Here's my Item class code:

public class ItemSheath extends Item {

	private final TileEntitySheath sheath;
	
	public ItemSheath() {
		super(new Properties().group(SurvivalEssentials.ESSENTIAL_TAB).maxStackSize(1));
		setRegistryName("sheath");
		sheath = new TileEntitySheath();
	}
	
	
	
	@Override
	public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
		PlayerEntity player = context.getPlayer();
		if(!context.getWorld().isRemote && player instanceof ServerPlayerEntity) {
			
			NetworkHooks.openGui((ServerPlayerEntity) player, new InterfaceSheath(sheath));
		}
		return ActionResultType.PASS;
	}

	
	
	
	public static class InterfaceSheath implements INamedContainerProvider {
		
		private final TileEntitySheath sheath;
		
		public InterfaceSheath(TileEntitySheath sheath) {
			this.sheath = sheath;
		}
		
		@Override
		public ITextComponent getDisplayName() {
			return NarratorChatListener.EMPTY;
		}

		@Override
		public Container createMenu(int windowID, PlayerInventory playerInventory, PlayerEntity playerIn) {
			return new ContainerSheath(windowID, playerInventory, sheath);
		}
	}
	
	
}

 

I can post my container class or tileentity class too, if needed. Thanks!

Link to comment
Share on other sites

I thought NBT was how the inventory information was saved... regardless, I found the initCapabilities method and am trying to understand capabilities on the forge docs. Not really sure where to go from here, sorry I’m kind of a bot... thanks for the pointer. 

Link to comment
Share on other sites

Create an item.

In initCapabilities, create an ItemStackHandler capability.

Done.

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

Ok, bad wording. Obviously the return type is ICapabilityProvider, so the IDE defaults to returning itemstack. Clearly, this is not creating a new capability. I don’t know how to create the itemstackhandler capability. According to what I’ve read on the forums and docs (couldn’t find much) the capability needs to be set to the item handler instance CapabilityItemHandler. But everything I’ve tried has thrown a compilation error. So I’m not sure where to go. Thanks. 

Link to comment
Share on other sites

Does this look right (it doesn't feel right):

private ItemStackHandler inventory;
	
	public ItemSheath() {
		super(new Properties().group(SurvivalEssentials.ESSENTIAL_TAB).maxStackSize(1));
		setRegistryName("sheath");
		
	}
	
	
	
	@Override
	public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
		PlayerEntity player = context.getPlayer();
		if(!context.getWorld().isRemote && player instanceof ServerPlayerEntity) {
			
			NetworkHooks.openGui((ServerPlayerEntity) player, new InterfaceSheath());
		}
		return ActionResultType.PASS;
	}

	
	@Override
	public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT nbt) {
		inventory = new ItemStackHandler(1);
		return super.initCapabilities(stack, nbt);
	}

If so do I have to figure out how to put in read and write NBT methods, or does the capability handle that?

Link to comment
Share on other sites

No, you cannot store the handler in your Item class (there is only one instance of that).

You need to create a class that implements ICapabilityProvider and INBTSerializable. This class is what will handle the capabilities of your item and you need to create a new instance of it and return that in initCapabilities.

Link to comment
Share on other sites

Ok. That makes sense. It also shows how much of a bot I am. Anyway, Item class:

 

private SheathCapability sheath = new SheathCapability();
	
	public ItemSheath() {
		super(new Properties().group(SurvivalEssentials.ESSENTIAL_TAB).maxStackSize(1));
		setRegistryName("sheath");
		
	}
	
	

	@Override
	public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
		PlayerEntity player = context.getPlayer();
		if(!context.getWorld().isRemote && player instanceof ServerPlayerEntity) {
			
			NetworkHooks.openGui((ServerPlayerEntity) player, new InterfaceSheath());
		}
		return ActionResultType.PASS;
	}

	
	@Override
	public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT nbt) {
		
		
		return sheath;
	}

 

Cap class:

 

public class SheathCapability implements ICapabilityProvider, INBTSerializable {
	
	private ItemStackHandler inventory = new ItemStackHandler(1);
	
	@Override
	public INBT serializeNBT() {
		
		return null;
	}

	@Override
	public void deserializeNBT(INBT nbt) {
	}

	@Override
	public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
		if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return LazyOptional.of(() -> this.inventory).cast();
		return null;
	}

}

 

I'm not sure what type INBTSerializable should be...

Link to comment
Share on other sites

1 minute ago, frankiecav said:

private SheathCapability sheath = new SheathCapability();

No, you cannot do this.

Again: There is only one instance of your item class. You need to do this in initCapabilities.

 

2 minutes ago, frankiecav said:

if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return LazyOptional.of(() -> this.inventory).cast();

Do not create a new LazyOptional every time.

 

3 minutes ago, frankiecav said:

return ActionResultType.PASS;

This is not correct. PASS is for when you don't care about the right click, which is not the case for you.

Link to comment
Share on other sites

public class ItemSheath extends Item {

	private SheathCapability sheath = null;
	
	public ItemSheath() {
		super(new Properties().group(SurvivalEssentials.ESSENTIAL_TAB).maxStackSize(1));
		setRegistryName("sheath");
		
	}
	
	

	@Override
	public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
		PlayerEntity player = context.getPlayer();
		if(!context.getWorld().isRemote && player instanceof ServerPlayerEntity) {
			
			NetworkHooks.openGui((ServerPlayerEntity) player, new InterfaceSheath());
		}
		return ActionResultType.SUCCESS;
	}

	
	@Override
	public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT nbt) {
		sheath = new SheathCapability();
		
		return sheath;
	}

 

I had it set to PASS because I didn't care about the return, only the openGui. Besides, it worked fine when I was using the TileEntity.

 

Also I don't know how to fix the LazyOptional, I don't understand what it does really...

Edited by frankiecav
Link to comment
Share on other sites

You are still storing the capability provider in your item class.

You cannot do this.

 

10 minutes ago, frankiecav said:

Also I don't know how to fix the LazyOptional, I don't understand what it does really...

Store it in a field. Do not create a new one every time.

As for what it does: it represents an optional value which is lazily computed. Read the Javadocs for more info.

Link to comment
Share on other sites

24 minutes ago, frankiecav said:

public class ItemSheath extends Item {

    private SheathCapability sheath; //REMOVE THIS

 

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

Ok.

 

@Override
	public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT nbt) {
		
		
		return new SheathCapability();
	}

 

public class SheathCapability implements ICapabilityProvider, INBTSerializable {
	
	private ItemStackHandler inventory = new ItemStackHandler(1);
	private LazyOptional<ItemStackHandler> lo;
	
	@Override
	public INBT serializeNBT() {
		
		return null;
	}

	@Override
	public void deserializeNBT(INBT nbt) {
	}

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

}

 

Link to comment
Share on other sites

26 minutes ago, frankiecav said:

private LazyOptional<ItemStackHandler> lo;

You need to give this a value.

26 minutes ago, frankiecav said:

return null;

You probably don't want null here, your cap won't be saved to disk.

 

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

Ok I think this is better:

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

Anyway I don't know if the capability will work, firstly because I have hardly any experience with them and secondly because of the compile error in my container class:

public ContainerSheath(final int windowID, PlayerInventory player) {
		super(EssentialContainers.SHEATH, windowID);
		
		
		for(int y = 0; y < 3; ++y)
			for(int x = 0; x < 9; ++x)
				this.addSlot(new Slot(player, 9 + x + y * 9, 8 + x * 18, 84 + y * 18));
		
		for(int x = 0; x < 9; ++x)
			this.addSlot(new Slot(player, x, 8 + x * 18, 142));
		this.addSlot(new SlotItemHandler(iitemhandler, 0, 50, 50));
	}
	
	
	@Override
	public boolean canInteractWith(PlayerEntity playerIn) {
		return true;
	}
	
	@Override
	public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
		ItemStack previous = ItemStack.EMPTY;
		Slot slot = (Slot) this.inventorySlots.get(index);
		
		if(slot != null && slot.getHasStack()) {
			ItemStack current = slot.getStack();
			previous = current.copy();
			
			//maybe 9 -> 27, 45 -> 45+18
			if(index < 9) {
				if(!this.mergeItemStack(current, 1, 37, true))
					return ItemStack.EMPTY;
			} else {
				if(!this.mergeItemStack(current, 0, 1, false))
					return ItemStack.EMPTY;
			}
			
			if(current.getCount() == 0)
				slot.putStack((ItemStack) ItemStack.EMPTY);
			else
				slot.onSlotChanged();
			
			if(current.getCount() == previous.getCount())
				return ItemStack.EMPTY;
			slot.onTake(playerIn, current);
		}
		
		return previous;
	}

I don't know how to put IItemHandler in the new SlotItemHandler. Usually I would keep ItemStackHandler in a tileentity class but there I'm not using one... I think it has to do with defining:

private LazyOptional<ItemStackHandler> lo;

which I'm not sure how to do.

Link to comment
Share on other sites

1 minute ago, frankiecav said:

@Override public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {

    if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return lo.cast();

    return getCapability(cap, side);

}

"If the cap isn't my cap, get the cap:"

    "If the cap isn't my cap, get the cap:"

        "If the cap isn't my cap, get the cap:"

            "If the cap isn't my cap, get the cap:"

                "If the cap isn't my cap, get the cap:"

                    ...

2 minutes ago, frankiecav said:

which I'm not sure how to do.

No? 

But.

You already wrote the code that does it:

1 hour ago, frankiecav said:

if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return LazyOptional.of(() -> this.inventory).cast();

 

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

public class SheathCapability implements ICapabilityProvider, INBTSerializable {
	
	private ItemStackHandler inventory = new ItemStackHandler(1);
	private LazyOptional<ItemStackHandler> lo = LazyOptional.of(() -> inventory);
	
	@Override
	public INBT serializeNBT() {
		
		return null;
	}

	@Override
	public void deserializeNBT(INBT nbt) {
	}

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

}

 

(finds LazyOptional.empty(), feels really smart).

 

So now, can I use the inventory field in the container class?

Link to comment
Share on other sites

5 minutes ago, frankiecav said:

So now, can I use the inventory field in the container class?

No, its private. Use getCapability

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

I'm not an intellectual.

 

public class ContainerSheath extends Container {

	
	
	private SheathCapability cap;
	
	
	
	public ContainerSheath(final int windowID, PlayerInventory player) {
		super(EssentialContainers.SHEATH, windowID);
		cap = new SheathCapability();
		
		for(int y = 0; y < 3; ++y)
			for(int x = 0; x < 9; ++x)
				this.addSlot(new Slot(player, 9 + x + y * 9, 8 + x * 18, 84 + y * 18));
		
		for(int x = 0; x < 9; ++x)
			this.addSlot(new Slot(player, x, 8 + x * 18, 142));
		this.addSlot(new SlotItemHandler(cap.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.getDefaultInstance(), null), 0, 50, 50));
	}
	
	
	@Override
	public boolean canInteractWith(PlayerEntity playerIn) {
		return true;
	}
	
	@Override
	public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
		ItemStack previous = ItemStack.EMPTY;
		Slot slot = (Slot) this.inventorySlots.get(index);
		
		if(slot != null && slot.getHasStack()) {
			ItemStack current = slot.getStack();
			previous = current.copy();
			
			//maybe 9 -> 27, 45 -> 45+18
			if(index < 9) {
				if(!this.mergeItemStack(current, 1, 37, true))
					return ItemStack.EMPTY;
			} else {
				if(!this.mergeItemStack(current, 0, 1, false))
					return ItemStack.EMPTY;
			}
			
			if(current.getCount() == 0)
				slot.putStack((ItemStack) ItemStack.EMPTY);
			else
				slot.onSlotChanged();
			
			if(current.getCount() == previous.getCount())
				return ItemStack.EMPTY;
			slot.onTake(playerIn, current);
		}
		
		return previous;
	}

}

CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.getDefaultInstance() would pass by itself put then my capability isn't used. I think? If you can't tell I'm lost

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

 Share




  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • Hi guys! I currently have a project that I've been developing in a 'vanilla' environment that I'm actually looking to transfer over to Forge, simply because of how much better the experience would be using Forge. Before starting on this Forge mod, I was planning ahead and was looking at options for proxies, of which I would greatly like to use Velocity. In their docs and by asking around their Discord, they don't support support versions of Forge of 1.13 or later because of changes in the "handshake protocol". But I also really don't want to use an unsupported version of Forge, such as 1.12.2, to be able to use a proxy. I was pointed in the direction of potentially making my own client-side mod to allow Forge to be compatible with an updated proxy, such as Velocity. When asking for a direction for achieving this, I was told to have a look at how the Forge server implements logins and that the discrepancy might be with how modified the handshake protocol is. This sounds like quite the challenge to me and I'm completely up for trying to accomplish it. So for the sake of planning ahead and having a rough idea of how I could accomplish that when the time comes to work on it, has anyone else had experience with trying to achieve this? I appreciate any help or direction offered! Thanks! 
    • Been trying to set up a server for myself and a few friends through BisectHosting. I ended up replicating the server on my own computer to see if the issue persisted (if it was on bisect's end) and it was still there. Every time a player tries to connect to the server they start connecting but after only around 2 seconds the player is disconnected with the error message Payload size exceeds 1048576 bytes.  Upon inspection of the server debug file, the player always disconnects while fmlhandshake ticking packet info is being sent, and I have repeatedly made sure the mods and their configs are identical. I tried to get RandomPatches to increase the max allowed byte size, as the default seems to be 32767, but either something is wrong with it or some other mod is limiting the packet size limit.     Server Debug: https://pastebin.com/xZLbtdQB (only includes portions from after the server launched as I couldn't upload the whole file) Server Log: https://pastebin.com/yrJ3tNaW (similarly only after server launched (hence the weird say commands) Client Log: https://pastebin.com/inSzZV96 (whole thing for once) Modlist: https://pastebin.com/Qvurg45j (All but Optifine and BetterFoliage are present on the server as they have caused issues during startup)   Honestly stumped on how to fix this, been working on it for 10 hours across two days to no avail.
    • quiero dormir uwu
    • Hi, mod called "charging gadgets" is crushing forge minecraft 1.18.1 when i place block from this mod, im temporary playing On 1.18 cuz its not happening on 1.18 but c'mon, pls fix it, 1.18.1 is better and I Wonder i could use this version
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.