crabsmadethis/d2r-horadric-tools

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.

Category
Visit Server

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 .d2s save 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

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured