Skip to content

Repository files navigation

D2BotNG

Mostly vibe-coded with Claude.

A modern rewrite of D2Bot - a Diablo II bot manager. Built with .NET 10 and React, hopes to provide full D2BS compatibility with a clean web-based interface.

Screenshots

Profiles
Profiles - manage bot instances with live status, run stats, and bulk actions
Items
Items - search muled items with DC6-rendered sprites and D2 tooltips

Character viewer

Equipment and inventory
Equipment & inventory - live gear, inventory, and stash
Stats and skills
Stats & skills - attributes and skill allocation
Quest and waypoint progression
Quests & waypoints - per-character progression
Analytics
Analytics - lifetime kills and time spent per area

Getting Started

Download the latest release from the Releases page. Two versions are available:

Version Size Requirements
Self-contained Larger Windows 10/11 (x64) — just run, no prerequisites
Framework-dependent Smaller Windows 10/11 (x64) + .NET 10 Runtime

To get started:

  1. Download the .exe for your preferred version
  2. Place it in a directory of your choice and run it — the web UI opens automatically in a desktop window
  3. Configure your Diablo II path and base path in Settings
  4. Add profiles and start botting

The web UI is also available at http://localhost:5000 from any browser.

For headless/server use (no GUI window), run with --headless. See Command Line for all options.

Configuration

App settings are stored in d2botng.json next to the exe (server, Discord, display, base path). Game and botting-framework configuration (game directory, D2BS path, inject DLLs, game version, health thresholds, cleanup) lives per framework, managed on the Frameworks tab: a built-in Default framework is created on first run and new profiles use it automatically. Add more frameworks (e.g. different kolbot installs or D2 versions) and a per-profile framework picker appears so you can assign them.

Bot data files are stored under the base path in data/ng/ (protobuf JSON format). The base path defaults to the exe directory but can be changed in Settings:

File Purpose
<base path>/data/ng/profiles.json Bot profiles
<base path>/data/ng/keylists.json CD key lists
<base path>/data/ng/frameworks.json Frameworks (game/d2bs/dll/version bundles)
<base path>/data/ng/proxies.json Proxies
<base path>/data/ng/characters.json Character snapshots from running bots
<base path>/data/ng/schedules.json Schedule configs
<base path>/data/ng/patches.json Memory patches (version-specific)
<base path>/data/ng/captures.db SQLite: character captures from newer d2bsng builds, with items broken out so they can be searched by stat
<base path>/images/ Item PNGs from the D2BS saveItem message

captures.db is derived state, not a record: a bot re-reports its whole character on the next game it enters, so deleting it costs only the kill and area-time totals of profiles that are not currently running.

Migration from Legacy Format

Legacy D2Bot data files (JSONL format in data/) are automatically migrated to data/ng/ on first startup. Migration also runs when the base path is changed from the Settings page.

  • Non-destructive - Original data/ files are left intact
  • Per-file - Each file is migrated independently; existing files in data/ng/ are skipped. Delete a specific file to re-migrate it
  • IRC profiles dropped - Legacy IRC-type profiles are not migrated
  • Legacy API migrated - server.json users and profiles are imported into Legacy API settings when no existing configuration is found
  • Settings not migrated - Other settings did not exist in the legacy format; d2botng.json is created fresh
  • Frameworks migrated - On first run of a frameworks-aware build, a Default framework is created from the previous game/engine settings (install path, game version, retention, health thresholds) and assigned to all existing profiles
  • Format change - Legacy JSONL (one JSON object per line) is converted to protobuf JSON (single document with typed wrapper messages)

No manual steps are required. To force re-migration of a specific file, delete it from data/ng/ and restart.

Features

