Jump to content

[1.12.2] Custom Furnace Doesn't Work?


SureenInk

Recommended Posts

I'm starting to assume that almost everyone on this forum is getting the same set of coding from the same tutorial (admittedly, it is the only tutorial I can find). Problem is, we're all using the same tutorial, but none of us seem to be getting straight answers on how to fix the issues (at least, in the 4 topics I found, no one mentioned a fix to the problems). Now, I'm a pretty big noob when it comes to modding in 1.12 (as in, this is my first time). Last time I did modding, it was back in 1.6.4. On that note... I'm noticing that 90% of how to code stuff seems to have changed. Because I've not had the advantage of updating my code through the years, I've had to fall back on tutorials just to relearn the basics again. In turn, I've fallen into the same trap everyone else seems to have had with the one existing tutorial on custom furnaces/machines that exists out there for 1.12.2. So, I'd like to see if I can help by asking for help, and in turn, maybe I can also determine what it is all of us are doing wrong and how we can all fix it. In truth, if someone could make a current and up-to-date tutorial on this matter, it'd help the most, but with 1.13 out now, it's unlikely.

 

So, the first thing is: I have no idea what this ItemHandler thing that Forge utilizes is... I've done my best to follow what others are posting for fixes, but simply put, the tutorial utilized IInventory, which I've also noticed people practically cussing about when it's used... While, yes, I agree this is apparently an issue... I feel that's taking it to an extreme... especially since all of us are following the same tutorial, and likely don't know of the alternatives.

 

So, what is wrong with my furnace, you ask? What needs fixing? Well, my guess is the update function in the Tile Entity, but I can't for the life of me figure out how to do it. The tutorial I followed had a large mess of code for the update function, and as best as I can guess, the function is running and taking the items from the itemstacks before it's even updating anything as when I add items into the furnace when it is off, it turns on and then removes all of the items. However, once it's on, it no longer does that. I honestly can't figure out why it is doing this, though. I assume it has to do with the really crummy tutorial I followed, but alas, as I said... it's the only one I can find, and I spent 2 hours looking for another one cause it's honestly that bad.

 

The other thing that is wrong is that I cannot shift+click any of the items into the slots. I have to click them into the furnace slots. That said, though, those are the only two issues I'm having. I believe I have been able to solve every other issue...

 

Oh yeah... I guess there is one other issue? To register my alloyer, I am using this code:

GameRegistry.registerTileEntity(TileEntityAlloyer.class, "alloyer");

Forge, however, says this is deprecated, but refuses to tell me how to do this otherwise? Could anyone help with that?

 

Here's the Block code:

	package com.sureenink.metallics.basemetals.machines.alloyer;
	import java.util.Random;
	import com.sureenink.metallics.Metallics;
