Releases: jbowensii/MoriaModCreator
Moria MOD Creator v3.0.0
Moria MOD Creator v3.0.0
Release date: April 2026
Previous release: v2.10.0 (April 6, 2026)
v3.0.0 is a major release: the entire application has been rewritten from Python / CustomTkinter to C# / WPF / .NET 10. The Python implementation is archived (not deleted) under old-python-src/ for reference. The new build is faster, native, self-contained, and no longer requires a Python runtime.
Highlights
- Full C# / WPF rewrite on .NET 10 — native Windows app, no Python or CustomTkinter required
- Feature parity with Python across all Advanced tabs — Mod Builder, Change Secrets, Change Constructions, Create DEF
- Self-contained installer — single
.exebundled with the .NET runtime; no prerequisites - Hardened security — zip-slip guard on all archive extraction; path-traversal validation on user-entered prefixes
- Structured logging — all services + ViewModels log through
ILogger, output captured to%APPDATA%\MoriaMODCreator\MoriaMODCreator.log - Global crash handling — unhandled exceptions on any thread (UI, background, unobserved Task) surface a copy-to-clipboard crash dialog instead of silent termination
- Signed executable + installer — SSL.com code-signing on both binaries
New features vs v2.10.0
Advanced UI
- Create DEF tab — added Description, Change Note, and Include Comments fields (Python parity). The
changeNoteattribute is only applied to<change>elements (not<delete>). Layout rewritten as a single centered scrollable column matching the Python reference. - Change Secrets / Change Constructions — prefix dialog split into two mode-specific dialogs with combobox-of-existing + "Or new prefix" text entry + Delete/Set/Cancel buttons (Python parity). Path-traversal validation on Create; defense-in-depth path-boundary check on Delete; combobox selection cleared after removal.
- Mod Builder (Definitions view) —
<add_property>elements are now correctly nested inside<change>with JSON text content, matching the Pythonbuild_managerschema. Previous C# output was self-consistent but incompatible with the Python build pipeline. - Object Editor — new view-model infrastructure for creating secrets-source items (8 categories: Buildings, Weapons, Armor, Tools, Flora, Loot, Items, Ores). Shared
FormBuilderhelpers extracted fromBuildingsViewModel. The toolbar button is intentionally hidden in v3.0.0 pending final UX review — the view, VM, commands, and DI wiring are all in place; flipVisibility="Collapsed"→"Visible"inMainWindow.xamlto re-enable. - All TextBox inputs — support
Tag-driven watermark/placeholder text via a dark-themed custom ControlTemplate. - Dropdowns — global dark
ComboBoxControlTemplate withPART_EditableTextBox, type-to-filter, and "click to open" behavior.
Platform & build
- .NET 10 target framework (
net10.0-windows) - Self-contained single-file publish —
dotnet publish -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true - New solution layout — C# source at
src/, solution fileMoriaMODCreator.slnxat repo root - Archived Python — moved to
old-python-src/for historical reference - Version metadata —
<Version>3.0.0</Version>baked into the exe's file-version properties (Windows Explorer shows it correctly)
Diagnostics
- Structured logging in
BuildingsViewModelandObjectEditorViewModel— silentcatch { }blocks in material-section parsing and dropdown-option scanning are now_logger.LogWarningcalls that capture the exception and context. - ImportService
.defparse failures now log viaXmlException/IOExceptionrather than being silently dropped.
Safety
- Zip-slip / path-traversal hardening in
ImportService.ExtractGitHubJsonFilesandExtractCompanionPaksFromNexusZipvia a newSafeCombinehelper. Entries containing..\segments or absolute paths are rejected. - Prefix dialog validation — rejects names with invalid filename chars,
.., or rooted paths. Delete verifies the resolved path stays within the Secrets/Constructions root before removing.
Fixes
- Display name resolution —
CategoryDataService.ResolveDisplayNamecorrectly extractsDisplayNamewhen the value is a plain string (previousis JsonNodecheck always failed sinceExtractPropertyValuereturnsstringforTextPropertyData). - Diff output —
DiffService.FormatValueno longer emits raw JSON blobs for struct / SoftObject array elements. ExtractsRowNamefrom DataTableRowHandle structs,AssetNamefrom SoftObjectPath,CultureInvariantStringfrom FText, and falls back to ak=v, k=vsummary. - Tag extraction —
ObjectTemplateService.ExtractTagNamestolerates wrappedNamePropertyDataentries (used to crash withGetValue<string>()on non-string tokens when loading Tools/Weapons). - Float / Int parsing — safe extraction with typed fallbacks to
ToString()for"None"-string values that previously crashed form rendering. - WPF ComboBox dropdown — fully dark-themed via custom ControlTemplate (WPF system-color overrides don't propagate to the default ComboBox popup).
Internal / developer-facing
- Test coverage: 158 xUnit tests covering services, ViewModels, converters, extraction, round-trip schemas, prefix validation
- Static analysis: builds clean at
AnalysisLevel=latest-all(0 warnings, 0 errors) — suppression rationale documented inline insrc/.globalconfig - Format:
dotnet format --verify-no-changesclean - Extracted
FormBuilderinsrc/MoriaMODCreator/ViewModels/FormBuilder.cs— shared form-field builders used by both Buildings and Object Editor view models
Breaking changes
- Python app no longer shipped. The
.exein the installer is C#/WPF, not PyInstaller. If you had scripts or shortcuts pointing at the oldMoriaMODCreator.exePyInstaller output, they continue to work because the filename is unchanged — but the Python source tree is no longer atsrc/, it's atold-python-src/. - Minimum OS: Windows 10 1809+ (required by .NET 10). Windows 7/8 users on the Python build are not supported by v3.0.0.
Known limitations
- Create/Edit Secret button is hidden pending final UX review (see above). All underlying code is preserved.
- Mod Builder right-pane Search & Replace bar — present in Python, not yet in C# (tracked for v3.1).
- Form builder duplication — ~500 lines shared between
BuildingsViewModelandObjectEditorViewModeltracked as tech debt; plannedCategoryFormBuilderextraction in v3.1.
Install & upgrade
- Run
MoriaMODCreator_Setup_v3.0.0.exe— installs to%LOCALAPPDATA%\Programs\Moria MOD Creator\(no admin required) - First launch extracts bundled Definitions / Secrets Source / Utilities / prebuilt mod files into
%APPDATA%\MoriaMODCreator\ - Existing
%APPDATA%\MoriaMODCreator\data from v2.x is preserved — your mods, prefixes, and edits continue working
Acknowledgments
Original Python implementation: John B Owens II (Mereak Firmaxe)
C# rewrite: collaborative effort
Create DEF feature: Sqitey (retained from Python)
🤖 Release prepared with Claude Code
Moria MOD Creator v2.10.0
What's New in v2.10.0
Critical Bug Fix: Secrets Build Data Loss
Mods built with "Secrets of Khazad-dum" enabled were missing all base game content. The secrets pak is a full replacement pak — its DataTables already contain all game + secrets rows (e.g., DT_Weapons has 167 rows: 158 game + 9 secrets). Previous versions incorrectly stripped game rows before building, producing mods with only the new secrets content.
Simplified Secrets Import Pipeline
The import pipeline has been completely rewritten for simplicity and speed:
- Import: Extracts secrets pak → converts ALL 232 files to
jsondata_full/(complete data) → copies tojsondata/→ strips game rows for UI display - Build: Phase B copies
jsondata_full/files over game files in staging — instant, no extraction needed - Removed: game pak copying (~15GB), merged extraction, manifest filtering, cross-reference step
- Import now completes in seconds instead of minutes
Other Changes
- CategoryFlags.json bundled in exe (fixes object editor category flags)
- retoc to-legacy crash handled gracefully (partial extraction continues)
- DT_Ores.def updated with PinkOpal MaxStackSize
- Per-file progress UI during secrets filtering step
- Code review cleanup: removed dead imports, pylint scores 9.98-10.00/10
- Both exe and installer code-signed (SSL.com eSigner, John B Owens II)
Important: After updating, run a fresh Import to populate the jsondata_full/ directory. Subsequent builds use this cached data instantly.
Acknowledgements
Thanks to ChaosGodstone for reporting import issues and providing logs that led to discovering the data loss bug.
Full Changelog: v2.9.0...v2.10.0
Moria MOD Creator v2.9.0
What's New in v2.9.0
Bug Fixes
- Secrets import crash fixed — Phase B1
retoc to-legacyno longer aborts the entire build when it encounters theasset_conversion.rs:1056panic. The build now checks for partial extraction results and falls back to per-file extraction using--filter, so one incompatible asset doesn't block the rest. - CategoryFlags.json bundled — Object editor category flags now load correctly in the packaged exe. The
docs/templates/directory was missing from the PyInstaller bundle. - DT_Ores.def updated — Added PinkOpal MaxStackSize=9999 change.
Technical Details
- Phase B1 fallback: extracts pak manifest, then runs
retoc to-legacy --filter <stem>individually for each asset. Assets that crash retoc are skipped with a debug log entry. - Both exe and installer are code-signed (SSL.com eSigner, John B Owens II).
Acknowledgements
Thanks to ChaosGodstone for reporting the import issues and providing detailed logs that made these fixes possible!
Full Changelog: v2.8.0...v2.9.0
v2.8.0 — Ores Category, Display Names, Edit Persistence & Build Fixes
What's New
New Features
- Ores category — 41 game ores (Stone, Iron, Gold, PinkOpal, etc.) as definition-only mode in Change Secrets & Constructions tabs
- Display name resolution in Secrets tab — ported from Constructions view, plus TobiModsAddons string table extraction (~300 additional in-game names)
- Edit persistence via edits.json manifest — user edits now survive force refresh and cache overwrites across sessions
- Items category expanded — shows ALL DT_Items entries without requiring a matching DT_ItemRecipes entry; right pane conditionally shows recipe/definition sections
Bug Fixes
- Fixed GameplayTagContainer diff emitting
Tags.Tagsdot-path instead ofTags, causing UAssetGUIFName[]conversion failure on DT_Ores.json builds - Fixed Tags save handler to properly split comma-separated tag values into arrays
- Fixed
COLOR_CHECKBOX_MIXEDdouble-wrapped tuple causing tri-state checkbox rendering issues in the definitions list - Updated DT_Ores.def with PinkOpal MaxStackSize change
Build Artifacts
MoriaMODCreator.exe— standalone signed executableMoriaMODCreator_Setup_v2.8.0.exe— signed installer (includes all bundled utilities, definitions, and prebuilt mods)
Both artifacts are code-signed by John B Owens II via SSL.com eSigner.
v2.7.1
Changes since v2.7.0
Secrets Build Pipeline — Fixed Import Index Crash
- Phase B rewritten: Instead of merging secrets rows into game JSON (which dropped the Imports array and caused
Bad import indexfatal errors in-game), Phase B now extractsRtoMSecretsOfKhazaddum_NoFatStacks_Pvia retoc + UAssetGUI and overwrites game files in staging with the complete secrets JSON — preserving correct Import indices - Import pipeline:
SecretsOfKhazadDum_Localization_PandTobiModsAddons_Pare now skipped during retoc/UAssetGUI processing on secrets import — onlyRtoMSecretsOfKhazaddum_NoFatStacks_Pis processed - Build output: When secrets are enabled, 4 passthrough files are copied as-is into the final mod:
SecretsOfKhazadDum_Localization_P.pak(localization text)TobiModsAddons_P.pak/.ucas/.utoc(addon assets)
Signed Artifacts
MoriaMODCreator.exe— code-signed standalone executableMoriaMODCreator_Setup_v2.7.1.exe— code-signed installer
Moria MOD Creator v2.7.0
What's New in v2.7.0
Bug Fixes
- UAssetGUI NameMap crash — TextPropertyData
TableIdandValueFNames now synced to NameMap, fixing "dummy FName" crash on DT_Armor with Secrets overlay - Secrets merge NameMap —
merge_secrets_rowsnow merges the secrets NameMap into the game file during Phase B - Material duplication — Recipe materials and definition repair cost no longer share the same list, preventing data corruption on save
- Cache staleness —
_json_row_cacheinvalidated after every save so subsequent reads get fresh data - .def diff completeness — Tags (GameplayTags), TextPropertyData Value (string table keys), and new array elements are now properly detected and written to .def files
Improvements
- VirtualScrollList rewrite — Row frames placed directly on canvas, eliminating blank space during scrolling. Rows 44px with font size 14 for readability.
- FilterableComboBox — Replaced FocusOut close with click-outside handler, dropdowns no longer close prematurely in scrollable forms. Increased dropdown height to prevent last-item cutoff.
- Prefix persistence — Secrets and Constructions prefix restored on app startup from
current_prefix.ini - Cache performance —
_refresh_cacheskips file copies when cache is already up-to-date (mtime check) - Form clearing — Right pane fully cleared when switching categories, preventing stale material/field carryover
- Secrets .def output — All secrets build .def files now go to
Definitions/Secrets/directory
New Features
- New Secrets directory — Object Editor (Create/Edit Secret) now reads/writes to
New Secrets/jsondata/instead of modifying Secrets Source originals - Raw JSON output — Each Object Editor save writes the individual row as
{row_name}.jsontoNew Secrets/Raw JSON/ - Secrets import copy — Import pipeline copies jsondata to New Secrets after conversion
- Repair Cost editing — Separate "+ Add Repair Material" button and row tracking for definition repair costs (weapons, armor, tools)
- Build instrumentation — Detailed logging across all secrets build phases for crash diagnosis
Signed
- Both
MoriaMODCreator.exeand installer are code-signed (CN=John B Owens II)
🤖 Generated with Claude Code
Moria MOD Creator v2.5.0
Moria MOD Creator v2.5.0
Release covering all changes from v1.5 through v2.5.0.
Object Editor (New — Advanced Tab)
A full Create/Edit Secret tab for creating and editing DataTable objects directly in the Secrets Source JSON files.
Two-Pane Layout
- Left pane: Browsable list of mod-only items per category (buildings, weapons, armor, tools, items, flora, loot) with type-to-filter search
- Right pane: Structured forms matching the Secrets tab layout with labeled fields, dropdowns, checkboxes, and material rows
- Base-game rows are automatically filtered out so only user-added objects appear
Per-Category Structured Forms
- Buildings: Construction Recipe (placement, materials, unlocks, sandbox) + Construction Definition (actor, icon, tags)
- Weapons: Item Recipe + Weapon Definition (damage, speed, durability, armor pen, stamina/energy cost, repair cost)
- Armor: Item Recipe + Armor Definition (damage reduction, protection, repair cost)
- Tools: Item Recipe + Tool Definition (durability, carve hits, mining rate, stamina/energy cost, repair cost)
- Items: Item Recipe + generic Item Definition (portability, stack size, trade value)
- Flora: Flora Definition only (growth timing, drop amounts, farming properties)
- Loot: Loot Definition only (drop chance, quantity range, required tags)
New Object Creation
- Template dropdown: Construction, Recipe, or Both
- Construction: Renders blank recipe + definition forms with game-accurate defaults
- Recipe: Blank item recipe form for weapons, armor, tools
- Both: Shared Row Name field linked between construction recipe and definition sections
- On save, rows are injected into Secrets Source JSON files (Architecture, Constructions, Recipes)
Editing and Management
- Click any item to view/edit its properties in structured forms
- Save writes edited values back to JSON with type conversion (int, float, bool, string)
- Delete with confirmation (type DELETE to confirm)
- Display names resolved from string table JSON files
Search and Replace
- Search bar added to Mod Builder, Secrets, Constructions, and Object Editor right panes
- Three modes: Search by Property names, Values, or Both via dropdown
- Substring replacement: Replace matches within values (not full-value overwrite)
- Replace All: Batch replace across all visible fields
- Shared logic centralized in
shared_utils.py
Create DEF Improvements
GameplayTagContainer Support
- Comparison algorithm now detects
GameplayTagContainerPropertyDatachanges (previously silently skipped) - Properly handles individual tag additions and removals within containers like
ExcludeItemsandAllowedItems - Set-based comparison: reports each added/removed tag individually
Full .def Syntax
<delete>elements for tag removals from containers<change>elements for value modifications and tag additions<change>with<add_property>for adding new properties- Handles
SetPropertyDataalongsideArrayPropertyData - Generic fallback for unhandled property types
Category Detection Fix
- Category now derived from DataTable filename (e.g.,
DT_Storage->Storage) instead of parent directory path (which was always "Items") - Complete mapping for 20+ DataTable names plus prefix fallbacks (
GE_*-> Buffs,Curve_*-> Buffs,Properties_*-> Ores)
Build Manager Enhancements
<delete>handling widened to work on all GameplayTagContainer properties (not just hardcodedExcludeItems/AllowedItems)- Runtime detection of GameplayTagContainers via
$type,StructType, and innerValuemarkers _is_gameplay_tag_container()method replaces hardcoded property name checks
UI Improvements
- Batch rendering: 8 cards at a time with font caching for Mod Builder performance
- Original Value field: Non-editable field showing the original value in Mod Builder change cards
- Material rows: Lazy frame packing — empty materials section takes no space, expands on first "+ Add Material" click
- Button ordering: Create/Edit Secret positioned between Secrets and Constructions tabs
Code Quality
- Dead code removal: ~500 lines of unused methods removed across buildings_view, constructions_view, and object_editor_view
- Removed unused imports: 7 unused imports cleaned up
- Narrowed exception handling: Bare
exceptcatches replaced with specific exception types - Pylint score: 9.84/10 on object_editor_view, 9.97/10 on other modules
- Comments overhaul: Redundant comments stripped, replaced with workflow-focused documentation
- Application documentation: New
docs/APPLICATION.md— comprehensive 16-section technical reference
Test Suite
- 275 tests across 6 test files, all passing
- 64 new tests added in
test_main_window.py: definition XML parsing, original value lookup, search/replace semantics, version validation
Credits
- Created by John B Owens II
- Create DEF functionality by Sqitey
- Co-Authored-By: Claude Opus 4.6
Full Changelog: v1.5...v2.5.0
Moria MOD Creator v1.5
Moria MOD Creator v1.5
Create DEF Tab (New)
A new Create DEF tab under Advanced mode enables automatic generation of .def definition files from IoStore mods.
IoStore Extraction Pipeline
- Automatic extraction: Detects
.ucas/.utocIoStore mod files and runs the full conversion pipeline (retoc to-legacy → UAssetGUI tojson) - Persistent output: Extraction outputs are saved to
retoc/andjsondata/subdirectories inside the Modded Files Folder (not a temp directory), so results persist for inspection - Global file resolution: Automatically copies the game's
global.ucas/global.utocfor retoc name resolution
Comparison & DEF Generation
- JSON diff comparison: Compares modded JSON against vanilla game JSON to identify changes
- Automatic .def creation: Generates properly formatted
.defXML files with correct<change>,<add_property>, and CDATA structures - Smart category detection: Uses the last path component (e.g., "Effects" from
Moria\Content\Items\Effects\DT_ItemTint.json) for category assignment - Batch save: "Save All .def Files" writes definitions to the Definitions directory and generates a prebuilt
.inifile
UI
- Larger fonts: Log and Preview textboxes use doubled font size (22pt) for readability
- Detailed logging: Full path logging for all save operations
New Mod Content
- More Wardrobe Colors: Added 5 definition files for the "More Wardrobe Colors" mod (Effects category) and prebuilt
.inifile- DT_ItemTint: EnabledState, Icon, RequiredMaterials, TintColor, TintName
Docs Cleanup
- Removed legacy directory: Deleted
docs/Ready Made Mods/(replaced bydocs/prebuilt modfiles/) - Updated installer zips: All 7 installer zip bundles regenerated with current content
Build Pipeline Fix
- Dynamic installer version:
build_release.pynow reads the installer version fromabout_dialog.pyinstead of using a hardcoded value
Credits
- Create DEF functionality by Sqitey — added to the About dialog credits
- Co-Authored-By: Claude Opus 4.6
Full Changelog: v1.1...v1.5
Moria MOD Creator v1.2
Moria MOD Creator v1.2
Performance Improvements
- Fast form display: Clicking items in the left pane now loads the right pane form significantly faster. Form rendering is deferred so the list highlight updates immediately, and the form is hidden during widget reconstruction to eliminate intermediate repaints.
- JSON row caching: Game data JSON files are parsed once and cached in memory. Subsequent item clicks do a simple dict lookup instead of re-reading large files from disk. Cache is automatically invalidated on refresh.
Virtual Scroll List
- Fixed blank list display: Resolved a Python 3.14 + CustomTkinter incompatibility where
heightandwidtharguments passed to.place()caused aValueError. Widget dimensions are now set at construction time. - Full viewport coverage: The secrets/constructions list now fills the available height instead of showing only 5 items.
- Eliminated white bar: Background color of the viewport frame now syncs with the canvas to match the current theme.
Import Pipeline Fixes
- GitHub ZIP cleanup: The upfront cleanup phase now removes ALL ZIP files from Secrets Source, including the GitHub ZIP. Previously the GitHub ZIP was skipped, causing stale data on re-import.
- Consistent ZIP cleanup: Both the combined import dialog and the Advanced path use the same cleanup logic.
UI Improvements
- Blank prefix on startup: The "Change Secrets" and "Change Constructions" text fields now start empty until the user explicitly selects a prefix, instead of auto-loading the last used value.
- Always-fresh cache on tab switch: Clicking category tabs (Buildings, Weapons, Armor, etc.) in both Advanced Secrets and Advanced Constructions now always refreshes the cache from source files.
- DLC content support: Added DLC brew buff duration and book buff definition files (community contribution by Letimineur).
Code Quality
- Pylint score: 9.97/10 (up from 9.77)
- All 211 tests passing
- Removed unused imports and overly broad exception handling
- Updated in-code documentation for accuracy
Moria MOD Creator v1.1
What's New in v1.1
Bug Fixes
-
Fixed novice mode builds for all users — Prebuilt mod INI files previously contained hard-coded absolute paths from the developer's machine, causing "No valid definition files in selected mods" for every other user. Paths are now stored relative to the definitions directory and resolved against each user's actual AppData location.
-
Fixed UAssetGUI crash on add_property definitions — The NameMap synchronization now registers property names, struct types, array types, and map key/value types as FNames. Previously, definitions that added new properties (e.g.
DropRatein ore definitions) would crash UAssetGUI with "Attempt to retrieve index of dummy FName". -
Fixed encoding issues on non-English Windows — All subprocess calls now use explicit
encoding='utf-8'witherrors='replace', preventing crashes on systems with Cyrillic (CP866), Japanese (CP932), Chinese (CP936), or other non-UTF-8 console code pages.
Improvements
- Added debug logging to novice build flow for easier diagnostics — logs which INI files are selected, how paths are resolved, and where definitions are looked up.
- Replaced non-ASCII characters in log messages to prevent mojibake when viewing logs with non-UTF-8 text editors.
Files Changed
- 17 files across production code, build scripts, and tests
Full Changelog: v1.0...v1.1