package cn.liutils.crafting; import java.io.File; import java.util.HashMap; import java.util.Map; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraftforge.oredict.OreDictionary; import org.apache.commons.io.IOUtils; import cn.liutils.core.LIUtils; import cn.liutils.util.generic.DebugUtils; import cn.liutils.util.generic.RegistryUtils; /** * @author EAirPeter, WeAthFolD */ public class RecipeRegistry { /** * This should only be visited for debug purpose. */ public final Map<String, Object> nameMapping = new HashMap(); public RecipeRegistry() { registerRecipeType("shaped", ShapedOreRegistry.INSTANCE); registerRecipeType("shaped_s", ShapedOreRegistry.INSTANCE); registerRecipeType("shapeless", ShapelessOreRegistry.INSTANCE); registerRecipeType("smelting", SmeltingRegistry.INSTANCE); } /** * Map a custom string specified in the recipe file to be a specific type of object. * The object can be an Item, a Block or a String (in oreDict). */ public void map(String key, Object obj) { if(!(obj instanceof Item) && !(obj instanceof Block) && !(obj instanceof String)) throw new RuntimeException("Invalid object to map " + key + "=>" + obj); nameMapping.put(key, obj); } private Object getNamedObject(String key) { if(key.equals("nil")) return null; Object o = nameMapping.get(key); if(o != null) return o; if(OreDictionary.doesOreNameExist(key)) return key; if(Item.itemRegistry.containsKey(key)) return Item.itemRegistry.getObject(key); throw new RuntimeException("Registry object " + key + " doesn't exist"); } private Object getRegistryObject(ParsedRecipeElement element) { Object o = getNamedObject(element.name); if(o == null) return o; if(o instanceof Item) { return new ItemStack((Item) o, element.amount, element.data); } else if(o instanceof Block) { return new ItemStack((Block) o, element.amount, element.data); } else { return (String) o; } } private ItemStack getOutput(ParsedRecipeElement element) { Object o = getNamedObject(element.name); if(o == null) throw new RuntimeException("Registry object " + element.name + " can't be nil"); if(o instanceof Item) { return new ItemStack((Item) o, element.amount, element.data); } else if(o instanceof Block) { return new ItemStack((Block) o, element.amount, element.data); } else { return OreDictionary.getOres(element.name).get(0); } } /** * Assign a registry to the type given * @param type The type * @param registry The registry */ public void registerRecipeType(String type, IRecipeRegistry registry) { if (map.containsKey(type)) throw new IllegalArgumentException("Recipe type \"" + type + "\" exists"); map.put(type, registry); } /** * Add all recipes from a file. The recipe's type must be registered before. * @param path The path of the file containing recipes */ public void addRecipeFromFile(String path) { addRecipeFromFile(new File(path)); } /** * Add all recipes from a file. The recipe's type must be registered before. * @param file The file containing recipes */ public void addRecipeFromFile(File file) { RecipeParser parser = null; try { parser = new RecipeParser(file); addRecipe(parser); } catch (Throwable e) { LIUtils.log.error("Failed to load recipes from file: " + file, e); } finally { parser.close(); } } public void addRecipeFromResourceLocation(ResourceLocation src) { try { addRecipeFromString(IOUtils.toString(RegistryUtils.getResourceStream(src))); } catch(Throwable e) { LIUtils.log.error("Failed to load recipes from file: " + src, e); e.printStackTrace(); } } /** * Add all recipes from a string. The recipe's type must be registered before. * @param recipes The string specifying recipes */ public void addRecipeFromString(String recipes) { RecipeParser parser = null; try { parser = new RecipeParser(recipes); addRecipe(parser); } catch (Throwable e) { LIUtils.log.error("Failed to load recipes from String: " + recipes, e); } finally { parser.close(); } } private void addRecipe(RecipeParser parser) { while (parser.parseNext()) { String type = parser.getType(); IRecipeRegistry registry = map.get(type); if (registry != null) { ParsedRecipeElement[] parsed = parser.getInput(); Object[] input = new Object[parsed.length]; for(int i = 0; i < input.length; ++i) { input[i] = getRegistryObject(parsed[i]); } //System.out.println(DebugUtils.formatArray(input)); registry.register(type, getOutput(parser.getOutput()), input, parser.getWidth(), parser.getHeight(), parser.getExperience()); } else LIUtils.log.error("Failed to register a recipe because the type \"" + type + "\" doesn't have its registry"); } } private HashMap<String, IRecipeRegistry> map = new HashMap<String, IRecipeRegistry>(); }