Jump to content

[1.14.4] Gui/Container for Player (No tile entity)


wog890

Recommended Posts

I'm attempting to override the default inventory GUI and replace it with my own. I have already created a simple Gui and have it implemented (opens on pressing k). I used it to test my code to override the vanilla inventory opening. In my client event subscriber I call

 

@SubscribeEvent
public static void onGuiOpenEvent(GuiOpenEvent event) {
	if (Minecraft.getInstance().player.getCapability(RPGProvider.RPG_CAP).orElse(null).isRPGActive() && event.getGui() instanceof InventoryScreen) {
  		event.setGui(new AbilityScoresScreen(new TranslationTextComponent("demo.help.title")));
    }
}

 

Not sure if that really is the best way, but it is working. Only downside is I can't seem to manage to have the new Gui closed when pressing "E".

 

Now I'm trying to actually create the new inventory screen and container. I'm not finding much information on how to implement this in 1.14 and all of what I have found deals with containers tied to block tile entities. Mcjty has one of the more descriptive examples but wasn't really what I needed and didn't match to what is largely mentioned and recommended by Desht. I have created a container that is largely a mimic of PlayerContainer, but places the slots in the correct x,y points and adds my many new equipment slots. It also skips all the logic for recipe book and crafting as my screen does not need them. I've now started on the new inventory screen and am kinda stuck.

 

The default InventoryScreen constructs with the code

 

public InventoryScreen(PlayerEntity player) {
	super(player.container, player.inventory, new TranslationTextComponent("container.crafting"));
	this.passEvents = true;
}

 

I can largely mimic this, but need access to my container instead of the default player.container. What is the correct way to be doing this?

 

For registering the container, or opening from the client, Desht states that I should use a constructor in the form of:

 

public MyContainer(int windowId, PlayerInv inv, PacketBuffer extraData) {
	super(ContainerType<?>, windowId);
	doThings();
}

And a second constructor for the server side. The vanilla inventory container uses the constructor below, which I mimicked and would be my server one?

 

public PlayerContainer(PlayerInventory playerInventory, boolean localWorld, PlayerEntity playerIn) {
	super((ContainerType<?>)null, 0);
	this.isLocalWorld = localWorld;
	this.player = playerIn;
    // All the code for placing slots is after this....  
}

I'm kinda stuck and not sure how to progress, any help would be much appreciated. As a summery my questions are:

 

  1. How do I get my container when calling the constructor for my inventory screen
  2. Proper registration of my container/correct set up of multiple constructors
  3. Not fully understanding why the client and server need separate constructors
  4. (Bonus and not really important) any recommendations on how to close the screen if "E" is pressed again. Doing a simple key bind on the "E" key doesn't ever fire. I'm guessing the default open inventory is capturing it and preventing it from continuing.

 

