Python
Craftwright’s editor subsystem, TACraftwrightEditorSubsystem, gives Blueprint and Python access to the same scans, reports and imports as the panel.
Get the subsystem
Section titled “Get the subsystem”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.
Functions
Section titled “Functions”| 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) |
scan_project and scan_paths
Section titled “scan_project and scan_paths”Read and check every Craftwright item, recipe and recipe book and return a report, like a scan in the panel.
scan_projectscans the Scan Folders from the settings (/Gamewhen empty).scan_pathsscans 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 and export_recipes_csv
Section titled “export_report and export_recipes_csv”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.
Panel functions
Section titled “Panel functions”| 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.
TACraftwrightReport
Section titled “TACraftwrightReport”| 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 |
TACraftwrightFinding
Section titled “TACraftwrightFinding”| 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) |
TACraftwrightRecipeRow
Section titled “TACraftwrightRecipeRow”| 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 |
TACraftwrightEntryRow
Section titled “TACraftwrightEntryRow”| 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) |
TACraftwrightImportResult
Section titled “TACraftwrightImportResult”| 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.
Runtime classes
Section titled “Runtime classes”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.
Examples
Section titled “Examples”Scan and list the findings
Section titled “Scan and list the findings”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)Duplication loops
Section titled “Duplication loops”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 materials and unused items
Section titled “Raw materials and unused 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)Reports
Section titled “Reports”files = craftwright.export_report(report, "Docs/RecipeReport", ["html", "json"])print(files)Rebalance craft times through a CSV
Section titled “Rebalance craft times through a CSV”import csvimport 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 runfor 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) # applyprint(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.
Let the user review an import
Section titled “Let the user review an import”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)Show results in the panel
Section titled “Show results in the panel”craftwright.open_panel(["/Game/Crafting"])craftwright.show_panel_page(2) # Findingsif report.recipes: craftwright.show_in_panel(report.recipes[0].path)