Minecraft × Counter-Strike bridge · Technical report · 8 October 2026

MineStrike 1.6

MineStrike 1.6 embeds Minecraft Java Edition gameplay in Counter-Strike 1.6 without modifying the engine binary. The Counter-Strike client library is closed-source. Its interface was recovered by static analysis of the shipped PE binaries and by instrumenting live calls, and it is extended through a proxy library that forwards all 42 exports. The server library is built from ReGameDLL_CS. The map de_dust2 is parsed, rendered and collided against by the modification itself. This allows any part of the original geometry to be excavated while the engine's movement behaviour is kept. That behaviour was checked against the engine on 4,000 randomized hull traces.

Figure 1. Excavation of de_dust2 in classic mode. The map is drawn by the modification from the original BSP file. Each removed 40-unit cell exposes cross-sections of the surrounding solid space, textured with the map's own WAD textures.
42client exports forwarded by the proxy, 17 of them wrapped
99.9%of 4,000 randomized hull traces end where the engine's do
5,383de_dust2 faces decoded and drawn by the modification
24,697lines of C++ (client, server, shared)
102Minecraft sound events, 311 variants
29scripted in-game test scenarios
Figure 2. Elytra flight over the block version of de_dust2: T spawn, mid, CT spawn, A site and long A. Glide physics follow LivingEntity.travel; firework rockets boost the glide. The middle stretch is the third-person camera.
1 · Method

Reverse engineering of the shipped binaries

The engine (hw.dll, HL25 build 10210) and the official Counter-Strike client (client.dll) are distributed only as 32-bit PE binaries. No source code or symbol files for either were used. Analysis proceeded in two stages.

Static analysis

Three purpose-written tools in tools/re/ parse the binaries directly. pe_exports.py reads the export directory. pe_info.py reads the section table and image base, and maps virtual addresses to file offsets. strings.py scans for printable strings with a regular-expression filter. Together they establish the exported entry points and their order, and the command names, console variables and error messages each binary contains.

Dynamic analysis

The proxy library logs every call it forwards, with arguments, which shows the calling order and the data that crosses each entry point. On the server side, mc_msgtrace intercepts the engine's user-message functions (RegUserMsg, MessageBegin, Write*). It records every message sent to a client, so a working and a failing session can be compared message by message.

FindingMethodConsequence for the design
The client exports the API-proxy entry point F. The engine passes it a function table with some slots already filled in: the destination-address and module-function conventions of APIProxy.h.Export table; call loggingThe proxy must call the original F on the engine's own buffer, then overwrite only the slots it wraps. Building a fresh table makes the engine fail to initialize.
The client copies the engine function table during Initialize and registers its commands later, in HUD_Init, through that copy.Call loggingThe proxy swaps pfnAddCommand and pfnHookUserMsg only for the duration of the original Initialize. That is how slot1–slot10, invnext, invprev and buy are redirected to the hotbar.
hw.dll maps the -game directory name to a Steam application ID: cstrike is 10, any other name is 70.Strings; engine logA separate mod directory fails Steam authentication. The modification is installed into a private copy of cstrike.
The argument of HUD_Frame is the frame interval, not a timestamp.Call loggingAll client animation is driven by GetClientTime(). An earlier build froze because it treated the argument as a clock.
The thirdperson command is registered but has no effect in this client build.Strings; runtime testThe modification has its own camera, and wraps CL_IsThirdPerson so the engine draws the local player model.
Esc is consumed by the engine's menu before HUD_Key_Event is called.Call loggingIN_DeactivateMouse is wrapped and used as the signal to close the modification's screens.
The renderer runs an OpenGL 4.6 compatibility context. Inside HUD_DrawNormalTriangles, program 0 is bound and the fixed-function matrices are valid.GL state queriesThe GLSL renderers draw in that callback, then restore the engine's state.
The HL25 default configuration binds the right mouse button to +alt1 (IN_ALT1, bit 14), not +attack2.Configuration files; input loggingThe server treats both bits as the use action. Scripted tests that set IN_ATTACK2 had passed while real clicks did nothing.
2 · Server

