Skip to content

Python

Craftwright’s editor subsystem, TACraftwrightEditorSubsystem, gives Blueprint and Python access to the same scans, reports and imports as the panel.

import unreal
craftwright = unreal.get_editor_subsystem(unreal.TACraftwrightEditorSubsystem)

In Blueprint (for example in an Editor Utility Widget), get the editor subsystem of class TACraftwrightEditorSubsystem and use the functions in the Craftwright category.

Function Returns
scan_project() TACraftwrightReport
scan_paths(package_paths) TACraftwrightReport
export_report(report, directory, formats) Array of str: the files written
export_recipes_csv(report, file_path) str: the path, or empty on failure
import_recipes(file_path, dry_run=False, new_folder="") TACraftwrightImportResult
review_and_import_recipes(file_path, new_folder) TACraftwrightImportResult (the applied result) or None
open_panel(package_paths) Nothing
show_in_panel(asset_path) Nothing
show_panel_page(page_index) Nothing
get_last_report() TACraftwrightReport
get_rule_display_name(rule_id) Text (static)

Read and check every Craftwright item, recipe and recipe book and return a report, like a scan in the panel.

  • scan_project scans the Scan Folders from the settings (/Game when empty).
  • scan_paths scans content folders such as "/Game/Crafting" and their subfolders. An empty list scans the Scan Folders.

Both wait for the Asset Registry if it is still discovering assets, and follow references out of the folders (included books, their recipes, the items they use, recipes taught by Learn Recipes). See What a scan reads.

export_report writes the report files. directory is the output folder; an empty string uses the Report Directory, and relative paths start at the project folder. formats is a list of "html", "json" and "csv"; an empty list writes all of them. It returns the full paths of the files written, or an empty list when nothing could be written.

export_recipes_csv writes only the recipes CSV (the file the import reads) to file_path, creating its folder.

import_recipes and review_and_import_recipes

Section titled “import_recipes and review_and_import_recipes”

import_recipes creates and updates recipes from a .csv or .json file, exactly like Import in the panel but without the review window. With dry_run=True nothing changes and the result lists what would. new_folder is where new recipes go and where rows without a path are looked up; empty uses the New Recipe Folder. See Import and export for the file format.

review_and_import_recipes shows the Review import window for the file and applies it when the user clicks Apply. It returns the applied result, or None when the import was not applied (cancelled, nothing to apply, or no editor UI). The folder picked with “…” in the window is the one the import uses.

Function What it does
open_panel(package_paths) Opens the panel and scans these folders (an empty list: the Scan Folders).
show_in_panel(asset_path) Opens the panel and selects a recipe or item (a SoftObjectPath); a recipe book shows its recipes.
show_panel_page(page_index) Shows page 0 (Recipes), 1 (Items) or 2 (Findings).

get_last_report returns the last report made by the panel or the subsystem. get_rule_display_name turns a rule id such as "Duplication" into its name, “Duplication loop”; it is static, so you can call it on the class.

The report types are read-only. Enum values are written in capitals in Python, for example unreal.TACraftwrightSeverity.ERROR.

Property Type Meaning
time DateTime When the scan ran
scope Array of str The scanned folders
recipes Array of TACraftwrightRecipeRow Every recipe, sorted by name
items Array of TACraftwrightItemRow Every item, sorted by name
books Array of TACraftwrightBookRow Every recipe book, sorted by name
station_tags Array of str The station tags recipes use
findings Array of TACraftwrightFinding Every finding, errors first
Property Type Meaning
severity TACraftwrightSeverity INFO (a suggestion), WARNING or ERROR
rule_id Name The rule id, for example Duplication or NotInBook. See Checks.
asset_path, asset_name SoftObjectPath, str The recipe, item or book the finding is about
message str The finding
related Array of SoftObjectPath Other assets it is about, for example every recipe in a loop
chain Array of SoftObjectPath Duplication loops and salvage that gives back more: the items of one round, with the first item again at the end
factor float Duplication loops and salvage that gives back more: items gained per round (1.5 = 50 % more)
Property Type Meaning
name, path str, SoftObjectPath Asset name and path
display_name, category str Display Name and Category
stations Array of str Station tags; empty for hand recipes
craft_time, max_batch float, int Craft Time and Max Batch
unlock str AlwaysKnown, Learned or Discovered
failure_chance, failure_refund, cancel_refund float As in the recipe
ingredients, outputs Array of TACraftwrightEntryRow One per ingredient or output
bonus_chance, bonus_outputs float, Array of TACraftwrightEntryRow Bonus Chance and Bonus Outputs
salvageable bool Salvageable
salvage_refund, salvage_time float Salvage Refund and Salvage Time
salvage_outputs Array of TACraftwrightEntryRow Salvage Outputs
unlock_hint str Unlock Hint
books Array of str Names of the books that list the recipe
conditions, effects int Number of conditions and effects
errors, warnings, suggestions int Findings about this recipe
Property Type Meaning
item, item_path str, SoftObjectPath The item’s asset name and path; empty for tag ingredients
item_display_name str The item’s display name
tag str The tag of a tag ingredient
count int Count
tool bool Ingredients: a tool
chance float Outputs: the chance per unit

TACraftwrightItemRow and TACraftwrightBookRow

