The Naming: Analyzing Minecraft c0.0.11a
The version where RubyDung died and Minecraft was born.
On May 16, 2009 — the same day rd-161348 shipped — Notch released another version. This one was different. Not in the number of files changed, not in the lines of code added, not in any single architectural leap. It was different because it had a name.
Minecraft 0.0.11a.
Not “rd-” followed by a timestamp. Not “RubyDung.” For the first time in this project’s life, the game had a version number that implied a future. Zero point zero point eleven alpha. A number that says: there will be a 0.0.12. There will be a 0.1. There will, eventually, be a 1.0. The timestamp-based versioning of the RubyDung era — where each build was identified by when it was compiled rather than what it contained — gave way to semantic versioning. The project had graduated from experiment to product.
The entry point class is now Minecraft.java. The window title reads “Minecraft 0.0.11a”. The HUD renders the version string “0.0.11a” in a bitmap font. These are cosmetic changes in isolation, but taken together they represent a commitment. Notch was no longer tinkering with a voxel prototype called RubyDung. He was building Minecraft.
What Changed
The Window
The window shrinks from 1024×768 to 854×480. This is an unusual resolution — not a standard 4:3 or 16:9 aspect ratio. 854×480 is approximately 16:9 (the exact ratio is 1.779:1, close enough to 16:9’s 1.778:1 that the difference is invisible). This is Minecraft’s first widescreen resolution, and it would persist for years. The choice suggests Notch was targeting the widescreen monitors that were becoming standard in 2009, while keeping the window small enough to coexist with a taskbar and other windows on a 1080p display.
The smaller window also means less rendering work per frame. At 1024×768, the GPU fills 786,432 pixels. At 854×480, it fills 409,920 — a 48% reduction. For a game running software-style immediate-mode OpenGL with per-face vertex submission, this is a meaningful performance improvement.
The Font System
This is c0.0.11a’s most significant technical addition. Font.java is a new class that loads default.gif — a 128×128 bitmap texture containing a grid of ASCII characters — and renders arbitrary text strings to the screen using textured quads.
The font system works like this:
-
Load
default.gifas a texture. The image is a 16×8 grid of characters, each cell 8×8 pixels. Characters are arranged in ASCII order starting from space (0x20). -
To render a string, iterate through each character. For each character, compute its position in the texture grid:
u = (char % 16) * 8,v = (char / 16) * 8. Emit a textured quad at the current screen position using those texture coordinates. Advance the screen position by 8 pixels. -
Text shadow: render the entire string once at offset (+1, +1) in a dark color, then render it again at the original position in the desired color. The shadow creates contrast against any background.
-
Color codes: the
&character followed by a hex digit (0-f) changes the current text color. Sixteen colors are available, matching a palette that will eventually become Minecraft’s standard chat color system. This is the foundation of the formatting system that survives to modern Minecraft.
The font is rendered in an orthographic projection overlaid on the 3D scene — the same HUD pass that draws the crosshair and block preview. Text is positioned in screen coordinates, not world coordinates. The font texture is loaded once and reused for all text rendering.
This is the system that will render chat messages, debug information, menu text, and every other piece of text in Minecraft for years to come. It is simple — bitmap fonts with fixed-width characters, no kerning, no Unicode beyond ASCII — but it is effective and fast. One texture lookup, one quad per character, no complex layout.
FPS on the HUD
The FPS counter moves from the window title to the HUD. In rd-161348, the frame rate was displayed by updating the window title string every second. In c0.0.11a, it is rendered using the new font system directly on the game view. The version string “0.0.11a” is rendered alongside it.
This is a small change with a large implication: the game now has a text rendering pipeline that can display arbitrary information on the screen. The window title is limited to a single string visible only when the window is not fullscreen. The HUD font can render multiple lines of text, in color, at any position on the screen, while the game is running. The debug overlay that modern Minecraft players toggle with F3 starts here, as two lines of text in the top-left corner.
Edit Mode Toggle
Previous versions had a single interaction mode: left-click destroyed blocks, and block placement (if it existed) was implicit or on a separate key. c0.0.11a introduces an explicit edit mode toggle. Right-click cycles between mode 0 (destroy) and mode 1 (place). Left-click executes whichever mode is active.
This is the first appearance of the destroy/place duality that defines Minecraft’s core gameplay loop. The implementation is minimal — a single integer that toggles between 0 and 1 — but the concept is fundamental. You break things or you build things. The entire game is this binary, and it starts here.
The isFree Check
When placing a block in mode 1, the game now checks whether the target position is free. “Free” means: no entity’s bounding box overlaps the block’s volume. The check iterates through all entities (the player and all zombies), tests each entity’s AABB against the proposed block position, and rejects the placement if any overlap is found.
This prevents two critical bugs:
1. The player cannot entomb themselves by placing a block at their own position.
2. The player cannot trap entities inside solid blocks.
The check is simple but architecturally significant. It is the first time that block placement considers entity positions — the first coupling between the block system and the entity system in the placement direction. (Block-entity coupling already existed in the collision direction: entities check blocks when moving. This adds the reverse: blocks check entities when being placed.)
The isFree() method lives on the Level class, taking an AABB parameter and returning true if no entity intersects it. This interface will persist, with modifications, through many future versions. The concept of “can I place something here?” remains relevant whenever Minecraft needs to validate block placement.
Y-Axis Mouse Inversion
Pressing the Y key toggles vertical mouse axis inversion. When inverted, moving the mouse up looks down and vice versa. This is Minecraft’s first user-configurable control option.
The implementation is a boolean field on the main class. When processing mouse input, the Y delta is negated if the flag is true. Simple, effective, and evidence that Notch was thinking about player preferences — not everyone agrees on which direction “up” should be.
Networking Foundation
The comm/ and server/ packages appear for the first time. SocketConnection.java, SocketServer.java, SocketListener.java — the infrastructure for multiplayer. NIO socket channels, connection state machines, packet serialization stubs.
None of this is functional. The networking code is scaffolding: classes exist, methods are defined, but no packets are sent and no connections are established during gameplay. The game remains strictly single-player. But the scaffolding tells us where Notch’s mind was. Multiplayer was not an afterthought bolted on later. It was being architected alongside the single-player game from the very beginning.
The networking code uses Java NIO (non-blocking I/O) rather than traditional blocking sockets. This is a sophisticated choice for 2009 Java game development. NIO allows a single thread to manage multiple connections without blocking, which is essential for a game server that needs to handle many clients while continuing to run the game loop. Notch was not planning for two-player LAN sessions. He was planning for a server.
Terrain Generation Extraction
In rd-161348, terrain generation was inline in Level.java. In c0.0.11a, it is extracted to LevelGen.java. The algorithm is the same — the same Perlin noise, the same height computation, the same water and lava placement, the same cave carving. But the code now lives in its own class with its own namespace.
This is a refactoring, not a feature change. The terrain looks the same, generates the same way, produces the same results. But the extraction makes Level.java shorter and makes LevelGen.java independently modifiable. Future versions can change terrain generation without touching the level management code. Separation of concerns, applied retroactively.
NoiseMap
PerlinNoiseFilter is renamed to NoiseMap. Same algorithm, same parameters, same output. The new name is arguably more descriptive — it is a map of noise values, not a filter that processes noise — but the change is purely cosmetic. The Perlin noise implementation continues to use the same octave summation, the same interpolation, the same scaling.
Zombie Death Floor
Zombies that fall below y = -100 are now removed from the entity list. Previously, zombies that fell below y = 100 (note: positive, not negative) were reset — teleported back up to a spawn position. The new behavior is simpler and more permanent: fall far enough and you die.
The threshold change from positive 100 to negative 100 is significant. The world’s ground level is approximately y = 64. A zombie at y = 100 is 36 blocks above ground — a zombie that has somehow climbed or been pushed to a high point, but is still within the normal game world. A zombie at y = -100 is 164 blocks below ground — a zombie that has fallen through a cave, through lava, through the void, well below any reachable terrain.
The old behavior (reset at y > 100) seemed wrong — it would reset zombies that were just at a high altitude. The new behavior (remove at y < -100) is targeted at zombies that have genuinely fallen out of the world, and the response (deletion rather than reset) is cleaner. No teleportation, no respawning. Just removal.
Entity List Generalization
The entity list changes from ArrayList<Zombie> to ArrayList<Entity>. Zombies are still the only entity type (besides the player), but the list can now hold any entity subclass. This is preparation for future entity types — animals, items, projectiles — without requiring a separate list for each.
Tesselator: noColor Flag
The Tesselator gains a noColor flag. When set, the tesselator skips color attribute submission for vertices. This is an optimization for geometry that uses a single color (white) — rather than submitting four bytes of color data per vertex, the color is set once via glColor and the per-vertex color is omitted. For a system that submits thousands of vertices per chunk, eliminating four bytes per vertex is a meaningful bandwidth reduction.
MinecraftApplet Expansion
MinecraftApplet grows from a 6-line empty stub to a 74-line class with a full applet lifecycle: init(), start(), stop(), destroy(), paint(). The applet creates a Minecraft instance, manages its thread lifecycle, and handles canvas rendering. This is the infrastructure needed to run Minecraft as an embedded Java applet in a web browser — which is, in fact, how many early players first experienced the game.
The applet is not relevant to the Rust port (applet is a Java web deployment mechanism with no Rust equivalent), but its expansion tells us that Notch was preparing to distribute the game via web pages. The classic Minecraft “play in browser” experience starts with this 74-line class.
The Identity Transition
The most important thing about c0.0.11a is not any individual feature. It is the naming.
Five versions in three days (May 14-16, 2009): rd-20090515, rd-160052, rd-161348, and now c0.0.11a. The first three were RubyDung builds, identified by timestamps, iterating on a voxel engine prototype. The fourth is Minecraft 0.0.11a, identified by a version number, declaring itself a game.
The “c” prefix in “c0.0.11a” stands for “classic” — a retronym applied later to distinguish these early versions from the subsequent Indev, Infdev, Alpha, Beta, and Release phases. At the time, this was just “0.0.11a.” The first Minecraft with a version number.
The transition from timestamp to version number is a commitment to continuity. Timestamps are anonymous: each build stands alone, identified only by when it was compiled. Version numbers are sequential: 0.0.11a implies 0.0.10, and promises 0.0.12. The project has a past and a future. It has a trajectory.
RubyDung.java becoming Minecraft.java is the same commitment in code. The entry point class is what you see when you open the project. It is the first file you read, the class that main() lives in. Renaming it is a statement of identity. This is not a voxel engine experiment named after a Ruby Roguelike. This is Minecraft.
What Did Not Change
The core game is the same game it was in rd-161348:
- Level generation: same Perlin noise, same height map, same caves, same water/lava placement. Extracted to LevelGen but functionally identical.
- Player physics: same 20 TPS constants. 0.1 ground speed, 0.02 air speed, 0.08 gravity, 0.5 jump velocity, 0.7 ground friction. The player feels the same.
- Tile system: same six tile types (air, rock, grass, dirt, stone brick, wood, bush). Same properties. Same rendering.
- Particle system: same deterministic age/lifetime death, same 0.04 gravity, same 0.4x speed factor with 0.1 upward bias. The revert from rd-161348 is preserved.
- Zombie AI: same random movement, same model, same rendering. New death floor at y < -100, but otherwise identical.
- Bush: still alive, still X-shaped, still dying in darkness.
- Collision: same AABB system, same physics integration.
- Save/load: same gzip-compressed level format.
The game that you play in c0.0.11a is recognizably the same game as rd-161348. The world looks the same. The player moves the same. The blocks break the same way. What changed is the infrastructure around the game: how text is rendered, how interactions are structured, how the project identifies itself.
By the Numbers
| Metric | rd-161348 | c0.0.11a | Delta |
|---|---|---|---|
| Files | 28 | 38+ | +10 |
| Window resolution | 1024×768 | 854×480 | -48% pixels |
| HUD text | None | Version + FPS | New |
| Font system | None | Bitmap font (default.gif) | New |
| Edit modes | Implicit | Explicit toggle (destroy/place) | New |
| Block placement check | None | isFree (entity AABB test) | New |
| Mouse Y inversion | Not available | Y key toggle | New |
| Networking | Not present | Scaffolding (deferred) | Stub |
| Entity list type | ArrayList\<Zombie> | ArrayList\<Entity> | Generalized |
| Zombie death condition | y > 100 (reset) | y < -100 (remove) | Changed |
| Terrain gen location | Inline in Level | Extracted to LevelGen | Refactored |
| Noise class name | PerlinNoiseFilter | NoiseMap | Renamed |
Looking Forward
c0.0.11a is a pivot point. Everything before it was RubyDung — a prototype, an experiment, a series of timestamped builds testing what a voxel game could be. Everything after it is Minecraft — a product with a version number, a font system, a networking stub, and a name.
The features added in this version are modest individually. A font renderer. An edit mode toggle. A placement validation check. A mouse inversion option. Networking scaffolding that does nothing. But collectively, they transform the project from “voxel engine that renders blocks” to “game that has a UI, validates user actions, and is being prepared for multiplayer.”
The font system alone changes the game’s communicative capacity. Before c0.0.11a, the game could display exactly three things: the 3D world, a crosshair, and a block preview. After c0.0.11a, it can display arbitrary text. Version strings. Frame rates. Eventually: chat messages, inventory labels, menu options, death screens, achievement notifications. Every piece of text you have ever seen in Minecraft traces its lineage back to this 128×128 bitmap of ASCII characters in default.gif.
The edit mode toggle changes the game’s interactive grammar. Before: you break blocks. After: you break blocks or you place blocks, and you choose which. The entire creative potential of Minecraft — building houses, bridges, castles, pixel art, redstone computers — depends on the ability to place blocks where you want them. That ability starts here, as a right-click toggle between mode 0 and mode 1.
The isFree() check changes the game’s relationship with its own rules. Before: the game trusts the player to place blocks sensibly. After: the game enforces physical constraints. You cannot entomb yourself. You cannot trap zombies in solid blocks. The game has opinions about what is valid. This is the beginning of Minecraft as a system that maintains invariants, not just a sandbox that does whatever you tell it.
RubyDung was an engine. Minecraft is a game. The difference is everything that c0.0.11a adds: text rendering, interaction modes, physics validation, and a name.
The version number says 0.0.11a. The ambition says: this is the beginning of something.