import com.sureenink.metallics.Reference;
import com.sureenink.metallics.basemetals.BaseMetalsBlocks;
import com.sureenink.metallics.blocks.BlockBase;
	import net.minecraft.block.BlockHorizontal;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
	public class BlockAlloyer extends BlockBase {
    public static final PropertyDirection FACING = BlockHorizontal.FACING;
    public static final PropertyBool ACTIVE = PropertyBool.create("active");
    
    public BlockAlloyer(String name)
    {
        super(Material.ROCK, name, "blockAlloyer", 3.0f, 3.0f, "pickaxe", 1);
        setSoundType(SoundType.STONE);
        this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(ACTIVE, false));
    }
    
    @Override
    public Item getItemDropped(IBlockState state, Random rand, int fortune)
    {
        return Item.getItemFromBlock(BaseMetalsBlocks.alloyer);
    }
    
    @Override
    public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
    {
        return new ItemStack(BaseMetalsBlocks.alloyer);
    }
    
    @Override
    public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
        if(!worldIn.isRemote)
        {
            playerIn.openGui(Metallics.instance, Reference.GUI_ALLOYER, worldIn, pos.getX(), pos.getY(), pos.getZ());
        }
        
        return true;
    }
    
    @Override
    public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
    {
        if (!worldIn.isRemote)
        {
            IBlockState north = worldIn.getBlockState(pos.north());
            IBlockState south = worldIn.getBlockState(pos.south());
            IBlockState west = worldIn.getBlockState(pos.west());
            IBlockState east = worldIn.getBlockState(pos.east());
            EnumFacing face = (EnumFacing)state.getValue(FACING);
	            if (face == EnumFacing.NORTH && north.isFullBlock() && !south.isFullBlock()) face = EnumFacing.SOUTH;
            else if (face == EnumFacing.SOUTH && south.isFullBlock() && !north.isFullBlock()) face = EnumFacing.NORTH;
            else if (face == EnumFacing.WEST && west.isFullBlock() && !east.isFullBlock()) face = EnumFacing.EAST;
            else if (face == EnumFacing.EAST && east.isFullBlock() && !west.isFullBlock()) face = EnumFacing.WEST;
            worldIn.setBlockState(pos, state.withProperty(FACING, face), 2);
        }
    }
    
    public static void setState(boolean active, World worldIn, BlockPos pos)
    {
        IBlockState state = worldIn.getBlockState(pos);
        TileEntity tileentity = worldIn.getTileEntity(pos);
        
        if(active) worldIn.setBlockState(pos, BaseMetalsBlocks.alloyer.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(ACTIVE, true), 3);
        else worldIn.setBlockState(pos, BaseMetalsBlocks.alloyer.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(ACTIVE, false), 3);
        
        if(tileentity != null)
        {
            tileentity.validate();
            worldIn.setTileEntity(pos, tileentity);
        }
    }
    
    @Override
    public boolean hasTileEntity(IBlockState state)
    {
        return true;
    }
    
    @Override
    public TileEntity createTileEntity(World world, IBlockState state)
    {
        return new TileEntityAlloyer();
    }
    
    @Override
    public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
    {
        return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite());
    }
    
    @Override
    public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
    {
        worldIn.setBlockState(pos, this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()), 2);
    }
    
    @Override
    public EnumBlockRenderType getRenderType(IBlockState state)
    {
        return EnumBlockRenderType.MODEL;
    }
    
    @Override
    public IBlockState withRotation(IBlockState state, Rotation rot)
    {
        return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
    }
    
    @Override
    public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
    {
        return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
    }
    
    @Override
    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {ACTIVE,FACING});
    }
    
    @Override
    public IBlockState getStateFromMeta(int meta)
    {
        EnumFacing facing = EnumFacing.getFront(meta);
        if(facing.getAxis() == EnumFacing.Axis.Y) facing = EnumFacing.NORTH;
        return this.getDefaultState().withProperty(FACING, facing);
    }
    
    @Override
    public int getMetaFromState(IBlockState state)
    {
        return ((EnumFacing)state.getValue(FACING)).getIndex();
    }    
    
    public void registerItemModel(Item itemBlock) {        
        Metallics.proxy.registerItemRenderer(itemBlock, 0, name);
    }
    
    public Item createItemBlock() {
        return new ItemBlock(this).setRegistryName(getRegistryName());
    }
    
    @Override
    public BlockAlloyer setCreativeTab(CreativeTabs tab) {
        super.setCreativeTab(tab);
        return this;
    }
}

 