Below is the entire code for my container and screen (although there isn't really anything to the screen yet).

 

RPGInventoryContainer.java

package com.github.wog890.wogmods.inventory.container;

import javax.annotation.Nullable;

import com.github.wog890.wogmods.enums.EEquipmentSlotType;
import com.github.wog890.wogmods.item.RPGItem;

import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.ContainerType;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

public class RPGInventoryContainer extends Container {
	
	private static final String [] ARMOR_SLOT_TEXTURES = new String[] {
			"item/empty_armor_slot_chestplate", "", "", "",
			"", "item/empty_armor_slot_boots", "", "item/empty_armor_slot_helmet",
			"", "", "",
			"", "", ""};
	
	
	private static final EEquipmentSlotType[] VALID_EQUIPMENT_SLOTS = new EEquipmentSlotType[] {
			EEquipmentSlotType.ARMOR, EEquipmentSlotType.BELT, EEquipmentSlotType.BODY, EEquipmentSlotType.CHEST,
			EEquipmentSlotType.EYES, EEquipmentSlotType.FEET, EEquipmentSlotType.HANDS, EEquipmentSlotType.HEAD,
			EEquipmentSlotType.HEADBAND, EEquipmentSlotType.NECK, EEquipmentSlotType.RING_LEFT,
			EEquipmentSlotType.RING_RIGHT, EEquipmentSlotType.SHOULDERS, EEquipmentSlotType.WRIST};
	
	public final boolean isLocalWorld;
	
	private final PlayerEntity player;
	
	public RPGInventoryContainer(int windowId, PlayerInventory inv, PacketBuffer extraData) {
		super((ContainerType<?>)null, windowId);
		player = inv.player;
              
        // Temporary to prevent error being fired. Will set this properly later
		isLocalWorld = false;
	}
	
	public RPGInventoryContainer(PlayerInventory invIn, boolean localWorld, PlayerEntity playerIn) {
		super((ContainerType<?>)null, 108);
		this.isLocalWorld = localWorld;
		this.player = playerIn;
		
		// Places the slots for the main player inventory
		// Index Range: 9 - 35
		for (int j=0; j<3; ++j) {
			for (int k=0; k<9; ++k) {
				this.addSlot(new Slot(invIn, k+(j+1)*9, 49+k*18, 92+j*18));
			}
		}
		
		// Places the slots for the main player hotbar
		// Index Range: 0 - 8
		for (int l=0; l<9; ++l) {
			this.addSlot(new Slot(invIn, l, 49+l*18, 150));
		}
		
		// Places the offhand slot
		// Index Range: 40
		this.addSlot(new Slot(invIn, 40, 122, 72) {
			@Nullable
			@OnlyIn(Dist.CLIENT)
			public String getSlotTexture() {
				return "item/empty_armor_slot_shield";
			}
		});
		
		// Places the many equipments slots
		// Index Range: 41 - 54
		for (int m=0; m<14; ++m) {
			final EEquipmentSlotType slotType = VALID_EQUIPMENT_SLOTS[m];
			this.addSlot(new Slot(invIn, slotType.getSlotIndex(), slotType.getX(), slotType.getY()) {
				
				public int getSlotStackLimit() {
					return 1;
				}
				
				public boolean isItemValid(ItemStack stack) {
					if (!(stack.getItem() instanceof RPGItem)) return false;
					return ((RPGItem)stack.getItem()).canEquip(slotType);
				}
				
				public boolean canTakeStack(PlayerEntity playerIn) {
					ItemStack itemstack = this.getStack();
					return !itemstack.isEmpty() && !playerIn.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(playerIn);
				}
				
				@Nullable
				@OnlyIn(Dist.CLIENT)
				public String getSlotTexture() {
					return RPGInventoryContainer.ARMOR_SLOT_TEXTURES[slotType.getIndex()];
				}
				
			});
		}
	}
	
	@Override
	public boolean canInteractWith(PlayerEntity playerIn) {
		return true;
	}

}

 

InventoryScreen.java

package com.github.wog890.wogmods.client.gui.screen;

import com.github.wog890.wogmods.inventory.container.RPGInventoryContainer;

import net.minecraft.client.gui.DisplayEffectsScreen;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.text.TranslationTextComponent;

public class RPGInventoryScreen extends DisplayEffectsScreen<RPGInventoryContainer> {
	
	public RPGInventoryScreen(PlayerEntity player) {
  		//null needs to be my RPGInventoryContainer
		super(null, player.inventory, new TranslationTextComponent("containers.wogmods.inv"));
		this.passEvents = true;
	}

	@Override
	protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
		// TODO Auto-generated method stub
		
	}

}

 

Link to comment
Share on other sites

56 minutes ago, wog890 said:

DisplayEffectsScreen<RPGInventoryContainer>

Extend ContainerScreen instead. This will solve the E button problem.

56 minutes ago, wog890 said:

How do I get my container when calling the constructor for my inventory screen

PlayerEntity#openContainer assuming your container is the one open on the client side.

58 minutes ago, wog890 said:

Proper registration of my container/correct set up of multiple constructors

Show what you are doing now.