Game logic on ReGameDLL_CS

The server library mp.dll is built from ReGameDLL_CS, an open-source reimplementation of Counter-Strike's game library, with a Minecraft module attached through its hook chains: spawn, damage, death, think, item use and buying. Minecraft's rules were reimplemented from the behaviour of the corresponding Java Edition 1.21 classes. These include FoodData (food level, saturation, and an exhaustion threshold of 4.0), the attack-damage and attack-speed tables with cooldown, critical hits, sweep and knockback, and the armor and toughness damage formula. Elytra flight follows LivingEntity.travel, and explosions use the ray-cast model. One Minecraft health point is 5 Counter-Strike health points. The player inventory uses the slot numbering of InventoryMenu, plus one extra slot (46) for disposal. Inventory clicks are server-authoritative: the client sends only the slot, the button and the Shift state. The network delta description (delta.lst) is widened so that player flags, armor codes and firework boosts reach client-side prediction.

3 · Map

Collision and rendering of an excavatable de_dust2

In classic mode, the engine loads a sealed, empty sky-box map. The modification loads de_dust2.bsp (BSP version 30) itself: 9,582 planes, 2,766 nodes, 8,321 clipnodes, 5,383 faces and 10 solid brush models.

Collision

Hull traces follow the engine's recursive hull check as implemented in ReHLDS, an open-source reimplementation of the engine. Hull selection follows SV_HullForBsp. Hull 0 is derived from the node tree, and hulls 1–3 come from the clipnodes. Traces from the player-movement code in both libraries pass through one shared function, so client prediction matches the server.

Excavation

The map is overlaid with a 40-unit grid. Each cell is untouched, excavated, or holds a placed block. When a trace touches excavated space, it switches to a carve-aware path. That path intersects each intact cell with the solid leaves of hull 0, which gives a set of convex pieces, then sweeps the player box against those pieces with bevel planes, as Quake III does against brushes. The switch happens only when the contact point itself lies in excavated space. An earlier rule, which switched near any excavation, caught players on hole edges.

Rendering

Textures are decoded from the WAD3 miptex data and stored in one texture array. Lightmaps are packed into a 2048 × 2048 atlas. Geometry is built in chunks of 8³ cells. Faces are clipped per cell where cells have been removed, and the exposed cross-sections are produced by clipping polygons through the BSP tree.

de_dust2 rendered by the Half-Life engine
Figure 3a. Reference view, drawn by the engine.
The same view drawn by the modification from the BSP file
Figure 3b. The same view, drawn by the modification from the BSP file.
An excavated cell in the dust2 floor
Figure 4. An excavated cell. The walls of the cut are generated from the map's solid space and align with the surrounding brushes.
Cobblestone blocks placed on the dust2 floor
Figure 5. Placed blocks. Each one occupies a cell in front of the surface that was hit.
A second view of de_dust2 drawn by the modification
Figure 6. A second comparison view. The baked lightmaps are reproduced with a configurable brightness curve.
4 · Survival systems

Inventory, hunger and regeneration

The survival inventory (Shift+E) implements Minecraft's click semantics. Left-click picks up, places or swaps a stack. Right-click splits a stack or places a single item. Shift-click moves a stack to its preferred destination: armor to the armor slots, hotbar to storage and back. Picked-up items fill the hotbar first, then the 27 storage slots. Partial stacks are accepted when space is short. On death, every weapon and item the player carries is dropped.

Counter-Strike's fixed health is replaced by Minecraft's food model. Movement, jumping, attacking, taking damage and healing add exhaustion. Every 4.0 points of exhaustion consumes one point of saturation, or one point of food when saturation is exhausted. With full food and saturation, the player heals every 10 ticks. At 18 food or more, the player heals every 80 ticks. At zero food, the player starves down to one health point. A golden apple grants Regeneration II for 5 s and 4 absorption points.