Now for the TileEntity code:

	package com.sureenink.metallics.basemetals.machines.alloyer;
	import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemHoe;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.ItemTool;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;
	public class TileEntityAlloyer extends TileEntity implements ITickable {
    private ItemStackHandler handler = new ItemStackHandler(4);
    private String customName;
    private ItemStack smelting = ItemStack.EMPTY;
    
    private int burnTime;
    private int currentBurnTime;
    private int cookTime;
    private int totalCookTime = 200;
	    @Override
    public boolean hasCapability(Capability<?> capability, EnumFacing facing)
    {
        if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return true;
        else return false;
    }
    
    @Override
    public <T> T getCapability(Capability<T> capability, EnumFacing facing)
    {
        if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T) this.handler;
        return super.getCapability(capability, facing);
    }
    
    public boolean hasCustomName()
    {
        return this.customName != null && !this.customName.isEmpty();
    }
    
    public void setCustomName(String customName)
    {
        this.customName = customName;
    }
    
    @Override
    public ITextComponent getDisplayName()
    {
        return this.hasCustomName() ? new TextComponentString(this.customName) : new TextComponentTranslation("container.basic_metallic_infuser");
    }
    
    @Override
    public void readFromNBT(NBTTagCompound compound)
    {
        super.readFromNBT(compound);
        this.handler.deserializeNBT(compound.getCompoundTag("Inventory"));
        this.burnTime = compound.getInteger("BurnTime");
        this.cookTime = compound.getInteger("CookTime");
        this.totalCookTime = compound.getInteger("CookTimeTotal");
        this.currentBurnTime = getItemBurnTime((ItemStack)this.handler.getStackInSlot(2));
        
        if(compound.hasKey("CustomName", 8)) this.setCustomName(compound.getString("CustomName"));
    }
    
    @Override
    public NBTTagCompound writeToNBT(NBTTagCompound compound)
    {
        super.writeToNBT(compound);
        compound.setInteger("BurnTime", (short)this.burnTime);
        compound.setInteger("CookTime", (short)this.cookTime);
        compound.setInteger("CookTimeTotal", (short)this.totalCookTime);
        compound.setTag("Inventory", this.handler.serializeNBT());
        
        if(this.hasCustomName()) compound.setString("CustomName", this.customName);
        return compound;
    }
    
    public boolean isBurning()
    {
        return this.burnTime > 0;
    }
    
    @SideOnly(Side.CLIENT)
    public static boolean isBurning(TileEntityAlloyer te)
    {
        return te.getField(0) > 0;
    }
    
    public void update()
    {    
        if(this.isBurning())
        {
            --this.burnTime;
            BlockAlloyer.setState(true, world, pos);
        }
        
        ItemStack[] inputs = new ItemStack[] {handler.getStackInSlot(0), handler.getStackInSlot(1)};
        ItemStack fuel = this.handler.getStackInSlot(2);
        
        if(this.isBurning() || !fuel.isEmpty() && !this.handler.getStackInSlot(0).isEmpty() || this.handler.getStackInSlot(1).isEmpty())
        {
            if(!this.isBurning() && this.canSmelt())
            {
                this.burnTime = getItemBurnTime(fuel);
                this.currentBurnTime = burnTime;
                
                if(this.isBurning() && !fuel.isEmpty())
                {
                    Item item = fuel.getItem();
                    fuel.shrink(1);
                    
                    if(fuel.isEmpty())
                    {
                        ItemStack item1 = item.getContainerItem(fuel);
                        this.handler.setStackInSlot(2, item1);
                    }
                }
            }
        }
        
        if(this.isBurning() && this.canSmelt() && cookTime > 0)
        {
            cookTime++;
            if(cookTime == totalCookTime)
            {
                if(handler.getStackInSlot(3).getCount() > 0)
                {
                    handler.getStackInSlot(3).grow(1);
                }
                else
                {
                    handler.insertItem(3, smelting, false);
                }
                
                smelting = ItemStack.EMPTY;
                cookTime = 0;
                return;
            }
        }
        else
        {
            if(this.canSmelt() && this.isBurning())
            {
                ItemStack output = AlloyerRecipes.getInstance().getAlloyerResult(inputs[0], inputs[1]);
                if(!output.isEmpty())
                {
                    smelting = output;
                    cookTime++;
                    inputs[0].shrink(1);
                    inputs[1].shrink(1);
                    handler.setStackInSlot(0, inputs[0]);
                    handler.setStackInSlot(1, inputs[1]);
                }
            }
        }
    }
    
    private boolean canSmelt()
    {
        if(((ItemStack)this.handler.getStackInSlot(0)).isEmpty() || ((ItemStack)this.handler.getStackInSlot(1)).isEmpty()) return false;
        else
        {
            ItemStack result =  AlloyerRecipes.getInstance().getAlloyerResult((ItemStack)this.handler.getStackInSlot(0), (ItemStack)this.handler.getStackInSlot(1));    
            if(result.isEmpty()) return false;
            else
            {
                ItemStack output = (ItemStack)this.handler.getStackInSlot(3);
                if(output.isEmpty()) return true;
                if(!output.isItemEqual(result)) return false;
                int res = output.getCount() + result.getCount();
                return res <= 64 && res <= output.getMaxStackSize();
            }
        }
    }
    
    public static int getItemBurnTime(ItemStack fuel)
    {
        if(fuel.isEmpty()) return 0;
        else
        {
            Item item = fuel.getItem();
	            if (item instanceof ItemBlock && Block.getBlockFromItem(item) != Blocks.AIR)
            {
                Block block = Block.getBlockFromItem(item);
	                if (block == Blocks.WOODEN_SLAB) return 150;
                if (block.getDefaultState().getMaterial() == Material.WOOD) return 300;
                if (block == Blocks.COAL_BLOCK) return 16000;
            }
	            if (item instanceof ItemTool && "WOOD".equals(((ItemTool)item).getToolMaterialName())) return 200;
            if (item instanceof ItemSword && "WOOD".equals(((ItemSword)item).getToolMaterialName())) return 200;
            if (item instanceof ItemHoe && "WOOD".equals(((ItemHoe)item).getMaterialName())) return 200;
            if (item == Items.STICK) return 100;
            if (item == Items.COAL) return 1600;
            if (item == Items.LAVA_BUCKET) return 20000;
            if (item == Item.getItemFromBlock(Blocks.SAPLING)) return 100;
            if (item == Items.BLAZE_ROD) return 2400;
	            return GameRegistry.getFuelValue(fuel);
        }
    }
        
    public static boolean isItemFuel(ItemStack fuel)
    {
        return getItemBurnTime(fuel) > 0;
    }
    
    public boolean isUsableByPlayer(EntityPlayer player)
    {
        return this.world.getTileEntity(this.pos) != this ? false : player.getDistanceSq((double)this.pos.getX() + 0.5D, (double)this.pos.getY() + 0.5D, (double)this.pos.getZ() + 0.5D) <= 64.0D;
    }
	    public int getField(int id)
    {
        switch(id)
        {
        case 0:
            return this.burnTime;
        case 1:
            return this.currentBurnTime;
        case 2:
            return this.cookTime;
        case 3:
            return this.totalCookTime;
        default:
            return 0;
        }
    }
	    public void setField(int id, int value)
    {
        switch(id)
        {
        case 0:
            this.burnTime = value;
            break;
        case 1:
            this.currentBurnTime = value;
            break;
        case 2:
            this.cookTime = value;
            break;
        case 3:
            this.totalCookTime = value;
        }
    }
	}

