Recipes and Durability

Discussion in 'Plugin Development' started by MucTweezer, Jun 7, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    MucTweezer

    Hey all,

    I'm relatively new at developing Bukkit plugins. My friends and I run a personal server and I've taken it upon myself to develop the plugins we need for our small group. I've done some java development quite a few years ago, but it's been a while.

    So on to the meat of the topic.

    So I'm sure someone must have come across this before, but I haven't been able to find anything else on it. I'm trying to develop some simple recipes for repairing items. For example, I want to add a crafting table recipe to allow a single diamond pick (that, as a practical matter, has suffered durability damage) to be combined with a single diamond to produce a new diamond pick (that has suffered no durability damage). Using the ShapelessRecipe class, I figure this should be rather simple:

    Code:
    ShapelessRecipe tempRecipe = new ShapelessRecipe(new ItemStack(Material.DIAMOND_PICKAXE, 1));
    tempRecipe.addIngredient(Material.DIAMOND_PICKAXE);
    tempRecipe.addIngredient(Material.DIAMOND);
    getServer().addRecipe(tempRecipe);
    However, when I test this recipe, it only functions if the diamond pick I use as the ingredient has no durability damage; obviously this doesn't function as a repairing recipe. I'm fairly confident that I could get around this problem using CraftItemEvent or PrepareItemCraftEvent, however, I'm wondering if this same issur occurs for anyone else and/or if anyone has any advice on how I might get ShapelessRecipe to ignore durability for ingredients.

    Sorry for the load of text! Any help would be much appreciated.
     
  2. Offline

    monster860

    Doing something like this is very difficult, and requires calling non-API functions. Here you go, though, this is the code.

    I have looked through the code of Bukkit. The Server implementation adds recipes through net.minecraft.server.CraftingManager.registerShapelessRecipe(whateverparametersareneeded). Apparently, since it is possible to combine broken tools, I looked in the net.minecraft.server CraftingManager. There is a CraftingRecipe class, where it might be possible to extend it and extend all the required methods. Here is an overview:

    public ShaplessRecipe toBukkitRecipe(); Make sure it returns a CraftShapelessRecipe, not a regular ShapelessRecipe.

    public net.minecraft.ItemStack b(); Returns the result of the recipe.

    public boolean a(net.minecraft.server.InventoryCrafting); Returns if the recipe is the correct recipe.

    public net.minecraft.server.ItemStack b(net.minecraft.server.InventoryCrafting); Just do return b().cloneItemStack();.

    public int a(); Returns the number of ingredients (Optimization?)

    One more thing before I get to the code, make sure you replace bukkit.jar in the build path with craftbukkit.jar. The code has some non-api methods that exist in the actual server implementation.

    and finally, the code, I didn't test this.

    Code:
    import net.minecraft.server.*;
    import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe;
     
    public class RecipeRepairDiamondPick implements CraftingRecipe {
        private final ItemStack result = new ItemStack(ITEM.DIAMOND_PICKAXE);
     
        public RecipeRepairDiamondPick() { }
     
        public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe() {
            CraftShapelessRecipe result = new CraftShapelessRecipe(org.bukkit.inventory.ItemStack(org.bukkit.Material.DIAMOND_PICKAXE));
            result.addIngredient(org.bukkit.Material.DIAMOND_PICKAXE);
            result.addIngredient(org.bukkit.Material.DIAMOND);
            return result;
        }
     
        public ItemStack b() {
            return result;
        }
     
        public boolean a(InventoryCrafting inventorycrafting) {
            ArrayList arraylist = new ArrayList();
            arrayList.add(new ItemStack(Block.DIAMOND_PICKAXE));
            arrayList.add(new ItemStack(Block.DIAMOND));
     
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    ItemStack itemstack = inventorycrafting.b(j, i);
     
                    if (itemstack != null) {
                        boolean flag = false;
                        Iterator iterator = arraylist.iterator();
     
                        while (iterator.hasNext()) {
                            ItemStack itemstack1 = (ItemStack)iterator.next();
     
                            if (itemstack.id == itemstack1.id) {
                                flag = true;
                                arraylist.remove(itemstack1);
                                break;
                            }
                        }
     
                        if (!flag) {
                            return false;
                        }
                    }
                }
            }
     
            return arraylist.isEmpty();
     
        }
     
        public ItemStack b(InventoryCrafting inventorycrafting) {
            return this.result.cloneItemStack();
        }
     
        public int a() { return 2; }
    }
    I didn't use an IDE, so there may be errors :p.

    And then, to add it:
    Code:
    net.minecraft.server.CraftingManager.getInstance().getRecipes().add(new RecipeRepairDiamondPick());
    If this doesn't work, then I don't think anything else will.
     
  3. Offline

    MucTweezer

    Thanks monster. Very comprehensive. My current work-around is to have a "forge" block that will use a diamond from the inventory of a player to repair the diamond pick in their hand when it is right clicked. It would still be fun to get a real handle on the recipe system though by going into the non-API side as you suggest.

    I haven't worked with any of the non-API methods. I guess I have some studying and research to do; very exciting.

    Quick question: is there documentation somewhere for the non-API methods that I could poke around? I could always reverse engineer what they're doing, and perhaps I should (for my own personal development as a programmer), but it would save me some effort in the short term if there was documentation.
     
  4. Offline

    monster860

    No, there isn't documentation. I figured it out by using the java decompiler, and reverse-engineering it. I just looked at ShapelessRecipes and made some guesses of what each method means by looking at the code of the method.
     
    MucTweezer likes this.
  5. Offline

    MucTweezer

    Okay, thanks. I guess that means I know what I need to do to move foward. :)
     
  6. it wont work because you forgot an missing )
    :p
     
  7. Offline

    MucTweezer

    I did some poking around and have found the source code for CraftBukkit is available at:
    https://github.com/Bukkit/CraftBukkit

    It's not documentation, but it saves me the effort of decompiling.

    Very fascinating stuff. I can see how this is working and I can see how the changes you've made should correct the issue.
     
  8. Offline

    monster860

    Just so you know, the net.minecraft.server part of the non-API area is half obfuscated. I guess the craftbukkit developers just wanted to leave as much of the code as possible alone... but not deobfuscate the classnames to prevent version problems so that it is possible to not spend the trouble of updating the modded part. I'm guessing they were taking guesses about what classes were modified in the official relesases?
    Grammar fail. A missing, not AN missing. :p
    Can you even read? I DIDN'T USE AN IDE!!!!! :p
     
  9. Offline

    aPandaification

    This made me laugh - I don't think I am ever excited to read tons of api lol
     
  10. All these codes for something so simple... data value -1 :) Setting it to that will accept *any* data/damage/durability value and you can place any damaged diamond pickaxe.

    If you just want to add recipes for your server, you could use my plugin http://dev.bukkit.org/server-mods/recipemanager/ :p
     
    MucTweezer likes this.
  11. Offline

    MucTweezer

    Haha, now you're making us look like keeners :p

    But yes, that worked flawlessly. Well played, sir.
     
Thread Status:
Not open for further replies.

Share This Page