Jump to content

[1.14.4] Entity with Inventory GUI


JayZX535

Recommended Posts

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!

Link to comment
Share on other sites

  • 3 weeks later...

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?

Link to comment
Share on other sites

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

 

 

  • Like 1
Link to comment
Share on other sites

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!

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



×
×
  • Create New...

Important Information

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