Jump to content

[1.6.4] Attaching NBT Data to Crafting Result Based on Recipe Items


Recommended Posts

Posted

Hi!

 

I guess the title is fairly self-explanatory, but I feel the need to elaborate so as to avoid any confusion. My question pretty much boils down to: "Is there a way to attach NBT data to the result of a vanilla crafting recipe based on the items used therein?" I've been trying to find something along these lines for the past two hours or so, but to no avail. (granted, I may have been trying out the wrong keywords...)

 

More elaboration: I have an item I call a Boon, and based on the items used in its crafting recipe, it can take on different 'jobs' so to speak. For example, using four Diamond Swords makes it a Boon with job: "Knight", or four bows for a Boon with job: "Archer".

 

Is there a way to do this using vanilla crafting or do I have to come up with my own method of crafting the item?

Posted

Hey there!

 

I had a similar problem in my mod, where I had multiple outcomes based on item combinations.

You can add NBT to an item stack and then pass it to the GameRegistry, and that NBT will be present when you craft it!

 

Here I used two metadata items, similar to how the color dyes work.

 

// iterate through all damage values for meat item

for(int i = 0; i < meatItem.getItemData().size(); i++) {

        // create item stack for crafting component

        ItemStack meatStack = new ItemStack(meatItem, 1, i);

        // iterate through all damage values for cheese item

        for(int j = 0; j < cheeseItem.getItemData().size(); j++) {

                // create item stack for crafting component

                ItemStack cheeseStack = new ItemStack(cheeseItem, 1, j);

 

                // this item stack will be the result with the NBT

                ItemStack sandwich = new ItemStack(sandwichItem, 1);

                // assign a new tag compound to the item stack

                sandwich.setTagCompound(new NBTTagCompound());

                // retrieve said compound for modifying

                NBTTagCompound tags = sandwich.stackTagCompound;

                // here you can set your NBT data on the item

                tags.setString("meat", meatStack.getDisplayName());

                tags.setByte("meatTier", (byte) ItemMeat.getTier(meatStack));

                tags.setString("cheese", cheeseStack.getDisplayName());

 

                // add the recipe to the GameRegistry

              GameRegistry.addShapelessRecipe(sandwich, new Object[] { breadSliceItem, breadSliceItem, meatStack, cheeseStack });

      }

}

 

Hope this helps! :) If I didn't explain anything well enough, please don't hesitate to ask!

Posted

Oooh! Thank you so much!

 

I was a bit confused at first but I think I understand what you're doing. *nods* Correct me if I'm wrong, but am I right in assuming that this code goes where I register my items/recipes?

 

Also, what you are doing is basically attaching the specific ingredients used to the resulting item as NBT data, right? I'm trying to reason out how to do this only AND ONLY for specific item combinations, while the recipe won't exist for others. Say, Three diamond swords plus one bow wouldn't work, but four diamond swords or two diamond swords and two bows would. *ponders*

Posted

So I was looking around, and I have no idea if the way I'm planning to do this will work. I'm not even sure exactly how to do it just yet, being a newbie to Java and all...

 

However, I have something in mind, and I may need some help implementing it. The fact that I want this thing to be configurable is beating me up. xD.

 

So, first, and obviously not done in the same class would be retrieving the number of player jobs that are configured. So that should be an integer. Say it's something like below. For now I'll set an arbitrary integer as its value.

 

public static final int NUMBER_OF_JOBS = 4;

 

Then, this is what I currently have written down on Eclipse after the above.:

 

public static void Init(){

     String[] jobNames = {
         //This is just arbitrary. In the future I'd like to pull these values from the config.
         "Knight", "Thief", "Mage", "Archer"
     }

     HashMap<String, Object> jobmap = new HashMap<String, Object>();
     for (int i = 0; i < NUMBER_OF_CLASSES; ++i){
  jobmap.put(jobKeys[i], *jobRecipes*);
     }

}

 

Where *jobRecipes* are to be the arrays of the "recipes" so to speak, and it's at this point that I am stuck because what I want to do next is a for loop with an if statement that checks the "recipes" against the hashmap key, and if the recipes match, sets the job NBT data to the same as the key...

 

I'm beginning to think it's worth the effort to create a custom block instead...

 

Posted

It seems you are trying to over complicate things just a tad. You know, just a teensy weensy bit.

 

After reading what you have said, it seems you are wanting to make it so certain jobs have certain recipes right? Well, if that's the case, time to harness the power of object orientated programming 8)

 

I would make a class called Job, and that class has all the basic stuff in it that every job will have. So an array of recipes etc.. Then, for each job, subclass Job (e.g. JobKnight, JobMage) and implement the job only stuff you need. You may need to make your own custom 'recipe' class as well that creates the special recipes you want.

 

Just my thoughts :)

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted

*nods*

 

