The zone walk and the runtime were the same types. A catalog carried the
walk's `Ptr → row` link maps, its half-captured names and its scratch into
the published result, so nothing said the linking was over except a
convention — and the runtime, which has no zone open any more, could not
have used them anyway.
Build and published types are now separate for materials, effects, tracers
and reticles: `MaterialDefinitions`, `FxDefinitions`, `TracerDefinitions`
are what a finished build hands on, `publish` is the only way to get one,
and the pointer lookups and absorbs stay behind on the builder. The
presence those pointers stood in for is one shared type, `AuthoredRef {
slot, alias }`. Every published asset type is free of zone pointers except
`WeaponCombatFx`, which waits on splitting `WeaponRegistry` the same way.
That split also turned up dead code the old types had hidden:
`resolve_after_absorb` looked weapon icons up by pointer after `finalize`
had emptied the map, so every lookup there returned `None`.
Map load is a transaction with one terminal outcome. Preflight assembles a
`MatchInstallPlan` — nothing to publish exists until every check that can
refuse has passed — and any refusal writes `MapLoadFailed` for the request,
including "no drawable world", which used to be a `MatchInstalled` the
lifecycle read as success and the UI read as failure. A canceled walk
returns `MatchLoadOutcome` instead of orchestrating on with empty products.
The match carries one material population (`PreparedMatch.materials`)
rather than reaching for it through geometry that may not exist, and the
transport schema around the boundary — the six `LoadCapture` wrappers,
`PreparedSpawn`, the doubly-owned map facts, `ZoneMemory` held to the end
of install — is gone.
Copies that had no reason to exist: the absorbs that already consume their
donor now move its rows instead of cloning every `ModelSkel` and
`RawXAnimParts`; sim and the dyn-ent physics share one `ClipMeshTables`
behind an Arc instead of each holding a deep copy of the collision.
Ownership on the live side follows the same cut. `SessionCore` takes a full
room identity and revision before any transport effect, so a stale
teardown cannot override a different match key. `HostMatchEvent::Applied`
carries no match key, so the peer's phase is its whole guard — it now
passes before anything is written, instead of landing a retired match's
connection id on the live peer on the way to being refused. `ClipStore` owns every PCM
conversion and every terminal decode failure, with Play/Stop on one ordered
channel scoped by namespace, entity and epoch. `SimContent` holds the
immutable definitions behind a consumed builder, so authority and
prediction share one backing instead of deep-copying per tick. Direct UDP
launch is removed; relay, listen and replay stay.
In the renderer each producer publishes whether its rows actually moved,
and the xmodel merge stops re-hashing seven producers' draws, materials and
vertex counts every frame to find out. Payload fields are `pub(crate)`
behind read-only accessors, so a consumer that wanted to finish a
producer's work no longer compiles. Colour extract is split from the
installed world, scene and shadow get their own bind caches, and record
census stays off the hot refusal path.
Docs: `CONTEXT.md` gains "Before shipping: the scaffolding goes back out",
and `make mr` and `cargo xtask mr` point at it. MAP-LOAD describes the
transaction as it now ends.
Scaffolding: the share and census probes that only proved the split are
out. What stays is five tests, each holding several independent systems to
one claim and each verified to fail when that claim is broken:
- one alias carried from two-zone capture through absorb, edge binding,
the alias-chain walk, the prep workers' decode and finally cancel —
every stage has to mean the same clip by it;
- a replacement match driven through all three cores that decide whether
a player is in one (host admission, session view, local load), then
every event the retired match still had in flight, replayed against a
live peer, moving nothing;
- a rejected room view leaving no bridge identity, membership, bootstrap
or admission effect behind;
- the seven draw producers published through their own API and asked of
the consumer that replaced the merge's per-frame hashing: the stamp
moves for exactly the producers whose rows moved;
- authority and prediction proved to share one immutable world by
tracing it, and to keep tracing their own after the other replaces it.
IW4L
IW4L is a standalone, experimental Call of Duty runtime written in Rust on top of bevy and wgpu. It reads the game data of an installation you already own and runs it in its own engine.
Development uses reverse engineering of the original binaries and public technical references to understand game data and behaviour. IW4L implements its own runtime architecture; it does not aim to reconstruct the original source code or to reproduce every behaviour exactly. Compatibility is incomplete, and behaviour may differ from the original games.
IW4L is not affiliated with, endorsed by or supported by the rights holders of the original games. No game assets are contained in this repository or in any IW4L release. You supply your own legally obtained installation.
This whole project is written by an LLM.
Scope
| area | what IW4L promises |
|---|---|
| IW4 / Modern Warfare 2 | the primary target of the runtime |
| IW5 (MW3) / T5 (Black Ops) | experimental: selected maps and weapons |
| IW4L multiplayer | experimental matches between IW4L clients |
| a drop-in replacement for the original games | not claimed |
| a general engine for every older CoD title | not claimed |
| the original network protocols, ABI or modified executables | not a goal, and no compatibility is promised |
Where reproducing a detail exactly would cost disproportionate complexity and the demo scenarios do not need it, IW4L implements it differently or leaves it out. That is a scope decision, not a blanket excuse: a desync in IW4L's own multiplayer is a bug in IW4L, while a difference from the original animation timing may be an accepted limitation.
What runs today
- loading IW4 maps, weapons, models, materials, effects and world geometry
- rendering the world, models, materials and effects
- player and entity simulation, animation, sound and effects
- p2p matches between IW4L clients, introduced through a master server
- selected IW5 and T5 data (see
docs/MAP-LOAD.mdfor what each lane actually accepts; MW3 x64 Steam zones are detected and refused)
Verified scenario for this cut: mp_boneyard from a retail MW2 multiplayer
install on Linux — map load, movement, weapons, bots and effects, driven by
make scenario and make chaos. Anything past that list is untested rather
than promised. Expect missing gameplay systems, incomplete compatibility, bugs
and desyncs.
Game data
IW4L needs a copy of the games whose content you want to load — MW2 for the
IW4 path, MW3 or Black Ops for the experimental lanes. Point IW4L_GAMES at
the folder holding those game trees.
The original installation is used read only. IW4L does not patch it,
replace files in it, or write into it; its own caches, settings, demos and logs
go to iw4l-artifacts/ next to the IW4L binary.
Build and run
cp .env.example .env # IW4L_GAMES — folder containing the game trees
make map mp_boneyard # run a map
make map mp_boneyard CMDS='spawn assault; wait 2s; quit'
make help # every recipe
Live runs use the [profile.play] profile, optimized for development builds.
PROFILE=release builds the full release binary. Windows setup is documented
in docs/WINDOWS.md.
Releases, network and updates
Builds are published as pre-releases (v0.1.0-demo.N, "IW4L Technical Demo
N"). Each one names the commit it was built from, the platforms it was actually
run on, the demo scenario and its known limitations, and carries LICENSE,
NOTICE and the bundled font licences. A platform appears in that list only
when a build for it was run, not when it merely compiled.
- Nothing is stable yet. The Rust API, the config format, caches, replay files and the network protocol may change between any two builds. Play a session on one release.
- The network is experimental, meant for arranged playtests between people who agreed to play. It is not a vetted environment for connecting to strangers.
- Updating is an explicit action. A release archive runs on its own; no build replaces its own binary without you asking it to.
- No telemetry. IW4L sends nothing home. Diagnostic files are yours to
attach to a report. The demo master keeps operational logs for its own
running; what it records is in
docs/MASTER.md. - The demo master is experimental infrastructure with no uptime promise. Running IW4L locally never depends on it, and you can run your own.
Security reports: SECURITY.md.
Documentation
Detailed implementation notes live under docs/ — start at
docs/INDEX.md.
| file | about |
|---|---|
docs/RUN.md |
running the game, console scripts, commands and traps |
docs/PERF.md |
Perfetto tracing and performance analysis |
docs/RENDER.md |
rendering pipeline |
docs/MAP-LOAD.md |
map loading and asset installation |
docs/ENTITIES.md |
simulation data flow and entity taxonomy |
docs/SIM-STEP.md |
simulation step architecture |
docs/ANIM.md |
animation system |
docs/WINDOWS.md |
portable Windows build |
docs/DEPLOY.md |
release, publishing and deployment |
docs/MASTER.md |
running your own master server |
Contributing and support
IW4L is a personal experimental project; see
CONTRIBUTING.md for what a useful bug report contains and
how changes are reviewed. Reports are welcome, with no promised fix date, and
"add everything the original had" is not a roadmap.
Acknowledgements
IW4L is written from scratch, but it was not worked out in a vacuum.
- OpenAssetTools and its iw4x-x64 fork — open-source modding tools whose asset-structure headers document the on-disk layouts IW4L reads.
- IW4x — a custom client for MW2 (2009); read as a cross-reference for asset and protocol behaviour.
- KisakCOD — an open-source CoD4 reimplementation; read as a cross-reference for engine structure in a neighbouring generation of the same engine family.
- Ghidra — the reverse engineering framework the original binaries were read with.
Nothing from these projects is vendored, linked or distributed with IW4L.
NOTICE carries the full attribution, their licences, and the
bundled fonts.
License
IW4L is licensed under the Apache License 2.0. Copyright and
attribution notices are in NOTICE.
This applies to the IW4L source code only. Call of Duty, Modern Warfare, Black Ops and related game assets, trademarks and other intellectual property belong to their respective owners and are not distributed with this project.
