Web
  Analytics
Categories
Games

Generating a 7 Days To Die World with Rust


7 Days To Die uses a proprietary binary format for its world files. Although the complete file format is not officially documented, modders have reverse-engineered many aspects of it. In this article, we build a simplified version of a map generator in Rust. The resulting file (named “Map.dat”) is structured with a header, dimensions, and a flattened array of block types. With further modifications, you can expand it to include additional metadata or features required by your particular setup.

Project Setup

First, create a new Rust project:

cargo new map_generator
cd map_generator

Then add the byteorder crate to your Cargo.toml for easy binary writing:

[dependencies]
byteorder = "1.4"

Code Walkthrough

Below is a complete example with comments to help you understand each part.

use std::fs::File;
use std::io::{BufWriter, Write};
use byteorder::{LittleEndian, WriteBytesExt};

/// A simple representation of our map.
/// In this example, we define a 3D world with width, height, and depth.
/// The `blocks` vector is a flat array where each u8 represents a block type.
struct Map {
    width: u32,
    height: u32,
    depth: u32,
    blocks: Vec<u8>,
}

impl Map {
    /// Creates a new map filled with block type 0 (empty).
    fn new(width: u32, height: u32, depth: u32) -> Self {
        let total = (width * height * depth) as usize;
        Self {
            width,
            height,
            depth,
            blocks: vec![0; total],
        }
    }

    /// Set a block at a specific (x, y, z) coordinate.
    /// The flat index is calculated using row-major order.
    fn set_block(&mut self, x: u32, y: u32, z: u32, value: u8) {
        let index = (y * self.width * self.depth) + (z * self.width) + x;
        self.blocks[index as usize] = value;
    }

    /// Saves the map data into a binary file.
    /// The file format consists of:
    /// 1. A 4-byte magic header ("7DTD") to identify the file.
    /// 2. Three u32 values (little-endian) representing width, height, and depth.
    /// 3. A flattened block array.
    fn save_to_file(&self, filename: &str) -> std::io::Result<()> {
        let file = File::create(filename)?;
        let mut writer = BufWriter::new(file);

        // Write a magic header – this is a placeholder for the game’s required header.
        writer.write_all(b"7DTD")?;

        // Write dimensions of the world.
        writer.write_u32::<LittleEndian>(self.width)?;
        writer.write_u32::<LittleEndian>(self.height)?;
        writer.write_u32::<LittleEndian>(self.depth)?;

        // Write the block data.
        writer.write_all(&self.blocks)?;

        Ok(())
    }
}

fn main() -> std::io::Result<()> {
    // Create a new map with chosen dimensions.
    let mut map = Map::new(16, 64, 16);

    // Generate a simple flat world:
    //   - At y = 32, place ground blocks (type 1).
    //   - Below ground, fill with block type 2 to simulate underground material.
    for x in 0..16 {
        for z in 0..16 {
            // Set a ground block.
            map.set_block(x, 32, z, 1);

            // Fill all blocks below ground with a different type.
            for y in 0..32 {
                map.set_block(x, y, z, 2);
            }
        }
    }

    // Save the world to a binary file.
    map.save_to_file("Map.dat")?;
    println!("Map generated and saved to Map.dat");

    Ok(())
}

Explanation

File Structure

  • Header (“7DTD”): This magic header helps the game (or your custom loader) quickly recognize the file type. In an official or more advanced implementation, you might need to mimic the exact header used by 7 Days To Die.
  • Dimensions: The next 12 bytes (three 4-byte unsigned integers) specify the world’s width, height, and depth. This tells the game how to reconstruct the 3D grid.
  • Block Array: Finally, the world’s blocks are stored in a single vector. Each block is a byte that represents its type (e.g., empty, ground, underground). When loaded, the game can reconstruct the grid using the dimensions provided.

Code Highlights

  • byteorder Crate: This crate simplifies writing binary data in little-endian order, which is essential for many game file formats.
  • BufWriter: Using a buffered writer optimizes file output.
  • Flat Array Storage: A simple, row-major order array keeps the implementation straightforward.

Running and Testing Your Generator

Compile and run your project with:

cargo run

If successful, the program will create a Map.dat file in your project directory. You can then copy this file over to your 7 Days To Die world directory. Remember, this sample file is a minimal representation. In a real-world scenario, you might need to include extra metadata, versioning information, or additional sections to fully meet the game’s requirements.

Extending the Generator

Here are some ideas for extending this simple generator:

  • Noise-Based Terrain: Integrate a noise library (like noise) to create natural landscapes.
  • Additional Block Types: Introduce more block types to simulate water, trees, or ores.
  • Metadata Section: Include extra data (e.g., spawn points, light levels, biome information) to further align with the official file format.

By following this guide, you’ve created a basic Rust program that generates a binary world file compatible with the format used by 7 Days To Die. With further tweaks and enhancements, this can serve as a strong foundation for a custom map generator tailored to your modding needs.

Related posts:

bookmarkGames

Intro I’m gonna dive right into it – the 1.2 update for 7 Days to

Streaming Platforms for Gamers
bookmarkGames

Welcome to the Topic “Streaming Platforms for Gamers” Over the course of the past few

bookmarkGames

Heya fellow survivors! So, as we all know, “7 Days to Die” has been dishing