59 minutes ago, wog890 said:

Not fully understanding why the client and server need separate constructors

They don't. The only reason to have a PacketBuffer parameter in your constructor is to pass extra data over from the server. I dont think yours needs that.

 

I'm not at my IDE at the moment so I cant give you definitive answers with code, but I think I can point you in the proper direction, where to look, ect.

  • Like 1

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

49 minutes ago, Animefan8888 said:

Extend ContainerScreen instead. This will solve the E button problem.

PlayerEntity#openContainer assuming your container is the one open on the client side.

Show what you are doing now.

They don't. The only reason to have a PacketBuffer parameter in your constructor is to pass extra data over from the server. I dont think yours needs that.

 

I'm not at my IDE at the moment so I cant give you definitive answers with code, but I think I can point you in the proper direction, where to look, ect.

Alrighty.

 

Updated RPGInventoryScreen

public class RPGInventoryScreen extends ContainerScreen<RPGInventoryContainer> {
	
	public RPGInventoryScreen(PlayerEntity player) {
		super((RPGInventoryContainer) player.openContainer, player.inventory, new TranslationTextComponent("containers.wogmods.inv"));
		this.passEvents = true;
	}

	@Override
	protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
		// TODO Auto-generated method stub
		
	}

}

 

 

So I started attempting to register the container like so:

@SubscribeEvent
public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) {
	event.getRegistry().registerAll(
		RPGInventoryContainer.class
	);
}

or
  
@SubscribeEvent
public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) {
	event.getRegistry().registerAll(
    	// Just a test, would need to pass a proper inventory as the middle argument. Wasn't sure how to do this though.
      	// Minecraft.getInstance().player.inventory would be accessing it through the ClientEntityPlayer which seems wrong...
      	// Sides still trip me up a good bit :-/
  		new RPGInventoryContainer(0, null, null)
	);
}

 

This of course didn't work as the event is registering ContainerTypes not Containers. Once I realized this I actually looked at what ContainerType was. Looking at that I can see it registering containers through calling something like

public static final ContainerType<RepairContainer>  = register("anvil", RepairContainer::new);

The container type is being passed a key and creating an instance of the passed container (right), but each of these is connected to a block except for MerchantContainer.

(I'm kinda just assuming that MerchantContainer is attached to villagers who trade). PlayerContainer is not registered here and because of this when constructed it simply calls

super((ContainerType<?>)null, 0);

 

Because of this I'm unsure of if I should be registering my container or not.

 

Halfway through typing this I realized I hadn't look at McJty's example to see how he registered his container. That was stupid of me. Matching his code I now have this:

 

@SubscribeEvent
public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) {
	event.getRegistry().register(IForgeContainerType.create((windowId, inv, data) -> {
		return new RPGInventoryContainer(windowId, inv, data);
	}).setRegistryName("rpg_inventory"));
}

@ObjectHolder("wogmods:rpg_inventory")
public static ContainerType<RPGInventoryContainer> RPG_INV_CONTAINER;

 

He also states that the ContainerType is only used client side. So I can register my container if needed.

 

Sorry for the rambling and long description. The only way I can think to describe my confusion is to go through my thought process. Thank you for the help!

Edited by wog890
Slight edits to registerContainers and adding @ObjectHolder
Link to comment
Share on other sites

14 minutes ago, wog890 said:

He also states that the ContainerType is only used client side. So I can register my container if needed.

Well I cant think of any reason why you wouldn't register it, it's also needed in the Container class so I'm not sure that's entirely accurate.

 

15 minutes ago, wog890 said:

Matching his code I now have this:

That all looks good. Though unless you are sending specific data to the client like a TileEntity's BlockPos(which you are not) you dont need to worry about the PacketBuffer Parameter. You can also have one constructor and deserialize the data in the lambda.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

On 9/30/2019 at 11:09 PM, Animefan8888 said:

Well I cant think of any reason why you wouldn't register it, it's also needed in the Container class so I'm not sure that's entirely accurate.

 

