    001    package net.minecraftforge.oredict;
    002
    003    import java.util.ArrayList;
    004    import java.util.HashMap;
    005
    006    import net.minecraft.src.Block;
    007    import net.minecraft.src.IRecipe;
    008    import net.minecraft.src.InventoryCrafting;
    009    import net.minecraft.src.Item;
    010    import net.minecraft.src.ItemStack;
    011    import net.minecraft.src.ShapedRecipes;
    012    import net.minecraft.src.World;
    013
    014    public class ShapedOreRecipe implements IRecipe
    015    {
    016        //Added in for future ease of change, but hard coded for now.
    017        private static final int MAX_CRAFT_GRID_WIDTH = 3;
    018        private static final int MAX_CRAFT_GRID_HEIGHT = 3;
    019
    020        private ItemStack output = null;
    021        private Object[] input = null;
    022        private int width = 0;
    023        private int height = 0;
    024        private boolean mirrored = true;
    025
    026        public ShapedOreRecipe(Block     result, Object... recipe){ this(new ItemStack(result), recipe); }
    027        public ShapedOreRecipe(Item      result, Object... recipe){ this(new ItemStack(result), recipe); }
    028        public ShapedOreRecipe(ItemStack result, Object... recipe)
    029        {
    030            output = result.copy();
    031
    032            String shape = "";
    033            int idx = 0;
    034
    035            if (recipe[idx] instanceof Boolean)
    036            {
    037                mirrored = (Boolean)recipe[idx];
    038                if (recipe[idx+1] instanceof Object[])
    039                {
    040                    recipe = (Object[])recipe[idx+1];
    041                }
    042                else
    043                {
    044                    idx = 1;
    045                }
    046            }
    047
    048            if (recipe[idx] instanceof String[])
    049            {
    050                String[] parts = ((String[])recipe[idx++]);
    051
    052                for (String s : parts)
    053                {
    054                    width = s.length();
    055                    shape += s;
    056                }
    057
    058                height = parts.length;
    059            }
    060            else
    061            {
    062                while (recipe[idx] instanceof String)
    063                {
    064                    String s = (String)recipe[idx++];
    065                    shape += s;
    066                    width = s.length();
    067                    height++;
    068                }
    069            }
    070
    071            if (width * height != shape.length())
    072            {
    073                String ret = "Invalid shaped ore recipe: ";
    074                for (Object tmp :  recipe)
    075                {
    076                    ret += tmp + ", ";
    077                }
    078                ret += output;
    079                throw new RuntimeException(ret);
    080            }
    081
    082            HashMap<Character, Object> itemMap = new HashMap<Character, Object>();
    083
    084            for (; idx < recipe.length; idx += 2)
    085            {
    086                Character chr = (Character)recipe[idx];
    087                Object in = recipe[idx + 1];
    088                Object val = null;
    089
    090                if (in instanceof ItemStack)
    091                {
    092                    itemMap.put(chr, ((ItemStack)in).copy());
    093                }
    094                else if (in instanceof Item)
    095                {
    096                    itemMap.put(chr, new ItemStack((Item)in));
    097                }
    098                else if (in instanceof Block)
    099                {
    100                    itemMap.put(chr, new ItemStack((Block)in, 1, -1));
    101                }
    102                else if (in instanceof String)
    103                {
    104                    itemMap.put(chr, OreDictionary.getOres((String)in));
    105                }
    106                else
    107                {
    108                    String ret = "Invalid shaped ore recipe: ";
    109                    for (Object tmp :  recipe)
    110                    {
    111                        ret += tmp + ", ";
    112                    }
    113                    ret += output;
    114                    throw new RuntimeException(ret);
    115                }
    116            }
    117
    118            input = new Object[width * height];
    119            int x = 0;
    120            for (char chr : shape.toCharArray())
    121            {
    122                input[x++] = itemMap.get(chr);
    123            }
    124        }
    125
    126        @Override
    127        public ItemStack getCraftingResult(InventoryCrafting var1){ return output.copy(); }
    128
    129        @Override
    130        public int getRecipeSize(){ return input.length; }
    131
    132        @Override
    133        public ItemStack getRecipeOutput(){ return output; }
    134
    135        @Override
    136        public boolean matches(InventoryCrafting inv, World world)
    137        {
    138            for (int x = 0; x <= MAX_CRAFT_GRID_WIDTH - width; x++)
    139            {
    140                for (int y = 0; y <= MAX_CRAFT_GRID_HEIGHT - height; ++y)
    141                {
    142                    if (checkMatch(inv, x, y, true))
    143                    {
    144                        return true;
    145                    }
    146
    147                    if (mirrored && checkMatch(inv, x, y, false))
    148                    {
    149                        return true;
    150                    }
    151                }
    152            }
    153
    154            return false;
    155        }
    156
    157        private boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirror)
    158        {
    159            for (int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++)
    160            {
    161                for (int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++)
    162                {
    163                    int subX = x - startX;
    164                    int subY = y - startY;
    165                    Object target = null;
    166
    167                    if (subX >= 0 && subY >= 0 && subX < width && subY < height)
    168                    {
    169                        if (mirror)
    170                        {
    171                            target = input[width - subX - 1 + subY * width];
    172                        }
    173                        else
    174                        {
    175                            target = input[subX + subY * width];
    176                        }
    177                    }
    178
    179                    ItemStack slot = inv.getStackInRowAndColumn(x, y);
    180
    181                    if (target instanceof ItemStack)
    182                    {
    183                        if (!checkItemEquals((ItemStack)target, slot))
    184                        {
    185                            return false;
    186                        }
    187                    }
    188                    else if (target instanceof ArrayList)
    189                    {
    190                        boolean matched = false;
    191
    192                        for (ItemStack item : (ArrayList<ItemStack>)target)
    193                        {
    194                            matched = matched || checkItemEquals(item, slot);
    195                        }
    196
    197                        if (!matched)
    198                        {
    199                            return false;
    200                        }
    201                    }
    202                    else if (target == null && slot != null)
    203                    {
    204                        return false;
    205                    }
    206                }
    207            }
    208
    209            return true;
    210        }
    211
    212        private boolean checkItemEquals(ItemStack target, ItemStack input)
    213        {
    214            if (input == null && target != null || input != null && target == null)
    215            {
    216                return false;
    217            }
    218            return (target.itemID == input.itemID && (target.getItemDamage() == -1 || target.getItemDamage() == input.getItemDamage()));
    219        }
    220
    221        public ShapedOreRecipe setMirrored(boolean mirror)
    222        {
    223            mirrored = mirror;
    224            return this;
    225        }
    226    }