Dark Magic is a clean-room engine rewrite targeting feature parity with Diablo II: Lord of Destruction Expansion 1.13c and 1.14d. The project aims to reproduce the game's authored behavior and presentation on a modern, deterministic, scriptable engine while making the systems underneath it easier to inspect, test, extend, and mod.
Dark Magic is under active development and is not yet a complete Diablo II replacement. It does not distribute Blizzard assets; running the real-asset client and tools requires legally obtained Diablo II game data.
Most of Dark Magic has been implemented with repository-aware LLM coding agents under active maintainer direction. Agents are used for codebase analysis, research synthesis, implementation, tests, documentation, and repeated review passes. The maintainer sets the target, curates evidence, decides architecture, and remains accountable for every merged change.
This is not a bulk-generated “ship whatever the model wrote” codebase. Work is scoped to linked GitHub issues and milestone acceptance boundaries, checked against existing ownership rules, exercised by tests and real-asset tooling where appropriate, and revised or discarded when it does not hold up. Review focuses on the resulting evidence and maintainability, not whether every line was typed by hand.
Performance is handled deliberately. Egregious problems—unbounded work, repeated asset I/O, accidental quadratic paths, runaway allocation, or long owner-thread stalls—are corrected when discovered. Broader profiling and optimization passes normally follow coherent foundations, completed acceptance work, or milestone closure, when the code is stable enough to measure and worth tuning. Contributors are encouraged to use the same workflow described in CONTRIBUTING.md.
TODO: gameplay GIF — short loop showing real-asset
game_worldmovement, combat, drops, UI, and world presentation.TODO: labs GIF — short montage of Composite Lab, DT1/DS1 Lab, Monster Lab, Missile Lab, Mapgen Lab, Combat Lab, and Warp Lab.
Dark Magic has one authoritative, renderer-independent game simulation shared by offline play, listen servers, dedicated servers, and Realm-managed games. The current focus is completing Diablo II gameplay on that foundation rather than building parallel implementations for each mode.
The project deliberately targets:
- Expansion 1.13c and 1.14d feature parity. These releases share the core gameplay feature set; later patches added targeted fixes and platform changes. Known differences remain version-specific. Classic mode, other patches, and Diablo II: Resurrected are outside the product target. See the patch-history research for the evidence and its limits. Current owned game data and runtime probes are pinned to 1.14d; they do not by themselves verify 1.13c behavior.
- Faithful, evidence-driven behavior. Mechanics are reconstructed from game data, repeatable observation, reverse-engineering research, and independent implementations rather than guessed where evidence exists.
- One authoritative simulation. Networking, replay, checkpointing, offline play, and Realm play share the same gameplay boundaries.
- Lua-owned Diablo policy, Go-owned engine mechanisms. The first-party
d2legacypackage defines Diablo rules; Go owns reusable simulation, rendering, transport, storage, audio, and lifecycle infrastructure. - First-class modding. Versioned capabilities, deterministic content layering, and extension packages are part of the architecture rather than an afterthought.
Live implementation status and ordered work are tracked in the Roadmap project, issues, and milestones. See ROADMAP.md for the stable high-level direction and docs/ARCHITECTURE.md for package ownership and dependency rules.
Dark Magic has three cooperating process roles. They share versioned content and session contracts, but each owns a different boundary.
| Process | Responsibility |
|---|---|
client |
Native player-facing application. It owns input, windowing, audio, UI, rendering, local profiles, and asset/mod mounting. Offline and listen-server play can compose the same authority locally; remote play consumes authenticated, player-scoped views from a server. |
server |
Headless authoritative game-session process. It runs one deterministic simulation, validates player commands, owns canonical world state, and produces checkpoints and bounded per-player projections. It can run standalone for self-hosted play or as a Realm-supervised worker. |
realm |
Account and session control plane. It owns verified accounts, trusted Realm characters, channels and named games, worker allocation, admission, leases, checkpoints, durable commits, recovery, and audit. It allocates and supervises server workers but never executes gameplay ticks. |
Realm is deliberately topology-neutral. Its first deployment contract uses
PostgreSQL and ordinary server worker processes on one machine. The deferred
cloud target adapts that same contract to a Cloudflare/HTTPS edge, Kubernetes
ingress, managed PostgreSQL, and an Agones warm fleet of one-game server
workers. Protected game assets remain outside container images and public
storage and are mounted read-only only by game workers; native gameplay
continues over QUIC/UDP. Cloudflare, Kubernetes, Agones, and the chosen cloud
provider are deployment adapters rather than dependencies of Realm's domain
logic.
Cloud deployment is a target, not a claim that production manifests or hosted infrastructure already exist. See the Realm overview, cloud deployment contract, and networking architecture.
Set MPQ_DIRECTORY to a legally obtained Diablo II installation or MPQ
directory. The repository currently uses Go 1.25.
export MPQ_DIRECTORY=/path/to/diablo-ii
make play-game-worldRaylib is the default native client backend. An experimental Ebitengine build uses the same gameplay, Lua scenes, retained composer, logical input, and capture path:
go run -tags ebitengine ./cmd/client --start-scene ui_labUse make build-client-backends to compile both choices and
MPQ_DIRECTORY=/path/to/diablo-ii make profile-render-backends for a matched,
audio-muted A/B capture. See docs/PERFORMANCE.md for the
current compile/runtime measurements, known Ebitengine parity gaps, and artifact
layout.
The development labs are intentionally small entry points into production systems. They are useful both for contributors and for exploring what the engine can already do.
| Entry point | What it exercises | Run it |
|---|---|---|
| Game World | Authored world, player movement, camera, collision, UI | make play-game-world |
| Combat Lab | Production world + authoritative combat diagnostics | make play-combat-lab |
| Monster Lab | Typed monster records and composites | make play-monster-lab |
| Missile Lab | Typed missile records and presentation | make play-missile-lab |
| Spell Lab | Production assignment, casts, missiles, states, and summon families | make play-spell-lab |
| Warp Lab | Production movement, interaction, and level transitions | make play-warp-lab |
| Composite Lab | Player composite animation assembly | go run ./cmd/client --start-scene=composite_lab |
| DT1 Lab | Tileset decoding and inspection | go run ./cmd/client --start-scene=dt1_lab |
| DS1 Lab | Map stamps, authored tiles, objects, and collision | go run ./cmd/client --start-scene=ds1_lab |
| Map Editor | Standalone DS1 authoring tool; edit, preview, and atomically save tile layers | go run ./tools/ds1-editor --output=/path/to/mod |
| Mapgen Lab | Deterministic level-generation topology and decisions | go run ./cmd/client --start-scene=mapgen_lab |
Most visual scenes can also be captured locally through the Makefile capture targets. Captures remain outside the repository so original game imagery is not committed.
The README is intentionally only an orientation guide. Detailed design, implementation notes, evidence, acceptance criteria, configuration, and tooling live with the documents and packages that own them.
| If you are interested in... | Start here |
|---|---|
| Current progress and next work | Roadmap project, issues, and milestones |
| High-level product direction | ROADMAP.md |
| Engine boundaries and package ownership | docs/ARCHITECTURE.md |
| Diablo gameplay rules | internal/content/d2legacy and its Lua modules |
| Deterministic game/session mechanisms | internal/game |
| Client presentation and native rendering | internal/presentation and internal/platform/desktop |
| Realm, accounts, sessions, persistence, and deployment | docs/realm/README.md |
| Mod architecture and authoring | docs/MODS.md, docs/MODDING_API.md, and the mod_template |
| Game-system research and fidelity evidence | docs/research/GAME_SYSTEMS_INDEX.md |
| File-format provenance and codec policy | docs/formats/SOURCE_MATRIX.md and CODECS.md |
| Developer inspection/capture tools | internal/dev/tools and the Makefile |
| Process configuration | docs/CONFIGURATION.md |
At a high level, cmd contains composition roots, internal/game contains
generic deterministic game mechanisms, and internal/content/d2legacy contains
the first-party Diablo II rules/content package. There is intentionally no
public Go API under pkg; independently versioned Diablo file codecs live in
separate repositories.
Run the main test suites with:
make test
make test-raceBefore adding a long-lived engine component, read the architecture guide. Contribution expectations are kept in CONTRIBUTING.md.
Dark Magic exists because decades of Diablo II modders, preservationists, reverse engineers, tool authors, and independent engine developers documented behavior that the original executable kept implicit. The project descends from OpenDiablo2, but its current architecture and gameplay implementation are being rebuilt around Dark Magic's own boundaries and evidence requirements.
Principal research and corroboration sources include:
- Paul Siramy's research and tools and the wider Phrozen Keep community, especially for maps, formats, editing/generation, animations, and engine behavior.
- ThePhrozenKeep/D2MOO, a major reverse-engineered Diablo II 1.10f runtime reference.
- jaenster/libd2, including independent 1.14d implementation evidence and strong retail-capture/holdout verification.
- Riiablo, including format, composite, rendering, UI, quest, dialogue, and object research.
- OpenD2 and AbyssEngine as independent behavioral and presentation references.
- nokka/d2s, community data-format guides, historical patch notes, forum research, and the many tools and references cited in the repository's research ledgers.
These sources are evidence, not code-generation templates. Dark Magic restates behavior independently, respects source licenses, records version conflicts and uncertainty, and prefers repeatable observations of lawfully owned game data. Detailed provenance and confidence tracking live in the format source matrix, gameplay-systems source matrix, and research index.
If you have contributed research, tools, code, testing, documentation, or knowledge to the Diablo II community: thank you. Dark Magic is built on that shared body of work.
Join development and discussion on the Dark Magic Discord.