That all looks good. Though unless you are sending specific data to the client like a TileEntity's BlockPos(which you are not) you dont need to worry about the PacketBuffer Parameter. You can also have one constructor and deserialize the data in the lambda.

So I thought I had it, but its all gone soooo downhill. From your second comment I updated container registry to:

 

@SubscribeEvent
public static void registerContainers(final RegistryEvent.Register<ContainerType<?>> event) {
	event.getRegistry().register(IForgeContainerType.create(RPGInventoryContainer::new).setRegistryName("rpg_inventory"));
}

 

The screen is now successfully opening and looks great! I then started adding the slots and ran into a weird amount of issues. I have the feeling the issues are being caused by me creating/registering the screen/container wrong or opening it wrong. I'll try to describe the issues first and then add the code I've written for opening the gui. Any help would be much appreciated.

 

Quick description, my inventory has the default 9 slots for the hotbar, 27 slots for the inventory, 1 slot for the offhand, and then 14 custom equipment slots. None of these 14 custom slots match to a vanilla armor slot. For testing my inventory I would first use the Vanilla inventory screen to place one item in the first hotbar slot, and then 4 items in the main inventory (one in each corner). When opening my modded inventory this appears exactly as it should.

 

Bug 1: I immediately noticed that I could not move any of my items. When clicking on a slot containing an item, nothing would happen. I then realized that if you clicked the slot directly below a slot containing an item, it would pick up the item in the slot above it. Likewise, while holding an item, clicking an empty slot will place the item into the slot above the one clicked. This was persistent whether I had all slots (vanilla and my custom), just vanilla slots, or just a single slot.

Bug 2: All kinds of weird behavior on shift-click. Kinda hard to describe, so just noting it exists.

Bug 3: The game crashes when I click the majority of my custom equipment slots. The error is

java.lang.IndexOutOfBoundsException: Index: 46, Size: 46

I originally thought this was being caused because I was adding my equipment slots directly to the player inventory by running:

//This was actually done as a for loop, but I don't have that code any longer and this gets the point across.
this.player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(h -> {
	this.addSlot(new SlotItemHandler(h, slotType.getSlotIndex(), slotType.getX(), slotType.getY()));
});

I should've read the error better. I instead added an ItemStackHandler of size 14 to my main RPGCapability and added some small code to the storage class to handle reading and writing. I then updated my container's code to:

this.player.getCapability(RPGProvider.RPG_CAP).ifPresent(rpg -> {
  ItemStackHandler itemstackHandler = rpg.getItemStackHandler();
  
  // Places the many equipments slots
  // Index Range: 0 - 13
  for (int m=0; m<14; ++m) {
    final EEquipmentSlotType slotType = VALID_EQUIPMENT_SLOTS[m];
    this.addSlot(new SlotItemHandler(itemstackHandler, slotType.getSlotIndex(), slotType.getX(), slotType.getY()) {
      
      public int getSlotStackLimit() {
        return 1;
      }
      
      public boolean isItemValid(ItemStack stack) {
        if (!(stack.getItem() instanceof RPGItem)) return false;
        return ((RPGItem)stack.getItem()).canEquip(slotType);
      }
      
      public boolean canTakeStack(PlayerEntity playerIn) {
        ItemStack itemstack = this.getStack();
        return !itemstack.isEmpty() && !playerIn.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(playerIn);
      }
      
      @Nullable
      @OnlyIn(Dist.CLIENT)
      public String getSlotTexture() {
        return RPGInventoryContainer.ARMOR_SLOT_TEXTURES[slotType.getIndex()];
      }
    });
  }
});

This in no way fixed the crashing and I decided that the slots were still being attached to my main player inventory. I spent an embarrassingly long time trying to fix this and then finally decided to look a little closer to the error log:

---- Minecraft Crash Report ----
// Ouch. That hurt :(

Time: 10/7/19 7:53 PM
Description: mouseClicked event handler