And the Container code:

	package com.sureenink.metallics.basemetals.machines.alloyer;
	import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler;
	public class ContainerAlloyer extends Container {
	    private final TileEntityAlloyer tileentity;
    private int cookTime, totalCookTime, burnTime, currentBurnTime;
    
    public ContainerAlloyer(InventoryPlayer player, TileEntityAlloyer tileentity)
    {
        this.tileentity = tileentity;
        IItemHandler handler = tileentity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
        
        this.addSlotToContainer(new SlotItemHandler(handler, 0, 30, 22));
        this.addSlotToContainer(new SlotItemHandler(handler, 1, 58, 22));
        this.addSlotToContainer(new SlotItemHandler(handler, 2, 45, 46));
        this.addSlotToContainer(new SlotItemHandler(handler, 3, 124, 22));
        
        for(int y = 0; y < 3; y++)
        {
            for(int x = 0; x < 9; x++)
            {
                this.addSlotToContainer(new Slot(player, x + y*9 + 9, 8 + x*18, 84 + y*18));
            }
        }
        
        for(int x = 0; x < 9; x++)
        {
            this.addSlotToContainer(new Slot(player, x, 8 + x * 18, 142));
        }
    }
    
    @Override
    public void detectAndSendChanges()
    {
        super.detectAndSendChanges();
        
        for(int i = 0; i < this.listeners.size(); ++i)
        {
            IContainerListener listener = (IContainerListener)this.listeners.get(i);
            
            if(this.cookTime != this.tileentity.getField(2)) listener.sendWindowProperty(this, 2, this.tileentity.getField(2));
            if(this.burnTime != this.tileentity.getField(0)) listener.sendWindowProperty(this, 0, this.tileentity.getField(0));
            if(this.currentBurnTime != this.tileentity.getField(1)) listener.sendWindowProperty(this, 1, this.tileentity.getField(1));
            if(this.totalCookTime != this.tileentity.getField(3)) listener.sendWindowProperty(this, 3, this.tileentity.getField(3));
        }
        
        this.cookTime = this.tileentity.getField(2);
        this.burnTime = this.tileentity.getField(0);
        this.currentBurnTime = this.tileentity.getField(1);
        this.totalCookTime = this.tileentity.getField(3);
    }
    
    @Override
    @SideOnly(Side.CLIENT)
    public void updateProgressBar(int id, int data)
    {
        this.tileentity.setField(id, data);
    }
    
    @Override
    public boolean canInteractWith(EntityPlayer playerIn)
    {
        return this.tileentity.isUsableByPlayer(playerIn);
    }
    
    @Override
    public ItemStack transferStackInSlot(EntityPlayer playerIn, int index)
    {
        ItemStack stack = ItemStack.EMPTY;
        Slot slot = (Slot)this.inventorySlots.get(index);
        
        if(slot != null && slot.getHasStack())
        {
            ItemStack stack1 = slot.getStack();
            stack = stack1.copy();
            
            if(index == 3)
            {
                if(!this.mergeItemStack(stack1, 4, 40, true)) return ItemStack.EMPTY;
                slot.onSlotChange(stack1, stack);
            }
            else if(index != 2 && index != 1 && index != 0)
            {        
                Slot slot1 = (Slot)this.inventorySlots.get(index + 1);
                
                if(!AlloyerRecipes.getInstance().getAlloyerResult(stack1, slot1.getStack()).isEmpty())
                {
                    if(!this.mergeItemStack(stack1, 0, 2, false))
                    {
                        return ItemStack.EMPTY;
                    }
                    else if(TileEntityAlloyer.isItemFuel(stack1))
                    {
                        if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
                    }
                    else if(TileEntityAlloyer.isItemFuel(stack1))
                    {
                        if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
                    }
                    else if(TileEntityAlloyer.isItemFuel(stack1))
                    {
                        if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
                    }
                    else if(index >= 4 && index < 31)
                    {
                        if(!this.mergeItemStack(stack1, 31, 40, false)) return ItemStack.EMPTY;
                    }
                    else if(index >= 31 && index < 40 && !this.mergeItemStack(stack1, 4, 31, false))
                    {
                        return ItemStack.EMPTY;
                    }
                }
            }
            else if(!this.mergeItemStack(stack1, 4, 40, false))
            {
                return ItemStack.EMPTY;
            }
            if(stack1.isEmpty())
            {
                slot.putStack(ItemStack.EMPTY);
            }
            else
            {
                slot.onSlotChanged();
	            }
            if(stack1.getCount() == stack.getCount()) return ItemStack.EMPTY;
            slot.onTake(playerIn, stack1);
        }
        return stack;
    }
	}