The survival inventory with diamond armor equipped and a Diamond Pickaxe tooltip
Figure 7. The survival inventory: armor slots, a preview of the player model, the 2×2 crafting grid and item tooltips.
Holding a golden apple, with two absorption hearts above the health bar
Figure 8. After a golden apple: two absorption hearts above the health row.
The HUD: armor, absorption, health, hunger, and a hotbar with a pistol and a knife
Figure 9. The HUD. Hotbar slots 1–5 hold the Counter-Strike weapons. Their icons are generated from the game's own weapon images by tools/assets/gun_icons.py.
5 · Combat and world rules

Hit boxes, fire and block light

Three places where Counter-Strike's rules disagreed with what the player sees, or with Minecraft's own rules, were resolved in favour of the latter.

Hit boxes

The client draws Minecraft models in place of Counter-Strike's, but the engine went on tracing bullets against the hidden Counter-Strike model. A Minecraft head is twice as wide as that model's, a creeper's head is lower, and an enderman's head lies entirely above it, so a shot at an enderman's head was a miss. For players drawn as Minecraft models, the engine's hit boxes are now switched off for the duration of each line trace, and the trace is completed against the cubes the client draws, in the same pose: head pitch, crouch, the arm pose of the held weapon, gliding, and a creeper's swelling. The cube that is hit sets the hit group, so a head shot is a shot at the drawn head. Bots aim at the drawn head or chest.

Armor wear

Minecraft removes max(1, damage / 4) durability from each armor piece per hit, and its half-second invulnerability window limits hits to two per second. A rifle lands ten per second, and armor that removes 90% of the damage lets its wearer survive many more of them, so armor wore out several times faster than its durability figures intend. Wear is now charged once per half-second window, sized by the largest hit in it. Every bullet is still reduced by the armor.

Fire

Flint and steel lights a fire on a floor or against anything flammable. Fire is a port of FireBlock.tick with its odds. A fire block has an age from 0 to 15 and ticks every 30 to 39 game ticks. On each tick, a plank-like neighbour burns out with probability 20 in 300 from the side and 20 in 250 from above or below, and each nearby air cell that touches something flammable ignites with a probability of a few percent. A fire with nothing flammable beside it goes out. In classic mode the crates and wooden doors of de_dust2 burn like planks, and TNT is primed. A player in fire loses one Minecraft health point every half second and stays alight for 8 s after leaving it.

Block light

The classic map is lit by its baked lightmaps, which cannot respond to a fire or a torch. Block light is therefore computed separately, as Minecraft computes it: a flood fill over the 40-unit cells from each source (fire 15, torch 14, glowstone and lit lamps 15) that loses one level per cell and is stopped by opaque blocks and by cells inside the map's solid space. The levels are held in a 3D texture that both renderers sample per pixel, half a cell off the surface, through the brightness curve and warm tint of LightTexture. The result is added to the baked light and clamped, so shaded areas are lifted and daylight is unchanged. Torches stand on floors or lean from walls, and drop when their support is removed.

A tunnel of de_dust2 in shadow
Figure 10a. A tunnel of de_dust2 under the baked lightmaps alone.
The same tunnel lit by one torch standing on the floor
Figure 10b. The same view with one torch on the floor. The light falls by one level per cell and is stopped by the walls.
An enderman with its hit boxes outlined, between a zombie and a creeper
Figure 11. The hit boxes of an enderman, outlined by mc_hitbox_show. The head lies above the 72-unit Counter-Strike hull.
Flames on a stack of de_dust2 crates
Figure 12. A stack of de_dust2 crates about 45 s after ignition, at Minecraft's rates. The fire has taken hold of a few cells and most of the stack is intact.
6 · Operation

Launch configurations and controls

