Jump to content

Recommended Posts

Posted

Hi, I'm trying to make a furnace, but with three inputs, and one output. Basically a shapeless crafting recipe for 1-3 items, but it has to be smeleted to get an output. I used to have a custom furnace of my own back in 1.8.1B, but i can't decompile it. :(

Does anyone know how I would start on something like this? (I've tried combining crafting bench and furnace code, but it doesn't work... at all...)

  • Replies 59
  • Created
  • Last Reply

Top Posters In This Topic

Posted

If you google forge custom furnace you will find tutorials to create a 1 input furnace.

Also if you understand the TileEntity furnace you should get far :)

  Quote

If you guys dont get it.. then well ya.. try harder...

Posted

I recommend forgoing using furnace code entirely and coding it yourself. Use the ItemStack[] array to hold the ingredients. Compare that against possible recipes (if you want it shapeless, use either a list or simple check-for-item algorithms). If it has all the ingredients and all other conditions are met, call make() (or whatever you want to call it) and produce the product by setStackInSlot().

 

Sample code (do not copy and paste it, as it will not work for you):

public void make() {
	boolean consume = (this.par5Random.nextInt(16) == 0);
	if (consume) {
		for (int i = 0; i < ingredients.length; i++) {
			ReikaInventoryHelper.decrStack(i, this.inv);
		}
	}
	this.fuel++;
	//this.fuel += par5Random.nextInt(11)+5;
	if (this.fuel > this.CAPACITY)
		this.fuel = this.CAPACITY;
}

public boolean process() {
	if (this.fuel >= CAPACITY)
		return false;
	boolean allitems = this.getAllIngredients();
	if (this.inv[ingredients.length] == null)
		return false;
	if (this.inv[ingredients.length].itemID != Item.ghastTear.itemID) //need a ghast tear as fuel solvent
		return false;
	return allitems;
}

public boolean getAllIngredients() {
	for (int k = 0; k < ingredients.length; k++)
		if (this.inv[k] == null)
			return false;
	for (int i = 0; i < ingredients.length; i++) {
		if (!ReikaInventoryHelper.checkForItemStack(ingredients[i].itemID, ingredients[i].getItemDamage(), this.inv))
			return false;
	}
	return true;
}

Posted

Thank you for your help,  but for the moment, I'm not at the experience level to be able to code my own furnace. I was hoping to just modify a furnace instead of writing it all myself. :P

Basically I don't really have a clue how to use what you have suggested.

Posted
  On 5/4/2013 at 7:40 PM, Eastonium said:

Thank you for your help,  but for the moment, I'm not at the experience level to be able to code my own furnace. I was hoping to just modify a furnace instead of writing it all myself. :P

Basically I don't really have a clue how to use what you have suggested.

I can walk you through it.

Here are the things you will need to understand:

  • Arrays
  • ItemStacks
  • IInventory and Slot Operations (set and get)

Which of those is currently causing you trouble?

Posted
  On 5/4/2013 at 9:41 PM, Reika said:

  Quote

Thank you for your help,  but for the moment, I'm not at the experience level to be able to code my own furnace. I was hoping to just modify a furnace instead of writing it all myself. :P

Basically I don't really have a clue how to use what you have suggested.

I can walk you through it.

Here are the things you will need to understand:

  • Arrays
  • ItemStacks
  • IInventory and Slot Operations (set and get)

Which of those is currently causing you trouble?

 

Arrays, and IInventory and Slot Operations. I'm not good at those stuffs. ItemStacks I think I understand well enough.

Posted

OK. We shall start with arrays since those are fundamental Java and will be useful to you pretty much forever.

An array is basically a collection of variables organized into an ordered structure. Imagine it as a row of "slots" (not unlike inventory slots) and each slot can hold one variable of the appropriate type. For example, an array of 21 double values (declared as double[] array = new double[21]; ) would store 21 doubles, accessed via their positions, called indices (singular: index).

Worth noting is that the indices start at zero and progress up to (size-1), for a total of (size) slots. So if you tried accessing slot 21 (or greater) out of the above example (with a line like double b = array[21]; ) you would crash with an "Array Index out of Bounds" exception. Similarly, negative numbers for indices will crash with the same error.

 

Inventories in a TileEntity are treated as an array of ItemStacks. Notice in the furnace code (near the top), something like ItemStack[] furnaceItemStacks = new ItemStack[3];?

That is declaring the ItemStack array of size 3 (indices 0-2), with each corresponding to a slot, in this case ingredient, fuel, output. Similarly, a chest has a size 27 array for its 27 slots.

[continued]

 

Posted

[continued]

Now for IInventory. That is an interface you implement (notice how the TileEntityFurnace extends TileEntity implements IInventory), which will force you to include a few methods. The names of these are rather self-explanatory, names like getStackInSlot(int i), which gets the ItemStack in slot i of your inventory, and setStackInSlot(int i, ItemStack itemstack), which sets the stack in slot i to itemstack, overwriting its original contents. Others are similarly clear.

