Define the container
public class MyContainer extends Container {
private final IWorldPosCallable iWorldPosCallable;
private final IntReferenceHolder intReferenceHolder = IntReferenceHolder.single();
private final World world;
private ItemStack result = ItemStack.EMPTY;
private long timeElapsed;
private final Slot inputSlot;
private final Slot outputSlot;
private Runnable inventoryUpdateListener = () -> {
};
private final IInventory inventory = new Inventory(1) {
@Override
public void markDirty() {
super.markDirty();
onCraftMatrixChanged(this);
inventoryUpdateListener.run();
}
};
private final CraftResultInventory resultInventory = new CraftResultInventory();
public MyContainer(int id, PlayerInventory playerInventory) {
this(id, playerInventory, IWorldPosCallable.DUMMY);
}
public MyContainer(int id, PlayerInventory playerInventory, final IWorldPosCallable iWorldPosCallable) {
super(ModContainers.MYCONTAINER, id);
this.iWorldPosCallable = iWorldPosCallable;
this.world = playerInventory.player.world;
this.inputSlot = addSlot(new Slot(this.inventory, 0, 20, 33));
this.outputSlot = addSlot(new Slot(this.resultInventory, 1, 143, 33) {
@Override
public boolean isItemValid(ItemStack stack) {
return false;
}
@Override
public ItemStack onTake(PlayerEntity thePlayer, ItemStack stack) {
ItemStack itemstack = inputSlot.decrStackSize(1);
stack.getItem().onCreated(stack, thePlayer.world, thePlayer);
return super.onTake(thePlayer, stack);
}
});
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
}
}
for (int k = 0; k < 9; ++k) {
addSlot(new Slot(playerInventory, k, 8 + k * 18, 142));
}
trackInt(this.intReferenceHolder);
}
@OnlyIn(Dist.CLIENT)
public int func_217073_e() {
return this.intReferenceHolder.get();
}
@OnlyIn(Dist.CLIENT)
public boolean func_217083_h() {
return this.inputSlot.getHasStack();
}
@Override
public boolean canInteractWith(PlayerEntity playerIn) {
return this.iWorldPosCallable.applyOrElse((world, pos) -> ModBlocks.MYCONTAINER.contains(world.getBlockState(pos).getBlock()) && playerIn.getDistanceSq((double) pos.getX() + 0.5d, (double) pos.getY() + 0.5d, (double) pos.getZ() + 0.5d) <= 64d, true);
}
@Override
public void onCraftMatrixChanged(IInventory inventoryIn) {
ItemStack stack = this.inputSlot.getStack();
if (stack.getItem() != this.result.getItem()) {
this.result = stack.copy();
}
}
@Override
public ContainerType<?> getType() {
return ModContainers.MYCONTAINER;
}
@OnlyIn(Dist.CLIENT)
public void setInventoryUpdateListener(Runnable runnable) {
this.inventoryUpdateListener = runnable;
}
@Override
public boolean canMergeSlot(ItemStack stack, Slot slotIn) {
return slotIn.inventory != this.inventory && super.canMergeSlot(stack, slotIn);
}
@Override
public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
ItemStack stack = ItemStack.EMPTY;
Slot slot = this.inventorySlots.get(index);
if (slot != null && slot.getHasStack()) {
ItemStack itemstack1 = slot.getStack();
Item item = itemstack1.getItem();
stack = itemstack1.copy();
if (index == 1) {
item.onCreated(itemstack1, playerIn.world, playerIn);
if (!this.mergeItemStack(itemstack1, 2, 38, true)) {
return ItemStack.EMPTY;
}
slot.onSlotChange(itemstack1, stack);
} else if (index == 0) {
if (!this.mergeItemStack(itemstack1, 2, 38, false)) {
return ItemStack.EMPTY;
}
} else if (item.isIn(ModTags.Items.ALLOWED_ITEMS)) {
if (!this.mergeItemStack(itemstack1, 0, 1, false)) {
return ItemStack.EMPTY;
}
} else if (index < 29) {
if (!this.mergeItemStack(itemstack1, 29, 38, false)) {
return ItemStack.EMPTY;
}
} else if (index < 38 && !this.mergeItemStack(itemstack1, 2, 29, false)) {
return ItemStack.EMPTY;
}
if (itemstack1.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
}
slot.onSlotChanged();
if (itemstack1.getCount() == stack.getCount()) {
return ItemStack.EMPTY;
}
slot.onTake(playerIn, itemstack1);
detectAndSendChanges();
}
return stack;
}
@Override
public void onContainerClosed(PlayerEntity playerIn) {
super.onContainerClosed(playerIn);
this.resultInventory.removeStackFromSlot(1);
this.iWorldPosCallable.consume((world, pos) -> clearContainer(playerIn, world, this.inventory));
}
}
Define your screen manager
@OnlyIn(Dist.CLIENT)
public class MyScreen extends ContainerScreen<MyContainer> {
private static final ResourceLocation BACKGROUND_TEXTURE = new ResourceLocation("textures/gui/container/my.png");
public MyScreen(MyContainer containerIn, PlayerInventory playerInv, ITextComponent title) {
super(containerIn, playerInv, title);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
this.renderBackground();
GlStateManager.color4f(1f, 1f, 1f, 1f);
getMinecraft().getTextureManager().bindTexture(BACKGROUND_TEXTURE);
}
}
Use it in a block (right click)
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) {
if (!worldIn.isRemote) {
player.openContainer(state.getContainer(worldIn, pos));
}
return true;
}
@Override
@Nullable
public INamedContainerProvider getContainer(BlockState state, World worldIn, BlockPos pos) {
ITextComponent translation = new TranslationTextComponent("mycontainer");
return new SimpleNamedContainerProvider((id, playerInventory, player) -> new MyContainer(id, playerInventory, IWorldPosCallable.of(worldIn, pos)), translation);
}