java.lang.IndexOutOfBoundsException: Index: 46, Size: 46
	at java.util.ArrayList.rangeCheck(Unknown Source) ~[?:1.8.0_181] {}
	at java.util.ArrayList.get(Unknown Source) ~[?:1.8.0_181] {}
	at net.minecraft.inventory.container.Container.slotClick(Container.java:258) ~[forge-1.14.4-28.0.11_mapped_snapshot_20190723-1.14.3-recomp.jar:?] {}

//Line 258 of Container.java
Slot slot6 = this.inventorySlots.get(slotId);

I've realized it is simply that the container's inventorySlots variable is what is actually being called as out of bounds exception. I've only just hit this point, so I haven't dug any deeper into this particular issue yet.

 

As my goal is to override the vanilla inventory screen, I am currently calling my screen by:

//This is within a client only event subscriber

@SubscribeEvent
public static void onGuiOpenEvent(GuiOpenEvent event) {
  	// I was having an issue with something being null and I got a little heavyhanded.....
	if (Minecraft.getInstance() != null && Minecraft.getInstance().player != null && event.getGui() != null) {
      	// This checks if the player is set to default vanilla behavior or if my mod should override
		if (Minecraft.getInstance().player.getCapability(RPGProvider.RPG_CAP).orElse(null).isRPGActive() && event.getGui() instanceof InventoryScreen) {
			ClientPlayerEntity player = Minecraft.getInstance().player;
          	// event.setGui(Screen gui)
          	// new RPGInventoryScreen(RPGInventoryContainer container, PlayerInventory inv, ITextComponent name)
          	// new RPGInventoryContainer(int windowId, PlayerInventory invIn)
			event.setGui(new RPGInventoryScreen(new RPGInventoryContainer(0, player.inventory), player.inventory, new TranslationTextComponent("demo.help.title")));
		}
	}
}

Once again, sorry for the long post and rambling. I appreciate any help provided. The equipment setup is the bottleneck for me to work on any other part of what I'm doing and I'm not really sure what is wrong here or what to dive deeper into.

Link to comment
Share on other sites

I forgot to add the container code in case it is helpful:

 

RPGInventoryContainer.java

public class RPGInventoryContainer extends Container {
	
	private static final String [] ARMOR_SLOT_TEXTURES = new String[] {
			"item/empty_armor_slot_chestplate", "", "", "",
			"wogmods:item/empty_equip_slot_eyes", "item/empty_armor_slot_boots", "item/empty_equip_slot_glove", "item/empty_equip_slot_hat",
			"item/empty_armor_slot_helmet", "", "item/empty_equip_slot_ring",
			"item/empty_equip_slot_ring", "", "item/empty_equip_slot_bracelet"};
	
	
	private static final EEquipmentSlotType[] VALID_EQUIPMENT_SLOTS = new EEquipmentSlotType[] {
			EEquipmentSlotType.ARMOR, EEquipmentSlotType.BELT, EEquipmentSlotType.BODY, EEquipmentSlotType.CHEST,
			EEquipmentSlotType.EYES, EEquipmentSlotType.FEET, EEquipmentSlotType.HANDS, EEquipmentSlotType.HEAD,
			EEquipmentSlotType.HEADBAND, EEquipmentSlotType.NECK, EEquipmentSlotType.RING_LEFT,
			EEquipmentSlotType.RING_RIGHT, EEquipmentSlotType.SHOULDERS, EEquipmentSlotType.WRIST};
	
	private final PlayerEntity player;
	
	public RPGInventoryContainer(int windowId, PlayerInventory invIn) {
		this(windowId, invIn, null);
	}
	