You can simply copy-and-paste these methods from the Furnace code if you like.

 

Now, notice how the furnace also has updateEntity(). This is called every tick (50 ms), and in the furnace is used to evaluate the contents of the inventory and act appropriately.

What you do next depends on what you plan to do with your furnace.

If you only plan on having a few recipes for this furnace, you can do is iterate through your inventory, and set a bunch of booleans depending on whether you come across various ingredient items (using getStackInSlot and loops). If all of them come out true (or if the right combination do), then you can call a smelt() method which uses setStackInSlot() as needed, adding to the output and subtracting from the input.

If you want a lot of different recipes, there is a shortcut, but it is a bit more complex. If you do intend to do this, I will explain it.

 

Also, you will need to interface with a container and a GUI if you want to use any nonstandard slot layout. Do you need assistance with this as well?

 

Also, to any admins: I apologize for making this two posts, but the forum system was not letting me post one long one.

Posted
  On 5/5/2013 at 1:06 AM, Reika said:

[continued]

Now for IInventory. That is an interface you implement (notice how the TileEntityFurnace extends TileEntity implements IInventory), which will force you to include a few methods. The names of these are rather self-explanatory, names like getStackInSlot(int i), which gets the ItemStack in slot i of your inventory, and setStackInSlot(int i, ItemStack itemstack), which sets the stack in slot i to itemstack, overwriting its original contents. Others are similarly clear.

You can simply copy-and-paste these methods from the Furnace code if you like.

 

Now, notice how the furnace also has updateEntity(). This is called every tick (50 ms), and in the furnace is used to evaluate the contents of the inventory and act appropriately.

What you do next depends on what you plan to do with your furnace.

If you only plan on having a few recipes for this furnace, you can do is iterate through your inventory, and set a bunch of booleans depending on whether you come across various ingredient items (using getStackInSlot and loops). If all of them come out true (or if the right combination do), then you can call a smelt() method which uses setStackInSlot() as needed, adding to the output and subtracting from the input.

If you want a lot of different recipes, there is a shortcut, but it is a bit more complex. If you do intend to do this, I will explain it.

 

Also, you will need to interface with a container and a GUI if you want to use any nonstandard slot layout. Do you need assistance with this as well?

 

Also, to any admins: I apologize for making this two posts, but the forum system was not letting me post one long one.

 

thanks so much for that. it really makes sense.  so do I put this all in my tile entity file? and yes. there will be lots of recipes.

Posted

All of that goes in your TileEntity, yes.

As for allowing lots of recipes, it is easier to use a Recipes file, much like the default Furnace does.

In your TileEntity's smelt function, use the following line to determine the output ItemStack:

ItemStack itemstack = RecipesClass.smelting().getSmeltingResult(inventory[0].itemID, inventory[1].itemID);

With whatever parameters you see fit (as per number of input items and metadata sensitivity). Here I assume no metadata and two ingredients.

 

And to test whether you have the right recipe, you can largely copy and paste code from the furnace, but the critical thing is this bit:

ItemStack itemstack = RecipesGrinder.smelting().getSmeltingResult(inventory[0].itemID, inventory[1].itemID);

if (itemstack == null)

return false;

This checks the result of the ingredients against the recipe file. If the result is null (no matching entry) it returns out and stops the smelting process from occurring.

 

You can largely copy the recipes file itself, but change the constructor (private RecipesClass() {}) to include your own recipes. You may need to change the number or type of parameters on the addSmelting method; using an ItemStack list is the best as it is dynamically sized.

 

Also, did you need aid in Container interface?

Posted

Sorry I haven't replied for a day. xD

I've been working on getting a basic furnace working, and I just got that done, so I'll finally get to incorporate this stuff you're telling me about.

I will need metadata for my recipes.. lots of it.

I'm guessing I won't be able to test the recipes with multiple stuff unless i have slots in the container to put them in so yes, i'll need help with that.

Thanks soo much. you've been a wonderful help.

Posted
  On 5/6/2013 at 4:34 AM, Eastonium said:

Sorry I haven't replied for a day. xD

I've been working on getting a basic furnace working, and I just got that done, so I'll finally get to incorporate this stuff you're telling me about.

I will need metadata for my recipes.. lots of it.

I'm guessing I won't be able to test the recipes with multiple stuff unless i have slots in the container to put them in so yes, i'll need help with that.

Thanks soo much. you've been a wonderful help.

If you use ItemStack arguments in the addSmelting, you can use the metadata property in them.