And finally the GUI code:

	package com.sureenink.metallics.basemetals.machines.alloyer;
	import com.sureenink.metallics.Metallics;
import com.sureenink.metallics.Reference;
	import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;
	public class GuiAlloyer extends GuiContainer {
    
    private static final ResourceLocation TEXTURES = new ResourceLocation(Reference.MODID + ":textures/gui/container/alloyer.png");
    private final InventoryPlayer player;
    private final TileEntityAlloyer tileEntity;
    
    public GuiAlloyer(InventoryPlayer player, TileEntityAlloyer tileEntity) {
        super(new ContainerAlloyer(player, tileEntity));
        this.player = player;
        this.tileEntity = tileEntity;
    }
    
    @Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
        String tileName = this.tileEntity.getDisplayName().getUnformattedText();
        this.fontRenderer.drawString(tileName, (this.xSize / 2 - this.fontRenderer.getStringWidth(tileName) / 2) + 3, 8, 4210752);
        this.fontRenderer.drawString(this.player.getDisplayName().getUnformattedText(), 122, this.ySize - 96 + 2, 4210752);
    }
	    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
        this.mc.getTextureManager().bindTexture(TEXTURES);
        this.drawTexturedModalRect(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);
        
        if(TileEntityAlloyer.isBurning(tileEntity)) {
            int k = this.getBurnLeftScaled(13);
            this.drawTexturedModalRect(this.guiLeft + 39, this.guiTop + 37 + 12 - k, 176, 12 - k, 14, k + 1);
        }
        
        int l = this.getCookingProgressScaled(24);
        this.drawTexturedModalRect(this.guiLeft + 80, this.guiTop + 35, 176, 14, l + 1, 16);
    }
    
    private int getBurnLeftScaled(int pixels) {
        int i = this.tileEntity.getField(1);
        if(i == 0) i = 200;
        return this.tileEntity.getField(0) * pixels / i;
    }
    
    private int getCookingProgressScaled(int pixels) {
        int i = this.tileEntity.getField(2);
        int j = this.tileEntity.getField(3);
        return j != 0 && i != 0 ? i * pixels / j : 0;
    }
	}

