Utilities for the recipe format as specified in

May 7, 2015 ยท View on GitHub

https://github.com/PrismarineJS/minecraft-data/wiki/Proposed-new-recipe-format

RecipeItem = namedtuple('RecipeItem', 'id metadata count') Recipe = namedtuple('Recipe', 'result ingredients in_shape out_shape')

def reformat_item(raw, default_metadata=-1): if isinstance(raw, dict): raw = raw.copy() # do not modify arg if 'metadata' not in raw: raw['metadata'] = default_metadata if 'count' not in raw: raw['count'] = 1 return RecipeItem(**raw) elif isinstance(raw, list): return RecipeItem(raw[0], raw[1], 1) else: # single ID or None return RecipeItem(raw or -1, default_metadata, 1)

def reformat_shape(shape): return [[reformat_item(item, -1) for item in row] for row in shape]

def to_recipe(raw): result = reformat_item(raw['result'], -1) if 'ingredients' in raw: ingredients = [reformat_item(item, 0) for item in raw['ingredients']] in_shape = out_shape = None else: in_shape = reformat_shape(raw['inShape']) out_shape = reformat_shape(raw['outShape']) if 'outShape' in raw else None ingredients = [item for row in in_shape for item in row] # flatten recipe = Recipe(result, ingredients, in_shape, out_shape) return recipe

def iter_recipes_for(item_id, metadata=-1): try: recipes_for_item = recipes[str(item_id)] except KeyError: return else: for raw in recipes_for_item: recipe = to_recipe(raw) if metadata == -1 or metadata == recipe.result.metadata: yield recipe

def find_recipe(item, metadata=-1): for matching in iter_recipes_for(item, metadata): return matching return None

def get_total_amounts_needed(recipe): totals = defaultdict(int) for id, metadata, count in recipe.ingredients: totals[(id, metadata)] += count return totals