As for containers, they are rather simple. Have a look in the container for the vanilla furnace. Most of that you can ignore for now - just copy and paste it. Now, see where, in the constructor, it has entries addSlotToContainer? That is where it adds the actual slots (the part of the GUI that makes the items "snap" in place). The arguments are the relevant inventory (player or furnace), id (corresponding to the index in the inventory of the TileEntity (eg inventory[6] -> addSlot(--, 6, --, --)), and x and y 2D coordinates. Simply add as many of these as you like wherever you like.

Posted

Hi there,

 

Reika you helped a lot in explaining this, thanks for that! gave you a couple of +

 

So i'm also working on a 2 input furnace, but i still didn't get it to work yet, especially the part with addRecipe and such.

The container and GUI work fine.

 

These are the tileentity and recipe files:

 

TileEntityGemcutter

 

  Reveal hidden contents

 

 

GemcutterRecipes

 

  Reveal hidden contents

 

 

I am probably doing somethings completely wrong. Appreciate your help!

Posted
  On 5/6/2013 at 6:29 AM, Reika said:

  Quote

Sorry I haven't replied for a day. xD

I've been working on getting a basic furnace working, and I just got that done, so I'll finally get to incorporate this stuff you're telling me about.

I will need metadata for my recipes.. lots of it.

I'm guessing I won't be able to test the recipes with multiple stuff unless i have slots in the container to put them in so yes, i'll need help with that.

Thanks soo much. you've been a wonderful help.

If you use ItemStack arguments in the addSmelting, you can use the metadata property in them.

As for containers, they are rather simple. Have a look in the container for the vanilla furnace. Most of that you can ignore for now - just copy and paste it. Now, see where, in the constructor, it has entries addSlotToContainer? That is where it adds the actual slots (the part of the GUI that makes the items "snap" in place). The arguments are the relevant inventory (player or furnace), id (corresponding to the index in the inventory of the TileEntity (eg inventory[6] -> addSlot(--, 6, --, --)), and x and y 2D coordinates. Simply add as many of these as you like wherever you like.

 

Alright, I have 3 input slots now, and they work for holding items.

I've been looking at the TileEntityClass and Recipe Class, and I'm seeing a lot of methods that involve the recipe stuff and making the recipes, and checking if it's valid and stuff, and I know I'm going to have to change that stuff, but for now... um... let me put it a different way.

In the TileEntityClass file, I think All I would need to edit is the canSmelt and smeltItem Functions, and in the RecipeClass File, the addSmelting (the one with metadata) and getSmeltingResult Functions.

How would I go about making these work for my furnace? And will I need to add anything extra? And how do I call on the multiple slots to use them ass the array for the possible ingredients?

Posted
  On 5/7/2013 at 2:03 AM, Eastonium said:

Alright, I have 3 input slots now, and they work for holding items.

I've been looking at the TileEntityClass and Recipe Class, and I'm seeing a lot of methods that involve the recipe stuff and making the recipes, and checking if it's valid and stuff, and I know I'm going to have to change that stuff, but for now... um... let me put it a different way.

In the TileEntityClass file, I think All I would need to edit is the canSmelt and smeltItem Functions, and in the RecipeClass File, the addSmelting (the one with metadata) and getSmeltingResult Functions.

How would I go about making these work for my furnace? And will I need to add anything extra? And how do I call on the multiple slots to use them ass the array for the possible ingredients?

You hardcode your recipes directly into the Recipes class, in the constructor. Basically call addSmelting a bunch of times, with arguments you choose and design. If you use ItemStacks, like addSmelting(is1, is2...), you can fetch IDs, metadata, and NBT as needed.

You see where the canSmelt checks if recipe(inputs) != null? That is how it knows if it is a valid recipe.

Posted
  On 5/7/2013 at 9:20 AM, OwnAgePau said:

Could any of you help me?

 

Create your own thread mate, just take the post u made above and make a new thread :)

That way we can focus on you alone there and not mix up problems :)

 

When you create your new thread remember to post code at www.pastebin.com

And set syntax highligthning to Java - this way reading youre code will be super easy = faster help <3

  Quote

If you guys dont get it.. then well ya.. try harder...

Posted
  On 5/7/2013 at 3:40 AM, Reika said:

You hardcode your recipes directly into the Recipes class, in the constructor. Basically call addSmelting a bunch of times, with arguments you choose and design. If you use ItemStacks, like addSmelting(is1, is2...), you can fetch IDs, metadata, and NBT as needed.

You see where the canSmelt checks if recipe(inputs) != null? That is how it knows if it is a valid recipe.

 

Ok, So I modified my TileEntityClass, and I don't think I have to do anything more with it, Hopefully... Here is the part I modified:

http://pastebin.com/V70LJ1K5

And in the Recipes File, My brain likes to twist into a pretzel.

There's something like "private HashMap<List<Integer>, Float> metaExperience = new HashMap<List<Integer>, Float>();" that woks with the metadata recipes and Experience, and I have no Idea how to use those. I know I probably need one, but how to implement it is the question...