Character Viewer, Item Search and SOCKS5 Proxy require the d2bsng engine (the modern C++ D2BS rewrite that reports character-state telemetry and supports proxy hooking). They stay inactive on legacy D2BS; everything else works on both.

  • Character Viewer (d2bsng) - Live per-character equipment, inventory, stash, stats, skills, and quest/waypoint progression, plus analytics: lifetime monster kills and time spent per area. Newer engine builds report each item's raw stats rather than a finished tooltip, so gear is rendered from the game's own tables — and holding Ctrl over an item swaps the tooltip for a breakdown: the range each modifier could have rolled within, the item level that decided them, and one labelled block per gem or rune instead of a merged total.
  • Item Search (d2bsng) - Search every character's gear by modifier, not just by name: "at least two resistances over 30", "any Amazon skill", "a Shako with 4 sockets". The ~1,200 searchable modifiers are derived from the game's own ItemStatCost table rather than written out by hand, so they are worded as the game words them. Conditions can be grouped with at-least-N and NOT, filtered by base item, type, tier, quality, runeword, item level and requirements, and the results sorted by clicking any modifier on them.
  • SOCKS5 Proxy (d2bsng) - Per-profile SOCKS5 proxy routing with a central Proxies tab for management, bulk import, and live connection testing.
  • Web UI - React frontend with Tailwind CSS, dark Diablo-inspired theme
  • Remote Access - Password-protected web interface accessible from anywhere
  • Real-time Updates - gRPC streaming for live profile status, console output, item drops
  • Item Rendering - DC6 sprite rendering with proper D2 color palettes and socket overlays
  • Discord Integration - Slash commands for remote control (/list, /status, /start, /stop, /restart, /mule, /schedule, /identify) and webhooks for items, console, and announcements
  • Key Management - Visual dashboard with round-robin rotation, usage tracking, hold/release
  • Scheduling - Automated profile scheduling with time-based rules (supports overnight ranges)
  • Drag & Drop - Reorder profiles and groups with drag-and-drop
  • Dual Mode - GUI (WebView2 desktop app) or headless server
  • Crash Safety - Job objects auto-kill child game processes if the manager crashes
  • Console - Real-time console output with source filtering, regex search, D2 color codes
  • Legacy API - Backwards-compatible D2Bot# HTTP API for external tools (Limedrop, D2BS scripts) with AES session auth, webhooks, and game action scheduling
  • Usage Statistics - Anonymous, opt-out counts of how the app is configured (how many profiles, which features are in use, Windows version) plus a periodic heartbeat. Never a name, path, key or address. See Usage Statistics

Remote Access

Edit d2botng.json or use the Settings page in the UI:

{
  "server": {
    "host": "0.0.0.0",
    "port": 5000,
    "password": "your-secret"
  }
}

When a password is set, the web UI will prompt for it on connection.

The Discord bot password is separate from the UI password — configure it independently in the Discord settings section.

Discord Bot

{
  "discord": {
    "enabled": true,
    "token": "your-bot-token",
    "serverId": "123456789"
  }
}

Use the Test Discord button in the Settings page to verify your configuration.

Discord Slash Commands

Command Description
/list List all profiles with status
/status <profile|all> Detailed profile status with stats
/start <profile|all> Start profile(s)
/stop <profile|all> Stop profile(s)
/restart <profile|all> Restart profile(s)
/mule <profile|all> Trigger mule run
/schedule <enable|disable> <profile|all> Control scheduling
/identify <password> Authenticate for privileged commands

Privileged commands (start, stop, restart, mule, schedule) require /identify first when a server password is set.

Usage Statistics

Official releases report anonymous usage to help decide what to work on. Turn it off in Settings → General → Usage Statistics; the switch applies immediately, to both the manager and the next game launched, with no restart.

What is sent is counts and yes/no answers — never a name, path, CD key, account or address:

  • Once per start: how many profiles, keys, schedules and frameworks exist, how many of them use each feature (proxies, Discord, scheduling), the game versions configured, and the machine's Windows version, core count, memory and whether it is running under Wine.
  • Every 12 hours: how many profiles are running, and how long the manager has been up.

Installs are counted by a hash of machine identifiers, so a returning install is not counted twice. The hash is derived on the fly and never stored.

Builds you compile yourself send nothing at all — the reporting key is baked in at build time from a secret that is not in this repository, and without it the whole feature is inert. D2BOTNG_ANALYTICS_HOST points a build at a different ingest host.

Command Line

D2BotNG.exe [options]

--headless    Run as server only (no GUI window)
--dev-ui      Proxy UI requests to Vite dev server

D2BS Compatibility

Full compatibility with D2BS:

  • Same command-line arguments (-d2c, -d2x, -handle, -profile)
  • WM_COPYDATA IPC messaging
  • DLL injection (LoadLibraryW remote thread)
  • Memory patches for various D2 versions
  • d2bs.ini generation with game paths and CD keys
  • All D2BS message types supported (heartbeat, status, console, items, key rotation, etc.)

