crabsmadethis/d2r-horadric-tools
Diablo II Resurrected modding toolkit — character builder, mod build/deploy pipeline, save inspector, CASC reader, and MCP server for Claude/Codex/AI integration. Linux/Steam Deck.
README
d2r-tools
D2R modding toolkit for Linux and Steam Deck (Proton). YAML-driven character builder, data modding pipeline, and an MCP server that exposes the tools to agentic clients (Claude Code, Codex, Cursor, etc.).
Features
- YAML character builder - declare characters in YAML, build
.d2ssave files - Data mod pipeline - YAML overlays applied to game tables, built and deployed
- JSON string patches - rename or add item / UI strings via YAML, no string-table surgery
- CASC read/write - pure Python, no external tools needed
- Integrated validation - scanner catches structural problems before loading the game
- Reign of the Warlock expansion support (8 classes including Warlock)
Quickstart
git clone <repo-url>
cd d2r-tools
pip3 install -e .
d2r-mod extract # extracts + generates data from your D2R install
d2r-chargen build MyChar
(or pip install -e . if pip points to Python 3 on your system)
Three commands from clone to working. The extract step generates Python data modules from your D2R installation (required for legal reasons - no game data is distributed).
# If D2R is not auto-detected:
d2r-mod extract --game-dir /path/to/Diablo\ II\ Resurrected
# Or set the environment variable:
export D2R_GAME_DIR="/path/to/Diablo II Resurrected"
An example character YAML is included in chars/ExamplePaladin.yaml.
Create your own characters in the chars/ directory.
D2R install path is auto-detected on Linux/Steam Deck and Windows. Use --game-dir to override.
Character Definition (YAML)
Characters are defined in YAML files placed in a chars/ directory. Here's a complete example:
schema_version: 1
name: MyPaladin
class: paladin
level: 85
stats:
strength: 156
dexterity: 100
vitality: 250
energy: 15
skills:
Holy Shield: 20
Smite: 20
Fanaticism: 20
Charge: 1
Salvation: 1
Cleansing: 1
equipment:
# Unique items - resolved automatically from game data
- slot: helm
unique: Guillaume's Face
# Runeword items - specify runeword name and base item code
- slot: body
runeword: Fortitude
base: utp # Archon Plate
# Rare/crafted items with explicit properties
- slot: hands
rare: true
base: uvg # Vampirebone Gloves
ilvl: 90
properties:
fire_res: 30
cold_res: 30
light_res: 30
life: 20
- slot: weapon
unique: Grief
base: 7cr # Phase Blade
- slot: shield
unique: Herald of Zakarum
- slot: belt
unique: Verdungo's Hearty Cord
- slot: feet
unique: Gore Rider
- slot: neck
rare: true
ilvl: 90
properties:
class_skills: [2, paladin]
fcr: 10
fire_res: 30
light_res: 25
- slot: ring_right
unique: Bul Katho's Wedding Band
- slot: ring_left
unique: Ravenfrost
inventory:
charms:
# Unique charms
- unique: Annihilus
properties:
all_skills: 1
strength: 20
dexterity: 20
fire_res: 20
cold_res: 20
light_res: 20
poison_res: 20
add_exp: 10
# Repeatable magic charms
- magic_grand_charm:
count: 8
properties:
skill_tab: [1, 15] # Combat skills (paladin)
life: 40
- magic_small_charm:
count: 5
properties:
life: 20
light_res: 11
merc:
equipment:
- slot: weapon
unique: The Reaper's Toll
ethereal: true
Slot Names
helm, body, weapon, shield, hands, belt, feet, neck, ring_right, ring_left, weapon_switch, shield_switch
Item Types
| Field | Description |
|---|---|
unique: "Name" |
Unique item - stats auto-resolved from game data |
set_item: "Name" |
Set item |
runeword: "Name" |
Runeword - requires base code |
rare: true |
Rare item - requires base and properties |
magic_grand_charm |
Magic grand charm with count and properties |
magic_small_charm |
Magic small charm with count and properties |
Classes
amazon, sorceress, necromancer, paladin, barbarian, druid, assassin, warlock
CLI Reference
d2r-chargen
d2r-chargen build <name> [--phase N] [--force] # Build character (phases 1-4)
d2r-chargen validate <name> [--yaml-only] # Validate YAML definition
d2r-chargen list # List defined characters
d2r-chargen scan <name> # Run scanner diagnostics
d2r-chargen import <name> [--force] # Import .d2s -> YAML
d2r-chargen diff <file1> <file2> # Compare .d2s files
d2r-mod
d2r-mod extract [--game-dir PATH] # Extract game data + generate Python modules
d2r-mod build [--no-regen] # Build mod from vanilla + overlays
d2r-mod deploy [--force] [--no-casc] # Deploy mod to game directory
d2r-mod undeploy # Remove mod from game
d2r-mod diff [--summary] # Compare vanilla vs modded tables
d2r-mod inject [--from-dir PATH] # Inject files into CASC archive
d2r-mod audit [--skills] [--items] # Audit game data
d2r-mod clean # Remove build/ and reset data
d2r-mod update # Re-extract after game update
Data Mod Overlays
Overlays modify D2R data tables declaratively using YAML. Place overlay files in an overlays/ directory and run d2r-mod build.
Create an overlays/ directory in your project root to add custom overlays.
If no overlays directory exists, d2r-mod build will proceed with vanilla data only.
target: data/global/excel/UniqueItems.txt
changes:
- row: {index: "The Gnasher"}
set:
prop4: "dmg%"
min4: "50"
max4: "50"
comment: "Buff The Gnasher with +50% Enhanced Damage"
Each overlay targets a specific game table (TSV file) and specifies row matches and column changes. See examples/sample_overlay.yaml for a complete example.
JSON String Patches
D2R reads item names, mercenary names, and most UI strings from JSON files in data/local/lng/strings/ (not from the older .tbl files). To add a new string or override a vanilla one, drop a YAML spec into patches/json_strings/ and rebuild.
# patches/json_strings/my_renames.yaml
description: "Rename a few potions"
target: item-names.json
entries:
- key: "vps" # vanilla string key (super healing potion)
value: "Wild Rice Cake" # what D2R should display instead
- key: "MyCustomItem" # new key — auto-allocated string ID
value: "Heart of the Mountain"
If the key already exists in the target JSON, its enUS value is overridden. If it doesn't, a new entry is appended with the next free string ID (read from data/local/lng/next_string_id.txt). Targets currently used: item-names.json, mercenaries.json, ui.json.
After d2r-mod build, the patched JSONs land in build/data/local/lng/strings/; d2r-mod deploy injects them into CASC. D2R caches strings at startup, so fully exit and relaunch to see changes.
If no patches/json_strings/ directory exists, the build skips this step.
Architecture
d2r_chargen/ YAML character builder
build_lib.py Binary item encoder (Huffman, stat encoding, checksums)
character.py Build orchestrator (YAML -> items -> .d2s)
resolve.py Name-to-ID resolution (uniques, runewords, stats, skills)
save.py Save file operations (stats, skills, waypoints, items)
scanner.py Diagnostic validator
data/ Game data (generated via extract, not distributed)
d2r_mod/ Data modding pipeline
casc.py Pure Python CASC reader (TBL, TXT, JSON)
casc_write.py CASC archive builder + ekey-hijack injection
overlay.py YAML overlay loader and applier
build.py Build orchestrator (vanilla + overlays -> build/)
build_steps/ Specialized build steps:
register_custom_uniques.py Auto-register custom unique names in TBL
build_string_registry.py Diff built TBLs vs vanilla into a registry
patch_json_strings.py Apply patches/json_strings/*.yaml to JSON
deploy.py Deploy/undeploy mod files
regen.py Generate chargen data from extracted tables
tools/ Standalone diagnostics
audit_string_registry.py Categorize string_registry entries vs JSON
Platform Support
| Platform | Status |
|---|---|
| Linux / Steam Deck (Proton) | Supported, tested |
| Windows | Untested — path detection included, contributions welcome |
| macOS | Unsupported |
Requirements
- Python 3.10+
- PyYAML
- Diablo II: Resurrected (for data extraction)
mcp(optional, only for the MCP server —pip install -e ".[mcp]")
License
MIT
MCP Server (Claude Code, Codex, Cursor, …)
d2r-tools ships an MCP server that exposes
game-data lookups, save inspection, the chargen pipeline, and the mod pipeline
as typed tools to any MCP-compatible agent. See d2r_mcp/README.md for the
full tool catalog (23 tools across lookup / save / chargen / mod).
Install
pip install -e ".[mcp]" # installs the `mcp` SDK alongside d2r-tools
Launch
python3 -m d2r_mcp # stdio transport
Client configuration
Claude Code (user-scoped):
claude mcp add d2r-tools --transport stdio --scope user -- python3 -m d2r_mcp
Codex / Cursor / any other MCP client — add to the client's MCP config:
{
"mcpServers": {
"d2r-tools": {
"command": "python3",
"args": ["-m", "d2r_mcp"],
"env": {}
}
}
}
Mutation tools (d2r_chargen_build, d2r_mod_deploy) enforce the project's
safety rules structurally: they back up the live save, build to a staging
file, run the scanner on the staging, and only promote to the live save if
the scanner passes.
Claude Code Plugin (optional)
The plugin/ directory is a Claude Code plugin that adds slash commands and
skills on top of the MCP server. Point Claude Code at the repo or symlink
plugin/ into your Claude Code plugins directory.
Slash commands
| Command | Description |
|---|---|
/d2r-build <name> |
Safe build cycle (backup → build → scan → verify) |
/d2r-validate <name> |
Validate character YAML without building |
/d2r-scan <name> |
Run diagnostic scanner |
/d2r-lookup <query> |
Look up items, stats, skills from game data |
Skills
- d2r-safe-edit — enforces backup→edit→scan→verify on every save file change
- d2r-parallel-agents — guides parallel-agent dispatch for multi-character work
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。