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

    • This honestly might just work for you @SubscribeEvent public static void onScreenRender(ScreenEvent.Render.Post event) { final var player = Minecraft.getInstance().player; if(!hasMyEffect(player)) return; // TODO: You provide hasMyEffect float f = Mth.lerp(p_109094_, this.minecraft.player.oSpinningEffectIntensity, this.minecraft.player.spinningEffectIntensity); float f1 = ((Double)this.minecraft.options.screenEffectScale().get()).floatValue(); if(f <= 0F || f1 >= 1F) return; float p_282656_ = ?; final var p_282460_ = event.getGuiGraphics(); int i = p_282460_.guiWidth(); int j = p_282460_.guiHeight(); p_282460_.pose().pushPose(); float f = Mth.lerp(p_282656_, 2.0F, 1.0F); p_282460_.pose().translate((float)i / 2.0F, (float)j / 2.0F, 0.0F); p_282460_.pose().scale(f, f, f); p_282460_.pose().translate((float)(-i) / 2.0F, (float)(-j) / 2.0F, 0.0F); float f1 = 0.2F * p_282656_; float f2 = 0.4F * p_282656_; float f3 = 0.2F * p_282656_; RenderSystem.disableDepthTest(); RenderSystem.depthMask(false); RenderSystem.enableBlend(); RenderSystem.blendFuncSeparate(SourceFactor.ONE, DestFactor.ONE, SourceFactor.ONE, DestFactor.ONE); p_282460_.setColor(f1, f2, f3, 1.0F); p_282460_.blit(NAUSEA_LOCATION, 0, 0, -90, 0.0F, 0.0F, i, j, i, j); p_282460_.setColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.defaultBlendFunc(); RenderSystem.disableBlend(); RenderSystem.depthMask(true); RenderSystem.enableDepthTest(); p_282460_.pose().popPose(); }   Note: Most of this is directly copied from GameRenderer as you pointed out you found. The only thing you'll have to likely do is update the `oSpinningEffectIntensity` + `spinningEffectIntensity` variables on the player when your effect is applied. Which values should be there? Not 100% sure, might be a game of guess and check, but `handleNetherPortalClient` in LocalPlayer has some hard coded you might be able to start with.
    • Dalam dunia perjudian online yang berkembang pesat, mencari platform yang dapat memberikan kemenangan maksimal dan hasil terbaik adalah impian setiap penjudi. OLXTOTO, dengan bangga, mempersembahkan dirinya sebagai jawaban atas pencarian itu. Sebagai platform terbesar untuk kemenangan maksimal dan hasil optimal, OLXTOTO telah menciptakan gelombang besar di komunitas perjudian online. Satu dari banyak keunggulan yang dimiliki OLXTOTO adalah koleksi permainan yang luas dan beragam. Dari togel hingga slot online, dari live casino hingga permainan kartu klasik, OLXTOTO memiliki sesuatu untuk setiap pemain. Dibangun dengan teknologi terkini dan dikembangkan oleh para ahli industri, setiap permainan di platform ini dirancang untuk memberikan pengalaman yang tak tertandingi bagi para penjudi. Namun, keunggulan OLXTOTO tidak hanya terletak pada variasi permainan yang mereka tawarkan. Mereka juga menonjol karena komitmen mereka terhadap keamanan dan keadilan. Dengan sistem keamanan tingkat tinggi dan proses audit yang ketat, OLXTOTO memastikan bahwa setiap putaran permainan berjalan dengan adil dan transparan. Para pemain dapat merasa aman dan yakin bahwa pengalaman berjudi mereka di OLXTOTO tidak akan terganggu oleh masalah keamanan atau keadilan. Tak hanya itu, OLXTOTO juga terkenal karena layanan pelanggan yang luar biasa. Tim dukungan mereka selalu siap sedia untuk membantu para pemain dengan segala pertanyaan atau masalah yang mereka hadapi. Dengan respon cepat dan solusi yang efisien, OLXTOTO memastikan bahwa pengalaman berjudi para pemain tetap mulus dan menyenangkan. Dengan semua fitur dan keunggulan yang ditawarkannya, tidak mengherankan bahwa OLXTOTO telah menjadi pilihan utama bagi jutaan penjudi online di seluruh dunia. Jika Anda mencari platform yang dapat memberikan kemenangan maksimal dan hasil optimal, tidak perlu mencari lebih jauh dari OLXTOTO. Bergabunglah dengan OLXTOTO hari ini dan mulailah petualangan Anda menuju kemenangan besar dan hasil terbaik!
    • Selamat datang di OLXTOTO, situs slot gacor terpanas yang sedang booming di industri perjudian online. Jika Anda mencari pengalaman bermain yang luar biasa, maka OLXTOTO adalah tempat yang tepat untuk Anda. Dapatkan sensasi tidak biasa dengan variasi slot online terlengkap dan peluang memenangkan jackpot slot maxwin yang sering. Di sini, Anda akan merasakan keseruan yang luar biasa dalam bermain judi slot. DAFTAR OLXTOTO DISINI LOGIN OLXTOTO DISINI AKUN PRO OLXTOTO DISINI   Jackpot Slot Maxwin Sering Untuk Peluang Besar Di OLXTOTO, kami tidak hanya memberikan hadiah slot biasa, tapi juga memberikan kesempatan kepada pemain untuk memenangkan jackpot slot maxwin yang sering. Dengan demikian, Anda dapat meraih keberuntungan besar dan memenangkan ribuan rupiah sebagai hadiah jackpot slot maxwin kami. Jackpot slot maxwin merupakan peluang besar bagi para pemain judi slot untuk meraih keuntungan yang lebih besar. Dalam permainan kami, Anda tidak harus terpaku pada kemenangan biasa saja. Kami hadir dengan jackpot slot maxwin yang sering, sehingga Anda memiliki peluang yang lebih besar untuk meraih kemenangan besar dengan hadiah yang menggiurkan. Dalam permainan judi slot, pengalaman bermain bukan hanya tentang keseruan dan hiburan semata. Kami memahami bahwa para pemain juga menginginkan kesempatan untuk meraih keberuntungan besar. Oleh karena itu, OLXTOTO hadir dengan jackpot slot maxwin yang sering untuk memberikan peluang besar kepada para pemain kami. Peluang Besar Menang Jackpot Slot Maxwin Peluang menang jackpot slot maxwin di OLXTOTO sangatlah besar. Anda tidak perlu khawatir tentang batasan atau pembatasan dalam meraih jackpot tersebut. Kami ingin memberikan kesempatan kepada semua pemain kami untuk merasakan sensasi menang dalam jumlah yang luar biasa. Jackpot slot maxwin kami dibuka untuk semua pemain judi slot di OLXTOTO. Anda memiliki peluang yang sama dengan pemain lainnya untuk memenangkan hadiah jackpot yang besar. Kami percaya bahwa semua orang memiliki kesempatan untuk meraih keberuntungan besar, dan itulah mengapa kami menyediakan jackpot slot maxwin yang sering untuk memenuhi harapan dan keinginan Anda.   Kesimpulan OLXTOTO adalah situs slot gacor terbaik yang memberikan pengalaman bermain judi slot online yang tak terlupakan. Dengan variasi slot online terlengkap dan peluang memenangkan jackpot slot maxwin yang sering, OLXTOTO menjadi pilihan terbaik bagi para pemain yang mencari kesenangan dan kemenangan besar dalam perjudian online. Di samping itu, OLXTOTO juga menawarkan layanan pelanggan yang ramah dan responsif, siap membantu setiap pemain dalam mengatasi masalah teknis atau pertanyaan seputar perjudian online. Kami menjaga integritas game dan memberikan lingkungan bermain yang adil serta menjalankan kebijakan perlindungan pelanggan yang cermat. Bergabunglah dengan OLXTOTO sekarang dan nikmati pengalaman bermain slot online yang luar biasa. Jadilah bagian dari komunitas perjudian yang mengagumkan ini dan raih kesempatan untuk meraih kemenangan besar. Dapatkan akses mudah dan praktis ke situs OLXTOTO dan rasakan sensasi bermain judi slot yang tak terlupakan.  
    • OLXTOTO: Platform Maxwin dan Gacor Terbesar Sepanjang Masa Di dunia perjudian online yang begitu kompetitif, mencari platform yang dapat memberikan kemenangan maksimal (Maxwin) dan hasil terbaik (Gacor) adalah prioritas bagi para penjudi yang cerdas. Dalam upaya ini, OLXTOTO telah muncul sebagai pemain kunci yang mengubah lanskap perjudian online dengan menawarkan pengalaman tanpa tandingan.     Sejak diluncurkan, OLXTOTO telah menjadi sorotan industri perjudian online. Dikenal sebagai "Platform Maxwin dan Gacor Terbesar Sepanjang Masa", OLXTOTO telah menarik perhatian pemain dari seluruh dunia dengan reputasinya yang solid dan kinerja yang luar biasa. Salah satu fitur utama yang membedakan OLXTOTO dari pesaingnya adalah komitmen mereka untuk memberikan pengalaman berjudi yang unik dan memuaskan. Dengan koleksi game yang luas dan beragam, termasuk togel, slot online, live casino, dan banyak lagi, OLXTOTO menawarkan sesuatu untuk semua orang. Dibangun dengan teknologi terkini dan didukung oleh tim ahli yang berdedikasi, platform ini memastikan bahwa setiap pengalaman berjudi di OLXTOTO tidak hanya menghibur, tetapi juga menguntungkan. Namun, keunggulan OLXTOTO tidak hanya terletak pada permainan yang mereka tawarkan. Mereka juga terkenal karena keamanan dan keadilan yang mereka berikan kepada para pemain mereka. Dengan sistem keamanan tingkat tinggi dan audit rutin yang dilakukan oleh otoritas regulasi independen, para pemain dapat yakin bahwa setiap putaran permainan di OLXTOTO adalah adil dan transparan. Tidak hanya itu, OLXTOTO juga dikenal karena layanan pelanggan yang luar biasa. Dengan tim dukungan yang ramah dan responsif, para pemain dapat yakin bahwa setiap pertanyaan atau masalah mereka akan ditangani dengan cepat dan efisien. Dengan semua fitur dan keunggulan yang ditawarkannya, tidak mengherankan bahwa OLXTOTO telah menjadi platform pilihan bagi para penjudi online yang mencari kemenangan maksimal dan hasil terbaik. Jadi, jika Anda ingin bergabung dengan jutaan pemain yang telah merasakan keajaiban OLXTOTO, jangan ragu untuk mendaftar dan mulai bermain hari ini!  
    • OLXTOTO adalah bandar slot yang terkenal dan terpercaya di Indonesia. Mereka menawarkan berbagai jenis permainan slot yang menarik dan menghibur. Dengan tampilan yang menarik dan grafis yang berkualitas tinggi, pemain akan merasa seperti berada di kasino sungguhan. OLXTOTO juga menyediakan layanan pelanggan yang ramah dan responsif, siap membantu pemain dengan segala pertanyaan atau masalah yang mereka hadapi. Daftar =  https://surkale.me/Olxtotodotcom1
  • Topics

×
×
  • Create New...

Important Information

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