But now I need help with point 5. I need to incorporate a slot for a dye. So how would I add the slot (into the container) and how to check if the dye AND the carving match a recipe without a new button? How would I output the result into the craftResult slot?
You should try find tutorials. I was hoping somebody else would answer or you'd find some help yourself because it's not the easiest to explain. Best example is to look at the crafting table's classes to see how they use the crafting slot.
Ok, I'll give you a brief explanation on how I would go about this, assuming that you've already setup your Container and TileEntity.
1. Adding the slots to your container. You wanna add 2 slots in total, one for your dye and one for your output. For this go into the constructor of your container and call addSlotToContainer(new Slot(IInventory inventoryIn, int index, int xPosition, int yPosition)). As the IInventory argument you wanna pass in your TileEntity.
2. Go into your TileEntity and implement ISidedInventory (You'll have to override a bunch of methods now, you probably wanna take a look at the vanilla furnace or my shelf)
3. Next you wanna create a public static int storing the size of your inventory (2) and a private ItemStack[] for storing the items. in the constructor you wanna initialize the array:inventory = new ItemStack[INVENTORY_SIZE];
4. I don't know how many different runes your wanna add but I would suggest creating a registry class for that. Add a method for adding a new recipe (This will take a ItemStack for the result, a ItemStack for the dye and a Boolean[][] for the carving), a method for returning an crafting result based on an ItemStack for the dye and an Boolean[][] (It will return null if it isn't a valid recipe), and maybe some other helper methods. (You could take a look at the FurnaceRecipes class for that)
5. I would store the grid in the TileEntity rather then in the GUI (I think it will be easier to work with). Of course you have to create getter and setter methods now ... (If you click a piece on the GUI now, you'll have to send a packet to the server, calling the setter method of your TileEntity)
6. It depends on you when you wanna check if there is a valid recipe. I've two ideas right now:
update: If you wanna override the update() method your TileEntity has to implement ITickable. This will check every tick if there is a valid recipe.
check when ever the dye / grid changes: This will probably be a bit more efficient ... You can use your setter method to check if there is a valid crafting recipe. And you can use the setInventorySlotContents(). method to check if there is a new dye placed in the inventory. Then you wanna check for a valid crafting as well. (Using your registry class)
7. If you detect a valid recipe you wanna use one of your dyes (and reset the carving grid?) and place the rune in the output slot.
DONE
Hope you can follow me ... and hope that I didn't forget something. If you have any problems with one of the steps, feel free to ask me (Or look for a tutorial)
2. Go into your TileEntity and implement ISidedInventory (You'll have to override a bunch of methods now, you probably wanna take a look at the vanilla furnace or my shelf)
Pretty sure you don't need to implement ISidedInventory unless you want your block to be able to transfer items between adjacent blocks, like a hopper.
Ok, I'll give you a brief explanation on how I would go about this, assuming that you've already setup your Container and TileEntity.
1. Adding the slots to your container. You wanna add 2 slots in total, one for your dye and one for your output. For this go into the constructor of your container and call addSlotToContainer(new Slot(IInventory inventoryIn, int index, int xPosition, int yPosition)). As the IInventory argument you wanna pass in your TileEntity.
2. Go into your TileEntity and implement ISidedInventory (You'll have to override a bunch of methods now, you probably wanna take a look at the vanilla furnace or my shelf)
3. Next you wanna create a public static int storing the size of your inventory (2) and a private ItemStack[] for storing the items. in the constructor you wanna initialize the array:inventory = new ItemStack[INVENTORY_SIZE];
4. I don't know how many different runes your wanna add but I would suggest creating a registry class for that. Add a method for adding a new recipe (This will take a ItemStack for the result, a ItemStack for the dye and a Boolean[][] for the carving), a method for returning an crafting result based on an ItemStack for the dye and an Boolean[][] (It will return null if it isn't a valid recipe), and maybe some other helper methods. (You could take a look at the FurnaceRecipes class for that)
5. I would store the grid in the TileEntity rather then in the GUI (I think it will be easier to work with). Of course you have to create getter and setter methods now ... (If you click a piece on the GUI now, you'll have to send a packet to the server, calling the setter method of your TileEntity)
6. It depends on you when you wanna check if there is a valid recipe. I've two ideas right now:
update: If you wanna override the update() method your TileEntity has to implement ITickable. This will check every tick if there is a valid recipe.
check when ever the dye / grid changes: This will probably be a bit more efficient ... You can use your setter method to check if there is a valid crafting recipe. And you can use the setInventorySlotContents(). method to check if there is a new dye placed in the inventory. Then you wanna check for a valid crafting as well. (Using your registry class)
7. If you detect a valid recipe you wanna use one of your dyes (and reset the carving grid?) and place the rune in the output slot.
DONE
Hope you can follow me ... and hope that I didn't forget something. If you have any problems with one of the steps, feel free to ask me (Or look for a tutorial)
Nice Greetings
TechMage66
Thanks for your reply! One question though. Afaik tileentities are used for blocks, but I need an item to open the GUI and not a block. What would I need to do in that case?
You can probably put most of the logic into the Container. Just remember the server doesn't have the GUI class, and you need to keep both sides synced using the methods provided.
You can probably put most of the logic into the Container. Just remember the server doesn't have the GUI class, and you need to keep both sides synced using the methods provided.
Yeah, I get that. But TechMage66 mentioned a tileentity for the container, which I cannot create since I want an item to open the GUI. In that case what would I pass on as an argument in the addSlotToContainer methods, where would I implement ISidedInventory and where would I store the grid if not in the tileentity?
Just don't use a tile entity. Instead of passing a tile entity as a parameter for the container, give it an inventory. Anything that extends IInventory can be used, so just give it an instance of an inventory to store items in.
As an example, have a look at this code I use for a custom crafting table. I create an instance of InventoryCrafting (same as a vanilla crafting table) and pass it to all of the slots used for the crafting within the GUI. If you look nearer the top of the class you can see my creation of the inventory. You may not want the same inventory, but have a look at the other vanilla inventories and pick one that works for you. If there's not one that works for you, then you can create your own by implementing IInventory.
To sum up, you don't need a tile entity, so you don't need to implement ISidedInventory at all. You can do most of your stuff within the Container, and even store things in the item's NBT if need be.
Just don't use a tile entity. Instead of passing a tile entity as a parameter for the container, give it an inventory. Anything that extends IInventory can be used, so just give it an instance of an inventory to store items in.
As an example, have a look at this code I use for a custom crafting table. I create an instance of InventoryCrafting (same as a vanilla crafting table) and pass it to all of the slots used for the crafting within the GUI. If you look nearer the top of the class you can see my creation of the inventory. You may not want the same inventory, but have a look at the other vanilla inventories and pick one that works for you. If there's not one that works for you, then you can create your own by implementing IInventory.
To sum up, you don't need a tile entity, so you don't need to implement ISidedInventory at all. You can do most of your stuff within the Container, and even store things in the item's NBT if need be.
Thanks for the reply. I passed InventoryPlayer as an argument.
So I got to creating a registry class for the recipes and I created a method that is supposed to add a recipe, but I have no idea how to store the values. I looked at furnaceRecipes and saw that it uses a hashmap, but then I looked at the smeltingResult method and got really confused. How should I go about this?
Nooo don't use InventoryPlayer, because that's used for the player's inventory! It's fine to use for slots in the bottom part of a GUI like a chest where you interact with the player's inventory, but for your new part which has the crafting inputs/outputs you need to use your own separate inventory!
You might not want to use the method that the furnace uses. It uses a hashmap because it's 1 ItemStack -> 1 ItemStack. You have a 2D array -> 1 ItemStack, so I suggest you do things a bit differently.
The vanilla crafting table stores a list of recipes which implement IRecipe (See CraftingManager class). If you have a look at a relevant implementation example, the ShapedRecipes class, you can see that there is an ItemStack array for the recipe ingredients and an ItemStack output. Creating your own class which implements IRecipe would probably be ideal for you, and you can then store many of them in a list in a similar manner to the vanilla crafting manager. So you can have an ItemStack output, and instead of an ItemStack array for inputs, have a 2D boolean array for your recipe.
Nooo don't use InventoryPlayer, because that's used for the player's inventory! It's fine to use for slots in the bottom part of a GUI like a chest where you interact with the player's inventory, but for your new part which has the crafting inputs/outputs you need to use your own separate inventory!
You might not want to use the method that the furnace uses. It uses a hashmap because it's 1 ItemStack -> 1 ItemStack. You have a 2D array -> 1 ItemStack, so I suggest you do things a bit differently.
The vanilla crafting table stores a list of recipes which implement IRecipe (See CraftingManager class). If you have a look at a relevant implementation example, the ShapedRecipes class, you can see that there is an ItemStack array for the recipe ingredients and an ItemStack output. Creating your own class which implements IRecipe would probably be ideal for you, and you can then store many of them in a list in a similar manner to the vanilla crafting manager. So you can have an ItemStack output, and instead of an ItemStack array for inputs, have a 2D boolean array for your recipe.
So would something like this work in my class that implemets IRecipe? :
private List<ItemStack> dye = new ArrayList<ItemStack>();
private List<boolean[][]> carvingGrid = new ArrayList<boolean[][]>();
private List<ItemStack> result = new ArrayList<ItemStack>();
private void addRecipe(boolean[][] carvingGrid, ItemStack dye, ItemStack result)
{
this.dye.add(dye);
this.carvingGrid.add(carvingGrid);
this.result.add(result);
}
And why exactly do I need to create my own inventory? If I just give an ID that is higher than 35 to the slot it should be fine.
It's just unnecessary and making things look more complicated. Plus the PlayerInventory from the player already contains the items of the player's actual inventory. You don't want to be adding you recipe items to new slots of the player's inventory. Just use a separate, new inventory which you can do what you want with. It just makes for cleaner and more understandable code too.
So you need a class that extends IRecipe to hold your recipe instances in. You then add your recipes to a list, so the list would be something like:
List<CarvingRecipe> recipes = new ArrayList<CarvingRecipe>();
You don't want all your results and inputs separate, otherwise it gets silly and more complicated.
It's just unnecessary and making things look more complicated. Plus the PlayerInventory from the player already contains the items of the player's actual inventory. You don't want to be adding you recipe items to new slots of the player's inventory. Just use a separate, new inventory which you can do what you want with. It just makes for cleaner and more understandable code too.
So I need to create two classes? One which extends IRecipe and another where I would add the recipes? In that case I see that in ShapedRecipes class there are arrays used for the itemStacks which means I would need to create an array for my 2D array which would make it a 3D array. How would I go about that?
I see that in ShapedRecipes class there are arrays used for the itemStacks which means I would need to create an array for my 2D array which would make it a 3D array. How would I go about that?
ShapedRecipes is a class that will hold 1 recipe. The CraftingManager will hold many of these in a list to hold all the shaped crafting recipes. You need your own version of a recipe class to hold a recipe, so it'll need a 2D array for the 'input' and an ItemStack for the crafting output.
ShapedRecipes is a class that will hold 1 recipe. The CraftingManager will hold many of these in a list to hold all the shaped crafting recipes. You need your own version of a recipe class to hold a recipe, so it'll need a 2D array for the 'input' and an ItemStack for the crafting output.
I mean, you don't have to use it, but the interface provides the basic methods required for interaction with a recipe. Plus, all of the vanilla recipes use it and it's a recognised way of anyone or any other mod recognising it as a recipe, which makes it compatible with other mods if need be.
There's nothing wrong with using it though. And having the matching in the recipe instead of the crafting manager means you could have a collection or recipes which work out their matches in different ways, but still be able to accommodate them all within the same manager class, because you're just called 1 method in the recipe. If you want an example, have a look at my own Hammer Crafting classes and how mine are implemented:
I mean, you don't have to use it, but the interface provides the basic methods required for interaction with a recipe. Plus, all of the vanilla recipes use it and it's a recognised way of anyone or any other mod recognising it as a recipe, which makes it compatible with other mods if need be.
There's nothing wrong with using it though. And having the matching in the recipe instead of the crafting manager means you could have a collection or recipes which work out their matches in different ways, but still be able to accommodate them all within the same manager class, because you're just called 1 method in the recipe. If you want an example, have a look at my own Hammer Crafting classes and how mine are implemented:
I see. But how would I code the matches() method then? Because I need to call the matches() method inside of the container class, but the method doesn't have the params I need (I need dye, boolean array).
This is strange I got it working just by changing the for loops.
http://pastebin.com/jStE4kQ0
But now I need help with point 5. I need to incorporate a slot for a dye. So how would I add the slot (into the container) and how to check if the dye AND the carving match a recipe without a new button? How would I output the result into the craftResult slot?
bump
bump
You should try find tutorials. I was hoping somebody else would answer or you'd find some help yourself because it's not the easiest to explain. Best example is to look at the crafting table's classes to see how they use the crafting slot.
Ok, I'll give you a brief explanation on how I would go about this, assuming that you've already setup your Container and TileEntity.
1. Adding the slots to your container. You wanna add 2 slots in total, one for your dye and one for your output. For this go into the constructor of your container and call addSlotToContainer(new Slot(IInventory inventoryIn, int index, int xPosition, int yPosition)). As the IInventory argument you wanna pass in your TileEntity.
2. Go into your TileEntity and implement ISidedInventory (You'll have to override a bunch of methods now, you probably wanna take a look at the vanilla furnace or my shelf)
3. Next you wanna create a public static int storing the size of your inventory (2) and a private ItemStack[] for storing the items. in the constructor you wanna initialize the array:inventory = new ItemStack[INVENTORY_SIZE];
4. I don't know how many different runes your wanna add but I would suggest creating a registry class for that. Add a method for adding a new recipe (This will take a ItemStack for the result, a ItemStack for the dye and a Boolean[][] for the carving), a method for returning an crafting result based on an ItemStack for the dye and an Boolean[][] (It will return null if it isn't a valid recipe), and maybe some other helper methods. (You could take a look at the FurnaceRecipes class for that)
5. I would store the grid in the TileEntity rather then in the GUI (I think it will be easier to work with). Of course you have to create getter and setter methods now ... (If you click a piece on the GUI now, you'll have to send a packet to the server, calling the setter method of your TileEntity)
6. It depends on you when you wanna check if there is a valid recipe. I've two ideas right now:
update: If you wanna override the update() method your TileEntity has to implement ITickable. This will check every tick if there is a valid recipe.
check when ever the dye / grid changes: This will probably be a bit more efficient ... You can use your setter method to check if there is a valid crafting recipe. And you can use the setInventorySlotContents(). method to check if there is a new dye placed in the inventory. Then you wanna check for a valid crafting as well. (Using your registry class)
7. If you detect a valid recipe you wanna use one of your dyes (and reset the carving grid?) and place the rune in the output slot.
DONE
Hope you can follow me ... and hope that I didn't forget something. If you have any problems with one of the steps, feel free to ask me (Or look for a tutorial)
Nice Greetings
TechMage66
Pretty sure you don't need to implement ISidedInventory unless you want your block to be able to transfer items between adjacent blocks, like a hopper.
Thanks for your reply! One question though. Afaik tileentities are used for blocks, but I need an item to open the GUI and not a block. What would I need to do in that case?
bump
You can probably put most of the logic into the Container. Just remember the server doesn't have the GUI class, and you need to keep both sides synced using the methods provided.
Yeah, I get that. But TechMage66 mentioned a tileentity for the container, which I cannot create since I want an item to open the GUI. In that case what would I pass on as an argument in the addSlotToContainer methods, where would I implement ISidedInventory and where would I store the grid if not in the tileentity?
Just don't use a tile entity. Instead of passing a tile entity as a parameter for the container, give it an inventory. Anything that extends IInventory can be used, so just give it an instance of an inventory to store items in.
As an example, have a look at this code I use for a custom crafting table. I create an instance of InventoryCrafting (same as a vanilla crafting table) and pass it to all of the slots used for the crafting within the GUI. If you look nearer the top of the class you can see my creation of the inventory. You may not want the same inventory, but have a look at the other vanilla inventories and pick one that works for you. If there's not one that works for you, then you can create your own by implementing IInventory.
To sum up, you don't need a tile entity, so you don't need to implement ISidedInventory at all. You can do most of your stuff within the Container, and even store things in the item's NBT if need be.
Thanks for the reply. I passed InventoryPlayer as an argument.
So I got to creating a registry class for the recipes and I created a method that is supposed to add a recipe, but I have no idea how to store the values. I looked at furnaceRecipes and saw that it uses a hashmap, but then I looked at the smeltingResult method and got really confused. How should I go about this?
Nooo don't use InventoryPlayer, because that's used for the player's inventory! It's fine to use for slots in the bottom part of a GUI like a chest where you interact with the player's inventory, but for your new part which has the crafting inputs/outputs you need to use your own separate inventory!
You might not want to use the method that the furnace uses. It uses a hashmap because it's 1 ItemStack -> 1 ItemStack. You have a 2D array -> 1 ItemStack, so I suggest you do things a bit differently.
The vanilla crafting table stores a list of recipes which implement IRecipe (See CraftingManager class). If you have a look at a relevant implementation example, the ShapedRecipes class, you can see that there is an ItemStack array for the recipe ingredients and an ItemStack output. Creating your own class which implements IRecipe would probably be ideal for you, and you can then store many of them in a list in a similar manner to the vanilla crafting manager. So you can have an ItemStack output, and instead of an ItemStack array for inputs, have a 2D boolean array for your recipe.
So would something like this work in my class that implemets IRecipe? :
And why exactly do I need to create my own inventory? If I just give an ID that is higher than 35 to the slot it should be fine.
So you need a class that extends IRecipe to hold your recipe instances in. You then add your recipes to a list, so the list would be something like:
You don't want all your results and inputs separate, otherwise it gets silly and more complicated.
It's just unnecessary and making things look more complicated. Plus the PlayerInventory from the player already contains the items of the player's actual inventory. You don't want to be adding you recipe items to new slots of the player's inventory. Just use a separate, new inventory which you can do what you want with. It just makes for cleaner and more understandable code too.
So I need to create two classes? One which extends IRecipe and another where I would add the recipes? In that case I see that in ShapedRecipes class there are arrays used for the itemStacks which means I would need to create an array for my 2D array which would make it a 3D array. How would I go about that?
ShapedRecipes is a class that will hold 1 recipe. The CraftingManager will hold many of these in a list to hold all the shaped crafting recipes. You need your own version of a recipe class to hold a recipe, so it'll need a 2D array for the 'input' and an ItemStack for the crafting output.
So would it look more like this? :
http://pastebin.com/ReLvKrer
I don't understand why I need to extend IRecipe though since I will be doing all of the 'matching' type methods in my crafting manager class anyway.
Yeah that looks good.
I mean, you don't have to use it, but the interface provides the basic methods required for interaction with a recipe. Plus, all of the vanilla recipes use it and it's a recognised way of anyone or any other mod recognising it as a recipe, which makes it compatible with other mods if need be.
There's nothing wrong with using it though. And having the matching in the recipe instead of the crafting manager means you could have a collection or recipes which work out their matches in different ways, but still be able to accommodate them all within the same manager class, because you're just called 1 method in the recipe. If you want an example, have a look at my own Hammer Crafting classes and how mine are implemented:
Crafting Manager
Crafting Recipe
I see. But how would I code the matches() method then? Because I need to call the matches() method inside of the container class, but the method doesn't have the params I need (I need dye, boolean array).