OrangeVillager61 Posted May 24, 2017 Posted May 24, 2017 (edited) Hello! I don't know how to access my mob's container with my gui. I want my button on this gui to fire a series of functions if there are enough emeralds in the gui slot. I do not know to access the slots to check this. Container: public class ContainerIvVillagerHireNitwit extends Container{ private IvVillager villager; private IItemHandler handler = villager.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); public ContainerIvVillagerHireNitwit(IvVillager villager, IInventory playerInv){ IItemHandler handler = villager.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); this.addSlotToContainer(new SlotItemHandler(handler, 3, 76, 47)); int xPos = 8; int yPos = 84; for (int y = 0; y < 3; ++y) { for (int x = 0; x < 9; ++x) { this.addSlotToContainer(new Slot(playerInv, x + y * 9 + 9, xPos + x * 18, yPos + y * 18)); } } for (int x = 0; x < 9; ++x) { this.addSlotToContainer(new Slot(playerInv, x, xPos + x * 18, yPos + 58)); } } @Override public boolean canInteractWith(EntityPlayer player) { // TODO Auto-generated method stub return false; } @Override public ItemStack transferStackInSlot(EntityPlayer playerIn, int fromSlot) { ItemStack previous = ItemStack.EMPTY; Slot slot = (Slot) this.inventorySlots.get(fromSlot); if (slot != null && slot.getHasStack()) { ItemStack current = slot.getStack(); previous = current.copy(); if (fromSlot < this.handler.getSlots()) { // From the block breaker inventory to player's inventory if (!this.mergeItemStack(current, handler.getSlots(), handler.getSlots() + 36, true)) return ItemStack.EMPTY; } else { // From the player's inventory to block breaker's inventory if (!this.mergeItemStack(current, 0, handler.getSlots(), false)) return ItemStack.EMPTY; } if (current.getCount() == 0) //Use func_190916_E() instead of stackSize 1.11 only 1.11.2 use getCount() slot.putStack(ItemStack.EMPTY); //Use ItemStack.field_190927_a instead of (ItemStack)null for a blank item stack. In 1.11.2 use ItemStack.EMPTY else slot.onSlotChanged(); if (current.getCount() == previous.getCount()) return null; slot.onTake(playerIn, current); } return previous; } } GUI public class GuiIvVillagerHireNitwit extends GuiContainer{ private IvVillager villager; private IInventory playerInv; public GuiIvVillagerHireNitwit(IvVillager villager, IInventory playerInv) { super(new ContainerIvVillagerHireNitwit(villager, playerInv)); this.xSize = 176; this.ySize = 166; this.villager = villager; this.playerInv = playerInv; } @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(new ResourceLocation(Reference.MOD_ID, "gui/hire_nitwit.png")); this.drawTexturedModalRect(this.getGuiLeft(), this.getGuiTop(), 0, 0, this.xSize, this.ySize); } @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { String s = this.villager.getName(); Boolean has_emeralds; this.mc.fontRenderer.drawString(s, this.xSize / 2 - this.mc.fontRenderer.getStringWidth(s) / 2, 6, 4210752); this.mc.fontRenderer.drawString(this.playerInv.getDisplayName().getFormattedText(), 8, 72, 4210752); if (){ //this is where the container needs to be accessed has_emeralds = true; } else { has_emeralds = false; } this.addButton(new Button_Hire(0, 115, 20, 40, 25, "Hire", this.villager, has_emeralds)); } } As well, does addSlotToContainer id need to be different across containers? Edited May 24, 2017 by OrangeVillager61 Quote
Choonster Posted May 24, 2017 Posted May 24, 2017 The GuiContainer#inventorySlots field stores the Container that you pass to the GuiContainer constructor. You could have found this out for yourself by looking at the GuiContainer class in your IDE. Slot IDs only have to be unique within the Container instance. Two different Container instances can each have their own Slot instance with ID 1. 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 24, 2017 Author Posted May 24, 2017 20 minutes ago, Choonster said: The GuiContainer#inventorySlots field stores the Container that you pass to the GuiContainer constructor. You could have found this out for yourself by looking at the GuiContainer class in your IDE. Slot IDs only have to be unique within the Container instance. Two different Container instances can each have their own Slot instance with ID 1. Okay, thanks, however, when I compare the slot.getStack and the new ItemStack I want with a standard >=, it is undefined and I cannot seem to find an alternative. Quote
Jay Avery Posted May 24, 2017 Posted May 24, 2017 7 minutes ago, OrangeVillager61 said: Okay, thanks, however, when I compare the slot.getStack and the new ItemStack I want with a standard >=, it is undefined and I cannot seem to find an alternative. >= compares numbers, you can't compare ItemStacks with it. 1 Quote
Choonster Posted May 24, 2017 Posted May 24, 2017 2 minutes ago, OrangeVillager61 said: Okay, thanks, however, when I compare the slot.getStack and the new ItemStack I want with a standard >=, it is undefined and I cannot seem to find an alternative. Java doesn't allow operator overloading, so you can't use relational operators like >= to compare non-numeric values. Use the static equality methods in the ItemStack class to check if two ItemStacks are equal or use the getter methods to get each part of the ItemStack (e.g. ItemStack#getItem to get the Item, ItemStack#getCount to get the count/stack size). 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 25, 2017 Author Posted May 25, 2017 Alright, when I try to test the GUI I get errors that arrays cannot be cast to IvVillager on the line below. return new ContainerIvVillagerHauler((IvVillager) world.getEntitiesWithinAABB(IvVillager.class, vilSearch), player.inventory); Since I require an IvVillager as an argument, how can I get the IvVillager and select it? Quote
Choonster Posted May 25, 2017 Posted May 25, 2017 (edited) 23 minutes ago, OrangeVillager61 said: Alright, when I try to test the GUI I get errors that arrays cannot be cast to IvVillager on the line below. return new ContainerIvVillagerHauler((IvVillager) world.getEntitiesWithinAABB(IvVillager.class, vilSearch), player.inventory); Since I require an IvVillager as an argument, how can I get the IvVillager and select it? World#getEntitiesWithinAABB returns a List<T>, where T is the class you pass as the first argument or any super class up to Entity. You can't cast a List<T> to T, you need to get an individual element from the list. This is basic Java knowledge. Edited May 25, 2017 by Choonster 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 27, 2017 Author Posted May 27, 2017 (edited) Ah, okay, however, whenever I call the UI, it can't find anything so the list is empty. I think it is my AxisAlignedBB since I'm not sure if I specified the right area. Where the error occurs: @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { AxisAlignedBB vilSearch = new AxisAlignedBB(x, y - 1.0D, z, x, y + 2.0D, z); if (ID == Villager_Hire){ return new ContainerIvVillagerHireNitwit((IvVillager)world.getEntitiesWithinAABB(IvVillager.class, vilSearch).get(0), player.inventory); } } Where it is called: @Override public boolean processInteract(EntityPlayer player, EnumHand hand){ if (this.getHired() == false && this.getProfession() == 5 && !world.isRemote && !this.isChild()) { BlockPos blockpos = new BlockPos(this); player.openGui(Iv.instance, GuiHandler.Villager_Hire, world, blockpos.getX(), blockpos.getY(), blockpos.getZ()); return true; } } Edit: As well, when I try to register the data parameter that holds the player id, I get this: [13:45:40] [Server thread/ERROR] [FML]: Exception caught during firing event net.minecraftforge.event.entity.EntityJoinWorldEvent@44fae74c: java.lang.IllegalArgumentException: Duplicate id value for 15! at net.minecraft.network.datasync.EntityDataManager.register(EntityDataManager.java:105) ~[EntityDataManager.class:?] at orangeVillager61.ImprovedVillagers.Entities.IvVillager.entityInit(IvVillager.java:210) ~[IvVillager.class:?] Erroring code: this.getDataManager().register(OWNER_DEFINED_ID, Optional.<UUID>absent()); Edited May 27, 2017 by OrangeVillager61 Quote
Choonster Posted May 27, 2017 Posted May 27, 2017 (edited) 6 hours ago, OrangeVillager61 said: Ah, okay, however, whenever I call the UI, it can't find anything so the list is empty. I think it is my AxisAlignedBB since I'm not sure if I specified the right area. Where the error occurs: @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { AxisAlignedBB vilSearch = new AxisAlignedBB(x, y - 1.0D, z, x, y + 2.0D, z); if (ID == Villager_Hire){ return new ContainerIvVillagerHireNitwit((IvVillager)world.getEntitiesWithinAABB(IvVillager.class, vilSearch).get(0), player.inventory); } } Where it is called: @Override public boolean processInteract(EntityPlayer player, EnumHand hand){ if (this.getHired() == false && this.getProfession() == 5 && !world.isRemote && !this.isChild()) { BlockPos blockpos = new BlockPos(this); player.openGui(Iv.instance, GuiHandler.Villager_Hire, world, blockpos.getX(), blockpos.getY(), blockpos.getZ()); return true; } } You're creating an AABB with the x and z coordinates of the BlockPos as both the minimum and maximum coordinates, so the entity will only be found if its bounding box overlaps the northwest corner of the block it's standing on (the area represented by the AABB). You should instead create the AABB with the x and z coordinates of the BlockPos as the minimum coordinates and the x and z coordinates plus 1 as the maximum coordinates. This way the AABB will cover the entire block instead of just the northwest corner. The AxisAlignedBB(BlockPos) constructor does this for you, you can then use AxisAlignedBB#expand to expand it by 1 in each direction of the y axis (i.e. up and down). I created this item to experiment with corner- and edge-based AABBs passed to World#getEntitiesWithinAABB. Side note: You don't need to cast the result of the List#get call to IvVillager; the result of World#getEntitiesWithinAABB is a List<IvVillager> (because of the first argument), so the List#get call returns an IvVillager. Quote Edit: As well, when I try to register the data parameter that holds the player id, I get this: [13:45:40] [Server thread/ERROR] [FML]: Exception caught during firing event net.minecraftforge.event.entity.EntityJoinWorldEvent@44fae74c: java.lang.IllegalArgumentException: Duplicate id value for 15! at net.minecraft.network.datasync.EntityDataManager.register(EntityDataManager.java:105) ~[EntityDataManager.class:?] at orangeVillager61.ImprovedVillagers.Entities.IvVillager.entityInit(IvVillager.java:210) ~[IvVillager.class:?] Erroring code: this.getDataManager().register(OWNER_DEFINED_ID, Optional.<UUID>absent()); Are you registering the data parameter more than once? Post the IvVillager class using Gist or Pastebin. Edited May 27, 2017 by Choonster 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 28, 2017 Author Posted May 28, 2017 IvVillager gist: https://gist.github.com/Orange1861/7f412fe1d4c37921c39d0e5dc01079df.js Quote
OrangeVillager61 Posted May 28, 2017 Author Posted May 28, 2017 I still get nullpointerexceptions on the return hire container (I can't use Blockpos since the game requires it to be x, y and z). @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { AxisAlignedBB vilSearch = new AxisAlignedBB(x, y - 1, z, x + 1, y + 2, z + 1); if (ID == Villager_Hire){ return new ContainerIvVillagerHireNitwit((IvVillager)world.getEntitiesWithinAABB(IvVillager.class, vilSearch).get(0), player.inventory); //Erroring code } else if (ID == Hauler){ return new ContainerIvVillagerHauler((IvVillager)world.getEntitiesWithinAABB(IvVillager.class, vilSearch).get(0), player.inventory); } else { return null; } } Quote
Choonster Posted May 28, 2017 Posted May 28, 2017 (edited) 7 hours ago, OrangeVillager61 said: IvVillager gist: https://gist.github.com/Orange1861/7f412fe1d4c37921c39d0e5dc01079df.js Data parameter IDs are automatically assigned per class hierarchy. You're passing EntityTameable.class as the first argument of EntityDataManager.createKey, so the DataParameter is being assigned the next ID for the EntityTameable class instead of the next ID for the IvVillager class. When you try to register it for the IvVillager instance, there's already a DataParamter registered for that ID so the game crashes with an IllegalArgumentException. In future, please select the appropriate syntax highlighting when posting code on a site like Gist or Pastebin. To get syntax highlighting on Gist, give each file the appropriate extension (.java for Java code). To get syntax highlighting on Pastebin, select the language from the dropdown at the bottom of the page. The Adult_Age data parameter is Stringly Typed. I suggest replacing the strings with an enum. 7 hours ago, OrangeVillager61 said: I still get nullpointerexceptions on the return hire container I can't see any obvious reason for this. If you haven't already, please create a Git repository for your mod, push it to a site like GitHub and link it here so I can debug it locally. See my mod and its .gitignore file for an example of the repository structure to use and the files to include. Quote (I can't use Blockpos since the game requires it to be x, y and z). You can still create a BlockPos from the individual coordinates. Edited May 28, 2017 by Choonster Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 28, 2017 Author Posted May 28, 2017 27 minutes ago, Choonster said: Data parameter IDs are automatically assigned per class hierarchy. You're passing EntityTameable.class as the first argument of EntityDataManager.createKey, so the DataParameter is being assigned the next ID for the EntityTameable class instead of the next ID for the IvVillager class. When you try to register it for the IvVillager instance, there's already a DataParamter registered for that ID so the game crashes with an IllegalArgumentException. Huh, interesting, I wonder when I am registering for EntityTameable? I went through entityInit() dataParameters and there is no EntityTameable between IvVillager and EntityLiving and most of all, I renamed the variable from OWNER_UNIQUE_ID to OWNER_DEFINED_ID to prevent this specific issue. 27 minutes ago, Choonster said: In future, please select the appropriate syntax highlighting when posting code on a site like Gist or Pastebin. To get syntax highlighting on Gist, give each file the appropriate extension (.java for Java code). To get syntax highlighting on Pastebin, select the language from the dropdown at the bottom of the page. The Adult_Age data parameter is Stringly Typed. I suggest replacing the strings with an enum. Thanks for the advice. 27 minutes ago, Choonster said: I can't see any obvious reason for this. If you haven't already, please create a Git repository for your mod, push it to a site like GitHub and link it here so I can debug it locally. See my mod and its .gitignore file for an example of the repository structure to use and the files to include. I'll make a comit containing the current code on my mod's github, https://github.com/Orange1861/Improved-Villagers/pull/4 Quote
Choonster Posted May 30, 2017 Posted May 30, 2017 (edited) On 2017-5-29 at 1:33 AM, OrangeVillager61 said: Huh, interesting, I wonder when I am registering for EntityTameable? I went through entityInit() dataParameters and there is no EntityTameable between IvVillager and EntityLiving and most of all, I renamed the variable from OWNER_UNIQUE_ID to OWNER_DEFINED_ID to prevent this specific issue. As I said: On 2017-5-28 at 11:40 PM, Choonster said: You're passing EntityTameable.class as the first argument of EntityDataManager.createKey, This is in the OWNER_DEFINED_ID field initialiser. The name of the field doesn't matter, you could call it FOO_BAR_BAZ and the issue would still be present. On 2017-5-29 at 1:33 AM, OrangeVillager61 said: I'll make a comit containing the current code on my mod's github, https://github.com/Orange1861/Improved-Villagers/pull/4 Please include your buildscript (build.gradle and gradle.properties) in the repository. Edited May 30, 2017 by Choonster 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 30, 2017 Author Posted May 30, 2017 Ah, I see now with createKey, I thought you meant the registry, thanks. I have updated my project to contain some of the new fixes and the build.grade file you requested. Quote
Choonster Posted May 30, 2017 Posted May 30, 2017 (edited) I'll start debugging it now. I also recommend using a proper Git client (either the CLI or a GUI client like GitKraken or your IDE) rather than using GitHub's upload system. Edit: You should also include the Gradle wrapper (gradlew, gradlew.bat and the gradle directory) in your repository, though this isn't as essential as the buildscript. Edit 2: You should also include a .gitignore file to ensure only the required files are included in the repository. I linked an example in this post. Edited May 30, 2017 by Choonster 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
Choonster Posted May 30, 2017 Posted May 30, 2017 (edited) I figured out the issue: In your Container constructors you were trying to use the villager field, but you never assigned it a value so it was always null. You were also assigning the IItemHandler to a handler local variable instead of the handler field. I fixed these issues in this commit. I also fixed several other issues and changed GuiHandler to use the entity ID instead of the entity's coordinates (which avoids the potential of clicking one villager and opening a GUI for another standing in the same space). You can view and/or merge my changes here. Edited June 12, 2017 by Choonster Fixed link to changes 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 30, 2017 Author Posted May 30, 2017 6 hours ago, Choonster said: I figured out the issue: In your Container constructors you were trying to use the villager field, but you never assigned it a value so it was always null. You were also assigning the IItemHandler to a handler local variable instead of the handler field. I fixed these issues in this commit. I also fixed several other issues and changed GuiHandler to use the entity ID instead of the entity's coordinates (which avoids the potential of clicking one villager and opening a GUI for another standing in the same space). You can view and/or merge my changes here. Thank you so much! This fixed the bulk of my issues. However, my skill with GUI (especially with MC/Java) is limited and I have a major issue where when I put an item into the hire slot and the item disappears, I suspect that this may happen with the other GUI for the hired Villager which is supposed to act as a moving chest. Quote
Choonster Posted May 30, 2017 Posted May 30, 2017 17 minutes ago, OrangeVillager61 said: Thank you so much! This fixed the bulk of my issues. However, my skill with GUI (especially with MC/Java) is limited and I have a major issue where when I put an item into the hire slot and the item disappears, I suspect that this may happen with the other GUI for the hired Villager which is supposed to act as a moving chest. I also noticed that, I believe it's due to the IItemHandler returned by EntityLivingBase#getCapability being a wrapper of EntityLivingBase#handInventory and EntityLivingBase#armorArray. EntityLivingBase#onUpdate replaces the contents of these each tick with the ItemStacks returned by EntityLivingBase#getItemStackFromSlot (which EntityLiving implements using its own lists: EntityLiving#inventoryHands and EntityLiving#inventoryArmor), so any changes made through the IItemHandler are overwritten the next tick. I'm going to see if I can reproduce this and create a Forge issue/PR for it. In the meantime, you should create your own IItemHandler field in IvVillager and expose it via hasCapability/getCapability. Currently you're using slot 0 of the combined armour/hands inventories, which is the feet slot. 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 30, 2017 Author Posted May 30, 2017 So something like this? Or do I need to create a capability for the items? I did have a fully functioning capability system but now since it is unused parts of it have been removed (mainly proxy references) public IItemHandler item_handler; public IItemHandler getCapability() { return this.item_handler; } Quote
Choonster Posted May 30, 2017 Posted May 30, 2017 You need to initialise the IItemHandler field with an instance of an IItemHandler implementation. The default implementation of IItemHandler is ItemStackHandler, which will probably suit your needs. The field should also be private. Override EntityLivingBase#hasCapability (which implements ICapabilityProvider#hasCapability) to return true if the Capability argument is CapabilityItemHandler.ITEM_HANDLER_CAPABILITY or return the result of the super method if it's not Override EntityLivingBase#getCapability (which implements ICapabilityProvider#getCapability) to return the IItemHandler instance if the Capability argument is CapabilityItemHandler.ITEM_HANDLER_CAPABILITY or return the result of the super method if it's not. Due to limitations of Java's generics, you'll need to call Capability#cast on CapabilityItemHandler.ITEM_HANDLER_CAPABILITY with the IItemHandler as the argument to cast it to the return type. Calling the super method allows capabilities to be provided by super classes or attached with AttachCapabilityEvent. 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 30, 2017 Author Posted May 30, 2017 18 minutes ago, Choonster said: Due to limitations of Java's generics, you'll need to call Capability#cast on CapabilityItemHandler.ITEM_HANDLER_CAPABILITY with the IItemHandler as the argument to cast it to the return type. Okay, I understand the rest of the text, but I don't really understand this. Is the below what you meant? @Override public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, @Nullable net.minecraft.util.EnumFacing facing) { if (capability.equals(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)) { return true; } else { return super.hasCapability(capability, facing); } } @SuppressWarnings("unchecked") @Override @Nullable public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable net.minecraft.util.EnumFacing facing) { if (capability.equals((Capability)CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)) { return (T) this.item_handler; } else { return super.getCapability(capability, facing); } } Quote
Choonster Posted May 30, 2017 Posted May 30, 2017 1 minute ago, OrangeVillager61 said: Okay, I understand the rest of the text, but I don't really understand this. Is the below what you meant? Almost, but not quite. Instead of casting this.item_handler directly to T and suppressing the unchecked warnings resulting from it, call CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast with this.item_handler as the argument. Capability objects are singletons, compare them with the equality operator (==) rather than the Object#equals method. CapabilityItemHandler.ITEM_HANDLER_CAPABILITY is a field of type Capability (more specifically Capability<IItemHandler>), there's no reason to cast it to Capability. In addition to that, there's no Capability#equals method with a Capability parameter; only Object#equals with an Object parameter. Only cast when it's required by the compiler. Import classes like Capability and EnumFacing instead of using fully-qualified names. Forge only uses fully-qualified names in vanilla patches to reduce the patch size (by removing the need for an import statement). 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
OrangeVillager61 Posted May 30, 2017 Author Posted May 30, 2017 5 minutes ago, Choonster said: Almost, but not quite. Instead of casting this.item_handler directly to T and suppressing the unchecked warnings resulting from it, call CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast with this.item_handler as the argument. Capability objects are singletons, compare them with the equality operator (==) rather than the Object#equals method. CapabilityItemHandler.ITEM_HANDLER_CAPABILITY is a field of type Capability (more specifically Capability<IItemHandler>), there's no reason to cast it to Capability. In addition to that, there's no Capability#equals method with a Capability parameter; only Object#equals with an Object parameter. Only cast when it's required by the compiler. Import classes like Capability and EnumFacing instead of using fully-qualified names. Forge only uses fully-qualified names in vanilla patches to reduce the patch size (by removing the need for an import statement). Oh, okay. Do I still cast this.item_handler to T since I get errors when I don't? Quote
Choonster Posted May 30, 2017 Posted May 30, 2017 1 minute ago, OrangeVillager61 said: Oh, okay. Do I still cast this.item_handler to T since I get errors when I don't? 1 minute ago, OrangeVillager61 said: Instead of casting this.item_handler directly to T and suppressing the unchecked warnings resulting from it, call CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast with this.item_handler as the argument. Capability#cast casts it for you without the unchecked warning. 1 Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
Recommended Posts
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.