Along with that, I made this:

public void addSmelting(ItemStack ingredient1, ItemStack ingredient2, ItemStack ingredient3, ItemStack Result, float experience)

    {

   

    }

But since I don't know what that other HashMap thing is I have no Idea what to put in here... :P

Posted
  On 5/7/2013 at 3:08 PM, Eastonium said:

Ok, So I modified my TileEntityClass, and I don't think I have to do anything more with it, Hopefully... Here is the part I modified:

http://pastebin.com/V70LJ1K5

And in the Recipes File, My brain likes to twist into a pretzel.

There's something like "private HashMap<List<Integer>, Float> metaExperience = new HashMap<List<Integer>, Float>();" that woks with the metadata recipes and Experience, and I have no Idea how to use those. I know I probably need one, but how to implement it is the question...

Along with that, I made this:

public void addSmelting(ItemStack ingredient1, ItemStack ingredient2, ItemStack ingredient3, ItemStack Result, float experience)

    {

   

    }

But since I don't know what that other HashMap thing is I have no Idea what to put in here... :P

Worth noting before I start is that I have never seen the class MaskForgeRecipes before and if it uses a different structural layout than I am familiar with, my advice may be somewhat inaccurate.

 

Anyways, a hashmap is just a list of objects with a given "key", that is an address. For example, if you declared HashMap map = new HashMap() then added map.put(new ItemStack(Item.diamond.itemID, 1, 0), Block.dirt.blockID), then there would be an object (in this case the ID of a dirt block) stored with the key of a diamond item ID. So if you were to call map.get(Item.diamond.itemID), you would get Block.dirt.blockID. What the hashmap in your recipes file is doing is storing a more complicated structure of this, using a list (are you familiar with Java lists?) of Items as the key, and the output as the object (also a pair of objects, one float experience value and one itemstack).

Posted
  On 5/8/2013 at 9:02 PM, Reika said:

Worth noting before I start is that I have never seen the class MaskForgeRecipes before and if it uses a different structural layout than I am familiar with, my advice may be somewhat inaccurate.

 

Anyways, a hashmap is just a list of objects with a given "key", that is an address. For example, if you declared HashMap map = new HashMap() then added map.put(new ItemStack(Item.diamond.itemID, 1, 0), Block.dirt.blockID), then there would be an object (in this case the ID of a dirt block) stored with the key of a diamond item ID. So if you were to call map.get(Item.diamond.itemID), you would get Block.dirt.blockID. What the hashmap in your recipes file is doing is storing a more complicated structure of this, using a list (are you familiar with Java lists?) of Items as the key, and the output as the object (also a pair of objects, one float experience value and one itemstack).

My furnace's name is "MaskForge" so that's why it has that name. It's basically the same as the FurnaceRecipes file.

So should I use a HashMap for my addSmeling method? or use what I attemped to make? or an array? If i'm correct, it can be done any of those ways. Thanks again for all the help.

Posted
  On 5/8/2013 at 11:47 PM, Eastonium said:

My furnace's name is "MaskForge" so that's why it has that name. It's basically the same as the FurnaceRecipes file.

So should I use a HashMap for my addSmeling method? or use what I attemped to make? or an array? If i'm correct, it can be done any of those ways. Thanks again for all the help.

Use the HashMap. The current key format is likely a pair of numbers (ID and metadata). Change that to use a few (dependent on ingredient count) ItemStacks instead, and then use Map.put((ItemStack arguments), ItemStack output).

Posted
  On 5/10/2013 at 6:29 PM, Reika said:

Use the HashMap. The current key format is likely a pair of numbers (ID and metadata). Change that to use a few (dependent on ingredient count) ItemStacks instead, and then use Map.put((ItemStack arguments), ItemStack output).

 

So, I use something like ((returnItemStack)ingredient1ItemStack, ingredient2ItemStack, ingredient3ItemStack) with the return items stack thing thing i'm using to find the recipe? And the part i'm not getting is how to connect the ingredients for the recipe to the slots in the furnace.

Posted

You connect the ingredients with array indices. Look again at the canSmelt() function. See the references to inventory[a], where a is an integer? Those are checking the specific slots in the inventory (which, as per your container file, relate to specific item "positions" in the GUI).

Posted
  On 5/12/2013 at 8:13 AM, Reika said:

You connect the ingredients with array indices. Look again at the canSmelt() function. See the references to inventory[a], where a is an integer? Those are checking the specific slots in the inventory (which, as per your container file, relate to specific item "positions" in the GUI).

 

Sorry I haven't replied. So I am not getting this... :P I don't know if I'm trying to make it more complicated than it needs to be, but I thought for a shapeless recipe I have to use an array or something, so I'm utterly confused.

Guest
This topic is now closed to further replies.

Announcements




×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.