mirror of
https://github.com/ForeverPyrite/blast-furnace-extended.git
synced 2025-12-10 01:38:07 +00:00
Inital commit.
Publishing this to GitHub cause I've forgotten to for so long.
This commit is contained in:
141
generate_recipes.py
Normal file
141
generate_recipes.py
Normal file
@@ -0,0 +1,141 @@
|
||||
import json
|
||||
from os.path import basename
|
||||
import zipfile
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
# --- Configuration ---
|
||||
# The path to the Minecraft server .jar file.
|
||||
# You'll need to download this for the version you want to target.
|
||||
# You can usually find it on the official Minecraft website.
|
||||
JAR_PATH = Path("server.jar")
|
||||
|
||||
# The directory where the generated datapack files will be placed.
|
||||
DATAPACK_DIR = Path("data")
|
||||
|
||||
|
||||
# --- Script ---
|
||||
def get_recipes_from_jar(
|
||||
jar_path: Path, recipe_type: str = "smelting"
|
||||
) -> dict[str, dict[str, str]]:
|
||||
"""Extracts all recipes of a specific type from the Minecraft server jar."""
|
||||
recipes: dict[str, dict[str, str]] = {}
|
||||
with zipfile.ZipFile(jar_path, "r") as jar:
|
||||
for filename in jar.namelist():
|
||||
if filename.startswith("data/minecraft/recipe/") and filename.endswith(
|
||||
".json"
|
||||
):
|
||||
with jar.open(filename) as recipe_file:
|
||||
try:
|
||||
recipe_data = json.load(recipe_file)
|
||||
if recipe_data.get("type") == f"minecraft:{recipe_type}":
|
||||
# Use the filename (without extension) as the recipe ID
|
||||
recipe_id = Path(filename).stem
|
||||
recipes[recipe_id] = recipe_data
|
||||
except (json.JSONDecodeError, UnicodeDecodeError):
|
||||
# This handles cases where a file isn't valid JSON, which can happen.
|
||||
print(f"Warning: Could not parse {filename}, skipping.")
|
||||
continue
|
||||
return recipes
|
||||
|
||||
|
||||
def convert_to_blasting(smelting_recipe: dict[str, str | int]) -> dict[str, str | int]:
|
||||
"""Converts a smelting recipe to a blasting recipe."""
|
||||
blasting_recipe = smelting_recipe.copy()
|
||||
blasting_recipe["type"] = "minecraft:blasting"
|
||||
# Blasting is twice as fast as smelting
|
||||
# gotta type check it to get pyright to shut up...
|
||||
if "cookingtime" in blasting_recipe and isinstance(
|
||||
blasting_recipe["cookingtime"], int
|
||||
):
|
||||
blasting_recipe["cookingtime"] = int(blasting_recipe["cookingtime"] / 2)
|
||||
else:
|
||||
# Default smelting time is 200 ticks
|
||||
blasting_recipe["cookingtime"] = 100
|
||||
return blasting_recipe
|
||||
|
||||
|
||||
def get_server_jar_from_jar(jar_path: Path) -> Path | None:
|
||||
with zipfile.ZipFile(jar_path, "r") as jar:
|
||||
for filename in jar.namelist():
|
||||
if filename.startswith("META-INF/versions/") and filename.endswith(".jar"):
|
||||
jar.extract(filename, basename(filename))
|
||||
return Path(basename(filename) + "/" + filename)
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to generate the blasting recipes."""
|
||||
print("Starting recipe generation...")
|
||||
|
||||
if not Path(JAR_PATH).exists():
|
||||
print("Error: The server file was not found.")
|
||||
print("Please download the Minecraft server .jar for the version you want,")
|
||||
print(
|
||||
f"rename it to '{JAR_PATH}', and place it in the same directory as this script."
|
||||
)
|
||||
return
|
||||
|
||||
server_jar_path = get_server_jar_from_jar(JAR_PATH)
|
||||
if server_jar_path is None:
|
||||
print(
|
||||
"Error: Unable to pull server jar out of server jar. (yes, you read that right)"
|
||||
)
|
||||
print("Are you sure you downloaded a proper server jar?")
|
||||
return
|
||||
|
||||
print("Loading recipes from the server jar...")
|
||||
smelting_recipes = get_recipes_from_jar(server_jar_path, "smelting")
|
||||
blasting_recipes = get_recipes_from_jar(server_jar_path, "blasting")
|
||||
smoking_recipes = get_recipes_from_jar(server_jar_path, "smoking")
|
||||
print(f"Found {len(smelting_recipes)} smelting recipes.")
|
||||
print(f"Found {len(blasting_recipes)} vanilla blasting recipes.")
|
||||
print(f"Found {len(smoking_recipes)} vanilla smoking recipes.")
|
||||
|
||||
# Determine which smelting recipes need a blasting equivalent
|
||||
# We do this by comparing the output item of the recipes
|
||||
blasting_results = [recipe.get("result") for recipe in blasting_recipes.values()]
|
||||
# Exclude recipes that are already handled by the smoker.
|
||||
smoking_results = [recipe.get("result") for recipe in smoking_recipes.values()]
|
||||
|
||||
# Holy list comprehension
|
||||
recipes_to_create = {
|
||||
name: recipe
|
||||
for name, recipe in smelting_recipes.items()
|
||||
if recipe.get("result") not in blasting_results
|
||||
and recipe.get("result") not in smoking_results
|
||||
}
|
||||
|
||||
print(
|
||||
f"\nFound {len(recipes_to_create)} smelting recipes to convert to blasting (after excluding existing blasting/smoking recipes)."
|
||||
)
|
||||
|
||||
# Clean up old recipes and create the directory structure
|
||||
# Using 'recipe' as the path, per your correction.
|
||||
recipes_path = DATAPACK_DIR / "minecraft" / "recipe"
|
||||
if recipes_path.exists():
|
||||
shutil.rmtree(recipes_path)
|
||||
recipes_path.mkdir(parents=True, exist_ok=True)
|
||||
print(f"Cleaned and created directory: {recipes_path}")
|
||||
|
||||
# Generate the new .json files
|
||||
for name, recipe in recipes_to_create.items():
|
||||
blasting_recipe = convert_to_blasting(recipe)
|
||||
# To avoid any potential conflicts, we'll add a suffix to the name
|
||||
output_filename = recipes_path / f"{name}_from_blasting.json"
|
||||
with open(output_filename, "w") as f:
|
||||
json.dump(blasting_recipe, f, indent=2)
|
||||
|
||||
print(f"\nSuccessfully generated {len(recipes_to_create)} new blasting recipes!")
|
||||
print(f"They have been saved in: {recipes_path}")
|
||||
print("\nNext steps:")
|
||||
print(
|
||||
"1. Make sure your `pack.mcmeta` file has the correct `pack_format` for the Minecraft version you are targeting."
|
||||
)
|
||||
print(
|
||||
"2. Zip the `data` directory and the `pack.mcmeta` file to create your distributable datapack."
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user