Posted June 14, 201411 yr 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?
June 14, 201411 yr 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!
June 14, 201411 yr Author 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*
June 15, 201411 yr Author 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. . 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...
June 15, 201411 yr 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 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.
June 15, 201411 yr Author *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*
June 15, 201411 yr Hmm... Well, you probably could do that 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.
June 15, 201411 yr Author 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. .
June 15, 201411 yr Author *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*
June 15, 201411 yr 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.
June 16, 201411 yr Author 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.
June 16, 201411 yr 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 We all stuff up sometimes... But I seem to be at the bottom of that pot.
June 16, 201411 yr Author 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.
June 16, 201411 yr Good job on that fix It probably isn't the most efficient, but it works right? 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.