- Flaxbeard
- Curse Premium
-
Member for 11 years, 5 months, and 26 days
Last active Mon, Nov, 14 2016 17:05:52
- 20 Followers
- 344 Total Posts
- 166 Thanks
-
3
LycaonX posted a message on [WIP] Advanced Thaumaturgy - Thaumcraft 4 Addonlol, Thaumcraft Extras. Just... lolPosted in: WIP Mods -
2
microjunk posted a message on Custom furnace source code?Have a look here, I had the same problem and then created this tutorial, you should always check the tut section....Posted in: Modification Development -
14
microjunk posted a message on [Forge] Micros Tutorials [Single chest posted, link inside]This is a link to my other tutorials here, please check these out too....Posted in: Tutorials
Link to the chest tutorial....link
Furnace Forge 1.4.7
This is going to be a simple explanation of how a furnace is made. This will be from the vanilla source plus a gui handler (I do not use proxy to extend the handler). So on with the code, this will be little explanation as I am not sure what or why for a lot of this, considering I had to piece this together from about 3 different tutorials to get it to work....
This has been revised for all those copy/pasters, you know who you are. The aim of this is to help you understand how the furnace works and have a better chance at success making one for your mod.
BlockFurnace
public class BlockFurnace extends BlockContainer { private Random furnaceRand = new Random(); private final boolean isActive; private static boolean keepFurnaceInventory = false; protected BlockFurnace(int par1, boolean par2) { super(par1, Material.rock); this.isActive = par2; this.blockIndexInTexture = 45; } public int idDropped(int par1, Random par2Random, int par3) { return Block.stoneOvenIdle.blockID; } public void onBlockAdded(World par1World, int par2, int par3, int par4) { super.onBlockAdded(par1World, par2, par3, par4); this.setDefaultDirection(par1World, par2, par3, par4); } private void setDefaultDirection(World par1World, int par2, int par3, int par4) { if (!par1World.isRemote) { int var5 = par1World.getBlockId(par2, par3, par4 - 1); int var6 = par1World.getBlockId(par2, par3, par4 + 1); int var7 = par1World.getBlockId(par2 - 1, par3, par4); int var8 = par1World.getBlockId(par2 + 1, par3, par4); byte var9 = 3; if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6]) { var9 = 3; } if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5]) { var9 = 2; } if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8]) { var9 = 5; } if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7]) { var9 = 4; } par1World.setBlockMetadataWithNotify(par2, par3, par4, var9); } } @SideOnly(Side.CLIENT) public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) { if (par5 == 1) { return this.blockIndexInTexture + 17; } else if (par5 == 0) { return this.blockIndexInTexture + 17; } else { int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); return par5 != var6 ? this.blockIndexInTexture : (this.isActive ? this.blockIndexInTexture + 16 : this.blockIndexInTexture - 1); } } @SideOnly(Side.CLIENT) public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) { if (this.isActive) { int var6 = par1World.getBlockMetadata(par2, par3, par4); float var7 = (float)par2 + 0.5F; float var8 = (float)par3 + 0.0F + par5Random.nextFloat() * 6.0F / 16.0F; float var9 = (float)par4 + 0.5F; float var10 = 0.52F; float var11 = par5Random.nextFloat() * 0.6F - 0.3F; if (var6 == 4) { par1World.spawnParticle("smoke", (double)(var7 - var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D); par1World.spawnParticle("flame", (double)(var7 - var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D); } else if (var6 == 5) { par1World.spawnParticle("smoke", (double)(var7 + var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D); par1World.spawnParticle("flame", (double)(var7 + var10), (double)var8, (double)(var9 + var11), 0.0D, 0.0D, 0.0D); } else if (var6 == 2) { par1World.spawnParticle("smoke", (double)(var7 + var11), (double)var8, (double)(var9 - var10), 0.0D, 0.0D, 0.0D); par1World.spawnParticle("flame", (double)(var7 + var11), (double)var8, (double)(var9 - var10), 0.0D, 0.0D, 0.0D); } else if (var6 == 3) { par1World.spawnParticle("smoke", (double)(var7 + var11), (double)var8, (double)(var9 + var10), 0.0D, 0.0D, 0.0D); par1World.spawnParticle("flame", (double)(var7 + var11), (double)var8, (double)(var9 + var10), 0.0D, 0.0D, 0.0D); } } } public int getBlockTextureFromSide(int par1) { return par1 == 1 ? this.blockIndexInTexture + 17 : (par1 == 0 ? this.blockIndexInTexture + 17 : (par1 == 3 ? this.blockIndexInTexture - 1 : this.blockIndexInTexture)); } public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { if (par1World.isRemote) { return true; } else { TileEntityFurnace var10 = (TileEntityFurnace)par1World.getBlockTileEntity(par2, par3, par4); if (var10 != null) { par5EntityPlayer.displayGUIFurnace(var10); } return true; } } public static void updateFurnaceBlockState(boolean par0, World par1World, int par2, int par3, int par4) { int var5 = par1World.getBlockMetadata(par2, par3, par4); TileEntity var6 = par1World.getBlockTileEntity(par2, par3, par4); keepFurnaceInventory = true; if (par0) { par1World.setBlockWithNotify(par2, par3, par4, Block.stoneOvenActive.blockID); } else { par1World.setBlockWithNotify(par2, par3, par4, Block.stoneOvenIdle.blockID); } keepFurnaceInventory = false; par1World.setBlockMetadataWithNotify(par2, par3, par4, var5); if (var6 != null) { var6.validate(); par1World.setBlockTileEntity(par2, par3, par4, var6); } } public TileEntity createNewTileEntity(World par1World) { return new TileEntityFurnace(); } public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) { int var6 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; if (var6 == 0) { par1World.setBlockMetadataWithNotify(par2, par3, par4, 2); } if (var6 == 1) { par1World.setBlockMetadataWithNotify(par2, par3, par4, 5); } if (var6 == 2) { par1World.setBlockMetadataWithNotify(par2, par3, par4, 3); } if (var6 == 3) { par1World.setBlockMetadataWithNotify(par2, par3, par4, 4); } } public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { if (!keepFurnaceInventory) { TileEntityFurnace var7 = (TileEntityFurnace)par1World.getBlockTileEntity(par2, par3, par4); if (var7 != null) { for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) { ItemStack var9 = var7.getStackInSlot(var8); if (var9 != null) { float var10 = this.furnaceRand.nextFloat() * 0.8F + 0.1F; float var11 = this.furnaceRand.nextFloat() * 0.8F + 0.1F; float var12 = this.furnaceRand.nextFloat() * 0.8F + 0.1F; while (var9.stackSize > 0) { int var13 = this.furnaceRand.nextInt(21) + 10; if (var13 > var9.stackSize) { var13 = var9.stackSize; } var9.stackSize -= var13; EntityItem var14 = new EntityItem(par1World, (double)((float)par2 + var10), (double)((float)par3 + var11), (double)((float)par4 + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage())); if (var9.hasTagCompound()) { var14.func_92014_d().setTagCompound((NBTTagCompound)var9.getTagCompound().copy()); } float var15 = 0.05F; var14.motionX = (double)((float)this.furnaceRand.nextGaussian() * var15); var14.motionY = (double)((float)this.furnaceRand.nextGaussian() * var15 + 0.2F); var14.motionZ = (double)((float)this.furnaceRand.nextGaussian() * var15); par1World.spawnEntityInWorld(var14); } } } } } super.breakBlock(par1World, par2, par3, par4, par5, par6); } }
Change this to the name of your custom furnace
public class BlockYourFurnace extends BlockContainer { private Random furnaceRand = new Random(); private final boolean isActive; private static boolean keepFurnaceInventory = false; protected BlockYourFurnace(int par1, boolean par2) { super(par1, Material.rock); this.isActive = par2; this.blockIndexInTexture = 45; }
Change the onBlockActivated method to this
public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { if (par1World.isRemote) { return true; } else if (!par5EntityPlayer.isSneaking()) { TileEntityYourFurnace var10 = (TileEntityYourFurnace) par1World.getBlockTileEntity(par2, par3, par4); if (var10 != null) { par5EntityPlayer.openGui(YourMod.instance, 0, par1World, par2, par3, par4); } return true; } else { return false; } }
Be sure to change any reference of the tile entity to your tile entity as follows
public TileEntity createNewTileEntity(World par1World) { return new TileEntityYourFurnace(); }
And Here Too
public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { if (!keepFurnaceInventory) { TileEntityYourFurnace var7 = (TileEntityYourFurnace)par1World.getBlockTileEntity(par2, par3, par4); if (var7 != null) {
And that should do it for the block
And Now The Gui Furnace
public class GuiFurnace extends GuiContainer { private TileEntityFurnace furnaceInventory; public GuiFurnace(InventoryPlayer par1InventoryPlayer, TileEntityFurnace par2TileEntityFurnace) { super(new ContainerFurnace(par1InventoryPlayer, par2TileEntityFurnace)); this.furnaceInventory = par2TileEntityFurnace; } protected void drawGuiContainerForegroundLayer(int par1, int par2) { this.fontRenderer.drawString(StatCollector.translateToLocal("container.furnace"), 60, 6, 4210752); this.fontRenderer.drawString(StatCollector.translateToLocal("container.inventory"), 8, this.ySize - 96 + 2, 4210752); } protected void drawGuiContainerBackgroundLayer(float par1, int par2, int par3) { int var4 = this.mc.renderEngine.getTexture("/gui/furnace.png"); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.renderEngine.bindTexture(var4); int var5 = (this.width - this.xSize) / 2; int var6 = (this.height - this.ySize) / 2; this.drawTexturedModalRect(var5, var6, 0, 0, this.xSize, this.ySize); int var7; if (this.furnaceInventory.isBurning()) { var7 = this.furnaceInventory.getBurnTimeRemainingScaled(12); this.drawTexturedModalRect(var5 + 56, var6 + 36 + 12 - var7, 176, 12 - var7, 14, var7 + 2); } var7 = this.furnaceInventory.getCookProgressScaled(24); this.drawTexturedModalRect(var5 + 79, var6 + 34, 176, 14, var7 + 1, 16); } }
Change this to fit your custom furnace code
public class GuiYourFurnace extends GuiContainer { private TileEntityYourFurnace furnaceInventory; public GuiYourFurnace(InventoryPlayer par1InventoryPlayer, TileEntityYourFurnace par2TileEntityYourFurnace) { super(new ContainerYourFurnace(par1InventoryPlayer, par2TileEntityYourFurnace)); this.furnaceInventory = par2TileEntityYourFurnace; }
GuiFurnace should reflect your mod GuiYourFurnace, TileEntityFurnace to TileEntityYourFurnace and the ContainerFurnace to ContainerYourFurnace...Also dont forget to change the texture path in the render to your texture path
Now for the ContainerFurnace
public class ContainerFurnace extends Container { private TileEntityFurnace furnace; private int lastCookTime = 0; private int lastBurnTime = 0; private int lastItemBurnTime = 0; public ContainerFurnace(InventoryPlayer par1InventoryPlayer, TileEntityFurnace par2TileEntityFurnace) { this.furnace = par2TileEntityFurnace; this.addSlotToContainer(new Slot(par2TileEntityFurnace, 0, 56, 17)); this.addSlotToContainer(new Slot(par2TileEntityFurnace, 1, 56, 53)); this.addSlotToContainer(new SlotFurnace(par1InventoryPlayer.player, par2TileEntityFurnace, 2, 116, 35)); int var3; for (var3 = 0; var3 < 3; ++var3) { for (int var4 = 0; var4 < 9; ++var4) { this.addSlotToContainer(new Slot(par1InventoryPlayer, var4 + var3 * 9 + 9, 8 + var4 * 18, 84 + var3 * 18)); } } for (var3 = 0; var3 < 9; ++var3) { this.addSlotToContainer(new Slot(par1InventoryPlayer, var3, 8 + var3 * 18, 142)); } } public void addCraftingToCrafters(ICrafting par1ICrafting) { super.addCraftingToCrafters(par1ICrafting); par1ICrafting.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime); par1ICrafting.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime); par1ICrafting.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime); } public void detectAndSendChanges() { super.detectAndSendChanges(); for (int var1 = 0; var1 < this.crafters.size(); ++var1) { ICrafting var2 = (ICrafting)this.crafters.get(var1); if (this.lastCookTime != this.furnace.furnaceCookTime) { var2.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime); } if (this.lastBurnTime != this.furnace.furnaceBurnTime) { var2.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime); } if (this.lastItemBurnTime != this.furnace.currentItemBurnTime) { var2.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime); } } this.lastCookTime = this.furnace.furnaceCookTime; this.lastBurnTime = this.furnace.furnaceBurnTime; this.lastItemBurnTime = this.furnace.currentItemBurnTime; } @SideOnly(Side.CLIENT) public void updateProgressBar(int par1, int par2) { if (par1 == 0) { this.furnace.furnaceCookTime = par2; } if (par1 == 1) { this.furnace.furnaceBurnTime = par2; } if (par1 == 2) { this.furnace.currentItemBurnTime = par2; } } public boolean canInteractWith(EntityPlayer par1EntityPlayer) { return this.furnace.isUseableByPlayer(par1EntityPlayer); } public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) { ItemStack var3 = null; Slot var4 = (Slot)this.inventorySlots.get(par2); if (var4 != null && var4.getHasStack()) { ItemStack var5 = var4.getStack(); var3 = var5.copy(); if (par2 == 2) { if (!this.mergeItemStack(var5, 3, 39, true)) { return null; } var4.onSlotChange(var5, var3); } else if (par2 != 1 && par2 != 0) { if (FurnaceRecipes.smelting().getSmeltingResult(var5) != null) { if (!this.mergeItemStack(var5, 0, 1, false)) { return null; } } else if (TileEntityFurnace.isItemFuel(var5)) { if (!this.mergeItemStack(var5, 1, 2, false)) { return null; } } else if (par2 >= 3 && par2 < 30) { if (!this.mergeItemStack(var5, 30, 39, false)) { return null; } } else if (par2 >= 30 && par2 < 39 && !this.mergeItemStack(var5, 3, 30, false)) { return null; } } else if (!this.mergeItemStack(var5, 3, 39, false)) { return null; } if (var5.stackSize == 0) { var4.putStack((ItemStack)null); } else { var4.onSlotChanged(); } if (var5.stackSize == var3.stackSize) { return null; } var4.onPickupFromSlot(par1EntityPlayer, var5); } return var3; } }
First lets change the top area to this..
public class ContainerYourFurnace extends Container { private TileEntityYourFurnace furnace; private int lastCookTime = 0; private int lastBurnTime = 0; private int lastItemBurnTime = 0; public ContainerYourFurnace(InventoryPlayer par1InventoryPlayer, TileEntityYourFurnace par2TileEntityYourFurnace) { this.furnace = par2TileEntityYourFurnace; this.addSlotToContainer(new Slot(par2TileEntityYourFurnace, 0, 56, 17)); this.addSlotToContainer(new Slot(par2TileEntityYourFurnace, 1, 56, 53)); this.addSlotToContainer(new SlotYourFurnace(par1InventoryPlayer.player, par2TileEntityYourFurnace, 2, 116, 35)); int var3; for (var3 = 0; var3 < 3; ++var3) { for (int var4 = 0; var4 < 9; ++var4) { this.addSlotToContainer(new Slot(par1InventoryPlayer, var4 + var3 * 9 + 9, 8 + var4 * 18, 84 + var3 * 18)); } }
In the method "public ItemStack transferStackInSlot" at line 107 change lines 126 to 141 to look like this
else if (par2 != 1 && par2 != 0) { if (YourRecipes.smelting().getSmeltingResult(var5) != null) { if (!this.mergeItemStack(var5, 0, 1, false)) { return null; } } else if (TileEntityYourFurnace.isItemFuel(var5)) { if (!this.mergeItemStack(var5, 1, 2, false)) { return null; } }
In the SlotFurnace we have this
public class SlotFurnace extends Slot { private EntityPlayer thePlayer; private int field_75228_b; public SlotFurnace(EntityPlayer par1EntityPlayer, IInventory par2IInventory, int par3, int par4, int par5) { super(par2IInventory, par3, par4, par5); this.thePlayer = par1EntityPlayer; } public boolean isItemValid(ItemStack par1ItemStack) { return false; } public ItemStack decrStackSize(int par1) { if (this.getHasStack()) { this.field_75228_b += Math.min(par1, this.getStack().stackSize); } return super.decrStackSize(par1); } public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack) { this.onCrafting(par2ItemStack); super.onPickupFromSlot(par1EntityPlayer, par2ItemStack); } protected void onCrafting(ItemStack par1ItemStack, int par2) { this.field_75228_b += par2; this.onCrafting(par1ItemStack); } protected void onCrafting(ItemStack par1ItemStack) { par1ItemStack.onCrafting(this.thePlayer.worldObj, this.thePlayer, this.field_75228_B); if (!this.thePlayer.worldObj.isRemote) { int var2 = this.field_75228_b; float var3 = FurnaceRecipes.smelting().getExperience(par1ItemStack); int var4; if (var3 == 0.0F) { var2 = 0; } else if (var3 < 1.0F) { var4 = MathHelper.floor_float((float)var2 * var3); if (var4 < MathHelper.ceiling_float_int((float)var2 * var3) && (float)Math.random() < (float)var2 * var3 - (float)var4) { ++var4; } var2 = var4; } while (var2 > 0) { var4 = EntityXPOrb.getXPSplit(var2); var2 -= var4; this.thePlayer.worldObj.spawnEntityInWorld(new EntityXPOrb(this.thePlayer.worldObj, this.thePlayer.posX, this.thePlayer.posY + 0.5D, this.thePlayer.posZ + 0.5D, var4)); } } this.field_75228_b = 0; GameRegistry.onItemSmelted(thePlayer, par1ItemStack); if (par1ItemStack.itemID == Item.ingotIron.itemID) { this.thePlayer.addStat(AchievementList.acquireIron, 1); } if (par1ItemStack.itemID == Item.fishCooked.itemID) { this.thePlayer.addStat(AchievementList.cookFish, 1); } } }
First we need to change the top section to this
public class SlotYourFurnace extends Slot { private EntityPlayer thePlayer; private int field_75228_b; public SlotYourFurnace(EntityPlayer par1EntityPlayer, IInventory par2IInventory, int par3, int par4, int par5) { super(par2IInventory, par3, par4, par5); this.thePlayer = par1EntityPlayer; }
At line 65 we have this
protected void onCrafting(ItemStack par1ItemStack) { par1ItemStack.onCrafting(this.thePlayer.worldObj, this.thePlayer, this.field_75228_B); if (!this.thePlayer.worldObj.isRemote) { int var2 = this.field_75228_b; float var3 = FurnaceRecipes.smelting().getExperience(par1ItemStack); int var4;
Change FurnaceRecipes to YourRecipes...
Now for the FurnaceRecipes
public class FurnaceRecipes { private static final FurnaceRecipes smeltingBase = new FurnaceRecipes(); private Map smeltingList = new HashMap(); private Map experienceList = new HashMap(); private HashMap<List<Integer>, ItemStack> metaSmeltingList = new HashMap<List<Integer>, ItemStack>(); private HashMap<List<Integer>, Float> metaExperience = new HashMap<List<Integer>, Float>(); public static final FurnaceRecipes smelting() { return smeltingBase; } private FurnaceRecipes() { this.addSmelting(Block.oreIron.blockID, new ItemStack(Item.ingotIron), 0.7F); this.addSmelting(Block.oreGold.blockID, new ItemStack(Item.ingotGold), 1.0F); this.addSmelting(Block.oreDiamond.blockID, new ItemStack(Item.diamond), 1.0F); this.addSmelting(Block.sand.blockID, new ItemStack(Block.glass), 0.1F); this.addSmelting(Item.porkRaw.itemID, new ItemStack(Item.porkCooked), 0.35F); this.addSmelting(Item.beefRaw.itemID, new ItemStack(Item.beefCooked), 0.35F); this.addSmelting(Item.chickenRaw.itemID, new ItemStack(Item.chickenCooked), 0.35F); this.addSmelting(Item.fishRaw.itemID, new ItemStack(Item.fishCooked), 0.35F); this.addSmelting(Block.cobblestone.blockID, new ItemStack(Block.stone), 0.1F); this.addSmelting(Item.clay.itemID, new ItemStack(Item.brick), 0.3F); this.addSmelting(Block.cactus.blockID, new ItemStack(Item.dyePowder, 1, 2), 0.2F); this.addSmelting(Block.wood.blockID, new ItemStack(Item.coal, 1, 1), 0.15F); this.addSmelting(Block.oreEmerald.blockID, new ItemStack(Item.emerald), 1.0F); this.addSmelting(Item.potato.itemID, new ItemStack(Item.bakedPotato), 0.35F); this.addSmelting(Block.oreCoal.blockID, new ItemStack(Item.coal), 0.1F); this.addSmelting(Block.oreRedstone.blockID, new ItemStack(Item.redstone), 0.7F); this.addSmelting(Block.oreLapis.blockID, new ItemStack(Item.dyePowder, 1, 4), 0.2F); } public void addSmelting(int par1, ItemStack par2ItemStack, float par3) { this.smeltingList.put(Integer.valueOf(par1), par2ItemStack); this.experienceList.put(Integer.valueOf(par2ItemStack.itemID), Float.valueOf(par3)); } @Deprecated public ItemStack getSmeltingResult(int par1) { return (ItemStack)this.smeltingList.get(Integer.valueOf(par1)); } public Map getSmeltingList() { return this.smeltingList; } @Deprecated //In favor of ItemStack sensitive version public float getExperience(int par1) { return this.experienceList.containsKey(Integer.valueOf(par1)) ? ((Float)this.experienceList.get(Integer.valueOf(par1))).floatValue() : 0.0F; } public void addSmelting(int itemID, int metadata, ItemStack itemstack, float experience) { metaSmeltingList.put(Arrays.asList(itemID, metadata), itemstack); metaExperience.put(Arrays.asList(itemID, metadata), experience); } public ItemStack getSmeltingResult(ItemStack item) { if (item == null) { return null; } ItemStack ret = (ItemStack)metaSmeltingList.get(Arrays.asList(item.itemID, item.getItemDamage())); if (ret != null) { return ret; } return (ItemStack)smeltingList.get(Integer.valueOf(item.itemID)); } public float getExperience(ItemStack item) { if (item == null || item.getItem() == null) { return 0; } float ret = item.getItem().getSmeltingExperience(item); if (ret < 0 && metaExperience.containsKey(Arrays.asList(item.itemID, item.getItemDamage()))) { ret = metaExperience.get(Arrays.asList(item.itemID, item.getItemDamage())); } if (ret < 0 && experienceList.containsKey(item.itemID)) { ret = ((Float)experienceList.get(item.itemID)).floatValue(); } return (ret < 0 ? 0 : ret); } }
Now for the changes, they mostly take place at the top and are references to FurnaceRecipes
public class YourRecipes { private static final YourRecipes smeltingBase = new YourRecipes(); private Map smeltingList = new HashMap(); private Map experienceList = new HashMap(); private HashMap<List<Integer>, ItemStack> metaSmeltingList = new HashMap<List<Integer>, ItemStack>(); private HashMap<List<Integer>, Float> metaExperience = new HashMap<List<Integer>, Float>(); public static final YourRecipes smelting() { return smeltingBase; } private YourRecipes() {
And that should do it for the Recipes class
Now we look at the very lengthy TileEntityFurnace class
public class TileEntityFurnace extends TileEntity implements IInventory, ISidedInventory { private ItemStack[] furnaceItemStacks = new ItemStack[3]; public int furnaceBurnTime = 0; public int currentItemBurnTime = 0; public int furnaceCookTime = 0; public int getSizeInventory() { return this.furnaceItemStacks.length; } public ItemStack getStackInSlot(int par1) { return this.furnaceItemStacks[par1]; } public ItemStack decrStackSize(int par1, int par2) { if (this.furnaceItemStacks[par1] != null) { ItemStack var3; if (this.furnaceItemStacks[par1].stackSize <= par2) { var3 = this.furnaceItemStacks[par1]; this.furnaceItemStacks[par1] = null; return var3; } else { var3 = this.furnaceItemStacks[par1].splitStack(par2); if (this.furnaceItemStacks[par1].stackSize == 0) { this.furnaceItemStacks[par1] = null; } return var3; } } else { return null; } } public ItemStack getStackInSlotOnClosing(int par1) { if (this.furnaceItemStacks[par1] != null) { ItemStack var2 = this.furnaceItemStacks[par1]; this.furnaceItemStacks[par1] = null; return var2; } else { return null; } } public void setInventorySlotContents(int par1, ItemStack par2ItemStack) { this.furnaceItemStacks[par1] = par2ItemStack; if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) { par2ItemStack.stackSize = this.getInventoryStackLimit(); } } public String getInvName() { return "container.furnace"; } public void readFromNBT(NBTTagCompound par1NBTTagCompound) { super.readFromNBT(par1NBTTagCompound); NBTTagList var2 = par1NBTTagCompound.getTagList("Items"); this.furnaceItemStacks = new ItemStack[this.getSizeInventory()]; for (int var3 = 0; var3 < var2.tagCount(); ++var3) { NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3); byte var5 = var4.getByte("Slot"); if (var5 >= 0 && var5 < this.furnaceItemStacks.length) { this.furnaceItemStacks[var5] = ItemStack.loadItemStackFromNBT(var4); } } this.furnaceBurnTime = par1NBTTagCompound.getShort("BurnTime"); this.furnaceCookTime = par1NBTTagCompound.getShort("CookTime"); this.currentItemBurnTime = getItemBurnTime(this.furnaceItemStacks[1]); } public void writeToNBT(NBTTagCompound par1NBTTagCompound) { super.writeToNBT(par1NBTTagCompound); par1NBTTagCompound.setShort("BurnTime", (short)this.furnaceBurnTime); par1NBTTagCompound.setShort("CookTime", (short)this.furnaceCookTime); NBTTagList var2 = new NBTTagList(); for (int var3 = 0; var3 < this.furnaceItemStacks.length; ++var3) { if (this.furnaceItemStacks[var3] != null) { NBTTagCompound var4 = new NBTTagCompound(); var4.setByte("Slot", (byte)var3); this.furnaceItemStacks[var3].writeToNBT(var4); var2.appendTag(var4); } } par1NBTTagCompound.setTag("Items", var2); } public int getInventoryStackLimit() { return 64; } @SideOnly(Side.CLIENT) public int getCookProgressScaled(int par1) { return this.furnaceCookTime * par1 / 200; } @SideOnly(Side.CLIENT) public int getBurnTimeRemainingScaled(int par1) { if (this.currentItemBurnTime == 0) { this.currentItemBurnTime = 200; } return this.furnaceBurnTime * par1 / this.currentItemBurnTime; } public boolean isBurning() { return this.furnaceBurnTime > 0; } public void updateEntity() { boolean var1 = this.furnaceBurnTime > 0; boolean var2 = 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) { var2 = 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 == 200) { this.furnaceCookTime = 0; this.smeltItem(); var2 = true; } } else { this.furnaceCookTime = 0; } if (var1 != this.furnaceBurnTime > 0) { var2 = true; BlockFurnace.updateFurnaceBlockState(this.furnaceBurnTime > 0, this.worldObj, this.xCoord, this.yCoord, this.zCoord); } } if (var2) { this.onInventoryChanged(); } } private boolean canSmelt() { if (this.furnaceItemStacks[0] == null) { return false; } else { ItemStack var1 = FurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]); if (var1 == null) return false; if (this.furnaceItemStacks[2] == null) return true; if (!this.furnaceItemStacks[2].isItemEqual(var1)) return false; int result = furnaceItemStacks[2].stackSize + var1.stackSize; return (result <= getInventoryStackLimit() && result <= var1.getMaxStackSize()); } } public void smeltItem() { if (this.canSmelt()) { ItemStack var1 = FurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]); if (this.furnaceItemStacks[2] == null) { this.furnaceItemStacks[2] = var1.copy(); } else if (this.furnaceItemStacks[2].isItemEqual(var1)) { furnaceItemStacks[2].stackSize += var1.stackSize; } --this.furnaceItemStacks[0].stackSize; if (this.furnaceItemStacks[0].stackSize <= 0) { this.furnaceItemStacks[0] = null; } } } public static int getItemBurnTime(ItemStack par0ItemStack) { if (par0ItemStack == null) { return 0; } else { int var1 = par0ItemStack.getItem().itemID; Item var2 = par0ItemStack.getItem(); if (par0ItemStack.getItem() instanceof ItemBlock && Block.blocksList[var1] != null) { Block var3 = Block.blocksList[var1]; if (var3 == Block.woodSingleSlab) { return 150; } if (var3.blockMaterial == Material.wood) { return 300; } } if (var2 instanceof ItemTool && ((ItemTool) var2).getToolMaterialName().equals("WOOD")) return 200; if (var2 instanceof ItemSword && ((ItemSword) var2).func_77825_f().equals("WOOD")) return 200; if (var2 instanceof ItemHoe && ((ItemHoe) var2).func_77842_f().equals("WOOD")) return 200; if (var1 == Item.stick.itemID) return 100; if (var1 == Item.coal.itemID) return 1600; if (var1 == Item.bucketLava.itemID) return 20000; if (var1 == Block.sapling.blockID) return 100; if (var1 == Item.blazeRod.itemID) return 2400; return GameRegistry.getFuelValue(par0ItemStack); } } public static boolean isItemFuel(ItemStack par0ItemStack) { return getItemBurnTime(par0ItemStack) > 0; } 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() {} @Override public int getStartInventorySide(ForgeDirection side) { if (side == ForgeDirection.DOWN) return 1; if (side == ForgeDirection.UP) return 0; return 2; } @Override public int getSizeInventorySide(ForgeDirection side) { return 1; } }
First off there really are not that many changes here, but first change this section here to YourTile
public class TileEntityYourFurnace extends
And at line 126
public String getInvName() { return "container.yourfurnace"; }
At line 279 you have this bit here
BlockFurnace.updateFurnaceBlockState
Be sure to reference your BlockYourFurnace
At lines 300 and 316 Change FurnaceRecipes to YourRecipes
At line 340..This section contains the fuel data, you can change this to reflect your fuel items
Now we are going to need a handler if we want this to work, and it should look like this...
public class GuiHandler implements IGuiHandler { @Override public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { TileEntity tile_entity = world.getBlockTileEntity(x, y, z); switch(id) { case 0: return new ContainerYourFurnace(player.inventory, (TileEntityYourFurnace) tile_entity); } return null; } @Override public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { TileEntity tile_entity = world.getBlockTileEntity(x, y, z); switch(id) { case 0: return new GuiYourFurnace(player.inventory, (TileEntityYourFurnace) tile_entity); } return null; } }
Notice the case 0... this is your GUI ID reference, remember this from the BlockYourFurnace...YouMod.instance, 0 <<< GUI ID
Setting up you GUIHandler like this will allow you to add more than one gui to your mod by simply adding another case point. This was give to me by jcm2606...
Your Mod File should look like this
@Mod(modid = "YouMod", name = "YouMod", version = "1.0") @NetworkMod(clientSideRequired = true, serverSideRequired = false) public class YouMod { @Instance("YouMod")//<<<Must be the same as your modid public static YouMod instance; private GuiHandler guiHandler = new GuiHandler(); //furnace public static Block yourFurnaceIdle; public static Block yourFurnaceActive; @SidedProxy(clientSide = "your.mod.client.ClientProxy", serverSide = "your.mod.common.CommonProxy") public static CommonProxy proxy; @cpw.mods.fml.common.Mod.PreInit public void PreInit(FMLPreInitializationEvent event) { } @Init public void load(FMLInitializationEvent event) { //Furnaces yourFurnaceIdle = new BlockYourFurnace(150, false).setHardness(3.5F).setStepSound(Block.soundStoneFootstep).setBlockName("extruder").setRequiresSelfNotify().setCreativeTab(CreativeTabs.tabMisc); yourFurnaceActive = new BlockYourFurnace(151, true).setHardness(3.5F).setStepSound(Block.soundStoneFootstep).setBlockName("extruder").setRequiresSelfNotify(); //RegFurnace GameRegistry.registerBlock(yourFurnaceIdle, "yourFurnaceIdle"); GameRegistry.registerBlock(yourFurnaceActive, "yourFurnaceActive"); LanguageRegistry.addName(yourFurnaceIdle, "YourFurnace Idle"); GameRegistry.addRecipe(new ItemStack(extruderIdle, 1), new Object[] {"BBB", "BBB", "BBB", Character.valueOf('B'), this.blackIngot}); YourFurnaceRecipes.smelting().addSmelting(this.blackOre.blockID, new ItemStack(this.blackIngot), 0.1F);//Add recipes this way or in the recipe class NetworkRegistry.instance().registerGuiHandler(this, guiHandler); GameRegistry.registerTileEntity(TileEntityYourFurnace.class,"tileEntityYourFurnace"); proxy.registerRenderThings(); } @cpw.mods.fml.common.Mod.PostInit public void PostInit(FMLPostInitializationEvent event) { } }
If this has helped you at all....Please hit the little green arrow over here>>>>>>> - To post a comment, please login.
2
2
1
You're right, it is accuracy =)
The dirt animation is a smart idea! I have to remember to implement that soon.
34
Info
Thaumic Exploration is a Thaumcraft 4 addon, with the goal of simply adding more balanced Thaumcraft content of the quality you would expect from Azanor himself. I will try as best I can to make my additions feel like they were part of Thaumcraft 4 itself. Although Thaumic Exploration is still a work in progress, it already boasts a ton of content. You can identify Thaumic Exploration research by looking for the [TX] tag.
As this is a WIP, please report bugs! I am open to suggestions.
Thaumic Exploration is open-source, and found on github.
Content
Thaumic Exploration currently contains six new blocks (two are remakes of Thaumcraft 2 blocks), one new wand rod, three new enchantments, four new usable items, and a few new transmutation recipes. Exact content can be found in the below spoiler.
Brain Curing: You have finally found a way to cure zombie brains. They are used in the Think Tank and TC4's advanced golems.
Think Tank: A block that generates research fragments when supplied with books.
Everfull Urn: Infinite water source. Use buckets, or cap it off with Buildcraft or Thermal Expansion pipes. Also fills nearby crucibles and puts out burning players.
Crucible of Souls: Slowly kills mobs for their precious essentia.
Amber Wand Core: A low-capacity, fast refilling wand core, perfect for smaller recipes. There is also a corresponding staff core.
Thaumic Replicator: A block that replicates building blocks in exchange for essentia.
Boots of the Meteor: Boots that allow you to jump high and deal AoE slam attacks.
Boots of the Comet: Boots that allow you to run really, really fast. They also temporarily freeze water.
Wispy Dreamcatcher: Anti-taint device that lowers taint damage.
Talisman of Nourishment: Stores food and automatically feeds you. Never eat again!
Sojourner's Wand Caps: Vis-seeking wand caps that automatically drain nearby nodes.
Mechanist's Wand Caps: Wand caps that dramatically increase node draining speed.
Videos/Images
Warning! Somewhat spoiler-ish!
Pictures:
Changelog:
Downloads:
Requires Thaumcraft 4.1, Minecraft Forge9.11.1.964
IMPORTANT: If using with Thaumic Tinkerer, ensure that you are using build 72 or above.
FSP is now being maintained by Nekosune.
May be a bit unstable
New TX for 1.7.10 is here
New TX for 1.7.2 is here
All OLD TX Downloads can be found here
Why the new download location? It helps me better keep track of download counts and other data. It also lets me keep all downloads in a central location.
Modpack Policy:
Bah do whatever I've received way too many notifications
For those of you who play with Reliquary, try out my new addon, Thaumic Reliquary.
1
Depressurizer
Link to model/anim
1
Coming in the next update. FSP uses a unique network system that doesn't allow for fluid steam to be used, instead, there's a converter block in the next update.
1
1
(1.7.2 too don't kill me)
1
Coming next. Zenith is being held up by some IRL stuff, but I'm still working. Here's a teaser to hold you guys over:
2
I'm not one to play with texture packs. Ever.
This will be my sole exception. Somehow you have made vanilla MC textures better. That's a truly incredible feat. Would it be possible for you to list the differences/show them? Several are obvious (dirt, logs, gravel, etc), but I'm not sure if I'm missing any.
EDIT: My only complaint is the leaves and chests... Everything else is great!