The problem is, that's perfectly fine for hard-coded jobs, which, in hindsight, are the better and far nicer way to go at this point in time. However, one of the features on the feature-list my friend -- who'll be working on the project with me eventually -- and I compiled is the ability to create jobs through a config file.

 

Unless there's a way to automatically create a subclass from the input of a config file...

 

*shakes his feature-list for being ambitious*

Posted

Hmm... Well, you probably could do that xD

 

You could modify what I said to suit that. Just store all the information you would need in the config file (I would suggest creating your own way of handling this config file though) and then make the Job class more generic. You would make the Job class so that it has multiple parameters passed to it that are taken from the config - same for the custom recipe class.

 

A lot of helper methods would need writing, but its doable.

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted

Yeaah. I don't think the config that comes with forge has the functionality we need. That other config is still useful for the basic stuff though.

 

*nodnods* I'll get back to everyone if I manage to pull it off with the configurability, but for now, I'll do the easy way of defining jobs and then, when I have that done, I'll start working on making it all configurable.

 

Sidenote: I call the jobs classes in the mod, but because talking java, well, it would get really confusing really fast. xD.

Posted

*flails*

 

@Override
@SideOnly(Side.CLIENT)
public void registerIcons(IconRegister register){

	Icon[] iconArray = new Icon[2];

	//registering the two icons
	iconArray[0] = register.registerIcon(BCMInfo.ID + ":" + getUnlocalizedName());
	iconArray[1] = register.registerIcon(BCMInfo.ID + ":" + getUnlocalizedName() + "Active");

}

@Override
@SideOnly(Side.CLIENT)
public Icon getIcon(ItemStack itemstack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining){
	NBTTagCompound properties = itemstack.stackTagCompound;
	if (!properties.getString("Owner").isEmpty()){
		return iconArray[1];
	} else {
		return iconArray[0];
	}
}

 

I have a new problem. >:( I have no idea what I'm doing wrong, but Eclipse is telling me that where I return the iconArray[] that it cannot be resolved to a variable. *is confused*

Posted

That's because you are trying to access it from somewhere it isn't.

Try this:

        @SideOnly(Side.CLIENT(
        private Icon[] iconArray;

        @Override
@SideOnly(Side.CLIENT)
public void registerIcons(IconRegister register) {
                iconArray = new Icon[2];

	//registering the two icons
	iconArray[0] = register.registerIcon(BCMInfo.ID + ":" + getUnlocalizedName());
	iconArray[1] = register.registerIcon(BCMInfo.ID + ":" + getUnlocalizedName() + "Active");
}

@Override
@SideOnly(Side.CLIENT)
public Icon getIcon(ItemStack itemstack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining){
	NBTTagCompound properties = itemstack.stackTagCompound;
	if (!properties.getString("Owner").isEmpty()){
		return iconArray[1];
	} else {
		return iconArray[0];
	}
}

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted

I seem to be running headlong into problems all day today. I got the thing working... sort of.

 

http://pastebin.com/WCqYX6yC

 

That's the crash report.

 

The full item class is over here: https://github.com/Malkuthe/BattleClasses/blob/master/battleclassmod/items/BoonItem.java#L68

 

It may have to do with rendering the object in the player's hand. The reason I say that is because the item is perfectly fine in my inventory. However, another issue is that instead of displaying a sprite, minecraft displays the no-icon texture. Anyway, the one with the iconIndex[1] works just fine rendering in the hand, but as soon as the one with iconIndex[0] is selected, minecraft crashes. I'm not sure what's going on.

 

 

Posted

No, your crash has to do with your NBT tag/and or the return from getString("Owner") being null. How about you change your check to:

        @Override
@SideOnly(Side.CLIENT)
public Icon getIcon(ItemStack itemstack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining){
	NBTTagCompound properties = itemstack.stackTagCompound;
                if (properties != null) {
	        if (!properties.getString("Owner").equals("none")) {
		        return iconIndex[1];
	        } 
		return iconIndex[0];
                }
                return this.itemIcon;
}

 

And if that still crashes with a NullPointerException again, change:

if (!properties.getString("Owner").equals("none")) {

to:

if (properties.getString("Owner") != null && !properties.getString("Owner").equals("none")) {

 

Hope that helps :D

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Posted

Yaay! It works now! I had to do a little fiddling around with the code too. Turns out part of the reason for the crash was that I was just taking the item out of the creative inventory and therefore it had no NBT Tag Compound associated with it. I fixed that part with a quick modification to the onUpdate method and made it so that if the item tag compound of the item is null, to set "Owner" to "none" by default.

 

Thanks so much for the help! Sorry for the relentless questions. I'm trying to learn as much as I can as fast as I can. :D

Posted

Good job on that fix :) It probably isn't the most efficient, but it works right? :P

 

No worries mate, questions are the only way you can learn really.

 

Keep asking away!

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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