Link to comment
Share on other sites

5 hours ago, SureenInk said:

I have no idea what this ItemHandler thing that Forge utilizes is...

It is simply a storage for items. It's the entire IInventory in one line of code. Elegant and simple.

Instead of defining the ItemStack array/list you define the ItemStackHandler with your desired size. Then you can use it the same way you would use the IInventory - there are getters and setters for items in slots and insert/extract methods. The best thing is that you do not need to implement IInventory anymore and simply need to expose your ItemStackHandler instance as a capability. 

 

5 hours ago, SureenInk said:

but simply put, the tutorial utilized IInventory

Then the tutorial is crap and you can tell the author of the tutorial just that. IInventory is what, 4-5 years outdated by this point and people might not even bother with checking for it anymore since they assume everyone moved to capabilities by now.

 

5 hours ago, SureenInk said:

I feel that's taking it to an extreme... especially since all of us are following the same tutorial, and likely don't know of the alternatives.

We simply try to provide a solution which gives you the best results and compatibility. We are not taking it to an extreme, we simply tell you "Don't use IInventory, use capabilities".

 

5 hours ago, SureenInk said:

Forge, however, says this is deprecated, but refuses to tell me how to do this otherwise?

Ahem. Direct method signature:

@Deprecated //TODO: Remove in 1.13, Use ResourceLocation version.
public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String key)
Quote

Use ResourceLocation version.

 

5 hours ago, SureenInk said:

extends BlockBase

BlockBase is an antipattern. 

 

Quote

public static void setState(boolean active, World worldIn, BlockPos pos)
    {
        IBlockState state = worldIn.getBlockState(pos);
        TileEntity tileentity = worldIn.getTileEntity(pos);
        
        if(active) worldIn.setBlockState(pos, BaseMetalsBlocks.alloyer.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(ACTIVE, true), 3);
        else worldIn.setBlockState(pos, BaseMetalsBlocks.alloyer.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(ACTIVE, false), 3);
        
        if(tileentity != null)
        {
            tileentity.validate();
            worldIn.setTileEntity(pos, tileentity);
        }
    }

What even is this? You do not need any of this. Just override TileEntity#shouldRefresh. 

 

Quote

@Override
    public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
    {
        worldIn.setBlockState(pos, this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()), 2);
    }

You do not need this. You already return the state for placement at Block#getStateForPlacement.

 

Quote

@Override
    public EnumBlockRenderType getRenderType(IBlockState state)
    {
        return EnumBlockRenderType.MODEL;
    }

You do not need this since the super implementation of this method should already return MODEL.

 

Quote

@Override
    public IBlockState getStateFromMeta(int meta)
    {
        EnumFacing facing = EnumFacing.getFront(meta);
        if(facing.getAxis() == EnumFacing.Axis.Y) facing = EnumFacing.NORTH;
        return this.getDefaultState().withProperty(FACING, facing);
    }
    
    @Override
    public int getMetaFromState(IBlockState state)
    {
        return ((EnumFacing)state.getValue(FACING)).getIndex();
    }    

You are only (de)serializing your facing property but not the ACTIVE one. I assume you want that one to persist too.

 

Quote

public void registerItemModel(Item itemBlock) {        
        Metallics.proxy.registerItemRenderer(itemBlock, 0, name);
    }

This is the IHasModel all over again just this time without an interface. You do not need this in your block class. This goes into your ModelRegistryEvent directly, even without the need for the proxy. All of the things you need are public. There is no need for this method to be anywhere else apart from your ModelRegistryEvent.

 

5 hours ago, SureenInk said:

        this.currentBurnTime = getItemBurnTime((ItemStack)this.handler.getStackInSlot(2));

Are you sure this is correct? What if I only put 1 piece of coal in your furnace? Then when this code is executed the stack in slot 2 will be empty and the currentBurnTime will be 0. Even though it should be the burn time of coal.

 

5 hours ago, SureenInk said:

