JayZX535 Posted April 24, 2020 Posted April 24, 2020 Hey all, I'm currently in the process of trying to implement an inventory for an entity. I want the player to be able to click the entity and access its inventory. So far I've been basing a lot off the horse classes, however the horse handles opening the gui by calling playerEntity.openHorseInventory(this, this.horseChest); , but since my entity isn't connected to the horse classes, that's not gonna work for me. Is there another way I can open the entity's GUI? I think everything else should be set up beyond that-- it's just a matter of opening the GUI in the first place. I assume registration is the same for an entity container as for a tileentity container, so unless that's different I think everything else should work... Thanks! Quote
ChampionAsh5357 Posted April 24, 2020 Posted April 24, 2020 If you have already created a block with a Container, you would know that using NetworkHooks#openGui is used to activate a container and its gui counterpart. Unless I'm mistaken, it should be the same process. Quote
JayZX535 Posted May 12, 2020 Author Posted May 12, 2020 Apologies for the massively delayed response. I've been troubleshooting... a lot 9.9 I was a little bit blind and was looking at the wrong method in the blocks. Blocks use this to open GUIs... public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { player.openContainer(state.getContainer(worldIn, pos)); return true; } Which works. Well, kind of. The game now tries to open the GUI-- before erroring and crashing. It's having issues with the inventory container, and in particular, the inventory getting passed to it being null. Which brings up a totally different problem... The registry: public static ContainerType<WCTradingPostContainer> WC_TRADING_POST_CONTAINER; public static ContainerType<WCKibblePressContainer> WC_KIBBLE_PRESS_CONTAINER; public static ContainerType<WCCanineEntityContainer> WC_CANINE_INVENTORY_CONTAINER; @SuppressWarnings ("unchecked") public static void registerContainerTypes(final RegistryEvent.Register<ContainerType<?>> event){ event.getRegistry().registerAll( WC_TRADING_POST_CONTAINER = (ContainerType<WCTradingPostContainer>) new ContainerType<WCTradingPostContainer>(WCTradingPostContainer::new).setRegistryName("wc_trading_post"), WC_KIBBLE_PRESS_CONTAINER = (ContainerType<WCKibblePressContainer>) new ContainerType<WCKibblePressContainer>(WCKibblePressContainer::new).setRegistryName("wc_kibble_press"), WC_CANINE_INVENTORY_CONTAINER = (ContainerType<WCCanineEntityContainer>) new ContainerType<WCCanineEntityContainer>(WCCanineEntityContainer::new).setRegistryName("wc_canine_inventory") ); } Relevant part of the container code... public WCCanineEntityContainer(int windowId, PlayerInventory playerInv) { this(windowId, playerInv, null); } public WCCanineEntityContainer(int windowId, PlayerInventory playerInv, final WCAnimalEntity animal) { super(WCRegistry.WC_CANINE_INVENTORY_CONTAINER, windowId); this.animal = animal; System.out.println(animal); this.animalInventory = animal.animalInventory(); animalInventory.openInventory(playerInv.player); } That print statement indicates that "animal" is null. I'm passing the animal in through the getContainer method I use to open the GUI... @Nullable @Override public INamedContainerProvider getContainer() { return new SimpleNamedContainerProvider((windowId, playerInv, name) -> { return new WCCanineEntityContainer(windowId, playerInv, this); }, this.getTranslationText()); } but I assume that's being overridden by the registry seems to call the first method, which passes the animal as "null". The block guis get around it by using this... public WCKibblePressContainer(int windowId, PlayerInventory playerInv) { this(windowId, playerInv, IWorldPosCallable.DUMMY); } public WCKibblePressContainer(int windowId, PlayerInventory playerInv, final IWorldPosCallable worldPos) { super(WCRegistry.WC_KIBBLE_PRESS_CONTAINER, windowId); this.worldPos = worldPos; } So... I can only assume that the difference comes from that "IWorldPosCallable.Dummy", unless I've just been staring at this for so long that I'm missing something glaring. But I don't have any sort of dummy method to use instead of null, and frankly I'm not quite sure how to make one. The animal itself does get initialized properly, so it shouldn't be an issue there? I feel like I'm missing something big, and I have yet to find an example of a working entity inventory to go off-- aside from horses, which have their own special opener hard-coded into the player (as mentioned previously). Anyone know how I could get around this? Quote
TheGreyGhost Posted May 12, 2020 Posted May 12, 2020 Howdy The open source Botania mod does something similar with Items (eg a bag that can hold items)- that may have some clues for you. Off the cuff, it sounds you may have a mismatch between client and server. It's not obvious in vanilla but when you open a container (eg for a chest), the container on the server is bound to the vanilla object (usually a tileentity) but the client container is not (in the case of a chest, for example, it's given a freshly-created (empty) IInventory instead of a TileEntity). The client container is synchronised with the server using the GUI slots packets. eg this diagram http://greyminecraftcoder.blogspot.com/2020/04/containers-1144.html -TGG 1 Quote
JayZX535 Posted May 15, 2020 Author Posted May 15, 2020 On 5/12/2020 at 4:45 PM, TheGreyGhost said: Howdy The open source Botania mod does something similar with Items (eg a bag that can hold items)- that may have some clues for you. Off the cuff, it sounds you may have a mismatch between client and server. It's not obvious in vanilla but when you open a container (eg for a chest), the container on the server is bound to the vanilla object (usually a tileentity) but the client container is not (in the case of a chest, for example, it's given a freshly-created (empty) IInventory instead of a TileEntity). The client container is synchronised with the server using the GUI slots packets. eg this diagram http://greyminecraftcoder.blogspot.com/2020/04/containers-1144.html -TGG Thank you so much-- this helped me a lot! Blocks seem to handle containers differently than most other things-- Forge handles them a bit better inherently (which is as to be expected-- most GUIs would be coming from blocks, after all). I eventually also found the registry method that allows me to send data with the container. I used that to pass the entityID, allowing me to register it as... event.getRegistry().register(IForgeContainerType.create((windowId, inv, data) -> { int id = data.readInt(); return new WCCanineEntityContainer(windowId, inv, id); }).setRegistryName("wc_canine_inventory")); It's now up and running as expected, so thank you again for your help! Quote
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.