• 0

    posted a message on Saving Zentopia
    Welcome! My name is Pyro and I rule the lands of Zentopia.

    Story:
    I founded my kingdom around a year ago and have been building it up from nothing ever since. My town grows with each day, slowly becoming the city I want it to be. But something is wrong. The terrain forms sudden changes at the edges of my kingdom, creating large walls that are too smooth to be natural. The grass is disturbed every night by creatures I rarely glimpse. Other creatures seek to end me and my peoples' lives.

    I hear roars in the night, but I have no idea where they come from. The townsfolk spread rumours by day. Some say that a dragon scouts our land, plotting to tear it all down. Others say that it waits in an unreachable place, sending its minions to do its bidding. All I know is that whatever it is and wherever it rests, I will find it and I will end it. I will not see my kingdom destroyed so soon.

    Alright, so if you read that little role-played blurb, you probably have an idea what I was getting at. In case you didn't read it, or didn't understand entirely: a year ago, I started a YouTube series that I promised I would complete (previously, I had started several YouTube series' that I never finished, but instead cancelled and deleted). I decided that the best milestone would be to kill the Ender Dragon, and I've created a small lore behind it.

    There's my kingdom, where I build house upon house in order to create a bustling city. There have been updates that have changed the way worlds generate, causing world errors, giant walls surrounding the previously generated chunks. And, of course, there's the Ender Dragon and all of the hostile mobs.

    Here is the latest episode (If you want to view the entire playlist, click here):

    I've had trouble keeping my series going, but I haven't failed, yet. I used to take ages to upload new episodes. Sometimes months passed between episodes. However, I am getting back into the swing of things and hope to upload two episode every week. I'm here to finally get this series off the ground.

    If you plan to watch all episodes, I warn you. My first 10 or so episodes weren't the greatest, and are probably some of the most boring pieces of crap I've ever made. I experimented a lot and failed miserably every time. But, now, I spend more time in the editing room, making my videos eventful, constructive, and (hopefully) entertaining.

    If you're just looking for something to watch for the hell of killing time, well there you go. If you actually wanted to see something entertaining, I can't promise that I can fill that void, but if you could, I would like some feedback so that I may create better and more entertaining content in the future.

    I also don't want to be tied down to Minecraft forever, so if you'd like to see me play anything else, just shoot me a suggestion.
    Posted in: Let's Plays
  • 0

    posted a message on Should Mojang add a human mob?
    That's where resource packs come in.
    Posted in: Discussion
  • 0

    posted a message on [Forge 1.5.2] Need help with generating trees in The End
    So, I've been looking around to find out how I can do so, and the closest I got was someone who made a tutorial on creating a biome and adding world gen to it. I figured, if they can extend BiomeGenBase, why can't I just extend BiomeGenEnd and go from there?

    So my trees...well...they generate...just not the way I wanted them to. Here's my attempt (they're not textured yet):

    They go from Y: 0 to the max world height. What's odd is, they don't seem to care if there's end stone under them or not, and they only spawn within a 2x2 chunk grid by the looks.

    Here's all my code relating to the trees and custom world gen:
    package dragontools_common;
    import java.util.Random;
    import net.minecraft.block.material.Material;
    import net.minecraft.world.biome.BiomeGenEnd;
    import net.minecraft.world.gen.feature.WorldGenerator;
    public class BiomeGenDragonTools extends BiomeGenEnd
    {
        public static Material blockMaterial;
        private WorldGenerator WorldGenEnderTrees;
        private Object worldGeneratorEnderBigTree;
        public BiomeGenDragonTools(int par1)
        {
    	    super(par1);
    	    this.theBiomeDecorator.treesPerChunk = 10;
    	    this.WorldGenEnderTrees = new WorldGenEnderTree(false);
        }
        /**
    	 * Gets a WorldGen appropriate for this biome.
    	 */
        public WorldGenerator getRandomWorldGenForTrees(Random par1Random)
        {
    	    return (WorldGenerator) (par1Random.nextInt(5) == 0 ? this.worldGeneratorForest
    			    : (par1Random.nextInt(10) == 0 ? this.WorldGenEnderTrees
    					    : this.worldGeneratorTrees));
        }
    }
    package dragontools_common;
    import java.util.Random;
    import net.minecraft.block.Block;
    import net.minecraft.util.Direction;
    import net.minecraft.world.World;
    import net.minecraft.world.chunk.IChunkProvider;
    import net.minecraft.world.gen.feature.WorldGenerator;
    import net.minecraftforge.common.ForgeDirection;
    import cpw.mods.fml.common.IWorldGenerator;
    public class WorldGenEnderTree extends WorldGenerator implements
    	    IWorldGenerator
    {
        /** The minimum height of a generated tree. */
        private final int minTreeHeight;
        /** True if this tree should grow Vines. */
        private final boolean vinesGrow;
        /** The metadata value of the wood to use in tree generation. */
        private final int metaWood;
        /** The metadata value of the leaves to use in tree generation. */
        private final int metaLeaves;
        public WorldGenEnderTree(boolean par1)
        {
    	    this(par1, 8, 0, 0, false);
        }
        public WorldGenEnderTree(boolean par1, int par2, int par3, int par4,
    		    boolean par5)
        {
    	    super(par1);
    	    this.minTreeHeight = par2;
    	    this.metaWood = par3;
    	    this.metaLeaves = par4;
    	    this.vinesGrow = par5;
        }
        public boolean generate(World par1World, Random par2Random, int par3,
    		    int par4, int par5)
        {
    	    int l = par2Random.nextInt(3) + this.minTreeHeight;
    	    boolean flag = true;
    	    if (par4 >= 1 && par4 + l + 1 <= 256)
    	    {
    		    int i1;
    		    byte b0;
    		    int j1;
    		    int k1;
    		    for (i1 = par4; i1 <= par4 + 1 + l; ++i1)
    		    {
    			    b0 = 1;
    			    if (i1 == par4)
    			    {
    				    b0 = 0;
    			    }
    			    if (i1 >= par4 + 1 + l - 2)
    			    {
    				    b0 = 2;
    			    }
    			    for (int l1 = par3 - b0; l1 <= par3 + b0 && flag; ++l1)
    			    {
    				    for (j1 = par5 - b0; j1 <= par5 + b0 && flag; ++j1)
    				    {
    					    if (i1 >= 0 && i1 < 256)
    					    {
    						    k1 = par1World.getBlockId(l1, i1 - 1, j1);
    						    Block block = Block.whiteStone;
    						    if (k1 != 0
    								    && !block.isLeaves(par1World, l1, i1, j1)
    								    && k1 != Block.whiteStone.blockID
    								    && k1 != Block.whiteStone.blockID
    								    && !block.isWood(par1World, l1, i1, j1))
    						    {
    							    flag = false;
    						    }
    					    } else
    					    {
    						    flag = false;
    					    }
    				    }
    			    }
    		    }
    		    if (!flag)
    		    {
    			    return false;
    		    } else
    		    {
    			    i1 = par1World.getBlockId(par3, par4 - 1, par5);
    			    Block soil = Block.whiteStone;
    			    boolean isSoil = (soil != null && soil.canSustainPlant(
    					    par1World, par3, par4 - 1, par5, ForgeDirection.UP,
    					    (BlockEnderSapling) DragonTools.enderSapling));
    			    if (isSoil && par4 < 256 - l - 1)
    			    {
    				    soil.onPlantGrow(par1World, par3, par4 - 1, par5, par3,
    						    par4, par5);
    				    b0 = 3;
    				    byte b1 = 0;
    				    int i2;
    				    int j2;
    				    int k2;
    				    for (j1 = par4 - b0 + l; j1 <= par4 + l; ++j1)
    				    {
    					    k1 = j1 - (par4 + l);
    					    i2 = b1 + 1 - k1 / 2;
    					    for (j2 = par3 - i2; j2 <= par3 + i2; ++j2)
    					    {
    						    k2 = j2 - par3;
    						    for (int l2 = par5 - i2; l2 <= par5 + i2; ++l2)
    						    {
    							    int i3 = l2 - par5;
    							    if (Math.abs(k2) != i2 || Math.abs(i3) != i2
    									    || par2Random.nextInt(2) != 0
    									    && k1 != 0)
    							    {
    								    int j3 = par1World.getBlockId(j2, j1, l2);
    								    Block block = Block.blocksList[j3];
    								    if (block == null
    										    || block.canBeReplacedByLeaves(
    												    par1World, j2, j1, l2))
    								    {
    									    this.setBlockAndMetadata(par1World, j2,
    											    j1, l2,
    											    DragonTools.enderLeaf.blockID,
    											    this.metaLeaves);
    								    }
    							    }
    						    }
    					    }
    				    }
    				    for (j1 = 0; j1 < l; ++j1)
    				    {
    					    k1 = par1World.getBlockId(par3, par4 + j1, par5);
    					    Block block = Block.blocksList[k1];
    					    if (k1 == 0
    							    || block == null
    							    || block.isLeaves(par1World, par3, par4 + j1,
    									    par5))
    					    {
    						    this.setBlockAndMetadata(par1World, par3,
    								    par4 + j1, par5, DragonTools.enderWood.blockID,
    								    this.metaWood);
    					    }
    				    }
    			    }
    			    return true;
    		    }
    	    }
    	    return flag;
        }
        @Override
        public void generate(Random random, int chunkX, int chunkZ, World world,
    		    IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
        {
    	    for (int i = 0; i < 10; i++)
    	    {
    		    int xCoord = chunkX + random.nextInt(16);
    		    int yCoord = random.nextInt(255);
    		    int zCoord = chunkZ + random.nextInt(16);
    		    (new WorldGenEnderTree(false, 9, 0, 0, false)).generate(world,
    				    random, xCoord, yCoord, zCoord);
    	    }
        }
    }
    package dragontools_common;
    import java.util.Random;
    import net.minecraft.block.Block;
    import net.minecraft.util.Direction;
    import net.minecraft.world.World;
    import net.minecraft.world.chunk.IChunkProvider;
    import net.minecraft.world.gen.feature.WorldGenerator;
    import net.minecraftforge.common.ForgeDirection;
    import cpw.mods.fml.common.IWorldGenerator;
    public class WorldGenEnderTree extends WorldGenerator implements
    	    IWorldGenerator
    {
        /** The minimum height of a generated tree. */
        private final int minTreeHeight;
        /** True if this tree should grow Vines. */
        private final boolean vinesGrow;
        /** The metadata value of the wood to use in tree generation. */
        private final int metaWood;
        /** The metadata value of the leaves to use in tree generation. */
        private final int metaLeaves;
        public WorldGenEnderTree(boolean par1)
        {
    	    this(par1, 8, 0, 0, false);
        }
        public WorldGenEnderTree(boolean par1, int par2, int par3, int par4,
    		    boolean par5)
        {
    	    super(par1);
    	    this.minTreeHeight = par2;
    	    this.metaWood = par3;
    	    this.metaLeaves = par4;
    	    this.vinesGrow = par5;
        }
        public boolean generate(World par1World, Random par2Random, int par3,
    		    int par4, int par5)
        {
    	    int l = par2Random.nextInt(3) + this.minTreeHeight;
    	    boolean flag = true;
    	    if (par4 >= 1 && par4 + l + 1 <= 256)
    	    {
    		    int i1;
    		    byte b0;
    		    int j1;
    		    int k1;
    		    for (i1 = par4; i1 <= par4 + 1 + l; ++i1)
    		    {
    			    b0 = 1;
    			    if (i1 == par4)
    			    {
    				    b0 = 0;
    			    }
    			    if (i1 >= par4 + 1 + l - 2)
    			    {
    				    b0 = 2;
    			    }
    			    for (int l1 = par3 - b0; l1 <= par3 + b0 && flag; ++l1)
    			    {
    				    for (j1 = par5 - b0; j1 <= par5 + b0 && flag; ++j1)
    				    {
    					    if (i1 >= 0 && i1 < 256)
    					    {
    						    k1 = par1World.getBlockId(l1, i1 - 1, j1);
    						    Block block = Block.whiteStone;
    						    if (k1 != 0
    								    && !block.isLeaves(par1World, l1, i1, j1)
    								    && k1 != Block.whiteStone.blockID
    								    && k1 != Block.whiteStone.blockID
    								    && !block.isWood(par1World, l1, i1, j1))
    						    {
    							    flag = false;
    						    }
    					    } else
    					    {
    						    flag = false;
    					    }
    				    }
    			    }
    		    }
    		    if (!flag)
    		    {
    			    return false;
    		    } else
    		    {
    			    i1 = par1World.getBlockId(par3, par4 - 1, par5);
    			    Block soil = Block.whiteStone;
    			    boolean isSoil = (soil != null && soil.canSustainPlant(
    					    par1World, par3, par4 - 1, par5, ForgeDirection.UP,
    					    (BlockEnderSapling) DragonTools.enderSapling));
    			    if (isSoil && par4 < 256 - l - 1)
    			    {
    				    soil.onPlantGrow(par1World, par3, par4 - 1, par5, par3,
    						    par4, par5);
    				    b0 = 3;
    				    byte b1 = 0;
    				    int i2;
    				    int j2;
    				    int k2;
    				    for (j1 = par4 - b0 + l; j1 <= par4 + l; ++j1)
    				    {
    					    k1 = j1 - (par4 + l);
    					    i2 = b1 + 1 - k1 / 2;
    					    for (j2 = par3 - i2; j2 <= par3 + i2; ++j2)
    					    {
    						    k2 = j2 - par3;
    						    for (int l2 = par5 - i2; l2 <= par5 + i2; ++l2)
    						    {
    							    int i3 = l2 - par5;
    							    if (Math.abs(k2) != i2 || Math.abs(i3) != i2
    									    || par2Random.nextInt(2) != 0
    									    && k1 != 0)
    							    {
    								    int j3 = par1World.getBlockId(j2, j1, l2);
    								    Block block = Block.blocksList[j3];
    								    if (block == null
    										    || block.canBeReplacedByLeaves(
    												    par1World, j2, j1, l2))
    								    {
    									    this.setBlockAndMetadata(par1World, j2,
    											    j1, l2,
    											    DragonTools.enderLeaf.blockID,
    											    this.metaLeaves);
    								    }
    							    }
    						    }
    					    }
    				    }
    				    for (j1 = 0; j1 < l; ++j1)
    				    {
    					    k1 = par1World.getBlockId(par3, par4 + j1, par5);
    					    Block block = Block.blocksList[k1];
    					    if (k1 == 0
    							    || block == null
    							    || block.isLeaves(par1World, par3, par4 + j1,
    									    par5))
    					    {
    						    this.setBlockAndMetadata(par1World, par3,
    								    par4 + j1, par5, DragonTools.enderWood.blockID,
    								    this.metaWood);
    					    }
    				    }
    			    }
    			    return true;
    		    }
    	    }
    	    return flag;
        }
        @Override
        public void generate(Random random, int chunkX, int chunkZ, World world,
    		    IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
        {
    	    for (int i = 0; i < 10; i++)
    	    {
    		    int xCoord = chunkX + random.nextInt(16);
    		    int yCoord = random.nextInt(255);
    		    int zCoord = chunkZ + random.nextInt(16);
    		    (new WorldGenEnderTree(false, 9, 0, 0, false)).generate(world,
    				    random, xCoord, yCoord, zCoord);
    	    }
        }
    }
    package dragontools_common;
    import java.util.Random;
    import net.minecraft.block.Block;
    import net.minecraft.block.BlockFlower;
    import net.minecraft.world.World;
    import net.minecraft.world.gen.feature.WorldGenBigTree;
    import net.minecraft.world.gen.feature.WorldGenForest;
    import net.minecraft.world.gen.feature.WorldGenTaiga2;
    import net.minecraft.world.gen.feature.WorldGenerator;
    import net.minecraftforge.event.terraingen.TerrainGen;
    public class BlockEnderSapling extends BlockFlower
    {
        /** change the name to your sapling name **/
        public static final String[] WOOD_TYPES = new String[]
        { "Ender" };
        public BlockEnderSapling(int i, int j)
        {
    	    super(i);
    	    float var3 = 0.4F;
    	    this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3,
    			    var3 * 2.0F, 0.5F + var3);
    	    this.setCreativeTab(DragonTools.dragonTools);
        }
        /**
    	 * Ticks the block if it's been scheduled
    	 */
        public void updateTick(World par1World, int par2, int par3, int par4,
    		    Random par5Random)
        {
    	    if (!par1World.isRemote)
    	    {
    		    super.updateTick(par1World, par2, par3, par4, par5Random);
    		    if (par1World.getBlockLightValue(par2, par3 + 1, par4) >= 9
    				    && par5Random.nextInt(7) == 0)
    		    {
    			    this.func_96477_c(par1World, par2, par3, par4, par5Random);
    		    }
    	    }
        }
        public void func_96477_c(World par1World, int par2, int par3, int par4,
    		    Random par5Random)
        {
    	    int l = par1World.getBlockMetadata(par2, par3, par4);
    	    if ((l & 8) == Block.whiteStone.blockID)
    	    {
    		    par1World.setBlockMetadataWithNotify(par2, par3, par4, l | 8, 4);
    	    } else
    	    {
    		    this.growTree(par1World, par2, par3, par4, par5Random);
    	    }
        }
        /**
    	 * Attempts to grow a sapling into a tree
    	 */
        public void growTree(World par1World, int par2, int par3, int par4,
    		    Random par5Random)
        {
    	    if (!TerrainGen
    			    .saplingGrowTree(par1World, par5Random, par2, par3, par4))
    		    return;
    	    int l = par1World.getBlockMetadata(par2, par3, par4) & 3;
    	    Object object = null;
    	    int i1 = 0;
    	    int j1 = 0;
    	    boolean flag = false;
    	    if (l == 1)
    	    {
    		    object = new WorldGenTaiga2(true);
    	    } else if (l == 2)
    	    {
    		    object = new WorldGenForest(true);
    	    } else if (l == 3)
    	    {
    		    for (i1 = 0; i1 >= -1; --i1)
    		    {
    			    for (j1 = 0; j1 >= -1; --j1)
    			    {
    				    if (this.isSameSapling(par1World, par2 + i1, par3, par4
    						    + j1, 3)
    						    && this.isSameSapling(par1World, par2 + i1 + 1,
    								    par3, par4 + j1, 3)
    						    && this.isSameSapling(par1World, par2 + i1, par3,
    								    par4 + j1 + 1, 3)
    						    && this.isSameSapling(par1World, par2 + i1 + 1,
    								    par3, par4 + j1 + 1, 3))
    				    {
    					    /** Change this to your WorldGenNAMETree **/
    					    object = new WorldGenEnderTree(true,
    							    10 + par5Random.nextInt(20), 3, 3, false);
    					    flag = true;
    					    break;
    				    }
    			    }
    			    if (object != null)
    			    {
    				    break;
    			    }
    		    }
    		    if (object == null)
    		    {
    			    j1 = 0;
    			    i1 = 0;
    			    /** Change this to your WorldGenNAMETree **/
    			    object = new WorldGenEnderTree(true,
    					    4 + par5Random.nextInt(7), 3, 3, false);
    		    }
    	    } else
    	    {
    		    /** Change this to your WorldGenNAMETree **/
    		    object = new WorldGenEnderTree(true); // Changed //
    		    if (par5Random.nextInt(10) == 0)
    		    {
    			    object = new WorldGenBigTree(true);
    		    }
    	    }
    	    if (flag)
    	    {
    		    par1World.setBlock(par2 + i1, par3, par4 + j1, 0, 0, 4);
    		    par1World.setBlock(par2 + i1 + 1, par3, par4 + j1, 0, 0, 4);
    		    par1World.setBlock(par2 + i1, par3, par4 + j1 + 1, 0, 0, 4);
    		    par1World.setBlock(par2 + i1 + 1, par3, par4 + j1 + 1, 0, 0, 4);
    	    } else
    	    {
    		    par1World.setBlock(par2, par3, par4, 0, 0, 4);
    	    }
    	    if (!((WorldGenerator) object).generate(par1World, par5Random, par2
    			    + i1, par3, par4 + j1))
    	    {
    		    if (flag)
    		    {
    			    par1World.setBlock(par2 + i1, par3, par4 + j1, this.blockID, l,
    					    4);
    			    par1World.setBlock(par2 + i1 + 1, par3, par4 + j1,
    					    this.blockID, l, 4);
    			    par1World.setBlock(par2 + i1, par3, par4 + j1 + 1,
    					    this.blockID, l, 4);
    			    par1World.setBlock(par2 + i1 + 1, par3, par4 + j1 + 1,
    					    this.blockID, l, 4);
    		    } else
    		    {
    			    par1World.setBlock(par2, par3, par4, this.blockID, l, 4);
    		    }
    	    }
        }
        /**
    	 * Determines if the same sapling is present at the given location.
    	 */
        public boolean isSameSapling(World par1World, int par2, int par3, int par4,
    		    int par5)
        {
    	    return par1World.getBlockId(par2, par3, par4) == this.blockID
    			    && (par1World.getBlockMetadata(par2, par3, par4) & 3) == par5;
        }
        /**
    	 * Gets passed in the blockID of the block below and supposed to return true
    	 * if its allowed to grow on the type of blockID passed in. Args: blockID
    	 */
        @Override
        protected boolean canThisPlantGrowOnThisBlockID(int par1)
        {
    	    /** Change this to your custom grass **/
    	    return par1 == Block.whiteStone.blockID;
        }
    }
    package dragontools_common;
    import java.util.Random;
    import net.minecraft.block.Block;
    import net.minecraft.block.material.Material;
    import net.minecraft.client.renderer.texture.IconRegister;
    public class BlockEnderLeaf extends Block
    {
        public BlockEnderLeaf(int par1)
        {
    	    super(par1, Material.leaves);
    	    this.setCreativeTab(DragonTools.dragonTools);
    	    this.setStepSound(soundGrassFootstep);
    	    this.setHardness(0.2F);
        }
        public boolean isOpaqueCube()
        {
    	    return false;
        }
        /**
    	 * Returns the ID of the items to drop on destruction.
    	 */
        public int idDropped(int par1, Random par2Random, int par3)
        {
    	    return this.blockID;
        }
        /**
    	 * Returns the quantity of items to drop on block destruction.
    	 */
        public int quantityDropped(Random par1Random)
        {
    	    return 1;
        }
       
        public void registerIcons(IconRegister par1IconRegister)
        {
    	    this.blockIcon = par1IconRegister.registerIcon(DragonTools.modid + ":"
    			    + (this.getUnlocalizedName().substring(5)));
        }
    }

    And I also have this in my load method in my main class:
    public static final BiomeGenEnd enderBiome = new BiomeGenEnd(25);


    I would appreciate it if people could either help me fix the problem or point me to an up-to-date tutorial that could help me add my own trees to the end.
    Posted in: Modification Development
  • 0

    posted a message on [Forge]Custom Furnace Slot Problems
    EDIT: I have managed to solve MOST of my problems. If you wish to see what they were or what they were related to, look inside:
    Okay, so I've been doing some work on a mod that adds a few tiers of tools, as well as a custom furnace which smelts twice as fast as a regular furnace. The furnace, itself, works fine. Every class, such as TileEntityCustomFurnace, or CustomFurnaceRecipes are all based on the vanilla furnace classes. It was working fine, with all the custom recipes I added and there were no problems. However, I wished to try something further.

    I plan on allowing the furnace to double the output. This isn't too difficult...it's just a matter of changing the furnace recipes. These aren't the problem. If I'm going to let the output double, I wish to make a second output slot (this is, of course, optional for the furnace to be functional, but it would be convenient for people who just throw more than half a stack of ore into a non-automated furnace).

    I set out through the code I almost barely understand and located a place I could add a new slot. Well, it wasn't too difficult to do. I created a simple 4th furnace slot, but it was simply a storage slot. I could put things in it, and take things out of it, but the furnace didn't actually drop its extra output into it like it should. I had to implement further.

    After a lot of trial and error, I finally got it working. One problem...whenever I took what was in the original output slot out of the furnace, the game would instantly crash...whether the second output slot had anything in it or not.

    So there goes another few hours of my life I'll never get back. I finally got it working again. The slots were filling up as they should, however, this time, when I took items out of the original output slot, the game wouldn't crash...until a new item was smelted. -sigh-

    A few more hours later, I'm stumped. I've done as much as I could and I've attempted to pinpoint the problem. I've done so much changing around of the code, that now it just won't smelt at all (well, it will, but it crashes as soon as a new item is smelted, whether any items were taken out of it or not...essentially, I can place the furnace down, put fuel into it, put an ore into it...it will begin smelting...then crash as soon as the item should go to the output slot).

    So, without further ado, I give you my TileEntityFurnace class. You shouldn't need any of my other classes, as none of them have been changed in any way, except for the names of a few methods and whatnot. The only exception is I added "this.addSlotToContainer(new SlotEnderFurnace(par1InventoryPlayer.player, par2TileEntityEnderFurnace, 3, 148, 35));" to my ContainerFurnace class
    package dragontools_common;
    import net.minecraft.block.Block;
    import net.minecraft.block.material.Material;
    import net.minecraft.entity.player.EntityPlayer;
    import net.minecraft.inventory.ISidedInventory;
    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.nbt.NBTTagList;
    import net.minecraft.tileentity.TileEntity;
    import net.minecraftforge.common.ForgeDirection;
    import net.minecraftforge.common.ForgeDummyContainer;
    import cpw.mods.fml.common.registry.GameRegistry;
    import cpw.mods.fml.relauncher.Side;
    import cpw.mods.fml.relauncher.SideOnly;
    public class TileEntityEnderFurnace extends TileEntity implements ISidedInventory, net.minecraftforge.common.ISidedInventory
    {
    private static final int[] field_102010_d = new int[] {0};
    private static final int[] field_102011_e = new int[] {2, 1};
    private static final int[] field_102009_f = new int[] {1};
    /**
    	 * The ItemStacks that hold the items currently being used in the furnace
    	 */
    private ItemStack[] furnaceItemStacks = new ItemStack[4];
    /** The number of ticks that the furnace will keep burning */
    public int furnaceBurnTime = 0;
    /**
    	 * The number of ticks that a fresh copy of the currently-burning item would keep the furnace burning for
    	 */
    public int currentItemBurnTime = 0;
    /** The number of ticks that the current item has been cooking for */
    public int furnaceCookTime = 0;
    private String field_94130_e;
    /**
    	 * Returns the number of slots in the inventory.
    	 */
    public int getSizeInventory()
    {
    	 return this.furnaceItemStacks.length;
    }
    /**
    	 * Returns the stack in slot i
    	 */
    public ItemStack getStackInSlot(int par1)
    {
    	 return this.furnaceItemStacks[par1];
    }
    /**
    	 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
    	 * new stack.
    	 */
    public ItemStack decrStackSize(int par1, int par2)
    {
    	 if (this.furnaceItemStacks[par1] != null)
    	 {
    		 ItemStack itemstack;
    		 if (this.furnaceItemStacks[par1].stackSize <= par2)
    		 {
    			 itemstack = this.furnaceItemStacks[par1];
    			 this.furnaceItemStacks[par1] = null;
    			 return itemstack;
    		 }
    		 else
    		 {
    			 itemstack = this.furnaceItemStacks[par1].splitStack(par2);
    			 if (this.furnaceItemStacks[par1].stackSize == 0)
    			 {
    				 this.furnaceItemStacks[par1] = null;
    			 }
    			 return itemstack;
    		 }
    	 }
    	 else
    	 {
    		 return null;
    	 }
    }
    /**
    	 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
    	 * like when you close a workbench GUI.
    	 */
    public ItemStack getStackInSlotOnClosing(int par1)
    {
    	 if (this.furnaceItemStacks[par1] != null)
    	 {
    		 ItemStack itemstack = this.furnaceItemStacks[par1];
    		 this.furnaceItemStacks[par1] = null;
    		 return itemstack;
    	 }
    	 else
    	 {
    		 return null;
    	 }
    }
    /**
    	 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
    	 */
    public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
    {
    	 this.furnaceItemStacks[par1] = par2ItemStack;
    	 if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
    	 {
    		 par2ItemStack.stackSize = this.getInventoryStackLimit();
    	 }
    }
    /**
    	 * Returns the name of the inventory.
    	 */
    public String getInvName()
    {
    	 return this.isInvNameLocalized() ? this.field_94130_e : "Ender Furnace";
    }
    /**
    	 * If this returns false, the inventory name will be used as an unlocalized name, and translated into the player's
    	 * language. Otherwise it will be used directly.
    	 */
    public boolean isInvNameLocalized()
    {
    	 return this.field_94130_e != null && this.field_94130_e.length() > 0;
    }
    public void func_94129_a(String par1Str)
    {
    	 this.field_94130_e = par1Str;
    }
    /**
    	 * Reads a tile entity from NBT.
    	 */
    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    {
    	 super.readFromNBT(par1NBTTagCompound);
    	 NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items");
    	 this.furnaceItemStacks = new ItemStack[this.getSizeInventory()];
    	 for (int i = 0; i < nbttaglist.tagCount(); ++i)
    	 {
    		 NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i);
    		 byte b0 = nbttagcompound1.getByte("Slot");
    		 if (b0 >= 0 && b0 < this.furnaceItemStacks.length)
    		 {
    			 this.furnaceItemStacks[b0] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
    		 }
    	 }
    	 this.furnaceBurnTime = par1NBTTagCompound.getShort("BurnTime");
    	 this.furnaceCookTime = par1NBTTagCompound.getShort("CookTime");
    	 this.currentItemBurnTime = getItemBurnTime(this.furnaceItemStacks[1]);
    	 if (par1NBTTagCompound.hasKey("Ender Furnace"))
    	 {
    		 this.field_94130_e = par1NBTTagCompound.getString("Ender Furnace");
    	 }
    }
    /**
    	 * Writes a tile entity to NBT.
    	 */
    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    {
    	 super.writeToNBT(par1NBTTagCompound);
    	 par1NBTTagCompound.setShort("BurnTime", (short)this.furnaceBurnTime);
    	 par1NBTTagCompound.setShort("CookTime", (short)this.furnaceCookTime);
    	 NBTTagList nbttaglist = new NBTTagList();
    	 for (int i = 0; i < this.furnaceItemStacks.length; ++i)
    	 {
    		 if (this.furnaceItemStacks[i] != null)
    		 {
    			 NBTTagCompound nbttagcompound1 = new NBTTagCompound();
    			 nbttagcompound1.setByte("Slot", (byte)i);
    			 this.furnaceItemStacks[i].writeToNBT(nbttagcompound1);
    			 nbttaglist.appendTag(nbttagcompound1);
    		 }
    	 }
    	 par1NBTTagCompound.setTag("Items", nbttaglist);
    	 if (this.isInvNameLocalized())
    	 {
    		 par1NBTTagCompound.setString("Ender Furnace", this.field_94130_e);
    	 }
    }
    /**
    	 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
    	 * this more of a set than a get?*
    	 */
    public int getInventoryStackLimit()
    {
    	 return 64;
    }
    @SideOnly(Side.CLIENT)
    /**
    	 * Returns an integer between 0 and the passed value representing how close the current item is to being completely
    	 * cooked
    	 */
    public int getCookProgressScaled(int par1)
    {
    	 return this.furnaceCookTime * par1 / 100;
    }
    @SideOnly(Side.CLIENT)
    /**
    	 * Returns an integer between 0 and the passed value representing how much burn time is left on the current fuel
    	 * item, where 0 means that the item is exhausted and the passed value means that the item is fresh
    	 */
    public int getBurnTimeRemainingScaled(int par1)
    {
    	 if (this.currentItemBurnTime == 0)
    	 {
    		 this.currentItemBurnTime = 100;
    	 }
    	 return this.furnaceBurnTime * par1 / this.currentItemBurnTime;
    }
    /**
    	 * Returns true if the furnace is currently burning
    	 */
    public boolean isBurning()
    {
    	 return this.furnaceBurnTime > 0;
    }
    /**
    	 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
    	 * ticks and creates a new spawn inside its implementation.
    	 */
    public void updateEntity()
    {
    	 boolean flag = this.furnaceBurnTime > 0;
    	 boolean flag1 = false;
    	 if (this.furnaceBurnTime > 0)
    	 {
    		 --this.furnaceBurnTime;
    	 }
    	 if (!this.worldObj.isRemote)
    	 {
    		 if (this.furnaceBurnTime == 0 && this.canSmelt())
    		 {
    			 this.currentItemBurnTime = this.furnaceBurnTime = getItemBurnTime(this.furnaceItemStacks[1]);
    			 if (this.furnaceBurnTime > 0)
    			 {
    				 flag1 = true;
    				 if (this.furnaceItemStacks[1] != null)
    				 {
    					 --this.furnaceItemStacks[1].stackSize;
    					 if (this.furnaceItemStacks[1].stackSize == 0)
    					 {
    						 this.furnaceItemStacks[1] = this.furnaceItemStacks[1].getItem().getContainerItemStack(furnaceItemStacks[1]);
    					 }
    				 }
    			 }
    		 }
    		 if (this.isBurning() && this.canSmelt())
    		 {
    			 ++this.furnaceCookTime;
    			 if (this.furnaceCookTime == 100)
    			 {
    				 this.furnaceCookTime = 0;
    				 this.smeltItem();
    				 flag1 = true;
    			 }
    		 }
    		 else
    		 {
    			 this.furnaceCookTime = 0;
    		 }
    		 if (flag != this.furnaceBurnTime > 0)
    		 {
    			 flag1 = true;
    			 BlockEnderFurnace.updateFurnaceBlockState(this.furnaceBurnTime > 0, this.worldObj, this.xCoord, this.yCoord, this.zCoord);
    		 }
    	 }
    	 if (flag1)
    	 {
    		 this.onInventoryChanged();
    	 }
    }
    /**
    	 * Returns true if the furnace can smelt an item, i.e. has a source item, destination stack isn't full, etc.
    	 */
    private boolean canSmelt()
    {
    	 if (this.furnaceItemStacks[0] == null)
    	 {
    		 return false;
    	 }
    	 else
    	 {
    		 ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    		 if (itemstack == null) return false;
    		 if (this.furnaceItemStacks[2] == null || this.furnaceItemStacks[3] == null) return true;
    		 if (!this.furnaceItemStacks[2].isItemEqual(itemstack) || !this.furnaceItemStacks[3].isItemEqual(itemstack)) return false;
    		 int result = furnaceItemStacks[2].stackSize + furnaceItemStacks[3].stackSize + itemstack.stackSize;
    		 return (result <= getInventoryStackLimit() && result <= itemstack.getMaxStackSize());
    	 }
    }
    
    /**
    	 * Turn one item from the furnace source stack into the appropriate smelted item in the furnace result stack
    	 */
    public void smeltItem()
    {
    	 if (this.canSmelt())
    	 {
    		 ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    		
    		 if(furnaceItemStacks[2].stackSize == itemstack.getMaxStackSize())
    		 {
    			 if (this.furnaceItemStacks[3] == null)
    			 {
    				 this.furnaceItemStacks[3] = itemstack.copy();
    			 }
    			 else if (this.furnaceItemStacks[3].isItemEqual(itemstack))
    			 {
    				 furnaceItemStacks[3].stackSize += itemstack.stackSize;
    			 }
    		 }
    		 else
    		 {
    			 if (this.furnaceItemStacks[2] == null)
    			 {
    				 this.furnaceItemStacks[2] = itemstack.copy();
    			 }
    			 else if (this.furnaceItemStacks[2].isItemEqual(itemstack))
    			 {
    				 furnaceItemStacks[2].stackSize += itemstack.stackSize;
    			 }
    		 }
    		
    		 --this.furnaceItemStacks[0].stackSize;
    		 if (this.furnaceItemStacks[0].stackSize <= 0)
    		 {
    			 this.furnaceItemStacks[0] = null;
    		 }
    	 }
    }
    /**
    	 * Returns the number of ticks that the supplied fuel item will keep the furnace burning, or 0 if the item isn't
    	 * fuel
    	 */
    public static int getItemBurnTime(ItemStack par0ItemStack)
    {
    	 if (par0ItemStack == null)
    	 {
    		 return 0;
    	 }
    	 else
    	 {
    		 int i = par0ItemStack.getItem().itemID;
    		 Item item = par0ItemStack.getItem();
    		 if (par0ItemStack.getItem() instanceof ItemBlock && Block.blocksList[i] != null)
    		 {
    			 Block block = Block.blocksList[i];
    			 if (block == Block.woodSingleSlab)
    			 {
    				 return 195;
    			 }
    			 if (block.blockMaterial == Material.wood)
    			 {
    				 return 390;
    			 }
    		 }
    		 if (item instanceof ItemTool && ((ItemTool) item).getToolMaterialName().equals("blazed")) return 100;
    		 if (item instanceof ItemSword && ((ItemSword) item).getToolMaterialName().equals("blazed")) return 100;
    		 if (item instanceof ItemHoe && ((ItemHoe) item).getMaterialName().equals("blazed")) return 100;
    		 if (i == DragonTools.blazedDust.itemID) return 800;
    		 if (i == DragonTools.blazedIngot.itemID) return 1600;
    		 if (i == DragonTools.blazedBlock.blockID) return 8000;
    		 return GameRegistry.getFuelValue(par0ItemStack);
    	 }
    }
    /**
    	 * Return true if item is a fuel source (getItemBurnTime() > 0).
    	 */
    public static boolean isItemFuel(ItemStack par0ItemStack)
    {
    	 return getItemBurnTime(par0ItemStack) > 0;
    }
    /**
    	 * Do not make give this method the name canInteractWith because it clashes with Container
    	 */
    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
    {
    	 return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
    }
    public void openChest() {}
    public void closeChest() {}
    /**
    	 * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot.
    	 */
    public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack)
    {
    	 return par1 == 2 ? false : (par1 == 1 ? isItemFuel(par2ItemStack) : true);
    }
    /**
    	 * Returns an array containing the indices of the slots that can be accessed by automation on the given side of this
    	 * block.
    	 */
    public int[] getAccessibleSlotsFromSide(int par1)
    {
    	 return par1 == 0 ? field_102011_e : (par1 == 1 ? field_102010_d : field_102009_f);
    }
    /**
    	 * Returns true if automation can insert the given item in the given slot from the given side. Args: Slot, item,
    	 * side
    	 */
    public boolean canInsertItem(int par1, ItemStack par2ItemStack, int par3)
    {
    	 return this.isStackValidForSlot(par1, par2ItemStack);
    }
    /**
    	 * Returns true if automation can extract the given item in the given slot from the given side. Args: Slot, item,
    	 * side
    	 */
    public boolean canExtractItem(int par1, ItemStack par2ItemStack, int par3)
    {
    	 return par3 != 0 || par1 != 1 || par2ItemStack.itemID == Item.bucketEmpty.itemID;
    }
    /***********************************************************************************
    	 * This function is here for compatibilities sake, Modders should Check for
    	 * Sided before ContainerWorldly, Vanilla Minecraft does not follow the sided standard
    	 * that Modding has for a while.
    	 *
    	 * In vanilla:
    	 *
    	 * Top: Ores
    	 * Sides: Fuel
    	 * Bottom: Output
    	 *
    	 * Standard Modding:
    	 * Top: Ores
    	 * Sides: Output
    	 * Bottom: Fuel
    	 *
    	 * The Modding one is designed after the GUI, the vanilla one is designed because its
    	 * intended use is for the hopper, which logically would take things in from the top.
    	 *
    	 * This will possibly be removed in future updates, and make vanilla the definitive
    	 * standard.
    	 */
    @Override
    public int getStartInventorySide(ForgeDirection side)
    {
    	 if (ForgeDummyContainer.legacyFurnaceSides)
    	 {
    		 if (side == ForgeDirection.DOWN) return 1;
    		 if (side == ForgeDirection.UP) return 0;
    		 return 2;
    	 }
    	 else
    	 {
    		 if (side == ForgeDirection.DOWN) return 2;
    		 if (side == ForgeDirection.UP) return 0;
    		 return 1;
    	 }
    }
    @Override
    public int getSizeInventorySide(ForgeDirection side)
    {
    	 return 1;
    }
    }

    Only a part of the code has been changed, and I have reason to believe the main problem is either within:
    private boolean canSmelt()
    {
    	 if (this.furnaceItemStacks[0] == null)
    	 {
    		 return false;
    	 }
    	 else
    	 {
    		 ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    		 if (itemstack == null) return false;
    		 if (this.furnaceItemStacks[2] == null || this.furnaceItemStacks[3] == null) return true;
    		 if (!this.furnaceItemStacks[2].isItemEqual(itemstack) || !this.furnaceItemStacks[3].isItemEqual(itemstack)) return false;
    		 int result = furnaceItemStacks[2].stackSize + itemstack.stackSize + furnaceItemStacks[3].stackSize + itemstack.stackSize;
    		 return (result <= getInventoryStackLimit() && result <= itemstack.getMaxStackSize());
    	 }
    }
    or
    public void smeltItem()
    {
    	 if (this.canSmelt())
    	 {
    		 ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    		
    //if first output slot is full, start outputting to second output slot
    		 if(furnaceItemStacks[2].stackSize == itemstack.getMaxStackSize())
    		 {
    			 if (this.furnaceItemStacks[3] == null)
    			 {
    				 this.furnaceItemStacks[3] = itemstack.copy();
    			 }
    			 else if (this.furnaceItemStacks[3].isItemEqual(itemstack))
    			 {
    				 furnaceItemStacks[3].stackSize += itemstack.stackSize;
    			 }
    		 }
    		 else
    		 {
    			 if (this.furnaceItemStacks[2] == null)
    			 {
    				 this.furnaceItemStacks[2] = itemstack.copy();
    			 }
    			 else if (this.furnaceItemStacks[2].isItemEqual(itemstack))
    			 {
    				 furnaceItemStacks[2].stackSize += itemstack.stackSize;
    			 }
    		 }
    		
    		 --this.furnaceItemStacks[0].stackSize;
    		 if (this.furnaceItemStacks[0].stackSize <= 0)
    		 {
    			 this.furnaceItemStacks[0] = null;
    		 }
    	 }
    }

    If you haven't figured out what I want the furnace to do by now...it's simple:

    1-Basic furnace-ly duties, such as check if the items inside can be smelted up together to create something else, then output the result
    2-If the first output slot is full, move on to fill the second output slot
    3-If both are full...do the obvious thing and stop smelting, all together

    The main error I've been getting when the game crashes in the ways I've described is
    Minecraft has crashed!	
    	 ----------------------	
    Minecraft has stopped running because it encountered a problem; Ticking tile entity
    ----------------------------------------------------------------------------------
    -- Head --
    Stacktrace:
    at dragontools_common.TileEntityEnderFurnace.smeltItem(TileEntityEnderFurnace.java:345)
    at dragontools_common.TileEntityEnderFurnace.updateEntity(TileEntityEnderFurnace.java:294)
    -- Tile entity being ticked --
    Details:
    Name: tileEntityEnderFurnace // dragontools_common.TileEntityEnderFurnace
    Block type: ID #509 (tile.enderFurnaceBurning // dragontools_common.BlockEnderFurnace)
    Block data value: 2 / 0x2 / 0b0010
    Block location: World: (188,4,232), Chunk: (at 12,0,8 in 11,14; contains blocks 176,0,224 to 191,255,239), Region: (0,0; contains chunks 0,0 to 31,31, blocks 0,0,0 to 511,255,511)
    Actual block type: ID #509 (tile.enderFurnaceBurning // dragontools_common.BlockEnderFurnace)
    Actual block data value: 2 / 0x2 / 0b0010
    Stacktrace:
    at net.minecraft.world.World.updateEntities(World.java:2202)
    at net.minecraft.world.WorldServer.updateEntities(WorldServer.java:546)


    It points out lines 345 ("if(furnaceItemStacks[2].stackSize == itemstack.getMaxStackSize())" and 294 ("this.smeltItem();") If anyone could help me out here, that would be great.

    As I said. I have managed to solve MOST of my problem. There is just ONE MORE THING that is keeping me from calling my furnace a complete machine.

    First of all, here is the updated TileEntityFurnace class of mine:
    package dragontools_common;
    import net.minecraft.block.Block;
    import net.minecraft.block.material.Material;
    import net.minecraft.entity.player.EntityPlayer;
    import net.minecraft.inventory.ISidedInventory;
    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.nbt.NBTTagList;
    import net.minecraft.tileentity.TileEntity;
    import net.minecraftforge.common.ForgeDirection;
    import net.minecraftforge.common.ForgeDummyContainer;
    import cpw.mods.fml.common.registry.GameRegistry;
    import cpw.mods.fml.relauncher.Side;
    import cpw.mods.fml.relauncher.SideOnly;
    public class TileEntityEnderFurnace extends TileEntity implements ISidedInventory, net.minecraftforge.common.ISidedInventory
    {
    private static final int[] field_102010_d = new int[] {0};
    private static final int[] field_102011_e = new int[] {2, 1};
    private static final int[] field_102009_f = new int[] {1};
    /**
    	 * The ItemStacks that hold the items currently being used in the furnace
    	 */
    private ItemStack[] furnaceItemStacks = new ItemStack[4];
    /** The number of ticks that the furnace will keep burning */
    public int furnaceBurnTime = 0;
    /**
    	 * The number of ticks that a fresh copy of the currently-burning item would keep the furnace burning for
    	 */
    public int currentItemBurnTime = 0;
    /** The number of ticks that the current item has been cooking for */
    public int furnaceCookTime = 0;
    private String field_94130_e;
    /**
    	 * Returns the number of slots in the inventory.
    	 */
    public int getSizeInventory()
    {
    	 return this.furnaceItemStacks.length;
    }
    /**
    	 * Returns the stack in slot i
    	 */
    public ItemStack getStackInSlot(int par1)
    {
    	 return this.furnaceItemStacks[par1];
    }
    /**
    	 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
    	 * new stack.
    	 */
    public ItemStack decrStackSize(int par1, int par2)
    {
    	 if (this.furnaceItemStacks[par1] != null)
    	 {
    		 ItemStack itemstack;
    		 if (this.furnaceItemStacks[par1].stackSize <= par2)
    		 {
    			 itemstack = this.furnaceItemStacks[par1];
    			 this.furnaceItemStacks[par1] = null;
    			 return itemstack;
    		 }
    		 else
    		 {
    			 itemstack = this.furnaceItemStacks[par1].splitStack(par2);
    			 if (this.furnaceItemStacks[par1].stackSize == 0)
    			 {
    				 this.furnaceItemStacks[par1] = null;
    			 }
    			 return itemstack;
    		 }
    	 }
    	 else
    	 {
    		 return null;
    	 }
    }
    /**
    	 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
    	 * like when you close a workbench GUI.
    	 */
    public ItemStack getStackInSlotOnClosing(int par1)
    {
    	 if (this.furnaceItemStacks[par1] != null)
    	 {
    		 ItemStack itemstack = this.furnaceItemStacks[par1];
    		 this.furnaceItemStacks[par1] = null;
    		 return itemstack;
    	 }
    	 else
    	 {
    		 return null;
    	 }
    }
    /**
    	 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
    	 */
    public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
    {
    	 this.furnaceItemStacks[par1] = par2ItemStack;
    	 if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
    	 {
    		 par2ItemStack.stackSize = this.getInventoryStackLimit();
    	 }
    }
    /**
    	 * Returns the name of the inventory.
    	 */
    public String getInvName()
    {
    	 return this.isInvNameLocalized() ? this.field_94130_e : "Ender Furnace";
    }
    /**
    	 * If this returns false, the inventory name will be used as an unlocalized name, and translated into the player's
    	 * language. Otherwise it will be used directly.
    	 */
    public boolean isInvNameLocalized()
    {
    	 return this.field_94130_e != null && this.field_94130_e.length() > 0;
    }
    public void func_94129_a(String par1Str)
    {
    	 this.field_94130_e = par1Str;
    }
    /**
    	 * Reads a tile entity from NBT.
    	 */
    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    {
    	 super.readFromNBT(par1NBTTagCompound);
    	 NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items");
    	 this.furnaceItemStacks = new ItemStack[this.getSizeInventory()];
    	 for (int i = 0; i < nbttaglist.tagCount(); ++i)
    	 {
    		 NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i);
    		 byte b0 = nbttagcompound1.getByte("Slot");
    		 if (b0 >= 0 && b0 < this.furnaceItemStacks.length)
    		 {
    			 this.furnaceItemStacks[b0] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
    		 }
    	 }
    	 this.furnaceBurnTime = par1NBTTagCompound.getShort("BurnTime");
    	 this.furnaceCookTime = par1NBTTagCompound.getShort("CookTime");
    	 this.currentItemBurnTime = getItemBurnTime(this.furnaceItemStacks[1]);
    	 if (par1NBTTagCompound.hasKey("Ender Furnace"))
    	 {
    		 this.field_94130_e = par1NBTTagCompound.getString("Ender Furnace");
    	 }
    }
    /**
    	 * Writes a tile entity to NBT.
    	 */
    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    {
    	 super.writeToNBT(par1NBTTagCompound);
    	 par1NBTTagCompound.setShort("BurnTime", (short)this.furnaceBurnTime);
    	 par1NBTTagCompound.setShort("CookTime", (short)this.furnaceCookTime);
    	 NBTTagList nbttaglist = new NBTTagList();
    	 for (int i = 0; i < this.furnaceItemStacks.length; ++i)
    	 {
    		 if (this.furnaceItemStacks[i] != null)
    		 {
    			 NBTTagCompound nbttagcompound1 = new NBTTagCompound();
    			 nbttagcompound1.setByte("Slot", (byte)i);
    			 this.furnaceItemStacks[i].writeToNBT(nbttagcompound1);
    			 nbttaglist.appendTag(nbttagcompound1);
    		 }
    	 }
    	 par1NBTTagCompound.setTag("Items", nbttaglist);
    	 if (this.isInvNameLocalized())
    	 {
    		 par1NBTTagCompound.setString("Ender Furnace", this.field_94130_e);
    	 }
    }
    /**
    	 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
    	 * this more of a set than a get?*
    	 */
    public int getInventoryStackLimit()
    {
    	 return 64;
    }
    @SideOnly(Side.CLIENT)
    /**
    	 * Returns an integer between 0 and the passed value representing how close the current item is to being completely
    	 * cooked
    	 */
    public int getCookProgressScaled(int par1)
    {
    	 return this.furnaceCookTime * par1 / 100;
    }
    @SideOnly(Side.CLIENT)
    /**
    	 * Returns an integer between 0 and the passed value representing how much burn time is left on the current fuel
    	 * item, where 0 means that the item is exhausted and the passed value means that the item is fresh
    	 */
    public int getBurnTimeRemainingScaled(int par1)
    {
    	 if (this.currentItemBurnTime == 0)
    	 {
    		 this.currentItemBurnTime = 100;
    	 }
    	 return this.furnaceBurnTime * par1 / this.currentItemBurnTime;
    }
    /**
    	 * Returns true if the furnace is currently burning
    	 */
    public boolean isBurning()
    {
    	 return this.furnaceBurnTime > 0;
    }
    /**
    	 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
    	 * ticks and creates a new spawn inside its implementation.
    	 */
    public void updateEntity()
    {
    	 boolean flag = this.furnaceBurnTime > 0;
    	 boolean flag1 = false;
    	 if (this.furnaceBurnTime > 0)
    	 {
    		 --this.furnaceBurnTime;
    	 }
    	 if (!this.worldObj.isRemote)
    	 {
    		 if (this.furnaceBurnTime == 0 && this.canSmelt())
    		 {
    			 this.currentItemBurnTime = this.furnaceBurnTime = getItemBurnTime(this.furnaceItemStacks[1]);
    			 if (this.furnaceBurnTime > 0)
    			 {
    				 flag1 = true;
    				 if (this.furnaceItemStacks[1] != null)
    				 {
    					 --this.furnaceItemStacks[1].stackSize;
    					 if (this.furnaceItemStacks[1].stackSize == 0)
    					 {
    						 this.furnaceItemStacks[1] = this.furnaceItemStacks[1].getItem().getContainerItemStack(furnaceItemStacks[1]);
    					 }
    				 }
    			 }
    		 }
    		 if (this.isBurning() && this.canSmelt())
    		 {
    			 ++this.furnaceCookTime;
    			 if (this.furnaceCookTime == 10)
    			 {
    				 this.furnaceCookTime = 0;
    				 this.smeltItem();
    				 flag1 = true;
    			 }
    		 }
    		 else
    		 {
    			 this.furnaceCookTime = 0;
    		 }
    		 if (flag != this.furnaceBurnTime > 0)
    		 {
    			 flag1 = true;
    			 BlockEnderFurnace.updateFurnaceBlockState(this.furnaceBurnTime > 0, this.worldObj, this.xCoord, this.yCoord, this.zCoord);
    		 }
    	 }
    	 if (flag1)
    	 {
    		 this.onInventoryChanged();
    	 }
    }
    /**
    	 * Returns true if the furnace can smelt an item, i.e. has a source item, destination stack isn't full, etc.
    	 */
    private boolean canSmelt()
    {
    	 if (this.furnaceItemStacks[0] == null)
    	 {
    		 return false;
    	 }
    	 else
    	 {
    		 ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    		 if (itemstack == null) return false;
    		 if (this.furnaceItemStacks[2] == null) return true;
    		 if (this.furnaceItemStacks[3] == null) return true;
    		 if (!this.furnaceItemStacks[2].isItemEqual(itemstack)) return false;
    		 if (!this.furnaceItemStacks[3].isItemEqual(itemstack)) return false;
    		 int result = (this.furnaceItemStacks[2].stackSize + this.furnaceItemStacks[3].stackSize) / 2 + itemstack.stackSize;
    		 return (result <= getInventoryStackLimit() && result <= itemstack.getMaxStackSize());
    	 }
    }
    
    /**
    	 * Turn one item from the furnace source stack into the appropriate smelted item in the furnace result stack
    	 */
    public void smeltItem()
    {
    	 if (this.canSmelt())
    	 {
    		 ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    		
    		 if (this.furnaceItemStacks[2] == null)
    		 {
    			 this.furnaceItemStacks[2] = itemstack.copy();
    		 }
    		 else if (this.furnaceItemStacks[2].isItemEqual(itemstack))
    		 {
    			 this.furnaceItemStacks[2].stackSize += itemstack.stackSize;
    			 if(this.furnaceItemStacks[2].stackSize > itemstack.getMaxStackSize())
    			 {
    				 this.furnaceItemStacks[3].stackSize += this.furnaceItemStacks[2].stackSize - itemstack.getMaxStackSize();
    				 this.furnaceItemStacks[2].stackSize = itemstack.getMaxStackSize();
    			 }
    		 }
    		
    		 ItemStack itemstack1 = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    		
    		 if (this.furnaceItemStacks[3] == null)
    		 {
    			 this.furnaceItemStacks[3] = itemstack1.copy();
    		 }
    		 else if (this.furnaceItemStacks[3].isItemEqual(itemstack1))
    		 {
    			 this.furnaceItemStacks[3].stackSize += itemstack1.stackSize;
    			 if(this.furnaceItemStacks[3].stackSize > itemstack1.getMaxStackSize())
    			 {
    				 this.furnaceItemStacks[2].stackSize += this.furnaceItemStacks[3].stackSize - itemstack1.getMaxStackSize();
    				 this.furnaceItemStacks[3].stackSize = itemstack1.getMaxStackSize();
    			 }
    		 }
    		
    		 --this.furnaceItemStacks[0].stackSize;
    		 if (this.furnaceItemStacks[0].stackSize <= 0)
    		 {
    			 this.furnaceItemStacks[0] = null;
    		 }
    	 }
    }
    /**
    	 * Returns the number of ticks that the supplied fuel item will keep the furnace burning, or 0 if the item isn't
    	 * fuel
    	 */
    public static int getItemBurnTime(ItemStack par0ItemStack)
    {
    	 if (par0ItemStack == null)
    	 {
    		 return 0;
    	 }
    	 else
    	 {
    		 int i = par0ItemStack.getItem().itemID;
    		 Item item = par0ItemStack.getItem();
    		 if (par0ItemStack.getItem() instanceof ItemBlock && Block.blocksList[i] != null)
    		 {
    			 Block block = Block.blocksList[i];
    			 if (block == Block.woodSingleSlab)
    			 {
    				 return 195;
    			 }
    			 if (block.blockMaterial == Material.wood)
    			 {
    				 return 390;
    			 }
    		 }
    		 if (item instanceof ItemTool && ((ItemTool) item).getToolMaterialName().equals("blazed")) return 100;
    		 if (item instanceof ItemSword && ((ItemSword) item).getToolMaterialName().equals("blazed")) return 100;
    		 if (item instanceof ItemHoe && ((ItemHoe) item).getMaterialName().equals("blazed")) return 100;
    		 if (i == DragonTools.blazedDust.itemID) return 800;
    		 if (i == DragonTools.blazedIngot.itemID) return 1600;
    		 if (i == DragonTools.blazedBlock.blockID) return 8000;
    		 return GameRegistry.getFuelValue(par0ItemStack);
    	 }
    }
    /**
    	 * Return true if item is a fuel source (getItemBurnTime() > 0).
    	 */
    public static boolean isItemFuel(ItemStack par0ItemStack)
    {
    	 return getItemBurnTime(par0ItemStack) > 0;
    }
    /**
    	 * Do not make give this method the name canInteractWith because it clashes with Container
    	 */
    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
    {
    	 return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
    }
    public void openChest() {}
    public void closeChest() {}
    /**
    	 * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot.
    	 */
    public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack)
    {
    	 return par1 == 2 ? false : (par1 == 1 ? isItemFuel(par2ItemStack) : true);
    }
    /**
    	 * Returns an array containing the indices of the slots that can be accessed by automation on the given side of this
    	 * block.
    	 */
    public int[] getAccessibleSlotsFromSide(int par1)
    {
    	 return par1 == 0 ? field_102011_e : (par1 == 1 ? field_102010_d : field_102009_f);
    }
    /**
    	 * Returns true if automation can insert the given item in the given slot from the given side. Args: Slot, item,
    	 * side
    	 */
    public boolean canInsertItem(int par1, ItemStack par2ItemStack, int par3)
    {
    	 return this.isStackValidForSlot(par1, par2ItemStack);
    }
    /**
    	 * Returns true if automation can extract the given item in the given slot from the given side. Args: Slot, item,
    	 * side
    	 */
    public boolean canExtractItem(int par1, ItemStack par2ItemStack, int par3)
    {
    	 return par3 != 0 || par1 != 1 || par2ItemStack.itemID == Item.bucketEmpty.itemID;
    }
    /***********************************************************************************
    	 * This function is here for compatibilities sake, Modders should Check for
    	 * Sided before ContainerWorldly, Vanilla Minecraft does not follow the sided standard
    	 * that Modding has for a while.
    	 *
    	 * In vanilla:
    	 *
    	 * Top: Ores
    	 * Sides: Fuel
    	 * Bottom: Output
    	 *
    	 * Standard Modding:
    	 * Top: Ores
    	 * Sides: Output
    	 * Bottom: Fuel
    	 *
    	 * The Modding one is designed after the GUI, the vanilla one is designed because its
    	 * intended use is for the hopper, which logically would take things in from the top.
    	 *
    	 * This will possibly be removed in future updates, and make vanilla the definitive
    	 * standard.
    	 */
    @Override
    public int getStartInventorySide(ForgeDirection side)
    {
    	 if (ForgeDummyContainer.legacyFurnaceSides)
    	 {
    		 if (side == ForgeDirection.DOWN) return 1;
    		 if (side == ForgeDirection.UP) return 0;
    		 return 2;
    	 }
    	 else
    	 {
    		 if (side == ForgeDirection.DOWN) return 2;
    		 if (side == ForgeDirection.UP) return 0;
    		 return 1;
    	 }
    }
    @Override
    public int getSizeInventorySide(ForgeDirection side)
    {
    	 return 1;
    }
    }

    As I thought, the main problem was in this part of the code:
    public void smeltItem()
    {
    	 if (this.canSmelt())
    	 {
    		 ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    	
    //if first output slot is full, start outputting to second output slot
    		 if(furnaceItemStacks[2].stackSize == itemstack.getMaxStackSize())
    		 {
    			 if (this.furnaceItemStacks[3] == null)
    			 {
    				 this.furnaceItemStacks[3] = itemstack.copy();
    			 }
    			 else if (this.furnaceItemStacks[3].isItemEqual(itemstack))
    			 {
    				 furnaceItemStacks[3].stackSize += itemstack.stackSize;
    			 }
    		 }
    		 else
    		 {
    			 if (this.furnaceItemStacks[2] == null)
    			 {
    				 this.furnaceItemStacks[2] = itemstack.copy();
    			 }
    			 else if (this.furnaceItemStacks[2].isItemEqual(itemstack))
    			 {
    				 furnaceItemStacks[2].stackSize += itemstack.stackSize;
    			 }
    		 }
    	
    		 --this.furnaceItemStacks[0].stackSize;
    		 if (this.furnaceItemStacks[0].stackSize <= 0)
    		 {
    			 this.furnaceItemStacks[0] = null;
    		 }
    	 }
    }

    I cleaned up that code. It's now:
    public void smeltItem()
    {
    if (this.canSmelt())
    {
    ItemStack itemstack = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    
    if (this.furnaceItemStacks[2] == null)
    {
    this.furnaceItemStacks[2] = itemstack.copy();
    }
    else if (this.furnaceItemStacks[2].isItemEqual(itemstack))
    {
    this.furnaceItemStacks[2].stackSize += itemstack.stackSize;
    if(this.furnaceItemStacks[2].stackSize > itemstack.getMaxStackSize())
    {
    this.furnaceItemStacks[3].stackSize += this.furnaceItemStacks[2].stackSize - itemstack.getMaxStackSize();
    this.furnaceItemStacks[2].stackSize = itemstack.getMaxStackSize();
    }
    }
    
    ItemStack itemstack1 = EnderFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
    
    if (this.furnaceItemStacks[3] == null)
    {
    this.furnaceItemStacks[3] = itemstack1.copy();
    }
    else if (this.furnaceItemStacks[3].isItemEqual(itemstack1))
    {
    this.furnaceItemStacks[3].stackSize += itemstack1.stackSize;
    if(this.furnaceItemStacks[3].stackSize > itemstack1.getMaxStackSize())
    {
    this.furnaceItemStacks[2].stackSize += this.furnaceItemStacks[3].stackSize - itemstack1.getMaxStackSize();
    this.furnaceItemStacks[3].stackSize = itemstack1.getMaxStackSize();
    }
    }
    
    --this.furnaceItemStacks[0].stackSize;
    
    if (this.furnaceItemStacks[0].stackSize <= 0)
    {
    this.furnaceItemStacks[0] = null;
    }
    }
    }

    For those who don't see exactly what it does, it will smelt one item and output one of that item's smelted variant in BOTH of the output slots. This way, I am effectively doubling any output, without needing to even touch the furnace recipes (handy if people install my mod alongside other mods that add new ores).

    The furnace will also check to see if one of the slots is more full than the other. If it is, then it will put two items into the other, instead of one in each.

    That last kinks I need help with:
    - When one of the slots has at least one kind of smelted material in it and a different kind of material is being smelted, one ingot will be put into the other slot, and then the furnace will stop cooking until either that ingot is removed, or the other slot is cleared of the incompatible material. How can I fix this, or get the furnace to at least not smelt ANYTHING except for the ore that matches what's currently in the slots, so that ore isn't being wasted.
    - When one of the slots is full and the other is at 63 (or at a number where the next output will bring it above 64...in this case 2+63), an item will still smelt and one of the stacks will become a number higher than 64 (in this case, 65). I would like it so that the furnace will not smelt unless there is enough room for the two outputs.
    Posted in: Modification Development
  • 0

    posted a message on [Forge]How can I add Tooltips to items I create?
    Quote from CrafterOfMines57

    Add this to your item's class
    @Override
    public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean par4)
    {
    list.add("Tooltip stuff goes here");
    }
    }



    Thank you. This is just what I needed.
    Posted in: Modification Development
  • 0

    posted a message on [Forge]How can I add Tooltips to items I create?
    So let me just start out by saying possibly the most-used sentence in any forum on any website: I'm not sure if this is the right place to post this, but...

    I'd also like to state that I'm a rookie coder with minimal modding experience (but mediocre coding knowledge). I'm using Forge to create my mod and I am currently modding version 1.5.2 of Minecraft.

    I am in development of a simple mod that adds a few new tiers of tools and armour and a bunch of materials to match. I feel the need to tell people what goes where or, at the very least, give them a subtle hint as to what goes where...for example, I have made a material that is used in strengthening tools during the crafting process (the resulting product having more durability, better enchantability, a nice item graphic, etc) and I think one problem would be, people wouldn't know that it's used for that (suddenly thinking it's useless when they find out it can't be used in creating its own set of tools and armour). Of course, I can easily mention it or give a full-detailed explanation wherever I post the mod, but not everyone will read it, and on top of that, not everyone bookmarks a page just to refresh their memory later on...or if they do, they don't always think their mind will need refreshing.

    So, I would like to know two things.

    The first would be, is it possible to pull off a short item description through tooltips, and the second would be, how would I code an item to have the tooltip?

    I wouldn't think this kind of question wouldn't need any source code to be answered, and I don't think there's much more info I can give to help someone answer, but if you need to know anything else, just ask.
    Posted in: Modification Development
  • 0

    posted a message on Mobs need an Active Player .. Do Crops?
    Crops need a player within like a 200 block radius in order to grow, whether the chunks are loaded or not.
    Posted in: Discussion
  • 0

    posted a message on How to Create and Dictate a town on Multiplayer
    It's very farfetch'd and would be difficult to pull off without being banned, or have all those players abandon the server...but it would certainly make do for an amazing role play between friends.
    Posted in: Survival Mode
  • 0

    posted a message on I don't bother with redstone. Am I the only one?
    I'm a redstone junkie...at least in Creative. Most of my creative worlds tend to be one big superflat redstone testing facility. But when it comes to survival, I barely use any. In multiplayer, I'll do my best to hide my stuff with redstone, but in singleplayer, I only ever use it for fun.
    Posted in: Survival Mode
  • 0

    posted a message on What is all this hype about SkyDoesMinecraft?
    Quote from snowball22

    There is a thing with being funny, and being innmature and yelling BUTTER! every time it mentions gold.

    Take this one video.. My proof:
    Look at the comments. He curses a ton in the video, screams butter and doesn't even get the song right. I havent listened to the song in awhile and even I could sing better. His fans are WAY to loyal. If I ever even liked sky, I wouldn't even of liked THAT.

    What does it matter what happened in THAT particular video. I could ­ all over the original music video by YogsCast and people would agree, just like everyone here is to Sky. His fans aren't LOYAL, so to speak. They just want to be noticed by a semi-famous person on YouTube, and they seem to think encouraging his love for budder is the way to go. And immaturity, believe it or not, is one of the top sources of comedy, if you watch stand up. Sky thinks being immature and obnoxious is funny. So does his fans. That's how it is. Get the ­ over it.
    Posted in: Discussion
  • 0

    posted a message on Should minecraft become free to play?
    "Become free to play" Implies that you have to pay monthly to play it. Sure, you have to pay for the game to initially play it, but once you've bought it, you're free from debt. You get all of the updates and new features, free...unlike games which usually only add content as purchasable DLC.
    Posted in: Discussion
  • 0

    posted a message on Stop. Just Stop.
    Quote from Gregrs

    Take Black Ops II for an example. The only updates they do are the ones for bugs/glitches and double exp, and that's it. How many people play that? Over half the world. They don't update, but the game is still fun.

    Does the DLC (8 multiplayer maps, a multiplayer weapon and 2 zombies maps) not count as content updates? The DLC in most games like CoD is what makes those games fun. More content means, not only more money, but players coming back for more. Not to mention, Minecraft is still in development, even though it went through it's "full release" back in 1.0.0.

    They could always release things like carpet, custom skins, the Nether, the End, villager trading and animal breeding as DLC that you have to pay 5-10 bucks for (per feature), so that you could choose what you want to add to the game, but then you'd be losing money. No. They add all of these features free of charge (after you've bought the game) and take so much of the community's feedback to account and add or change things based on it (without making the game unbalanced). They constantly fix bugs and constantly add what they can to please the community, yet there are haters like you who are too childish to accept the new features. It's not like they're removing anything from the previous updates. You, or any of the update-haters out there have NO reason to be so picky about these sort of things. Not unless they remove something big in the game like the dimensions, diamonds, charcoal, boats, minecarts, booster rails...shall I keep going? If you REALLY can't stand the update, don't update. You're given a choice. Or, you can stop being stingy and just update, for the benefit of the bug fixes and forget about the updated features...just ignore them.
    Posted in: Discussion
  • 0

    posted a message on What bothers you most in Minecraft Let's Plays?
    One thing that bothers me is hearing my own voice and fails for hours through editing, then waiting 400+ minutes to upload each 10-15min video...­ YouTube.
    Posted in: Discussion
  • 0

    posted a message on What is all this hype about SkyDoesMinecraft?
    Using pewdiepie as an example, Sky is about the same with butter and sqids as pewds is with stephano and barrels. It's his signature. There's nothing wrong with it, so leave him alone. He doesn't go around judging you for things you like/hate. Also not subbed to him/not a regular viewer.
    Posted in: Discussion
  • 0

    posted a message on What City Should Minecon 2013 be in?
    Melbourne, Australia
    Posted in: Discussion
  • To post a comment, please or register a new account.