1## Craft 2 3Minecraft clone for Windows, Mac OS X and Linux. Just a few thousand lines of C using modern OpenGL (shaders). Online multiplayer support is included using a Python-based server. 4 5http://www.michaelfogleman.com/craft/ 6 7![](http://www.michaelfogleman.com/static/img/craft1.png) 8 9### Features 10 11* Simple but nice looking terrain generation using perlin / simplex noise. 12* More than 10 types of blocks and more can be added easily. 13* Supports plants (grass, flowers, trees, etc.) and transparency (glass). 14* Simple clouds in the sky (they don't move). 15* Day / night cycles and a textured sky dome. 16* World changes persisted in a sqlite3 database. 17* Multiplayer support! 18 19### Download 20 21Mac and Windows binaries are available on the website. 22 23http://www.michaelfogleman.com/craft/ 24 25See below to run from source. 26 27### Install Dependencies 28 29#### Mac OS X 30 31Download and install [CMake](http://www.cmake.org/cmake/resources/software.html) 32if you don't already have it. You may use [Homebrew](http://brew.sh) to simplify 33the installation: 34 35 brew install cmake 36 37#### Linux (Ubuntu) 38 39 sudo apt-get install cmake libglew-dev xorg-dev 40 sudo apt-get build-dep glfw 41 42#### Windows 43 44Download and install [CMake](http://www.cmake.org/cmake/resources/software.html) 45and [MinGW](http://www.mingw.org/). Add `C:\MinGW\bin` to your `PATH`. 46 47Download and install [cURL](http://curl.haxx.se/download.html) so that 48CURL/lib and CURL/include are in your Program Files directory. 49 50Use the following commands in place of the ones described in the next section. 51 52 cmake -G "MinGW Makefiles" 53 mingw32-make 54 55### Compile and Run 56 57Once you have the dependencies (see above), run the following commands in your 58terminal. 59 60 git clone https://github.com/fogleman/Craft.git 61 cd Craft 62 cmake . 63 make 64 ./craft 65 66### Multiplayer 67 68Register for an account! 69 70https://craft.michaelfogleman.com/ 71 72#### Client 73 74You can connect to a server with command line arguments... 75 76 ./craft michaelfogleman.com 77 78Or, with the "/online" command in the game itself. 79 80 /online michaelfogleman.com 81 82#### Server 83 84You can run your own server or connect to mine. The server is written in Python 85but requires a compiled DLL so it can perform the terrain generation just like 86the client. 87 88 gcc -std=c99 -O3 -shared -o world -I src -I deps/noise deps/noise/noise.c src/world.c 89 python server.py [HOST [PORT]] 90 91### Controls 92 93- WASD to move forward, left, backward, right. 94- Space to jump. 95- Left Click to destroy a block. 96- Right Click or Cmd + Left Click to create a block. 97- 1-9 to select the block type to create. 98- E to cycle through the block types. 99- Tab to toggle between walking and flying. 100- ZXCVBN to move in exact directions along the XYZ axes. 101- Left shift to zoom. 102- F to show the scene in orthographic mode. 103- O to observe players in the main view. 104- P to observe players in the picture-in-picture view. 105- Arrow keys emulate mouse movement. 106- Enter emulates mouse click. 107 108### Chat Commands 109 110 /goto [NAME] 111 112Teleport to another user. 113If NAME is unspecified, a random user is chosen. 114 115 /list 116 117Display a list of connected users. 118 119 /login NAME 120 121Switch to another registered username. 122The login server will be re-contacted. The username is case-sensitive. 123 124 /logout 125 126Unauthenticate and become a guest user. 127Automatic logins will not occur again until the /login command is re-issued. 128 129 /offline [FILE] 130 131Switch to offline mode. 132FILE specifies the save file to use and defaults to "craft". 133 134 /online HOST [PORT] 135 136Connect to the specified server. 137 138 /pq P Q 139 140Teleport to the specified chunk. 141 142 /spawn 143 144Teleport back to the spawn point. 145 146### Screenshot 147 148![](http://www.michaelfogleman.com/static/img/craft3.png) 149 150### Implementation Details 151 152#### Terrain Generation 153 154The terrain is generated using Simplex noise - a deterministic noise function seeded based on position. So the world will always be generated the same way in a given location. 155 156The world is split up into 32x32 block chunks in the XZ plane (Y is up). This allows the world to be “infinite” (floating point precision is currently a problem at large X or Z values) and also makes it easier to manage the data. Only visible chunks need to be queried from the database. 157 158#### Rendering 159 160Only exposed faces are rendered. This is an important optimization as the vast majority of blocks are either completely hidden or are only exposing one or two faces. Each chunk records a one-block width overlap for each neighboring chunk so it knows which blocks along its perimeter are exposed. 161 162Only visible chunks are rendered. A naive frustum-culling approach is used to test if a chunk is in the camera’s view. If it is not, it is not rendered. This results in a pretty decent performance improvement as well. 163 164Chunk buffers are completely regenerated when a block is changed in that chunk, instead of trying to update the VBO. 165 166Text is rendered using a bitmap atlas. Each character is rendered onto two triangles forming a 2D rectangle. 167 168“Modern” OpenGL is used - no deprecated, fixed-function pipeline functions are used. Vertex buffer objects are used for position, normal and texture coordinates. Vertex and fragment shaders are used for rendering. Matrix manipulation functions are in matrix.c for translation, rotation, perspective, orthographic, etc. matrices. The 3D models are made up of very simple primitives - mostly cubes and rectangles. These models are generated in code in cube.c. 169 170Transparency in glass blocks and plants (plants don’t take up the full rectangular shape of their triangle primitives) is implemented by discarding magenta-colored pixels in the fragment shader. 171 172#### Database 173 174User changes to the world are stored in a sqlite database. Only the delta is stored, so the default world is generated and then the user changes are applied on top when loading. 175 176The main database table is named “block” and has columns p, q, x, y, z, w. (p, q) identifies the chunk, (x, y, z) identifies the block position and (w) identifies the block type. 0 represents an empty block (air). 177 178In game, the chunks store their blocks in a hash map. An (x, y, z) key maps to a (w) value. 179 180The y-position of blocks are limited to 0 <= y < 256. The upper limit is mainly an artificial limitation to prevent users from building unnecessarily tall structures. Users are not allowed to destroy blocks at y = 0 to avoid falling underneath the world. 181 182#### Multiplayer 183 184Multiplayer mode is implemented using plain-old sockets. A simple, ASCII, line-based protocol is used. Each line is made up of a command code and zero or more comma-separated arguments. The client requests chunks from the server with a simple command: C,p,q,key. “C” means “Chunk” and (p, q) identifies the chunk. The key is used for caching - the server will only send block updates that have been performed since the client last asked for that chunk. Block updates (in realtime or as part of a chunk request) are sent to the client in the format: B,p,q,x,y,z,w. After sending all of the blocks for a requested chunk, the server will send an updated cache key in the format: K,p,q,key. The client will store this key and use it the next time it needs to ask for that chunk. Player positions are sent in the format: P,pid,x,y,z,rx,ry. The pid is the player ID and the rx and ry values indicate the player’s rotation in two different axes. The client interpolates player positions from the past two position updates for smoother animation. The client sends its position to the server at most every 0.1 seconds (less if not moving). 185 186Client-side caching to the sqlite database can be performance intensive when connecting to a server for the first time. For this reason, sqlite writes are performed on a background thread. All writes occur in a transaction for performance. The transaction is committed every 5 seconds as opposed to some logical amount of work completed. A ring / circular buffer is used as a queue for what data is to be written to the database. 187 188In multiplayer mode, players can observe one another in the main view or in a picture-in-picture view. Implementation of the PnP was surprisingly simple - just change the viewport and render the scene again from the other player’s point of view. 189 190#### Collision Testing 191 192Hit testing (what block the user is pointing at) is implemented by scanning a ray from the player’s position outward, following their sight vector. This is not a precise method, so the step rate can be made smaller to be more accurate. 193 194Collision testing simply adjusts the player’s position to remain a certain distance away from any adjacent blocks that are obstacles. (Clouds and plants are not marked as obstacles, so you pass right through them.) 195 196#### Sky Dome 197 198A textured sky dome is used for the sky. The X-coordinate of the texture represents time of day. The Y-values map from the bottom of the sky sphere to the top of the sky sphere. The player is always in the center of the sphere. The fragment shaders for the blocks also sample the sky texture to determine the appropriate fog color to blend with based on the block’s position relative to the backing sky. 199 200#### Ambient Occlusion 201 202Ambient occlusion is implemented as described on this page: 203 204http://0fps.wordpress.com/2013/07/03/ambient-occlusion-for-minecraft-like-worlds/ 205 206#### Dependencies 207 208* GLEW is used for managing OpenGL extensions across platforms. 209* GLFW is used for cross-platform window management. 210* CURL is used for HTTPS / SSL POST for the authentication process. 211* lodepng is used for loading PNG textures. 212* sqlite3 is used for saving the blocks added / removed by the user. 213* tinycthread is used for cross-platform threading. 214