These tutorials are being redone one at a time, as that is all about the time I have available honestly...and for the most part for the 1.6.4 update, they will only be videos....this means no written text except for those pieces specified in the videos that will be available.... This is the first set of videos and are for the 3x3 basic table....
Part one of the basic crafting table tutorial.....
this covers the mod class and container and crafting manager
Part two of the basic crafting table tutorial....
this covers the end of the crafting manager and recipe sorter, GUI class and GUI Handler
GUI Handler example
public class GuiHandlerBuild 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 id == 0 && world.getBlockId(x, y, z) == Builder.builder.blockID ? new BuildContainer(player.inventory, world, x, y, z) : null;
case 1: return new BookContainer();
}
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 id == 0 && world.getBlockId(x, y, z) == Builder.builder.blockID ? new BuildTableGui(player.inventory, world, x, y, z) : null;
case 1: return new BookGui();
}
return null;
}
}
The 2x2 tutorial is being replaced because I need the space for something better. I am going to use this space to try and explain as much as I know about the container class for the Crafting Table and how you can change some things to make the table look and function differently.
Lets get started....
Container....
In the container we have this inside the constructor and its where we will make the first changes
//the crafting matrix is made by rows and columns
//in this case 4 rows by 2 columns
public InventoryCrafting craftMatrix = new InventoryCrafting(this, 4, 2);
public IInventory craftResult = new InventoryCraftResult();
private World worldObj;
private int posX;
private int posY;
private int posZ;
As stated in the code the crafting matrix is made by ROWS and COLUMNS. so if you simply want to redesign the table keep in mind you can move the matrix just the same as any slot.
This is your output slot. It has coordinates that we can use to move the slot anywhere we want...in this example it is (0, 124, 35).
Next is the matrix....
for (l = 0; l < 4; ++l)
{
for (i1 = 0; i1 < 2; ++i1)
{
this.addSlotToContainer(new Slot(this.craftMatrix, i1 + l * 2, 30 + i1 * 18, 17 + l * 18));
}
}
Remember, it is rows and columns. The matrix is also using coordinates. And as I dont really know why, (i1 + l * 2) the 2 in this instance seems to work, and 4 seems to crash it. If anyone knows why please explain.
The next 2 are for inventory and player hotbar.
for (l = 0; l < 3; ++l)
{
for (i1 = 0; i1 < 9; ++i1)
{
this.addSlotToContainer(new Slot(par1InventoryPlayer, i1 + l * 9 + 9, 8 + i1 * 18, 84 + l * 18));
}
}
for (l = 0; l < 9; ++l)
{
this.addSlotToContainer(new Slot(par1InventoryPlayer, l, 8 + l * 18, 142));
}
These are there for your inventories...
The next important method is the onContainerClosed...
public void onContainerClosed(EntityPlayer par1EntityPlayer)
{
super.onContainerClosed(par1EntityPlayer);
if (!this.worldObj.isRemote)
{
for (int i = 0; i < 8; ++i)
{
The 8 in the loop is a multiple of the rows and columns...so if it were 3x5, the 8 would be a 15...or say 5x5, the 8 would be 25.
If you dont change this to your block, in this case (ContainerTutorial.ctutorial.blockID), it will not allow you to open and use you GUI...YOU MUST CHANGE THIS TO YOUR BLOCK
Now since you changed things in the container class a bit, you must also make changes elsewhere...
If you said recipe classes you're right...
Recipes
Recipe Sorter
Here you will need to change all the Shaped and Shapeless references, like the following example I use ShapedCTRecipes and ShapelessCTRecipes
In your Shaped recipe class you will want to change the methods match and checkMatch to reflect your rows and columns like so...
public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World)
{
for (int i = 0; i <= 4 - this.recipeWidth; ++i)
{
for (int j = 0; j <= 2 - this.recipeHeight; ++j)
{
private boolean checkMatch(InventoryCrafting par1InventoryCrafting, int par2, int par3, boolean par4)
{
for (int k = 0; k < 4; ++k)
{
for (int l = 0; l < 2; ++l)
{
In your Shapeless class you will also want to reflect the change in the method matches like the following...
public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World)
{
ArrayList arraylist = new ArrayList(this.recipeItems);
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 2; ++j)
{
You will also need to make a few changes to your crafting manager as well.....
In the method CraftingManager(), you will want to replace that with what ever you named your manager..., this is mine..
private CraftingManagerContainerTutorial()
{
this.addRecipe(new ItemStack(Item.paper, 3), new Object[] {"###", '#', Item.reed});
Collections.sort(this.recipes, new RecipeSorterContainerTutorial(this));
}
So this recipe wont work now will it?...No because it has variables for 3 slots. We have 4 rows of 2 columns. Recipes are read from left to right. The first row in the grid will have 2 columns across, or 2 slots....and then repeat this 4 times...so or recipes should look like this...
private CraftingManagerContainerTutorial()
{
//this.addRecipe(new ItemStack(Item.paper, 3), new Object[] {"###", '#', Item.reed});
this.addRecipe(new ItemStack(Item.paper, 3), new Object[] {"XX", "XX", "XX", "XX", 'X', Block.dirt});
Collections.sort(this.recipes, new RecipeSorterContainerTutorial(this));
}
Make them however you want, but keep in mind, its from left to right, rows and columns.....so in this case no more than 2 items 4 times.
You must also make sure that all recipes instances ShapedRecipes and ShapelessRecipes get changed to your custom classes.
Hope this helps you understand a bit more on how this works for changing the way the grid is shaped. You can also add extra or custom slots by adding custom slot classes. Some changes may even require custom inventory classes. I do not now how to make these, please dont ask me to explain them....
All three of these tables with the grid sizes of 2x2 3x3 and 5x5 can be seen in the mod and they function as well. So if you have doubts, cant get them working or are just wondering how they look in game, stop by and check them out. About 75% of the code was written in Notepad++ but tested in Eclipse before doing anything else. Most of my modding is done at work as I dont have much time at home. Though as I said it is all tested prior to posting <at home> but should you spot any errors please respond and let me know. I dont want to hear, this dont work, or whats wrong with your code. This is all tested first before posting. So respond with this is my error and here is my log or I may not be able to help, if I can help at all. Now without any further adieu, here is the code for the 5x5 table....
You will notice here in the constructor the table size is changed to the 5x5 and also the variables have changed, you can see how they are different from the 2x2 and standard 3x3 variables
public ContainerBetterTable(InventoryPlayer inventoryplayer, World world, int i, int j, int k)
{
craftMatrix = new InventoryCrafting(this, 5, 5);
craftResult = new InventoryCraftResult();
worldObj = world;
posX = i;
posY = j;
posZ = k;
this.addSlotToContainer(new SlotCrafting(inventoryplayer.player, craftMatrix, craftResult, 0, 131, 36));
for(int l = 0; l < 5; l++)
{
for(int k1 = 0; k1 < 5; k1++)
{
this.addSlotToContainer(new Slot(craftMatrix, k1 + l * 5, 4 + k1 * 18, 3 + l * 18));
}
}
And also near the bottom the variable 25 is for the full range of the grid, just like the 2x2 has a return of 4...5 times 5 is 25, and 2 times 2 is 4....this must be reflected or it will not work correctly, if at all.
package bcblocks.bettertable.table;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import bcblocks.bettertable.BetterTable;
import bcblocks.bettertable.tablecare.BetterRecipeSorter;
import bcblocks.bettertable.tablecare.BetterShapedRecipes;
import bcblocks.bettertable.tablecare.BetterShapelessRecipes;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
public class BetterCraftingManager
{
public static final int WILDCARD_VALUE = Short.MAX_VALUE;
private static final BetterCraftingManager instance = new BetterCraftingManager();
private List recipes = new ArrayList();
public static final BetterCraftingManager getInstance()
{
return instance;
}
private BetterCraftingManager()
{
recipes = new ArrayList();
//This is where your recipes will go
Collections.sort(this.recipes, new BetterRecipeSorter(this));
System.out.println(this.recipes.size() + " recipes");
}
public BetterShapedRecipes func_92051_a(ItemStack par1ItemStack, Object ... par2ArrayOfObj)
{
String var3 = "";
int var4 = 0;
int var5 = 0;
int var6 = 0;
if (par2ArrayOfObj[var4] instanceof String[])
{
String[] var7 = (String[])((String[])par2ArrayOfObj[var4++]);
for (int var8 = 0; var8 < var7.length; ++var8)
{
String var9 = var7[var8];
++var6;
var5 = var9.length();
var3 = var3 + var9;
}
}
else
{
while (par2ArrayOfObj[var4] instanceof String)
{
String var11 = (String)par2ArrayOfObj[var4++];
++var6;
var5 = var11.length();
var3 = var3 + var11;
}
}
HashMap var12;
for (var12 = new HashMap(); var4 < par2ArrayOfObj.length; var4 += 2)
{
Character var13 = (Character)par2ArrayOfObj[var4];
ItemStack var14 = null;
if (par2ArrayOfObj[var4 + 1] instanceof Item)
{
var14 = new ItemStack((Item)par2ArrayOfObj[var4 + 1]);
}
else if (par2ArrayOfObj[var4 + 1] instanceof Block)
{
var14 = new ItemStack((Block)par2ArrayOfObj[var4 + 1], 1, -1);
}
else if (par2ArrayOfObj[var4 + 1] instanceof ItemStack)
{
var14 = (ItemStack)par2ArrayOfObj[var4 + 1];
}
var12.put(var13, var14);
}
ItemStack[] var15 = new ItemStack[var5 * var6];
for (int var16 = 0; var16 < var5 * var6; ++var16)
{
char var10 = var3.charAt(var16);
if (var12.containsKey(Character.valueOf(var10)))
{
var15[var16] = ((ItemStack)var12.get(Character.valueOf(var10))).copy();
}
else
{
var15[var16] = null;
}
}
BetterShapedRecipes var17 = new BetterShapedRecipes(var5, var6, var15, par1ItemStack);
this.recipes.add(var17);
return var17;
}
public void addBuilderShapelessRecipe(ItemStack par1ItemStack, Object ... par2ArrayOfObj)
{
ArrayList var3 = new ArrayList();
Object[] var4 = par2ArrayOfObj;
int var5 = par2ArrayOfObj.length;
for (int var6 = 0; var6 < var5; ++var6)
{
Object var7 = var4[var6];
if (var7 instanceof ItemStack)
{
var3.add(((ItemStack)var7).copy());
}
else if (var7 instanceof Item)
{
var3.add(new ItemStack((Item)var7));
}
else
{
if (!(var7 instanceof Block))
{
throw new RuntimeException("Invalid shapeless recipy!");
}
var3.add(new ItemStack((Block)var7));
}
}
this.recipes.add(new BetterShapelessRecipes(par1ItemStack, var3));
}
public ItemStack findMatchingRecipe(InventoryCrafting par1InventoryCrafting, World par2World)
{
int var3 = 0;
ItemStack var4 = null;
ItemStack var5 = null;
int var6;
for (var6 = 0; var6 < par1InventoryCrafting.getSizeInventory(); ++var6)
{
ItemStack var7 = par1InventoryCrafting.getStackInSlot(var6);
if (var7 != null)
{
if (var3 == 0)
{
var4 = var7;
}
if (var3 == 1)
{
var5 = var7;
}
++var3;
}
}
if (var3 == 2 && var4.itemID == var5.itemID && var4.stackSize == 1 && var5.stackSize == 1 && Item.itemsList[var4.itemID].isRepairable())
{
Item var11 = Item.itemsList[var4.itemID];
int var13 = var11.getMaxDamage() - var4.getItemDamageForDisplay();
int var8 = var11.getMaxDamage() - var5.getItemDamageForDisplay();
int var9 = var13 + var8 + var11.getMaxDamage() * 5 / 100;
int var10 = var11.getMaxDamage() - var9;
if (var10 < 0)
{
var10 = 0;
}
return new ItemStack(var4.itemID, 1, var10);
}
else
{
for (var6 = 0; var6 < this.recipes.size(); ++var6)
{
IRecipe var12 = (IRecipe)this.recipes.get(var6);
if (var12.matches(par1InventoryCrafting, par2World))
{
return var12.getCraftingResult(par1InventoryCrafting);
}
}
return null;
}
}
/**
* returns the List<> of all recipes
*/
public List getRecipeList()
{
return this.recipes;
}
}
With this table, you can craft all your standard 3x3 recipes as well as anything up to 5x5 obviously. I put all my recipes in this class, but if you need, and absolutely must, I can tell you how to add them to your mod class
--------------------------------
-------------------------------- Recipe Sorter, shaped recipes and shapless recipes will all have errors if you are just copying and pasting. Please dont just copy and paste, you will not learn anything that way. And please change names accordingly to your mod, it will make more sense to you later, and help keep your mod in order for your mod. Like other tutorials that use terms like BlockTuorial, I would hope you change it to your block, and not leave it as tutorial.
Recipe Sorter
package bcblocks.bettertable.tablecare;
import java.util.Comparator;
import bcblocks.bettertable.table.BetterCraftingManager;
import net.minecraft.item.crafting.IRecipe;
public class BetterRecipeSorter implements Comparator
{
final BetterCraftingManager betterCraftingManager;
public BetterRecipeSorter(BetterCraftingManager par1BetterCraftingManager)
{
this.betterCraftingManager = par1BetterCraftingManager;
}
public int compareRecipes(IRecipe par1IRecipe, IRecipe par2IRecipe)
{
return par1IRecipe instanceof BetterShapelessRecipes && par2IRecipe instanceof BetterShapedRecipes ? 1 : (par2IRecipe instanceof BetterShapelessRecipes && par1IRecipe instanceof BetterShapedRecipes ? -1 : (par2IRecipe.getRecipeSize() < par1IRecipe.getRecipeSize() ? -1 : (par2IRecipe.getRecipeSize() > par1IRecipe.getRecipeSize() ? 1 : 0)));
}
public int compare(Object par1Obj, Object par2Obj)
{
return this.compareRecipes((IRecipe)par1Obj, (IRecipe)par2Obj);
}
}
Shaped Recipes
package bcblocks.bettertable.tablecare;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
public class BetterShapedRecipes implements IRecipe
{
/** How many horizontal slots this recipe is wide. */
public final int recipeWidth;
/** How many vertical slots this recipe uses. */
public final int recipeHeight;
/** Is a array of ItemStack that composes the recipe. */
public final ItemStack[] recipeItems;
/** Is the ItemStack that you get when craft the recipe. */
private ItemStack recipeOutput;
/** Is the itemID of the output item that you get when craft the recipe. */
public final int recipeOutputItemID;
private boolean field_92101_f = false;
public BetterShapedRecipes(int par1, int par2, ItemStack[] par3ArrayOfItemStack, ItemStack par4ItemStack)
{
this.recipeOutputItemID = par4ItemStack.itemID;
this.recipeWidth = par1;
this.recipeHeight = par2;
this.recipeItems = par3ArrayOfItemStack;
this.recipeOutput = par4ItemStack;
}
public ItemStack getRecipeOutput()
{
return this.recipeOutput;
}
/**
* Used to check if a recipe matches current crafting inventory
*/
public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World)
{
for (int i = 0; i <= 5 - this.recipeWidth; ++i)
{
for (int j = 0; j <= 5 - this.recipeHeight; ++j)
{
if (this.checkMatch(par1InventoryCrafting, i, j, true))
{
return true;
}
if (this.checkMatch(par1InventoryCrafting, i, j, false))
{
return true;
}
}
}
return false;
}
/**
* Checks if the region of a crafting inventory is match for the recipe.
*/
private boolean checkMatch(InventoryCrafting par1InventoryCrafting, int par2, int par3, boolean par4)
{
for (int k = 0; k < 5; ++k)
{
for (int l = 0; l < 5; ++l)
{
int i1 = k - par2;
int j1 = l - par3;
ItemStack itemstack = null;
if (i1 >= 0 && j1 >= 0 && i1 < this.recipeWidth && j1 < this.recipeHeight)
{
if (par4)
{
itemstack = this.recipeItems[this.recipeWidth - i1 - 1 + j1 * this.recipeWidth];
}
else
{
itemstack = this.recipeItems[i1 + j1 * this.recipeWidth];
}
}
ItemStack itemstack1 = par1InventoryCrafting.getStackInRowAndColumn(k, l);
if (itemstack1 != null || itemstack != null)
{
if (itemstack1 == null && itemstack != null || itemstack1 != null && itemstack == null)
{
return false;
}
if (itemstack.itemID != itemstack1.itemID)
{
return false;
}
if (itemstack.getItemDamage() != 32767 && itemstack.getItemDamage() != itemstack1.getItemDamage())
{
return false;
}
}
}
}
return true;
}
/**
* Returns an Item that is the result of this recipe
*/
public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting)
{
ItemStack itemstack = this.getRecipeOutput().copy();
if (this.field_92101_f)
{
for (int i = 0; i < par1InventoryCrafting.getSizeInventory(); ++i)
{
ItemStack itemstack1 = par1InventoryCrafting.getStackInSlot(i);
if (itemstack1 != null && itemstack1.hasTagCompound())
{
itemstack.setTagCompound((NBTTagCompound)itemstack1.stackTagCompound.copy());
}
}
}
return itemstack;
}
/**
* Returns the size of the recipe area
*/
public int getRecipeSize()
{
return this.recipeWidth * this.recipeHeight;
}
public BetterShapedRecipes func_92100_c()
{
this.field_92101_f = true;
return this;
}
}
Here you will notice in the methods matches and check matches the for ints have changed, they must match your grid size from the container, example this is a 5x5 so they must be 5, if it were 6x6 or 1x1 or whatever the size, they must match
public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World)
{
for (int i = 0; i <= 5 - this.recipeWidth; ++i)
{
for (int j = 0; j <= 5 - this.recipeHeight; ++j)
{
if (this.checkMatch(par1InventoryCrafting, i, j, true))
{
return true;
}
if (this.checkMatch(par1InventoryCrafting, i, j, false))
{
return true;
}
}
}
return false;
}
/**
* Checks if the region of a crafting inventory is match for the recipe.
*/
private boolean checkMatch(InventoryCrafting par1InventoryCrafting, int par2, int par3, boolean par4)
{
for (int k = 0; k < 5; ++k)
{
for (int l = 0; l < 5; ++l)
{
int i1 = k - par2;
int j1 = l - par3;
ItemStack itemstack = null;
Shapless Recipes
package bcblocks.bettertable.tablecare;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
public class BetterShapelessRecipes implements IRecipe
{
/** Is the ItemStack that you get when craft the recipe. */
private final ItemStack recipeOutput;
/** Is a List of ItemStack that composes the recipe. */
public final List recipeItems;
public BetterShapelessRecipes(ItemStack par1ItemStack, List par2List)
{
this.recipeOutput = par1ItemStack;
this.recipeItems = par2List;
}
public ItemStack getRecipeOutput()
{
return this.recipeOutput;
}
/**
* Used to check if a recipe matches current crafting inventory
*/
public boolean matches(InventoryCrafting par1InventoryCrafting, World par2World)
{
ArrayList arraylist = new ArrayList(this.recipeItems);
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
ItemStack itemstack = par1InventoryCrafting.getStackInRowAndColumn(j, i);
if (itemstack != null)
{
boolean flag = false;
Iterator iterator = arraylist.iterator();
while (iterator.hasNext())
{
ItemStack itemstack1 = (ItemStack)iterator.next();
if (itemstack.itemID == itemstack1.itemID && (itemstack1.getItemDamage() == 32767 || itemstack.getItemDamage() == itemstack1.getItemDamage()))
{
flag = true;
arraylist.remove(itemstack1);
break;
}
}
if (!flag)
{
return false;
}
}
}
}
return arraylist.isEmpty();
}
/**
* Returns an Item that is the result of this recipe
*/
public ItemStack getCraftingResult(InventoryCrafting par1InventoryCrafting)
{
return this.recipeOutput.copy();
}
/**
* Returns the size of the recipe area
*/
public int getRecipeSize()
{
return this.recipeItems.size();
}
}
The same goes for this class too, the matches section must match your grid size....
Gui
package bcblocks.bettertable.table;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import org.lwjgl.opengl.GL11;
public class BetterTableGui extends GuiContainer
{
private ResourceLocation better = new ResourceLocation("textures/bettertable/textures/gui/betterone.png");
public BetterTableGui(InventoryPlayer inventoryplayer, World world, int i, int j, int k)
{
super(new ContainerBetterTable(inventoryplayer, world, i, j, k));
}
public void onGuiClosed()
{
super.onGuiClosed();
}
protected void drawGuiContainerForegroundLayer(int par1, int par2)
{
this.fontRenderer.drawString(StatCollector.translateToLocal("\u00a76Better"), 120, 5, 0x404040);
this.fontRenderer.drawString(StatCollector.translateToLocal("\u00a76Crafting"), 116, 20, 0x404040);
//this.fontRenderer.drawString(StatCollector.translateToLocal("container.inventory"), 8, this.ySize - 96 - 14, 0x404040);
}
protected void drawGuiContainerBackgroundLayer(float f, int i, int j)
{
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
mc.renderEngine.func_110577_a(better);
int l = (width - xSize) / 2;
int i1 = (height - ySize) / 2;
drawTexturedModalRect(l, i1, 0, 0, xSize, ySize);
}
}
You will notice here, as with the other GUI's some variables for size of the GUI have changed, please take note of this...
I may do one more if I can figure out how to make a 2x4 table....
Good luck and have fun
Source code for the 5x5 table, fully functioning and working 100%, there will be no help given if you drop this in mcp and cant get it to work. This works and is my entire source code for the better table mod....
I have a slight problem: My gui doesn't open up.
I copied your files and modified them to fit my mod(changed names)
But the gui doesn't open.(If you want to see my codes I'll happily post them)
first, did you make sure you have your instance correct? did you apply your gui handler? and yes let me see the code, I may have missed something and have to fix....
Edit, yes I did forget something...please check the post again in the main class for the network registry. I am sorry I forgot that, I am doing this at work, and am quite tired from long midnight shifts....
I believe I have correct instance,and I did check the network registry as you mentioned but it still doesn't open.
Well i understand you forgot something long midnight shifts at work isn't easy.
Anyway Here's my codes:
Main Class:
package erikstinker;
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.Mod.PostInit;
import cpw.mods.fml.common.Mod.PreInit;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
@Mod(modid = "Tinkering", name = "Erik's Tinker Mod", version = "1.5.1")
@NetworkMod(clientSideRequired = true, serverSideRequired = false, channels = {"EriksTinkerMod"}, packetHandler = ErikPacketHandler.class)
public class Erikstinker {
@SidedProxy(clientSide = "erikstinker.ClientProxy", serverSide = "erikstinker.ServerProxy")
public static ServerProxy proxy;
@Instance ("Tinkering")
public static Erikstinker instance;
private GuiHandler guihandler = new GuiHandler();
private GuiHandler PrepTableGuiHandler = new GuiHandler();
public static Block RaohFurnaceIdle;
public static Block RaohFurnaceBurning;
public static Block RaohStone;
public static Block PrepTable;
@PreInit
public void load(FMLPreInitializationEvent PreEvent){
}
@Init
public void load(FMLInitializationEvent event){
proxy.registerRenderThings();
RaohStone = new RaohBlock(450).setHardness(3.0F).setResistance(10.0F).setUnlocalizedName("Raoh Stone");
RaohFurnaceIdle = new RaohFurnace(1580, false).setHardness(3.5F).setUnlocalizedName("Raoh Furnace Idle").setCreativeTab(CreativeTabs.tabDecorations);
RaohFurnaceBurning = new RaohFurnace(1581, true).setHardness(3.5F).setUnlocalizedName("Raoh Furnace Burning").setCreativeTab(CreativeTabs.tabDecorations);
PrepTable = new BlockPrepTable(1582).setHardness(5.0F).setResistance(2000.0F).setUnlocalizedName("PrepTable");
GameRegistry.registerBlock(RaohStone, "Erikstinker.RaohStone");
GameRegistry.registerBlock(RaohFurnaceIdle, "Erikstinker.RaohFurnaceIdle");
GameRegistry.registerBlock(RaohFurnaceIdle, "Erikstinker.RaohFurnaceBurning");
GameRegistry.registerBlock(PrepTable, "Erikstinker.PrepTable");
GameRegistry.registerTileEntity(TileEntityRaohFurnace.class, "tileentityraohfurnace");
NetworkRegistry.instance().registerGuiHandler(this, guihandler);
NetworkRegistry.instance().registerGuiHandler(this, PrepTableGuiHandler);
LanguageRegistry.addName(RaohStone, "Raoh Stone");
LanguageRegistry.addName(RaohFurnaceIdle, "Raoh Furnace");
LanguageRegistry.addName(RaohFurnaceBurning, "Raoh Furnace Burning");
LanguageRegistry.addName(PrepTable, "Preporation Table");
GameRegistry.addShapedRecipe(new ItemStack(PrepTable, 1), new Object[] {" ", "xzx", "xxx", Character.valueOf('x'),RaohStone, Character.valueOf('z'), Block.workbench});
}
@PostInit
public void PostLoad(FMLPostInitializationEvent PostEvent) {
}
{
}
}
BlockPrepTable(The BlockWorkbench):
package erikstinker;
import java.util.Random;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.src.ModLoader;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Icon;
import net.minecraft.world.World;
public class BlockPrepTable extends Block
{
@SideOnly(Side.CLIENT)
private Icon field_94385_a;
@SideOnly(Side.CLIENT)
private Icon field_94384_b;
public BlockPrepTable(int par1)
{
super(par1, Material.wood);
//blockIndexInTexture = 59;
this.setCreativeTab(CreativeTabs.tabDecorations);
}
@SideOnly(Side.CLIENT)
/**
* From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
*/
public Icon getBlockTextureFromSideAndMetadata(int par1, int par2)
{
return par1 == 1 ? this.field_94385_a : (par1 == 0 ? Block.planks.getBlockTextureFromSide(par1) : (par1 != 2 && par1 != 4 ? this.blockIcon : this.field_94384_B));
}
@SideOnly(Side.CLIENT)
/**
* When this method is called, your block should register all the icons it needs with the given IconRegister. This
* is the only chance you get to register icons.
*/
public void registerIcons(IconRegister par1IconRegister)
{
this.blockIcon = par1IconRegister.registerIcon("workbench_side");
this.field_94385_a = par1IconRegister.registerIcon("workbench_top");
this.field_94384_b = par1IconRegister.registerIcon("workbench_front");
}
public boolean onBlockActivated(World var1, int var2, int var3, int var4, EntityPlayer player, int var6, float var7, float var8, float var9)
{
if (!player.isSneaking())
{
player.openGui(Erikstinker.instance, 1, var1, var2, var3, var4);
return true;
}
else
{
return false;
}
}
}
ContainerPrepTable:
package erikstinker;
import net.minecraft.block.Block;
import erikstinker.BlockPrepTable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCraftResult;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.inventory.Slot;
import net.minecraft.inventory.SlotCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.world.World;
public class ContainerPrepTable extends Container
{
/** The crafting matrix inventory (3x3). */
public InventoryCrafting craftMatrix = new InventoryCrafting(this, 3, 3);
public IInventory craftResult = new InventoryCraftResult();
private World worldObj;
private int posX;
private int posY;
private int posZ;
public ContainerPrepTable(InventoryPlayer par1InventoryPlayer, World par2World, int par3, int par4, int par5)
{
this.worldObj = par2World;
this.posX = par3;
this.posY = par4;
this.posZ = par5;
this.addSlotToContainer(new SlotPrepTable(par1InventoryPlayer.player, this.craftMatrix, this.craftResult, 0, 124, 35));
int var6;
int var7;
for (var6 = 0; var6 < 3; ++var6)
{
for (var7 = 0; var7 < 3; ++var7)
{
this.addSlotToContainer(new Slot(this.craftMatrix, var7 + var6 * 3, 30 + var7 * 18, 17 + var6 * 18));
}
}
for (var6 = 0; var6 < 3; ++var6)
{
for (var7 = 0; var7 < 9; ++var7)
{
this.addSlotToContainer(new Slot(par1InventoryPlayer, var7 + var6 * 9 + 9, 8 + var7 * 18, 84 + var6 * 18));
}
}
for (var6 = 0; var6 < 9; ++var6)
{
this.addSlotToContainer(new Slot(par1InventoryPlayer, var6, 8 + var6 * 18, 142));
}
this.onCraftMatrixChanged(this.craftMatrix);
}
/**
* Callback for when the crafting matrix is changed.
*/
public void onCraftMatrixChanged(IInventory par1IInventory)
{
this.craftResult.setInventorySlotContents(0, PrepTableCraftingManager.getInstance().findMatchingRecipe(this.craftMatrix, this.worldObj));
}
/**
* Callback for when the crafting gui is closed.
*/
public void onCraftGuiClosed(EntityPlayer par1EntityPlayer)
{
super.onCraftGuiClosed(par1EntityPlayer);
if (!this.worldObj.isRemote)
{
for (int var2 = 0; var2 < 9; ++var2)
{
ItemStack var3 = this.craftMatrix.getStackInSlotOnClosing(var2);
if (var3 != null)
{
par1EntityPlayer.dropPlayerItem(var3);
}
}
}
}
public boolean canInteractWith(EntityPlayer par1EntityPlayer)
{
return this.worldObj.getBlockId(this.posX, this.posY, this.posZ) != Erikstinker.PrepTable.blockID ? false : par1EntityPlayer.getDistanceSq((double)this.posX + 0.5D, (double)this.posY + 0.5D, (double)this.posZ + 0.5D) <= 64.0D;
}
/**
* Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
*/
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 == 0)
{
if (!this.mergeItemStack(var5, 10, 46, true))
{
return null;
}
var4.onSlotChange(var5, var3);
}
else if (par2 >= 10 && par2 < 37)
{
if (!this.mergeItemStack(var5, 37, 46, false))
{
return null;
}
}
else if (par2 >= 37 && par2 < 46)
{
if (!this.mergeItemStack(var5, 10, 37, false))
{
return null;
}
}
else if (!this.mergeItemStack(var5, 10, 46, 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;
}
}
GuiPrepTable:
package erikstinker;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class GuiPrepTable extends GuiContainer
{
public GuiPrepTable(InventoryPlayer par1InventoryPlayer, World par2World, int par3, int par4, int par5)
{
super(new ContainerPrepTable(par1InventoryPlayer, par2World, par3, par4, par5));
}
/**
* Draw the foreground layer for the GuiContainer (everything in front of the items)
*/
protected void drawGuiContainerForegroundLayer(int par1, int par2)
{
this.fontRenderer.drawString(StatCollector.translateToLocal("container.crafting"), 28, 6, 4210752);
this.fontRenderer.drawString(StatCollector.translateToLocal("container.inventory"), 8, this.ySize - 96 + 2, 4210752);
}
/**
* Draw the background layer for the GuiContainer (everything behind the items)
*/
protected void drawGuiContainerBackgroundLayer(float par1, int par2, int par3)
{
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
this.mc.renderEngine.bindTexture("/gui/crafting.png");
int var5 = (this.width - this.xSize) / 2;
int var6 = (this.height - this.ySize) / 2;
this.drawTexturedModalRect(var5, var6, 0, 0, this.xSize, this.ySize);
}
}
PrepTableGuiHandler:
package erikstinker;
import erikstinker.GuiPrepTable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import cpw.mods.fml.common.network.IGuiHandler;
public class PrepTableGuiHandler 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 ContainerExtruder(player.inventory, (TileEntityExtruder) tile_entity);
case 1: return id == 1 && world.getBlockId(x, y, z) == Erikstinker.PrepTable.blockID ? new ContainerPrepTable(player.inventory, world, x, y, z) : null;
//case 2: return new ContainerSpiritTable(player.inventory, (world), x, y, z);
//case 3: return new ContainerTreeTrunk(player.inventory, (TileEntityTreeTrunk) tile_entity);
//case 4: return id == 4 && world.getBlockId(x, y, z) == MTJT.forge.blockID ? new ContainerForgeBench(player.inventory, world, x, y, z) : null;
//case 5: return new ContainerIceMachine(player.inventory, (TileEntityIceMachine) tile_entity);
//case 6: return new ContainerGemMachine(player.inventory, (TileEntityGemMachine) tile_entity);
//case 7: return id == 7 && world.getBlockId(x, y, z) == MTJT.builder.blockID ? new ContainerBlueprintTable(player.inventory, world, x, y, z) : null;
}
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 GuiExtruder(player.inventory, (TileEntityExtruder) tile_entity);
case 1: return id == 1 && world.getBlockId(x, y, z) == Erikstinker.PrepTable.blockID ? new GuiPrepTable(player.inventory, world, x, y, z) : null;
//case 2: return new GuiSpiritTable(player.inventory, (world), x, y, z);
//case 3: return new GuiTreeTrunk(player.inventory, (TileEntityTreeTrunk) tile_entity);
//case 4: return id == 4 && world.getBlockId(x, y, z) == MTJT.forge.blockID ? new GuiForgeCrafting(player.inventory, world, x, y, z) : null;
//case 5: return new GuiIceMachine(player.inventory, (TileEntityIceMachine) tile_entity);
//case 6: return new GuiGemMachine(player.inventory, (TileEntityGemMachine) tile_entity);
//case 7: return id == 7 && world.getBlockId(x, y, z) == MTJT.builder.blockID ? new BlueprintTableGui(player.inventory, world, x, y, z) : null;
}
return null;
}
}
SlotPrepTable:
package erikstinker;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.AchievementList;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
public class SlotPrepTable extends Slot
{
/** The craft matrix inventory linked to this result slot. */
private final IInventory craftMatrix;
/** The player that is using the GUI where this slot resides. */
private EntityPlayer thePlayer;
/**
* The number of items that have been crafted so far. Gets passed to ItemStack.onCrafting before being reset.
*/
private int amountCrafted;
public SlotPrepTable(EntityPlayer par1EntityPlayer, IInventory par2IInventory, IInventory par3IInventory, int par4, int par5, int par6)
{
super(par3IInventory, par4, par5, par6);
this.thePlayer = par1EntityPlayer;
this.craftMatrix = par2IInventory;
}
/**
* Check if the stack is a valid item for this slot. Always true beside for the armor slots.
*/
public boolean isItemValid(ItemStack par1ItemStack)
{
return false;
}
/**
* Decrease the size of the stack in slot (first int arg) by the amount of the second int arg. Returns the new
* stack.
*/
public ItemStack decrStackSize(int par1)
{
if (this.getHasStack())
{
this.amountCrafted += Math.min(par1, this.getStack().stackSize);
}
return super.decrStackSize(par1);
}
/**
* the itemStack passed in is the output - ie, iron ingots, and pickaxes, not ore and wood. Typically increases an
* internal count then calls onCrafting(item).
*/
protected void onCrafting(ItemStack par1ItemStack, int par2)
{
this.amountCrafted += par2;
this.onCrafting(par1ItemStack);
}
/**
* the itemStack passed in is the output - ie, iron ingots, and pickaxes, not ore and wood.
*/
protected void onCrafting(ItemStack par1ItemStack)
{
par1ItemStack.onCrafting(this.thePlayer.worldObj, this.thePlayer, this.amountCrafted);
this.amountCrafted = 0;
if (par1ItemStack.itemID == Block.workbench.blockID)
{
this.thePlayer.addStat(AchievementList.buildWorkBench, 1);
}
else if (par1ItemStack.itemID == Item.pickaxeWood.itemID)
{
this.thePlayer.addStat(AchievementList.buildPickaxe, 1);
}
else if (par1ItemStack.itemID == Block.furnaceIdle.blockID)
{
this.thePlayer.addStat(AchievementList.buildFurnace, 1);
}
else if (par1ItemStack.itemID == Item.hoeWood.itemID)
{
this.thePlayer.addStat(AchievementList.buildHoe, 1);
}
else if (par1ItemStack.itemID == Item.bread.itemID)
{
this.thePlayer.addStat(AchievementList.makeBread, 1);
}
else if (par1ItemStack.itemID == Item.cake.itemID)
{
this.thePlayer.addStat(AchievementList.bakeCake, 1);
}
else if (par1ItemStack.itemID == Item.pickaxeStone.itemID)
{
this.thePlayer.addStat(AchievementList.buildBetterPickaxe, 1);
}
else if (par1ItemStack.itemID == Item.swordWood.itemID)
{
this.thePlayer.addStat(AchievementList.buildSword, 1);
}
else if (par1ItemStack.itemID == Block.enchantmentTable.blockID)
{
this.thePlayer.addStat(AchievementList.enchantments, 1);
}
else if (par1ItemStack.itemID == Block.bookShelf.blockID)
{
this.thePlayer.addStat(AchievementList.bookcase, 1);
}
}
public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack)
{
GameRegistry.onItemCrafted(par1EntityPlayer, par2ItemStack, craftMatrix);
this.onCrafting(par2ItemStack);
for (int var3 = 0; var3 < this.craftMatrix.getSizeInventory(); ++var3)
{
ItemStack var4 = this.craftMatrix.getStackInSlot(var3);
if (var4 != null)
{
this.craftMatrix.decrStackSize(var3, 1);
if (var4.getItem().hasContainerItem())
{
ItemStack var5 = var4.getItem().getContainerItemStack(var4);
if (var5.isItemStackDamageable() && var5.getItemDamage() > var5.getMaxDamage())
{
MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thePlayer, var5));
var5 = null;
}
if (var5 != null && (!var4.getItem().doesContainerItemLeaveCraftingGrid(var4) || !this.thePlayer.inventory.addItemStackToInventory(var5)))
{
if (this.craftMatrix.getStackInSlot(var3) == null)
{
this.craftMatrix.setInventorySlotContents(var3, var5);
}
else
{
this.thePlayer.dropPlayerItem(var5);
}
}
}
}
}
}
}
TileEntityPrepTable:
package erikstinker;
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 TileEntityRaohFurnace extends TileEntity implements ISidedInventory, net.minecraftforge.common.ISidedInventory
{
private static final int[] field_102010_d = new int[] {0,3};
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 : "Raoh 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("Raoh Furnace"))
{
this.field_94130_e = par1NBTTagCompound.getString("Raoh 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("Tut 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 / 200;
}
@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 = 200;
}
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 == 200)
{
this.furnaceCookTime = 0;
this.smeltItem();
flag1 = true;
}
}
else
{
this.furnaceCookTime = 0;
}
if (flag != this.furnaceBurnTime > 0)
{
flag1 = true;
RaohFurnace.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
{
if (this.furnaceItemStacks[3] == null)
{
}
{
}
ItemStack itemstack = RaohFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
if (itemstack == null) return false;
if (this.furnaceItemStacks[2] == null) return true;
if (!this.furnaceItemStacks[2].isItemEqual(itemstack)) return false;
int result = furnaceItemStacks[2].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 = RaohFurnaceRecipes.smelting().getSmeltingResult(this.furnaceItemStacks[0]);
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 150;
}
}
if (i == Erikstinker.RaohStone.blockID) return 200;
if (i == Item.coal.itemID) return 1600;
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);
}
/**
* Get the size of the side inventory.
*/
public int[] getSizeInventorySide(int par1)
{
return par1 == 0 ? field_102011_e : (par1 == 1 ? field_102010_d : field_102009_f);
}
public boolean func_102007_a(int par1, ItemStack par2ItemStack, int par3)
{
return this.isStackValidForSlot(par1, par2ItemStack);
}
public boolean func_102008_b(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;
}
}
PrepTableCraftingManager:
package erikstinker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.ShapedRecipes;
import net.minecraft.item.crafting.ShapelessRecipes;
import net.minecraft.world.World;
public class PrepTableCraftingManager
{
/** The static instance of this class */
private static final PrepTableCraftingManager instance = new PrepTableCraftingManager();
/** A list of all the recipes added */
private List recipes = new ArrayList();
/**
* Returns the static instance of this class
*/
public static final PrepTableCraftingManager getInstance()
{
return instance;
}
private PrepTableCraftingManager()
{
recipes = new ArrayList();
//Place your custom recipes here following this format
//this.func_prep(new ItemStack(Path.Block/Item, Amount), new Object[] {"3x3",*Repeat*, *Character.valueOf('Symbol'),Path.Block/Item, Repeat*});
Collections.sort(this.recipes, new PrepTableRecipeSorter(this));
System.out.println(this.recipes.size() + " recipes");
}
public ShapedRecipes func_prep(ItemStack par1ItemStack, Object ... par2ArrayOfObj)
{
String var3 = "";
int var4 = 0;
int var5 = 0;
int var6 = 0;
if (par2ArrayOfObj[var4] instanceof String[])
{
String[] var7 = (String[])((String[])par2ArrayOfObj[var4++]);
for (int var8 = 0; var8 < var7.length; ++var8)
{
String var9 = var7[var8];
++var6;
var5 = var9.length();
var3 = var3 + var9;
}
}
else
{
while (par2ArrayOfObj[var4] instanceof String)
{
String var11 = (String)par2ArrayOfObj[var4++];
++var6;
var5 = var11.length();
var3 = var3 + var11;
}
}
HashMap var12;
for (var12 = new HashMap(); var4 < par2ArrayOfObj.length; var4 += 2)
{
Character var13 = (Character)par2ArrayOfObj[var4];
ItemStack var14 = null;
if (par2ArrayOfObj[var4 + 1] instanceof Item)
{
var14 = new ItemStack((Item)par2ArrayOfObj[var4 + 1]);
}
else if (par2ArrayOfObj[var4 + 1] instanceof Block)
{
var14 = new ItemStack((Block)par2ArrayOfObj[var4 + 1], 1, -1);
}
else if (par2ArrayOfObj[var4 + 1] instanceof ItemStack)
{
var14 = (ItemStack)par2ArrayOfObj[var4 + 1];
}
var12.put(var13, var14);
}
ItemStack[] var15 = new ItemStack[var5 * var6];
for (int var16 = 0; var16 < var5 * var6; ++var16)
{
char var10 = var3.charAt(var16);
if (var12.containsKey(Character.valueOf(var10)))
{
var15[var16] = ((ItemStack)var12.get(Character.valueOf(var10))).copy();
}
else
{
var15[var16] = null;
}
}
ShapedRecipes var17 = new ShapedRecipes(var5, var6, var15, par1ItemStack);
this.recipes.add(var17);
return var17;
}
public void addShapelessRecipe(ItemStack par1ItemStack, Object ... par2ArrayOfObj)
{
ArrayList var3 = new ArrayList();
Object[] var4 = par2ArrayOfObj;
int var5 = par2ArrayOfObj.length;
for (int var6 = 0; var6 < var5; ++var6)
{
Object var7 = var4[var6];
if (var7 instanceof ItemStack)
{
var3.add(((ItemStack)var7).copy());
}
else if (var7 instanceof Item)
{
var3.add(new ItemStack((Item)var7));
}
else
{
if (!(var7 instanceof Block))
{
throw new RuntimeException("Invalid shapeless recipy!");
}
var3.add(new ItemStack((Block)var7));
}
}
this.recipes.add(new ShapelessRecipes(par1ItemStack, var3));
}
public ItemStack findMatchingRecipe(InventoryCrafting par1InventoryCrafting, World par2World)
{
int var3 = 0;
ItemStack var4 = null;
ItemStack var5 = null;
int var6;
for (var6 = 0; var6 < par1InventoryCrafting.getSizeInventory(); ++var6)
{
ItemStack var7 = par1InventoryCrafting.getStackInSlot(var6);
if (var7 != null)
{
if (var3 == 0)
{
var4 = var7;
}
if (var3 == 1)
{
var5 = var7;
}
++var3;
}
}
if (var3 == 2 && var4.itemID == var5.itemID && var4.stackSize == 1 && var5.stackSize == 1 && Item.itemsList[var4.itemID].isRepairable())
{
Item var11 = Item.itemsList[var4.itemID];
int var13 = var11.getMaxDamage() - var4.getItemDamageForDisplay();
int var8 = var11.getMaxDamage() - var5.getItemDamageForDisplay();
int var9 = var13 + var8 + var11.getMaxDamage() * 5 / 100;
int var10 = var11.getMaxDamage() - var9;
if (var10 < 0)
{
var10 = 0;
}
return new ItemStack(var4.itemID, 1, var10);
}
else
{
for (var6 = 0; var6 < this.recipes.size(); ++var6)
{
IRecipe var12 = (IRecipe)this.recipes.get(var6);
if (var12.matches(par1InventoryCrafting, par2World))
{
return var12.getCraftingResult(par1InventoryCrafting);
}
}
return null;
}
}
/**
* returns the List<> of all recipes
*/
public List getRecipeList()
{
return this.recipes;
}
}
@Mod(modid = "Tinkering", name = "Erik's Tinker Mod", version = "1.5.1")
@NetworkMod(clientSideRequired = true, serverSideRequired = false, channels = {"EriksTinkerMod"}, packetHandler = ErikPacketHandler.class)
public class Erikstinker {
@SidedProxy(clientSide = "erikstinker.ClientProxy", serverSide = "erikstinker.ServerProxy")
public static ServerProxy proxy;
@Instance ("Tinkering")
public static Erikstinker instance;
private GuiHandler guihandler = new GuiHandler();
private GuiHandler PrepTableGuiHandler = new GuiHandler();
First this is a problem here (PrepTableGuiHandler = new GuiHandler();)
PrepTableGuiHandler should = PrepTableGuiHandler....and also you only need one GUI Handler for your mod, if you notice i have all my GUI ID in one handler and you can delete the commented code by the way, was just showing as an example
PrepTableGuiHandler:
package erikstinker;
import erikstinker.GuiPrepTable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import cpw.mods.fml.common.network.IGuiHandler;
public class PrepTableGuiHandler 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 ContainerExtruder(player.inventory, (TileEntityExtruder) tile_entity);
case 1: return id == 1 && world.getBlockId(x, y, z) == Erikstinker.PrepTable.blockID ? new ContainerPrepTable(player.inventory, world, x, y, z) : null;
}
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 GuiExtruder(player.inventory, (TileEntityExtruder) tile_entity);
case 1: return id == 1 && world.getBlockId(x, y, z) == Erikstinker.PrepTable.blockID ? new GuiPrepTable(player.inventory, world, x, y, z) : null;
}
return null;
}
}
Since you have 2 GUI ID's apparently, only assuming from the 2 handlers use this set up like this with a 0 and a 1 switch statement in the handler it will work just fine. When I first learned how to do this I did the same thing with 2 handlers and it did some weird things.....Give that a shot and make the suggested changes and let me know
First this is a problem here (PrepTableGuiHandler = new GuiHandler()
PrepTableGuiHandler should = PrepTableGuiHandler....and also you only need one GUI Handler for your mod, if you notice i have all my GUI ID in one handler and you can delete the commented code by the way, was just showing as an example
Ok,so I got rid of PrepTableGuiHandler and used my first which was only for the furnace.
Yes I know I could delete the commented code but I just didn't bother
Since you have 2 GUI ID's apparently, only assuming from the 2 handlers use this set up like this with a 0 and a 1 switch statement in the handler it will work just fine. When I first learned how to do this I did the same thing with 2 handlers and it did some weird things.....Give that a shot and make the suggested changes and let me know
I changed it with your suggestion and it does work,and now I can finally see why it didn't before.
Thank you so much for that! You just ended my week long suffering of not understanding.
That is sweet,now I can finally start my next project.Thanks a lot!
It says The method registerGuiHandler(Object, IGuiHandler) in the type NetworkRegistry is not applicable for the arguments (MTcraftingManager, MTcraftingManager)
My workbench won't open whenever I try opening it. Upon attempting to open it I get this error:
2013-06-09 17:54:45 [WARNING] [ForgeModLoader] A mod tried to open a gui on the server without being a NetworkMod
Can you look over my code to see what I did wrong?
package GOTW;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.item.EnumToolMaterial;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraftforge.common.EnumHelper;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
@Mod(modid = mod_GOTW.modid, name = "Mod Name", version = "1.0")
@NetworkMod(clientSideRequired = true, serverSideRequired = false)
public class mod_GOTW
{
public static final String modid = "GOTW";
@Instance("mod_GOTW")
public static mod_GOTW instance;
private GuiHandlerGOTW guiHandlerGOTW = new GuiHandlerGOTW();
//Blocks
public static Block tutorialBlock;
public static Block advWorkBench;
//Items
public static Item tutorialItem;
public static Item ironString;
public static Item reinforcedStick;
//Tools
public static Item reinforcedAxe;
public static Item reinforcedHoe;
public static Item reinforcedPickaxe;
public static Item reinforcedSpade;
//Weapons
public static Item reinforcedSword;
public static Item recurveBow;
@Init
public void load(FMLInitializationEvent event)
{
//Blocks
tutorialBlock = new BlockTutorialBlock(500, Material.rock).setUnlocalizedName("tutorialBlock");
advWorkBench = new BlockAdvWorkBench(501, Material.wood).setUnlocalizedName("advWorkBench");
//Block Registry
GameRegistry.registerBlock(tutorialBlock, modid + tutorialBlock.getUnlocalizedName()); //check this for errors as getUnlocalizedName2 is now a string
GameRegistry.registerBlock(advWorkBench, modid + advWorkBench.getUnlocalizedName());
//Block Names
LanguageRegistry.addName(tutorialBlock, "Tutorial Block");
LanguageRegistry.addName(advWorkBench, "Advanced Work Bench");
//Items
tutorialItem = new ItemTutorial(5000).setUnlocalizedName("tutorialItem");
ironString = new ItemGeneral(5001).setUnlocalizedName("ironString");
reinforcedStick = new ItemGeneral(5002).setUnlocalizedName("reinforcedStick");
//Item Names
LanguageRegistry.addName(tutorialItem, "Tutorial Item");
LanguageRegistry.addName(ironString, "Iron String");
LanguageRegistry.addName(reinforcedStick, "Reinforced Stick");
//Tool/Weapons
//Sets Tool Type;May add own separate file later if there are many of them
EnumToolMaterial REINFORCED = EnumHelper.addToolMaterial("REINFORCED", 3, 500, 15F, 3, 30);
reinforcedAxe = new ItemReinAxe(5003, REINFORCED).setUnlocalizedName("reinforcedAxe");
reinforcedHoe = new ItemReinHoe(5004, REINFORCED).setUnlocalizedName("reinforcedHoe");
reinforcedPickaxe = new ItemReinPickaxe(5005, REINFORCED).setUnlocalizedName("reinforcedPickaxe");
reinforcedSpade = new ItemReinSpade(5006, REINFORCED).setUnlocalizedName("reinforcedSpade");
reinforcedSword = new ItemReinSword(5007, REINFORCED).setUnlocalizedName("reinforcedSword");
recurveBow = new ItemRecurveBow (5008).setUnlocalizedName("recurveBow");
//Tool/Weapon Names
LanguageRegistry.addName(reinforcedAxe, "Reinforced Axe");
LanguageRegistry.addName(reinforcedHoe, "Reinforced Hoe");
LanguageRegistry.addName(reinforcedPickaxe, "Reinforced Pickaxe");
LanguageRegistry.addName(reinforcedSpade, "Reinforced Shovel");
LanguageRegistry.addName(reinforcedSword, "Reinforced Sword");
LanguageRegistry.addName(recurveBow, "Recurve Bow");
//Recipes
GOTWCrafting.addRecipes();
//GuiHandler
NetworkRegistry.instance().registerGuiHandler(this, guiHandlerGOTW);
}
}
package GOTW;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.BlockWorkbench;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.Icon;
import net.minecraft.world.World;
public class BlockAdvWorkBench extends Block
{
@SideOnly(Side.CLIENT)
private Icon field_94393_a;
@SideOnly(Side.CLIENT)
private Icon field_94392_b;
protected BlockAdvWorkBench(int par1, Material wood)
{
super(par1, wood);
this.setCreativeTab(CreativeTabs.tabDecorations);
}
@SideOnly(Side.CLIENT)
/**
* From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
*/
public Icon getIcon(int par1, int par2) {
return par1 == 0 ? this.field_94392_b : (par1 == 1 ? this.field_94393_a
: this.blockIcon);
}
@SideOnly(Side.CLIENT)
/**
* When this method is called, your block should register all the icons it needs with the given IconRegister. This
* is the only chance you get to register icons.
*/
public void registerIcons(IconRegister par1IconRegister)
{
this.blockIcon = par1IconRegister.registerIcon("GOTW:advWorkBenchSide");//Side
this.field_94393_a = par1IconRegister.registerIcon("GOTW:advWorkBenchTop");//Top
this.field_94392_b = par1IconRegister.registerIcon("GOTW:advWorkBenchBottom");//Bottom
}
/**
* Called upon block activation (right click on the block.)
*/
public boolean onBlockActivated(World var1, int var2, int var3, int var4, EntityPlayer player, int var6, float var7, float var8, float var9)
{
if (!player.isSneaking())
{
player.openGui(mod_GOTW.instance, 1, var1, var2, var3, var4);
return true;
}
else
{
return false;
}
}
}
package GOTW;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import cpw.mods.fml.common.network.IGuiHandler;
public class GuiHandlerGOTW 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 ContainerExtruder(player.inventory, (TileEntityExtruder) tile_entity);
case 1: return id == 1 && world.getBlockId(x, y, z) == mod_GOTW.advWorkBench.blockID ? new ContainerAdvBench(player.inventory, world, x, y, z) : null;
//case 2: return new ContainerSpiritTable(player.inventory, (world), x, y, z);
//case 3: return new ContainerTreeTrunk(player.inventory, (TileEntityTreeTrunk) tile_entity);
//case 4: return id == 4 && world.getBlockId(x, y, z) == MTJT.forge.blockID ? new ContainerForgeBench(player.inventory, world, x, y, z) : null;
//case 5: return new ContainerIceMachine(player.inventory, (TileEntityIceMachine) tile_entity);
//case 6: return new ContainerGemMachine(player.inventory, (TileEntityGemMachine) tile_entity);
//case 7: return id == 7 && world.getBlockId(x, y, z) == MTJT.builder.blockID ? new ContainerBlueprintTable(player.inventory, world, x, y, z) : null;
}
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 GuiExtruder(player.inventory, (TileEntityExtruder) tile_entity);
case 1: return id == 1 && world.getBlockId(x, y, z) == mod_GOTW.advWorkBench.blockID ? new GuiAdvBench(player.inventory, world, x, y, z) : null;
//case 2: return new GuiSpiritTable(player.inventory, (world), x, y, z);
//case 3: return new GuiTreeTrunk(player.inventory, (TileEntityTreeTrunk) tile_entity);
//case 4: return id == 4 && world.getBlockId(x, y, z) == MTJT.forge.blockID ? new GuiForgeCrafting(player.inventory, world, x, y, z) : null;
//case 5: return new GuiIceMachine(player.inventory, (TileEntityIceMachine) tile_entity);
//case 6: return new GuiGemMachine(player.inventory, (TileEntityGemMachine) tile_entity);
//case 7: return id == 7 && world.getBlockId(x, y, z) == MTJT.builder.blockID ? new BlueprintTableGui(player.inventory, world, x, y, z) : null;
}
return null;
}
}
package GOTW;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.AchievementList;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
public class SlotAdvBench extends Slot
{
/** The craft matrix inventory linked to this result slot. */
private final IInventory craftMatrix;
/** The player that is using the GUI where this slot resides. */
private EntityPlayer thePlayer;
/**
* The number of items that have been crafted so far. Gets passed to ItemStack.onCrafting before being reset.
*/
private int amountCrafted;
public SlotAdvBench(EntityPlayer par1EntityPlayer, IInventory par2IInventory, IInventory par3IInventory, int par4, int par5, int par6)
{
super(par3IInventory, par4, par5, par6);
this.thePlayer = par1EntityPlayer;
this.craftMatrix = par2IInventory;
}
/**
* Check if the stack is a valid item for this slot. Always true beside for the armor slots.
*/
public boolean isItemValid(ItemStack par1ItemStack)
{
return false;
}
/**
* Decrease the size of the stack in slot (first int arg) by the amount of the second int arg. Returns the new
* stack.
*/
public ItemStack decrStackSize(int par1)
{
if (this.getHasStack())
{
this.amountCrafted += Math.min(par1, this.getStack().stackSize);
}
return super.decrStackSize(par1);
}
/**
* the itemStack passed in is the output - ie, iron ingots, and pickaxes, not ore and wood. Typically increases an
* internal count then calls onCrafting(item).
*/
protected void onCrafting(ItemStack par1ItemStack, int par2)
{
this.amountCrafted += par2;
this.onCrafting(par1ItemStack);
}
/**
* the itemStack passed in is the output - ie, iron ingots, and pickaxes, not ore and wood.
*/
protected void onCrafting(ItemStack par1ItemStack)
{
par1ItemStack.onCrafting(this.thePlayer.worldObj, this.thePlayer, this.amountCrafted);
this.amountCrafted = 0;
if (par1ItemStack.itemID == Block.workbench.blockID)
{
this.thePlayer.addStat(AchievementList.buildWorkBench, 1);
}
else if (par1ItemStack.itemID == Item.pickaxeWood.itemID)
{
this.thePlayer.addStat(AchievementList.buildPickaxe, 1);
}
else if (par1ItemStack.itemID == Block.furnaceIdle.blockID)
{
this.thePlayer.addStat(AchievementList.buildFurnace, 1);
}
else if (par1ItemStack.itemID == Item.hoeWood.itemID)
{
this.thePlayer.addStat(AchievementList.buildHoe, 1);
}
else if (par1ItemStack.itemID == Item.bread.itemID)
{
this.thePlayer.addStat(AchievementList.makeBread, 1);
}
else if (par1ItemStack.itemID == Item.cake.itemID)
{
this.thePlayer.addStat(AchievementList.bakeCake, 1);
}
else if (par1ItemStack.itemID == Item.pickaxeStone.itemID)
{
this.thePlayer.addStat(AchievementList.buildBetterPickaxe, 1);
}
else if (par1ItemStack.itemID == Item.swordWood.itemID)
{
this.thePlayer.addStat(AchievementList.buildSword, 1);
}
else if (par1ItemStack.itemID == Block.enchantmentTable.blockID)
{
this.thePlayer.addStat(AchievementList.enchantments, 1);
}
else if (par1ItemStack.itemID == Block.bookShelf.blockID)
{
this.thePlayer.addStat(AchievementList.bookcase, 1);
}
}
public void onPickupFromSlot(EntityPlayer par1EntityPlayer, ItemStack par2ItemStack)
{
GameRegistry.onItemCrafted(par1EntityPlayer, par2ItemStack, craftMatrix);
this.onCrafting(par2ItemStack);
for (int var3 = 0; var3 < this.craftMatrix.getSizeInventory(); ++var3)
{
ItemStack var4 = this.craftMatrix.getStackInSlot(var3);
if (var4 != null)
{
this.craftMatrix.decrStackSize(var3, 1);
if (var4.getItem().hasContainerItem())
{
ItemStack var5 = var4.getItem().getContainerItemStack(var4);
if (var5.isItemStackDamageable() && var5.getItemDamage() > var5.getMaxDamage())
{
MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(thePlayer, var5));
var5 = null;
}
if (var5 != null && (!var4.getItem().doesContainerItemLeaveCraftingGrid(var4) || !this.thePlayer.inventory.addItemStackToInventory(var5)))
{
if (this.craftMatrix.getStackInSlot(var3) == null)
{
this.craftMatrix.setInventorySlotContents(var3, var5);
}
else
{
this.thePlayer.dropPlayerItem(var5);
}
}
}
}
}
}
}
My workbench won't open whenever I try opening it. Upon attempting to open it I get this error:
2013-06-09 17:54:45 [WARNING] [ForgeModLoader] A mod tried to open a gui on the server without being a NetworkMod
Can you look over my code to see what I did wrong?
@Mod(modid = mod_GOTW.modid, name = "Mod Name", version = "1.0")
@NetworkMod(clientSideRequired = true, serverSideRequired = false)
public class mod_GOTW
{
public static final String modid = "GOTW";
@Instance("mod_GOTW")
public static mod_GOTW instance;
private GuiHandlerGOTW guiHandlerGOTW = new GuiHandlerGOTW();
Look in your main class, this line here
@Mod(modid = mod_GOTW.modid, name = "Mod Name", version = "1.0")
doesnt match anything I have shown. Some people are soing their mods this way now, but it also makes it a bit more challenging to do GUI stuff because of how most people do their handlers. Look over my code again, it shows you exactly what I am talking about. If your modid does not match your @instance("modid") method, your gui will not open....
@Mod(modid = mod_GOTW.modid, name = "Mod Name", version = "1.0")
doesnt match anything I have shown. Some people are soing their mods this way now, but it also makes it a bit more challenging to do GUI stuff because of how most people do their handlers. Look over my code again, it shows you exactly what I am talking about. If your modid does not match your @instance("modid") method, your gui will not open....
Ah, okay. I got it to work now but the GUI is still messed up. I can't seem to move the x and y coordinates in the foreground layers of the GUI code, but I can move the background freely.
Not sure exactly what you mean....the gui boxes have to be made in a graphic editor like paint.net or photoshop, make the gui how you want with the boxes where you want and then move the slots to match in the code using the coordinates...not real hard, but time consuming for sure
Part one of the basic crafting table tutorial.....
this covers the mod class and container and crafting manager
Part two of the basic crafting table tutorial....
this covers the end of the crafting manager and recipe sorter, GUI class and GUI Handler
GUI Handler example
Find out how I generate....coolAlias...world structure generation and rotation tool...
Lets get started....
Container....
In the container we have this inside the constructor and its where we will make the first changes
As stated in the code the crafting matrix is made by ROWS and COLUMNS. so if you simply want to redesign the table keep in mind you can move the matrix just the same as any slot.
In the next method you will find this...
This is your output slot. It has coordinates that we can use to move the slot anywhere we want...in this example it is (0, 124, 35).
Next is the matrix....
Remember, it is rows and columns. The matrix is also using coordinates. And as I dont really know why, (i1 + l * 2) the 2 in this instance seems to work, and 4 seems to crash it. If anyone knows why please explain.
The next 2 are for inventory and player hotbar.
These are there for your inventories...
The next important method is the onContainerClosed...
The 8 in the loop is a multiple of the rows and columns...so if it were 3x5, the 8 would be a 15...or say 5x5, the 8 would be 25.
Next is this method here....the canInteractWith.
If you dont change this to your block, in this case (ContainerTutorial.ctutorial.blockID), it will not allow you to open and use you GUI...YOU MUST CHANGE THIS TO YOUR BLOCK
Now since you changed things in the container class a bit, you must also make changes elsewhere...
If you said recipe classes you're right...
Recipes
Recipe Sorter
Here you will need to change all the Shaped and Shapeless references, like the following example I use ShapedCTRecipes and ShapelessCTRecipes
In your Shaped recipe class you will want to change the methods match and checkMatch to reflect your rows and columns like so...
In your Shapeless class you will also want to reflect the change in the method matches like the following...
You will also need to make a few changes to your crafting manager as well.....
In the method CraftingManager(), you will want to replace that with what ever you named your manager..., this is mine..
So this recipe wont work now will it?...No because it has variables for 3 slots. We have 4 rows of 2 columns. Recipes are read from left to right. The first row in the grid will have 2 columns across, or 2 slots....and then repeat this 4 times...so or recipes should look like this...
Make them however you want, but keep in mind, its from left to right, rows and columns.....so in this case no more than 2 items 4 times.
You must also make sure that all recipes instances ShapedRecipes and ShapelessRecipes get changed to your custom classes.
Hope this helps you understand a bit more on how this works for changing the way the grid is shaped. You can also add extra or custom slots by adding custom slot classes. Some changes may even require custom inventory classes. I do not now how to make these, please dont ask me to explain them....
Find out how I generate....coolAlias...world structure generation and rotation tool...
All three of these tables with the grid sizes of 2x2 3x3 and 5x5 can be seen in the mod and they function as well. So if you have doubts, cant get them working or are just wondering how they look in game, stop by and check them out. About 75% of the code was written in Notepad++ but tested in Eclipse before doing anything else. Most of my modding is done at work as I dont have much time at home. Though as I said it is all tested prior to posting <at home> but should you spot any errors please respond and let me know. I dont want to hear, this dont work, or whats wrong with your code. This is all tested first before posting. So respond with this is my error and here is my log or I may not be able to help, if I can help at all. Now without any further adieu, here is the code for the 5x5 table....
Container
You will notice here in the constructor the table size is changed to the 5x5 and also the variables have changed, you can see how they are different from the 2x2 and standard 3x3 variables
And also near the bottom the variable 25 is for the full range of the grid, just like the 2x2 has a return of 4...5 times 5 is 25, and 2 times 2 is 4....this must be reflected or it will not work correctly, if at all.
Crafting manager
With this table, you can craft all your standard 3x3 recipes as well as anything up to 5x5 obviously. I put all my recipes in this class, but if you need, and absolutely must, I can tell you how to add them to your mod class
--------------------------------
--------------------------------
Recipe Sorter, shaped recipes and shapless recipes will all have errors if you are just copying and pasting. Please dont just copy and paste, you will not learn anything that way. And please change names accordingly to your mod, it will make more sense to you later, and help keep your mod in order for your mod. Like other tutorials that use terms like BlockTuorial, I would hope you change it to your block, and not leave it as tutorial.
Recipe Sorter
Shaped Recipes
Here you will notice in the methods matches and check matches the for ints have changed, they must match your grid size from the container, example this is a 5x5 so they must be 5, if it were 6x6 or 1x1 or whatever the size, they must match
Shapless Recipes
The same goes for this class too, the matches section must match your grid size....
Gui
You will notice here, as with the other GUI's some variables for size of the GUI have changed, please take note of this...
I may do one more if I can figure out how to make a 2x4 table....
Good luck and have fun
Source code for the 5x5 table, fully functioning and working 100%, there will be no help given if you drop this in mcp and cant get it to work. This works and is my entire source code for the better table mod....
Find out how I generate....coolAlias...world structure generation and rotation tool...
I copied your files and modified them to fit my mod(changed names)
But the gui doesn't open.(If you want to see my codes I'll happily post them)
Edit, yes I did forget something...please check the post again in the main class for the network registry. I am sorry I forgot that, I am doing this at work, and am quite tired from long midnight shifts....
Find out how I generate....coolAlias...world structure generation and rotation tool...
Well i understand you forgot something long midnight shifts at work isn't easy.
Anyway Here's my codes:
Main Class:
BlockPrepTable(The BlockWorkbench):
First this is a problem here (PrepTableGuiHandler = new GuiHandler();)
PrepTableGuiHandler should = PrepTableGuiHandler....and also you only need one GUI Handler for your mod, if you notice i have all my GUI ID in one handler and you can delete the commented code by the way, was just showing as an example
PrepTableGuiHandler:
Find out how I generate....coolAlias...world structure generation and rotation tool...
My $200* rig - http://pcpartpicker.com/b/IsU
Ok,so I got rid of PrepTableGuiHandler and used my first which was only for the furnace.
Yes I know I could delete the commented code but I just didn't bother
I changed it with your suggestion and it does work,and now I can finally see why it didn't before.
Thank you so much for that! You just ended my week long suffering of not understanding.
That is sweet,now I can finally start my next project.Thanks a lot!
Find out how I generate....coolAlias...world structure generation and rotation tool...
Thanks, I try to help the community as much as possible....
Find out how I generate....coolAlias...world structure generation and rotation tool...
Find out how I generate....coolAlias...world structure generation and rotation tool...
NetworkRegistry.instance().registerGuiHandler(this, MTcraftingManager);
It says The method registerGuiHandler(Object, IGuiHandler) in the type NetworkRegistry is not applicable for the arguments (MTcraftingManager, MTcraftingManager)
Find out how I generate....coolAlias...world structure generation and rotation tool...
Can you look over my code to see what I did wrong?
Thanks!
Look in your main class, this line here
doesnt match anything I have shown. Some people are soing their mods this way now, but it also makes it a bit more challenging to do GUI stuff because of how most people do their handlers. Look over my code again, it shows you exactly what I am talking about. If your modid does not match your @instance("modid") method, your gui will not open....
Find out how I generate....coolAlias...world structure generation and rotation tool...
Ah, okay. I got it to work now but the GUI is still messed up. I can't seem to move the x and y coordinates in the foreground layers of the GUI code, but I can move the background freely.
Find out how I generate....coolAlias...world structure generation and rotation tool...