Three launchers in the repository root start a local, offline listen server with bots:

  • PLAY_MineStrike_dust2.bat: classic mode. The original de_dust2 with standard rounds, bomb sites, buy zones and player models, and the map can be excavated.
  • PLAY_Minecraft_dust2.bat: de_dust2 converted to 123 × 141 × 37 Minecraft blocks, with mobs.
  • PLAY_classic_dust2_with_Minecraft_items.bat: the unmodified map with the Minecraft items and HUD only.

Setup requirements are listed in README.md. Counter-Strike's files come from the user's own installation. Minecraft assets are downloaded from Mojang's servers for the user's own account. Neither is included in this repository.

BCounter-Strike buy menu; in creative mode, the Minecraft creative inventory
Shift+ESurvival inventory
1–5 / 6–9Counter-Strike weapons / Minecraft hotbar
Mouse 1Attack, or hold to mine
Mouse 2Use: place, open, eat, equip, throw, fire
Space while fallingElytra glide
F5Camera: first person, rear, front
GDrop the held item
7 · Recordings

Scripted scenarios

Each recording is a scripted scenario executed in the unmodified engine and captured from the game window. The server drives the local player. No frame was edited.

Melee combat. A diamond sword against a bot: attack cooldown, critical hits, knockback, experience orbs and an advancement.
Creeper. Approach, 1.5 s fuse with swelling, then a ray-cast explosion that removes 91 blocks.
Enderman. Every projectile hit is converted into a teleport; melee damage is applied normally.
Creative inventory. Operated with real mouse clicks and key presses.
Mining. Break times by tool tier and material, crack stages, fragments and drops.
TNT. Ignition with flint and steel, the fuse, and the explosion's effect on terrain.
Items. Bow, ender pearl, Bottle o' Enchanting, fireworks, golden apple, and a totem of undying absorbing a 500-damage hit.
Tour. HUD, text-menu fallback, a door, and a take-off.
8 · Additional figures

Models and interface

Third-person view of a player gliding on an elytra
Figure 13. Elytra in third person, posed as in ElytraModel.
Creative inventory with a Diamond Sword tooltip
Figure 14. Creative inventory with attribute tooltips, drawn with Minecraft's own textures.
Kits tab laid out like saved hotbars
Figure 15. Equipment kits, laid out like Minecraft's saved hotbars.
Advancement toast after a kill
Figure 16. An advancement notification and a death message in Minecraft's wording.
Third-person Minecraft player model in diamond armor
Figure 17. The player model, a port of HumanoidModel with armor layers.
A second de_dust2 reference view drawn by the engine
Figure 18. Reference view drawn by the engine (pair of Figure 6).
9 · Architecture

Components and toolchain

Toolchain

clang-cl and lld cross-compile 32-bit Windows libraries against the MSVC runtime and Windows SDK, obtained with xwin. No Visual Studio installation is required. CMake and Ninja drive the build.

Block-world conversion

A voxelizer samples BSP point contents at half-block resolution, keeps thin walls watertight, and maps WAD textures to blocks. It then compiles a sealed shell map with SDHLT for the engine to load. Bot navigation meshes are generated from the voxels.

10 · Verification

Methodology and results

Collision was checked against the engine directly. With the engine running the real de_dust2, mc_bsptest fires randomized traces through both the engine's trace function and the modification's, and compares the end position, the start-solid flag, the surface normal and the point contents. Each gameplay feature has a scripted scenario. The server drives the local player and logs checkpoints, and a runner captures the game window at each one. Where noted, input is real: key presses and mouse clicks sent to the game window.