Section titled “TACraftwrightItemRow and TACraftwrightBookRow”
Type Properties
TACraftwrightItemRow name, path, display_name, tags, max_stack, has_icon, made_by (recipe names), used_in (recipe names, by item or tag), errors, warnings, suggestions. An item that is used but not made is a raw material.
TACraftwrightBookRow name, path, recipes (the number of recipes, including included books), included_books (names)
Property Type Meaning
success bool True when no row had an error
created, updated, unchanged int Number of recipes
errors Array of str One line per problem, for example Line 5 (Recipe_Torch): Unknown item "Item_Wick".
changes Array of str One line per created or updated recipe
recipes Array of TACraftwrightImportRecipe Every recipe in the file: action (CREATE, UPDATE or UNCHANGED), name, path, line and fields
skipped Array of TACraftwrightImportSkip The skipped rows: line (0 for the whole file), name and reason
new_folder str Where new recipes go

Each entry of fields (TACraftwrightImportField) has field (the column name), current (empty for new recipes) and imported, as readable text.

The crafter, station, recipe and library classes can be used from Python too. Their names are the Blueprint names in lower case with underscores. Bool properties lose their “b” (bSalvageable is salvageable), and enum values are in capitals.

Class Python
Craftwright Crafter unreal.TACraftwrightCrafterComponent
Craftwright Crafter GAS unreal.TACraftwrightGASCrafterComponent: the crafter’s names, plus speed_attribute and luck_attribute
Craftwright Station unreal.TACraftwrightStationComponent
Craftwright Station GAS unreal.TACraftwrightGASStationComponent: the station’s names, plus speed_attribute
Craftwright Recipe unreal.TACraftwrightRecipe
Library unreal.TACraftwrightLibrary

The calls and properties added in 1.1:

Class Blueprint Python
Crafter Request Salvage, Check Salvage, Get Max Salvageable, Get Salvage Recipes request_salvage, check_salvage, get_max_salvageable, get_salvage_recipes
Crafter Track Recipe, Untrack Recipe, Is Recipe Tracked, Get Tracked Recipes track_recipe, untrack_recipe, is_recipe_tracked, get_tracked_recipes
Crafter Get Locked Recipes, Get Ingredient Status, Get Crafting Luck get_locked_recipes, get_ingredient_status, get_crafting_luck
Crafter Crafting Luck, Max Tracked Recipes, Untrack When Crafted crafting_luck, max_tracked_recipes, untrack_when_crafted
Crafter On Bonus Outputs, On Salvaged, On Tracked Recipes Changed on_bonus_outputs, on_salvaged, on_tracked_recipes_changed
Station Get Station Speed, Get Speed For, Use Crafter Speed get_station_speed, get_speed_for, use_crafter_speed
Recipe Get Main Output Count, Can Salvage, Get Salvage Outputs get_main_output_count, can_salvage, get_salvage_outputs
Recipe Bonus Chance, Bonus Outputs, Salvageable, Salvage Refund, Salvage Outputs, Salvage Time, Unlock Hint bonus_chance, bonus_outputs, salvageable, salvage_refund, salvage_outputs, salvage_time, unlock_hint
Library Recipe Matches Search, Get Tag Short Name recipe_matches_search, get_tag_short_name

The crafting menu’s new functions follow the same rule, for example set_search_text, toggle_track_selected and handle_menu_key. See Crafting and Crafting UI for what they do.

import unreal
craftwright = unreal.get_editor_subsystem(unreal.TACraftwrightEditorSubsystem)
report = craftwright.scan_paths(["/Game/Crafting"])
for finding in report.findings:
print(finding.severity, finding.rule_id, finding.asset_name, finding.message)
for finding in report.findings:
if str(finding.rule_id) == "Duplication":
items = [path.export_text() for path in finding.chain]
print("x%.2f per round:" % finding.factor, " -> ".join(items))
raw = [item.name for item in report.items if item.used_in and not item.made_by]
unused = [item.name for item in report.items if not item.used_in and not item.made_by]
print("Raw materials:", raw)
print("Not made or used by any recipe:", unused)
files = craftwright.export_report(report, "Docs/RecipeReport", ["html", "json"])
print(files)
import csv
import os
folder = unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_saved_dir())
path = os.path.join(folder, "Craftwright", "recipes.csv")
craftwright.export_recipes_csv(report, path)
with open(path, newline="", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
for row in rows:
row["CraftTime"] = str(round(float(row["CraftTime"]) * 0.8, 2)) # 20 % faster
with open(path, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["Recipe", "Path", "CraftTime"], extrasaction="ignore")
writer.writeheader()
writer.writerows(rows)
preview = craftwright.import_recipes(path, True) # dry run
for entry in preview.recipes:
for field in entry.fields:
print(entry.name, field.field, field.current, "->", field.imported)
print(preview.errors)
result = craftwright.import_recipes(path) # apply
print(result.created, "created,", result.updated, "updated")

The CSV written back has only the Recipe, Path and CraftTime columns, so the import changes nothing else. Instant recipes (0) stay instant.

result = craftwright.review_and_import_recipes("C:/Path/Balance/recipes.csv", "")
if result: # None when the user cancelled or there was nothing to apply
print(result.changes)
craftwright.open_panel(["/Game/Crafting"])
craftwright.show_panel_page(2) # Findings
if report.recipes:
craftwright.show_in_panel(report.recipes[0].path)