compound.setInteger("BurnTime", (short)this.burnTime);         

compound.setInteger("CookTime", (short)this.cookTime);         

compound.setInteger("CookTimeTotal", (short)this.totalCookTime);

This code makes no sense. "Serialize these as an integer using 4 bytes but truncate them to shorts first thus discarding the first 2 bytes". Why? Don't cast them to shorts at all just save them as ints in the first place. The fact that they are casted to shorts in TileEntityFurnace is a Mojang bug.

 

5 hours ago, SureenInk said:

te.getField(0)

Sigh. You do not need the get/setField nonesense if you are not using IInventory. And you are not. Just access the fields directly. 

 

Quote

if(this.isBurning())
        {
            --this.burnTime;
            BlockAlloyer.setState(true, world, pos);
        }

You probably do not want to be setting the state to a new one every tick. Only do it when the "should be" and "current" states do not match.

 

5 hours ago, SureenInk said:

        ItemStack[] inputs = new ItemStack[] {handler.getStackInSlot(0), handler.getStackInSlot(1)};

Any particular reasons for this array to exist? You are not iterating it. You are just using it to access elements at an index. You might as well use ItemStackHandler#getStackInSlot directly then.

 

5 hours ago, SureenInk said:

if(this.isBurning() && !fuel.isEmpty())

You already know that fuel isn't empty by now. If isBurning returns true then the burnTime for the fuel is not 0. Then the fuel isn't empty.

 

5 hours ago, SureenInk said:

                    handler.insertItem(3, smelting, false);

Why use insertItem here? You might as well be using setStackInSlot.

 

5 hours ago, SureenInk said:

smelting = ItemStack.EMPTY;                 

cookTime = 0;               

return;

This return is pointless since it is the last statement that gets executed. I don't know about eclipse but Idea warns you about these kinds of things. This is not really an issue btw, just me nitpicking. ?

 

5 hours ago, SureenInk said:

inputs[0].shrink(1);                     

inputs[1].shrink(1);                     

handler.setStackInSlot(0, inputs[0]);                     

handler.setStackInSlot(1, inputs[1]);

Why?

handler.getStackInSlot(0).shrink();
handler.getStackInSlot(1).shrink();

Does the same and is 50% less code.

 

5 hours ago, SureenInk said:

ItemStack result =  AlloyerRecipes.getInstance().getAlloyerResult((ItemStack)this.handler.getStackInSlot(0), (ItemStack)this.handler.getStackInSlot(1)); 

ItemStackHandler#getStackInSlot already returns an ItemStack there is no need to cast it to one. Again, a normal IDE would warn you about these kind of things.

 

5 hours ago, SureenInk said:

    public static int getItemBurnTime(ItemStack fuel)

You do not need this method since it is directly copied from TileEntityFurnace. Why did you do it in the first place? The method is static and public, you do not need to copy it.

 

As for the actual issue... It's a bit hard for me to tell just by looking at this code. I'll try to debug this locally and provide you with an answer in a bit.

 

As for shift-clicking - something is wrong with your logic in Container#transferStackInSlot. Use the debugger to find out what exactly.

 

 

Link to comment
Share on other sites

I've debugged your code.

What's happening with the tile entity is by your logic first it consumes the items for the operation and sets the cookTime to 1. It also sets the smelting field to the output of the recipe. Everything seems correct so far.

Apart from this condition:

        if(this.isBurning() && this.canSmelt() && cookTime > 0)

This checks if the smelter is burning(true), if the cookTime is greater than 0(true) and if the recipe is correct(false)! It shouldn't check for the recipe since it already cached the output. Check whether the output is empty instead.

 

As for the shift-clicking this is your issue:

Slot slot1 = this.inventorySlots.get(index + 1);
if(!AlloyerRecipes.getInstance().getAlloyerResult(stack1, slot1.getStack()).isEmpty())

You check if the item in the next slot + the item in the current slot make for a recipe. This

  • Only works for one item, the one the player clicks and not the other since now the condition isn't true.
  • Crashes the game if the player attemts to shift-click the item in their last slot

You have to change your logic here and instead check if the clicked item can be used in a recipe, and if it can in which position, determine the slot according to that position and attempt to merge. Or just transfer the item in the slot regardless of whether it should be in that slot or not.

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.