aboutsummaryrefslogtreecommitdiff
path: root/minecrafttrivia/recipe_provider.py
diff options
context:
space:
mode:
authorRoman Gräf <romangraef@loves.dicksinhisan.us>2020-12-04 23:49:55 +0100
committerRoman Gräf <romangraef@loves.dicksinhisan.us>2020-12-04 23:49:55 +0100
commit987f3bc618574ea52ea551dd31d131a2d523d7dc (patch)
tree05f8f87d33b7d5be5dfd49b1860df162db7d51ba /minecrafttrivia/recipe_provider.py
downloadRedCog-MinecraftTrivia-987f3bc618574ea52ea551dd31d131a2d523d7dc.tar.gz
RedCog-MinecraftTrivia-987f3bc618574ea52ea551dd31d131a2d523d7dc.tar.bz2
RedCog-MinecraftTrivia-987f3bc618574ea52ea551dd31d131a2d523d7dc.zip
Initial commit
Diffstat (limited to 'minecrafttrivia/recipe_provider.py')
-rw-r--r--minecrafttrivia/recipe_provider.py131
1 files changed, 131 insertions, 0 deletions
diff --git a/minecrafttrivia/recipe_provider.py b/minecrafttrivia/recipe_provider.py
new file mode 100644
index 0000000..fe99d59
--- /dev/null
+++ b/minecrafttrivia/recipe_provider.py
@@ -0,0 +1,131 @@
+import json
+import typing
+from collections import defaultdict
+from dataclasses import dataclass
+from pathlib import Path
+
+data_source_dir = Path(__file__).parent / 'mcdata'
+recipe_dir = data_source_dir / 'recipes'
+tags_dir = data_source_dir / 'tags'
+lang_file = data_source_dir / 'lang.json'
+
+
+@dataclass
+class Ingredient:
+ allowed_items: typing.List[str]
+ count: int
+
+
+@dataclass
+class CraftingRecipe:
+ result: str
+ ingredients: typing.List[Ingredient]
+
+
+def deminecraft(name: str) -> str:
+ return name[10:]
+
+
+class RecipeProvider:
+
+ def __init__(self):
+ self.tags: typing.Dict[str, typing.List[str]] = {}
+ self.recipes: typing.List[CraftingRecipe] = []
+ self.lang: typing.Dict[str, str] = {}
+ self.load_everything()
+
+ def get_all_names(self, obj: str) -> typing.List[str]:
+ names = [obj]
+ obj = obj.casefold()
+ item_name = self.lang.get(f'item.minecraft.{obj}')
+ if item_name:
+ names.append(item_name)
+ block_name = self.lang.get(f'block.minecraft.{obj}')
+ if block_name:
+ names.append(block_name)
+ return names
+
+ def load_everything(self):
+ self.load_lang()
+ self.load_all_tags()
+ self.load_all_recipes()
+
+ def load_all_recipes(self):
+ for recipe_file in recipe_dir.iterdir():
+ with recipe_file.open() as fp:
+ self.load_recipe(fp)
+
+ def load_lang(self):
+ with lang_file.open() as fp:
+ self.lang = json.load(fp)
+
+ def load_all_tags(self):
+ for subdir in tags_dir.iterdir():
+ self.load_tags(subdir)
+
+ def load_tags(self, tag_dir: Path):
+ for tag_file in tag_dir.iterdir():
+ with tag_file.open() as fp:
+ self.load_tag(tag_file.name.split(".")[0], fp)
+
+ def load_tag(self, name, fp):
+ data = json.load(fp)
+ if name not in self.tags:
+ self.tags[name] = []
+ self.tags[name] += data['values']
+
+ def follow_tags(self, tag: str) -> typing.List[str]:
+ def internal(t):
+ if t == "":
+ print("x")
+ for el in self.tags[t]:
+ if el[0] == '#':
+ for subel in internal(deminecraft(el[1:])):
+ yield subel
+ else:
+ yield el
+
+ return list(internal(tag))
+
+ def parse_ingredient(self, obj: dict) -> typing.List[str]:
+ if isinstance(obj, list):
+ x = []
+ for i in obj:
+ x += self.parse_ingredient(i)
+ return x
+ if 'item' in obj:
+ return [deminecraft(obj['item'])]
+ if 'tag' in obj:
+ return self.follow_tags(deminecraft(obj['tag']))
+ raise RuntimeError("Invalid recipe")
+
+ def load_crafting_shapeless(self, data: dict) -> CraftingRecipe:
+ result = deminecraft(data['result']['item'])
+ ingredients = []
+ for i in data['ingredients']:
+ ingredients.append(Ingredient(self.parse_ingredient(i), 1))
+ return CraftingRecipe(result, ingredients)
+
+ def load_crafting_shaped(self, data: dict) -> CraftingRecipe:
+ item_counts = defaultdict(int)
+ for row in data['pattern']:
+ for cell in row:
+ if cell != " ":
+ item_counts[cell] += 1
+ ingredients = []
+ for item, count in item_counts.items():
+ obj = data['key'][item]
+ ingredients.append(Ingredient(self.parse_ingredient(obj), count))
+ result = deminecraft(data['result']['item'])
+ return CraftingRecipe(result, ingredients)
+
+ def load_recipe(self, fp):
+ data = json.load(fp)
+ loader = 'load_' + deminecraft(data['type'])
+ if not hasattr(self, loader):
+ return
+ recipe = getattr(self, loader)(data)
+ self.recipes.append(recipe)
+
+
+DEFAULT_RECIPE_PROVIDER = RecipeProvider()