#!/usr/bin/env python3 """Emit Discord-ready (monospace code-block) tables of all craftable recipes: the workbench recipes (T1 + T2, both on the Trampler; T2 also at world workbenches) and the world conveyor production lines with their island locations. """ import json, collections NAMES = json.load(open("extracted/item_names.json"))["items"] REC = json.load(open("extracted/crafting_recipes.json"))["recipes"] PL = json.load(open("extracted/production_lines.json"))["production_lines"] PLACE = json.load(open("extracted/conveyor_placements.json")) ISL = json.load(open("extracted/island_names.json"))["islands"] def nm(item_id): e = NAMES.get(item_id) if e and e.get("name"): return e["name"] return item_id # fall back to raw id (no i2 term) def fmt_side(ings): # merge duplicate item slots (some recipes list the same id in two output slots) merged = {} order = [] for i in ings: k = i["itemId"] if k not in merged: merged[k] = 0 order.append(k) merged[k] += i["amount"] return " + ".join("%d %s" % (merged[k], nm(k)) for k in order) def table(rows, headers): cols = list(zip(*([headers] + rows))) if rows else [[h] for h in headers] w = [max(len(str(c)) for c in col) for col in cols] line = lambda r: "| " + " | ".join(str(c).ljust(w[i]) for i, c in enumerate(r)) + " |" sep = "|" + "|".join("-" * (w[i] + 2) for i in range(len(headers))) + "|" out = [line(headers), sep] + [line(r) for r in rows] return "\n".join(out) def recipe_rows(keys): rows = [] for key in keys: for r in REC[key]: rows.append([fmt_side(r["inputs"]), fmt_side(r["outputs"]), "%gs" % r["craftTimeSeconds"]]) return rows # ---- island placement map: conveyor base name -> [in-game island names] ---- def island_disp(prefab): d = ISL.get(prefab, {}) return d.get("toponym") or prefab.replace("island_", "") conv_to_islands = collections.defaultdict(list) for prefab, d in PLACE["islands"].items(): if prefab.startswith("island_test"): continue for rc in d["recipes"]: conv_to_islands[rc["conveyor"]].append(island_disp(prefab)) for u in d["product_conveyors_without_matching_recipe"]: # name-mismatch: singular placed instance maps to its plural recipe key conv_to_islands[u["conveyor"] + "s"].append(island_disp(prefab)) OUT = [] OUT.append("## Workbench Crafts\n") for title, keys in [("Tier 1", ["Recipes_Utility_Workbench_T1", "Recipes_Armament_Workbench_T1"]), ("Tier 2", ["Recipes_Armament_Workbench_T2"])]: OUT.append("**%s**" % title) OUT.append("```") OUT.append(table(recipe_rows(keys), ["Inputs", "Output", "Time"])) OUT.append("```") OUT.append("\n## World Conveyor Production Lines (single-recipe, fixed locations)\n") # the game_conveyor_base* lines are test-island stubs (placeholder recipes); skip them rows = [] for conv, r in sorted(PL.items()): if conv.startswith("game_conveyor_base"): continue islands = conv_to_islands.get(conv, []) loc = ", ".join(sorted(set(islands))) if islands else "(defined, not placed)" rows.append([fmt_side(r["inputs"]), fmt_side(r["outputs"]), "%gs" % r["craftTimeSeconds"], loc]) OUT.append("```") OUT.append(table(rows, ["Inputs", "Output", "Time", "Location (island)"])) OUT.append("```") print("\n".join(OUT))