Collision measurementResult
Hull traces, all four hulls, intact map (4,000)3,996 identical end positions (99.9%). The 4 disagreements, and the 3 start-solid disagreements, occur only on traces that start inside solid space.
Cost per trace, intact map0.74 µs for the modification, 0.47 µs for the engine
Carve-aware path against the engine, point hull (250)0 disagreements
Carve-aware path against the engine, hulls 1–3 (750)131 disagreements (17.5%). These come from player-clip brushes, which exist only in hulls 1–3 and are absent from the pieces derived from hull 0.
Cost per trace, carve-aware path52.7 µs, used only for contacts in excavated space
ScenarioObservationResult
viewsEight reference views drawn by the engine and by the modification. The geometry and textures agree; the modification's output is slightly darker, by an engine-to-modification ratio of about 1.05 in red, 1.1 in green and 1.2–1.3 in blue.PASS
pitReal key input: entering a newly excavated pit, moving along its edge, leaving itPASS
placeReal right-clicks place blocks on floors and wallsPASS
invPick up and place stacks, Shift-click armor into its slots, delete an item in the disposal slotPASS
foodBread raises food from 14 to 19. Natural regeneration raises health from 85 to 90 within 4 s. A golden apple adds 20 absorption HP.PASS
combatDamage and cooldown, death, experience orbs, level-up, advancementPASS
flight / elytraGlide physics; firework boost to about 1,300 units/sPASS
mine / tntBreak times, drops, crack overlay, explosion craterPASS
creeper / creeperwatchFuse after 1.5 s; 100→54 HP through diamond armor; in a live round the creeper crossed the map to the playerPASS
endermanBullet hits cause a teleport and no damage; three sword hits killPASS
itemsEnder pearl teleport (−25 HP); the totem survives 500 damagePASS
guiReal clicks through the creative inventory, including a kit and a number-key transferPASS
changelevelde_dust2 → mc_dust2 → de_dust2 with the inventory preservedPASS
hitboxReal AK-47 shots at the drawn models: the middle of an enderman's head and the edge of Steve's head are head shots, a shot just above a creeper's head misses, a zombie's chest is a chest hit. A bot's aim at the head and at the chest of each model lands on that cube. Ten 36-damage hits in one window cost an armor piece 1 durability.PASS
fireFlint and steel on a crate stack of de_dust2, at Minecraft's rates: 1 flame became 7 in about 20 s, the first of 82 crate cells burned out 20 s after ignition, and 9 had gone after 40 s. At eight times the rate, a wooden door burned through and fell as one piece. A player in the fire lost health and stayed alight after leaving it.PASS
lightA torch lights a tunnel, and the view returns to the baked lighting when it is removed. A torch whose supporting blocks are removed drops as an item. A fire lights its surroundings.PASS
userflowReal input from the launcher through the MOTD, team selection, spawn and inventoryPASS

Defects found in interactive testing

  • Block placement ignored real right-clicks, because of the +alt1 binding described in section 1.
  • Players stopped at the edges of excavations. The carve-aware path had taken over anywhere near excavated space; it now takes over only when the contact lies in it.
  • Items could not be picked up once the hotbar was full. Fixed by adding inventory storage and partial pickup.
  • Clicks arrived as Shift-clicks after the inventory was opened with Shift+E, because the tracked modifier state stuck. Modifier state is now read from the operating system.
  • Held items were mirrored by an obsolete transform. They now use Minecraft's first-person transforms exactly.

Defects found by scripted tests

  • The team menu was lost after the MOTD. The round restart dropped the queued menu, and equipping unjoined players re-sent the MOTD.
  • All client animation froze, because of the HUD_Frame argument described in section 1.
  • Particle texture names were corrupted, because they were referenced through pointers into a vector that reallocates.

Limitations

  • The carve-aware collision ignores player-clip brushes, as measured above.
  • Lightmap brightness differs slightly from the engine's.
  • Esc closes the modification's screens but also opens the engine menu.
  • Bots use Counter-Strike weapons only. Minecraft items are not yet drawn on Counter-Strike player models in third person.
  • The hit boxes of Minecraft models do not follow the walk swing of arms and legs.
  • Block light is computed on the 40-unit grid. A wall that does not cover a cell centre does not stop it.
  • All verification so far was done by the author. No independent review has taken place.
11 · Further work

In progress