Container class:
import net.jmb19905.medievalworlds.entities.tile.AlloyFurnaceTileEntity;
import net.jmb19905.medievalworlds.registryhandlers.BlockHandler;
import net.jmb19905.medievalworlds.registryhandlers.ContainerTypeHandler;
import net.jmb19905.medievalworlds.util.recipe.AlloyRecipe;
import net.jmb19905.medievalworlds.util.slots.OutputSlot;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.*;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IWorldPosCallable;
import net.minecraft.util.IntReferenceHolder;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.ForgeHooks;
import java.util.*;
@SuppressWarnings("ALL")
public class AlloyFurnaceContainer extends Container {
public AlloyFurnaceTileEntity tileEntity;
private IWorldPosCallable canInteractWithCallable;
public boolean burning = false;
public int currentMaxBurnTime = 0;
public int currentBurnTime = 0;
public static final int MAX_ALLOY_TIME = 200;
public int currentAlloyTime = MAX_ALLOY_TIME;
private boolean fuelRemoved = false;
private final World world;
public AlloyFurnaceContainer(final int windowId, final PlayerInventory playerInventory, final AlloyFurnaceTileEntity tileEntity) {
super(ContainerTypeHandler.ALLOY_FURNACE.get(), windowId);
this.tileEntity = tileEntity;
this.canInteractWithCallable = IWorldPosCallable.of(tileEntity.getWorld(), tileEntity.getPos());
this.world = playerInventory.player.world;
trackInt(new IntReferenceHolder() {
@Override
public int get() {
return currentAlloyTime;
}
@Override
public void set(int val) {
currentAlloyTime = val;
}
});
trackInt(new IntReferenceHolder() {
@Override
public int get() {
return currentBurnTime;
}
@Override
public void set(int val) {
currentBurnTime = val;
}
});
trackInt(new IntReferenceHolder() {
@Override
public int get() {
return currentMaxBurnTime;
}
@Override
public void set(int val) {
currentMaxBurnTime = val;
}
});
//Main Inventory
this.addSlot(new Slot(tileEntity, 0, 25, 17));
this.addSlot(new Slot(tileEntity, 1, 25, 48));
this.addSlot(new Slot(tileEntity, 2, 80, 66));
this.addSlot(new OutputSlot(tileEntity, 3, 133, 33));
//Main Player Inventory
int startPlayerInvX = 8;
int startPlayerInvY = 84;
int slotSizePlus2 = 18;
for(int row = 0;row<3;row++){
for(int column = 0;column<9;column++){
this.addSlot(new Slot(playerInventory, 9 + (row * 9) + column, startPlayerInvX + (column * slotSizePlus2), startPlayerInvY + (row * slotSizePlus2)));
}
}
//Hotbar
int hotBarY = 142;
for(int column = 0; column < 9;column++){
this.addSlot(new Slot(playerInventory, column, startPlayerInvX + (column * slotSizePlus2), hotBarY));
}
}
private static AlloyFurnaceTileEntity getTileEntity(final PlayerInventory playerInventory, final PacketBuffer data){
Objects.requireNonNull(playerInventory, "playerInventory cannot be null!");
Objects.requireNonNull(data, "data cannot be null!");
final TileEntity tileAtPos = playerInventory.player.world.getTileEntity(data.readBlockPos());
if(tileAtPos instanceof AlloyFurnaceTileEntity){
return (AlloyFurnaceTileEntity)tileAtPos;
}
throw new IllegalStateException("Tile Entity is not correct!" + tileAtPos);
}
public AlloyFurnaceContainer(final int windowId, PlayerInventory playerInventory, final PacketBuffer data){
this(windowId, playerInventory, getTileEntity(playerInventory, data));
}
@Override
public boolean canInteractWith(PlayerEntity playerIn) {
return isWithinUsableDistance(canInteractWithCallable, playerIn, BlockHandler.ALLOY_FURNACE_BLOCK.get());
}
@Override
public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
ItemStack itemStack = ItemStack.EMPTY;
Slot slot = this.inventorySlots.get(index);
if(slot != null && slot.getHasStack()){
ItemStack itemStack1 = slot.getStack();
itemStack = itemStack1.copy();
if(index < 4){
if(!this.mergeItemStack(itemStack1, 4, this.inventorySlots.size(), true)){
return ItemStack.EMPTY;
}
}else if(!this.mergeItemStack(itemStack1, 0, 4, false)){
return ItemStack.EMPTY;
}
if(itemStack1.isEmpty()){
slot.putStack(ItemStack.EMPTY);
}else{
slot.onSlotChanged();
}
}
return itemStack;
}
public void tick(World world){
if(world instanceof ServerWorld) {
if (currentBurnTime > 0) {
burning = true;
if (!fuelRemoved) {
getSlot(2).getStack().shrink(1);
fuelRemoved = true;
}
alloy();
currentBurnTime--;
} else {
burning = false;
if (ForgeHooks.getBurnTime(getSlot(2).getStack()) > 0 && currentMaxBurnTime != ForgeHooks.getBurnTime(getSlot(2).getStack())) {
currentMaxBurnTime = ForgeHooks.getBurnTime(getSlot(2).getStack());
}
if (ingredientsAvailable() && getSlot(3).getStack().getCount() < 64 && currentMaxBurnTime > 0) {
currentBurnTime = currentMaxBurnTime;
fuelRemoved = false;
}
}
if (ingredientsAvailable() && currentAlloyTime <= 0) {
currentAlloyTime = MAX_ALLOY_TIME;
}
}
}
private boolean ingredientsAvailable(){
for(IRecipe recipe:world.getRecipeManager().getRecipes()){
if(recipe instanceof AlloyRecipe) {
if ((((AlloyRecipe) recipe).ingredient1.getItem() == getSlot(0).getStack().getItem() &&
((AlloyRecipe) recipe).ingredient1.getCount() <= getSlot(0).getStack().getCount() &&
((AlloyRecipe) recipe).ingredient2.getItem() == getSlot(1).getStack().getItem() &&
((AlloyRecipe) recipe).ingredient2.getCount() <= getSlot(1).getStack().getCount())
||
(((AlloyRecipe) recipe).ingredient1.getItem() == getSlot(1).getStack().getItem() &&
((AlloyRecipe) recipe).ingredient1.getCount() <= getSlot(1).getStack().getCount() &&
((AlloyRecipe) recipe).ingredient2.getItem() == getSlot(0).getStack().getItem() &&
((AlloyRecipe) recipe).ingredient2.getCount() <= getSlot(0).getStack().getCount())
) {
return true;
}
}
}
return false;
}
private boolean alloy(){
boolean alloying = false;
for(IRecipe recipe:world.getRecipeManager().getRecipes()){
if(recipe instanceof AlloyRecipe) {
if (alloySpecific(((AlloyRecipe) recipe).ingredient1.getItem(), ((AlloyRecipe) recipe).ingredient1.getCount(), ((AlloyRecipe) recipe).ingredient2.getItem(), ((AlloyRecipe) recipe).ingredient2.getCount(), ((AlloyRecipe) recipe).result.getItem(), ((AlloyRecipe) recipe).result.getCount())) {
alloying = true;
break;
}
}
}
return alloying;
}
private boolean alloySpecific(Item firstIngredient, int fIVal, Item secondIngredient, int sIVal, Item out, int outVal){
if(getSlot(0).getStack().getItem().equals(firstIngredient) && getSlot(0).getStack().getCount() >= fIVal && getSlot(1).getStack().getItem().equals(secondIngredient) && getSlot(1).getStack().getCount() >= sIVal){
currentAlloyTime--;
if(currentAlloyTime <= 0) {
currentAlloyTime = 0;
if (getSlot(3).getStack().getItem().equals(out) && getSlot(3).getStack().getCount() < 64) {
getSlot(0).getStack().shrink(fIVal);
getSlot(1).getStack().shrink(sIVal);
getSlot(3).getStack().grow(outVal);
} else {
getSlot(0).getStack().shrink(fIVal);
getSlot(1).getStack().shrink(sIVal);
getSlot(3).putStack(new ItemStack(out, outVal));
}
}
return true;
}
return false;
}
public boolean isBurning(){
return burning;
}
}
Screen class:
import com.mojang.blaze3d.systems.RenderSystem;
import net.jmb19905.medievalworlds.container.AlloyFurnaceContainer;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public abstract class AbstractAlloyFurnaceScreen<T extends AlloyFurnaceContainer> extends ContainerScreen<T> {
private ResourceLocation backgroundTexture;
public AbstractAlloyFurnaceScreen(T screenContainer, PlayerInventory playerInventory, ITextComponent title, ResourceLocation backgroundTexture){
super(screenContainer, playerInventory, title);
this.backgroundTexture = backgroundTexture;
this.guiLeft = 0;
this.guiTop = 0;
this.xSize = 175;
this.ySize = 165;
}
@Override
public void render(final int mouseX,final int mouseY,final float partialTicks) {
this.renderBackground();
super.render(mouseX, mouseY, partialTicks);
this.renderHoveredToolTip(mouseX, mouseY);
}
@Override
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
super.drawGuiContainerForegroundLayer(mouseX, mouseY);
this.font.drawString(this.title.getFormattedText(), 8.0f, 6.0f, 4210752);
this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8.0f, 66, 4210752);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
this.minecraft.getTextureManager().bindTexture(backgroundTexture);
int x = (this.width - this.xSize) / 2;
int y = (this.height - this.ySize) / 2;
this.blit(x, y, 0, 0, this.xSize, this.ySize);
this.blit(x+80, y+33, 177, 14, calculateAlloyProgression(), 16);
if(this.container.currentMaxBurnTime != 0) {
this.blit(x+81, y+51+calculateBurnProgression(), 176, 14-calculateInvertedBurnProgression(), 14, calculateInvertedBurnProgression());
}
}
private int calculateAlloyProgression(){
float MAX_ALLOY_TIME = AlloyFurnaceContainer.MAX_ALLOY_TIME;
float alloyTime = this.container.currentAlloyTime;
float length = 23;
float out = Math.abs(((length/MAX_ALLOY_TIME)*alloyTime)-length);
return (int) out;
}
private int calculateInvertedBurnProgression(){
float maxBurnTime = this.container.currentMaxBurnTime;
float burnTime = this.container.currentBurnTime;
float height = 14;
float out = (height/maxBurnTime)*burnTime;
return (int) out;
}
private int calculateBurnProgression(){
float maxBurnTime = this.container.currentMaxBurnTime;
float burnTime = this.container.currentBurnTime;
float height = 14;
float out = Math.abs(((height/maxBurnTime)*burnTime)-height);
return (int) out;
}
}
TE class:
import net.jmb19905.medievalworlds.block.AlloyFurnaceBlock;
import net.jmb19905.medievalworlds.container.AlloyFurnaceContainer;
import net.jmb19905.medievalworlds.registryhandlers.TileEntityTypeHandler;
import net.minecraft.block.Block;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.inventory.container.Container;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.LockableLootTileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull;
//TODO: Issues when multiple Blocks in world
public class AlloyFurnaceTileEntity extends LockableLootTileEntity implements ITickableTileEntity {
private NonNullList<ItemStack> contents = NonNullList.withSize(4, ItemStack.EMPTY);
protected int numPlayerUsing;
private final IItemHandlerModifiable items = createHandler();
private LazyOptional<IItemHandlerModifiable> itemHandler = LazyOptional.of(() -> items);
private AlloyFurnaceContainer container;
public boolean lit = false;
public AlloyFurnaceTileEntity(){
super(TileEntityTypeHandler.ALLOY_FURNACE.get());
}
@Override
public int getSizeInventory(){
return 4;
}
@Override
public void setItems(NonNullList<ItemStack> itemsIn) {
this.contents = itemsIn;
}
public NonNullList<ItemStack> getItems(){
return this.contents;
}
@Override
protected ITextComponent getDefaultName() {
return new TranslationTextComponent("container.alloy_furnace");
}
@Override
protected Container createMenu(int id, PlayerInventory player) {
container = new AlloyFurnaceContainer(id, player, this);
return container;
}
@Override
public CompoundNBT write(CompoundNBT compound) {
super.write(compound);
if(!this.checkLootAndWrite(compound)){
ItemStackHelper.saveAllItems(compound, this.contents);
}
return compound;
}
@Override
public void read(CompoundNBT compound) {
super.read(compound);
this.contents = NonNullList.withSize(this.getSizeInventory(), ItemStack.EMPTY);
if(!this.checkLootAndRead(compound)){
ItemStackHelper.loadAllItems(compound, this.contents);
}
}
@Override
public boolean receiveClientEvent(int id, int type) {
if(id == 1){
this.numPlayerUsing = type;
return true;
}else{
return super.receiveClientEvent(id, type);
}
}
@Override
public void openInventory(PlayerEntity player) {
if(!player.isSpectator()){
if(this.numPlayerUsing < 0){
numPlayerUsing = 0;
}
++this.numPlayerUsing;
this.onOpenOrClose();
}
}
@Override
public void closeInventory(PlayerEntity player) {
if(!player.isSpectator()){
--this.numPlayerUsing;
this.onOpenOrClose();
}
}
protected void onOpenOrClose(){
Block block = this.getBlockState().getBlock();
if(block instanceof AlloyFurnaceBlock){
assert this.world != null;
this.world.addBlockEvent(this.pos, block, 1, this.numPlayerUsing);
this.world.notifyNeighborsOfStateChange(this.pos, block);
}
}
@Override
public void updateContainingBlockInfo() {
super.updateContainingBlockInfo();
if(this.itemHandler != null){
this.itemHandler.invalidate();
this.itemHandler = null;
}
}
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, Direction side) {
if(cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY){
return itemHandler.cast();
}
return super.getCapability(cap, side);
}
private IItemHandlerModifiable createHandler(){
return new InvWrapper(this);
}
@Override
public void remove() {
super.remove();
if(itemHandler != null){
itemHandler.invalidate();
}
}
@Override
public void tick(){
if(container != null){
container.tick(this.world);
}
}
}
Here you go...