	public RPGInventoryContainer(int windowId, PlayerInventory invIn, PacketBuffer extraData) {
		super(WogMods.RPG_INV_CONTAINER, windowId);
		player = invIn.player;
		
		// Places the slots for the main player inventory
		// Index Range: 9 - 35
		for (int j=0; j<3; ++j) {
			for (int k=0; k<9; ++k) {
				this.addSlot(new Slot(invIn, k+(j+1)*9, 30+k*18, 89+j*18));
			}
		}
		
		// Places the slots for the main player hotbar
		// Index Range: 0 - 8
		for (int l=0; l<9; ++l) {
			this.addSlot(new Slot(invIn, l, 30+l*18, 147));
		}
		
		// Places the offhand slot
		// Index Range: 40
		this.addSlot(new Slot(invIn, 40, 103, 69) {
			@Nullable
			@OnlyIn(Dist.CLIENT)
			public String getSlotTexture() {
				return "item/empty_armor_slot_shield";
			}
		});
		
		this.player.getCapability(RPGProvider.RPG_CAP).ifPresent(rpg -> {
			
			ItemStackHandler itemstackHandler = rpg.getItemStackHandler();
			
			// Places the many equipments slots
			// Index Range: 41 - 54
			for (int m=0; m<14; ++m) {
				final EEquipmentSlotType slotType = VALID_EQUIPMENT_SLOTS[m];
				this.addSlot(new SlotItemHandler(itemstackHandler, slotType.getSlotIndex(), slotType.getX(), slotType.getY()) {
								
					public int getSlotStackLimit() {
						return 1;
					}
								
					public boolean isItemValid(ItemStack stack) {
						if (!(stack.getItem() instanceof RPGItem)) return false;
						return ((RPGItem)stack.getItem()).canEquip(slotType);
					}
					
					public boolean canTakeStack(PlayerEntity playerIn) {
						ItemStack itemstack = this.getStack();
						return !itemstack.isEmpty() && !playerIn.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(playerIn);
					}
					
					@Nullable
					@OnlyIn(Dist.CLIENT)
					public String getSlotTexture() {
						return RPGInventoryContainer.ARMOR_SLOT_TEXTURES[slotType.getIndex()];
					}
					
				});
			}
		});
	}
	
	@Override
	public boolean canInteractWith(PlayerEntity playerIn) {
		return true;
	}

}

 

Link to comment
Share on other sites

38 minutes ago, wog890 said:

I forgot to add the container code in case it is helpful:

You are only ever changing the gui. This is a problem you must also change the container on the server.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

19 minutes ago, Animefan8888 said:

You are only ever changing the gui. This is a problem you must also change the container on the server.

Ahhh, that does make sense. Would you know the correct way to do this.

 

I added player.openContainer(new RPGProvider()); just after event.setGui(); call.

 

With the RPGProvider class being:

public class RPGInventoryProvider implements INamedContainerProvider {

	@Override
	public Container createMenu(int windowId, PlayerInventory invIn, PlayerEntity player) {
		return new RPGInventoryContainer(windowId, invIn);
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TranslationTextComponent("containers.wogmods.rpgInv");
	}
	
}

I'm guessing I might be messing up the sides and need to call player.openContainer() from the server side? Do I need to have my clientEventSubscriber send a packet to the server that then calls this instead?

Link to comment
Share on other sites

8 minutes ago, wog890 said:

Do I need to have my clientEventSubscriber send a packet to the server that then calls this instead?

If I remember correctly there is a ContainerOpenEvent but part of me says that you are not allowed to change the container from inside it. Though you can check it might even say it in the javadoc.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

13 minutes ago, Animefan8888 said:

If I remember correctly there is a ContainerOpenEvent but part of me says that you are not allowed to change the container from inside it. Though you can check it might even say it in the javadoc.

There is an event:

PlayerContainerEvent.Open

I'll mess with this some, but I did find a post from 2016 when googling OpenContainerEvent 

It seems like he is essentially doing the same thing! Diesieben07 says that using that event won't work as expected? The only other suggestion in the post is to send a packet and use IGuiHandler to open a custom container and gui? I'll tinker with both and see what happens :-).

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.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
    • It is an issue with quark - update it to this build: https://www.curseforge.com/minecraft/mc-mods/quark/files/3642325
  • Topics

×
×
  • Create New...

Important Information

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