Note: Built for x64, but still injects the 32-bit D2BS into the 32-bit game (it resolves the game's LoadLibrary address across the bitness boundary).

Development

Requirements

  • Windows 10/11 (x64)
  • .NET 10 SDK
  • Node.js 20+

Quick Start

# Build frontend
cd src/D2BotNG.UI
npm install
npm run build

# Build and run backend
cd ../D2BotNG
dotnet run

The web UI will be available at http://localhost:5000.

Dev Server

# Terminal 1 - Vite dev server with hot reload
cd src/D2BotNG.UI
npm run dev

# Terminal 2 - Backend with UI proxy
cd src/D2BotNG
dotnet run -- --dev-ui

The Vite dev server runs on port 4200, and the backend proxies UI requests to it in --dev-ui mode.

Checks

The same gates CI runs on every pull request. SkipUIBuild matters for the C# ones: the app project builds the frontend by default, which the backend checks do not need.

# C#
dotnet build src/D2BotNG/D2BotNG.csproj -p:SkipUIBuild=true
dotnet test tests/D2BotNG.Tests/D2BotNG.Tests.csproj -p:SkipUIBuild=true
dotnet format D2BotNG.sln --verify-no-changes
dotnet jb inspectcode D2BotNG.sln --project=D2BotNG --properties:SkipUIBuild=true --severity=WARNING

# TypeScript
cd src/D2BotNG.UI
npm run build
npx eslint src --max-warnings 0
npx prettier --check "src/**/*.{ts,tsx,css}"

dotnet build -p:RunFormat=true formats the solution before compiling, and -p:RunInspect=true writes an inspection report to src/D2BotNG/obj/inspect.sarif. Close the app first — a running D2BotNG.exe holds its own bin/ directory open and the build cannot replace it.

Building

Build produces a single D2BotNG.exe with the UI and all game assets embedded.

cd src/D2BotNG

# Self-contained — bundles .NET runtime, no prerequisites on target machine
dotnet publish -c Release --self-contained

# Framework-dependent — smaller exe, requires .NET 10 runtime installed
dotnet publish -c Release --no-self-contained

Output: bin/Release/net10.0-windows/win-x64/publish/D2BotNG.exe

Architecture

protos/              # Protobuf service definitions (source of truth)
src/
  D2BotNG/           # .NET 10 backend
    Services/        # gRPC service implementations
    Engine/          # Profile lifecycle, scheduling
    Windows/         # Win32 interop, DLL injection, IPC
    Data/            # Protobuf JSON persistence (data/ng/)
    Capture/         # Character captures: ingest, SQLite storage, stat search
    Rendering/       # DC6 sprite decoding
    Legacy/          # D2Bot# API compatibility (middleware, handler, models, migration)
    UI/              # WinForms + WebView2 host
  D2BotNG.UI/        # React 18 frontend
    src/
      features/      # Page components per feature
      components/    # UI component library + layout
      stores/        # Zustand state stores
      hooks/         # React Query mutations
      lib/           # gRPC client, auth, rendering
      generated/     # Protobuf-generated TypeScript types
tests/
  D2BotNG.Tests/     # xUnit — contract and invariant tests
Resources/           # DC6 sprites, palettes, fonts

Tech Stack

Layer Technology
Backend .NET 10, C# 13, ASP.NET Core, gRPC, Serilog
Frontend React 18, TypeScript, Vite 6, Tailwind CSS
State Zustand (real-time events), TanStack React Query (mutations)
Communication gRPC-Web via Connect-RPC
Desktop WebView2, WinForms, system tray
Windows P/Invoke, WM_COPYDATA IPC

How It Works

The backend manages Diablo II game processes through Win32 APIs:

  1. Launch - Creates a suspended game process, applies memory patches, resumes, injects D2BS.dll
  2. Communicate - D2BS scripts send messages back via WM_COPYDATA (JSON payloads)
  3. Monitor - Heartbeat tracking detects hung processes, crash recovery auto-restarts
  4. Stream - All state changes broadcast to connected web clients via a single gRPC server-stream

The frontend connects to a single StreamEvents gRPC call and receives all updates in real-time. Mutations (create, update, delete) return empty responses - the UI updates arrive through the event stream.

License

See LICENSE file.

About

Next generation implementation of D2Bot

Topics

Resources

Stars

12 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages