mirror of
https://github.com/Cactus-minecraft-server/World.git
synced 2025-12-07 10:40:37 +00:00
starting procedural generation
This commit is contained in:
@@ -4,3 +4,4 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
noise = "0.9.0"
|
||||||
|
|||||||
69
TODO.md
Normal file
69
TODO.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# TODO List for a Minecraft-Like Terrain Generator in Rust
|
||||||
|
|
||||||
|
## 1. Define Objectives and Requirements
|
||||||
|
- **Features:**
|
||||||
|
- Global terrain generation (overall elevation)
|
||||||
|
- Local detail (surface variations)
|
||||||
|
- Biome transitions and optionally cave systems
|
||||||
|
- **Technical Constraints:**
|
||||||
|
- Chunk dimensions (e.g., 16×16 blocks horizontally with a fixed vertical height)
|
||||||
|
- Memory management (chunk caching, on-demand generation)
|
||||||
|
- Server integration (protocol, networking, etc.)
|
||||||
|
- **Output Format:**
|
||||||
|
- How to represent the world (e.g., a 3D array of block types)
|
||||||
|
- Block types (Air, Grass, Dirt, Stone, Water, etc.)
|
||||||
|
|
||||||
|
## 2. Research and Select Noise Algorithms
|
||||||
|
- Study noise algorithms such as Perlin and Simplex.
|
||||||
|
- Understand Fractal Brownian Motion (fBm) to combine multiple octaves.
|
||||||
|
- Define parameters like frequency, amplitude, persistence, number of octaves, and scaling factors.
|
||||||
|
|
||||||
|
## 3. Set Up Your Rust Project
|
||||||
|
- Create a new project with Cargo.
|
||||||
|
- Add necessary dependencies in `Cargo.toml` (e.g., the `noise` crate).
|
||||||
|
- Set up version control (Git).
|
||||||
|
|
||||||
|
## 4. Implement Basic Noise Generation
|
||||||
|
- Write a simple prototype to generate noise values.
|
||||||
|
- Use a scaling factor to avoid sampling only on integer coordinates.
|
||||||
|
- Test with a fixed seed for reproducibility.
|
||||||
|
|
||||||
|
## 5. Implement Fractal Brownian Motion (fBm)
|
||||||
|
- Create a function to combine multiple noise octaves.
|
||||||
|
- Adjust parameters (octaves, persistence, etc.) and test the results.
|
||||||
|
|
||||||
|
## 6. Map Noise to Terrain Height
|
||||||
|
- Convert normalized noise values (e.g., from -1 to 1) to block heights.
|
||||||
|
- Define a mapping strategy (for example, scaling to a maximum height).
|
||||||
|
|
||||||
|
## 7. Design the Chunk Data Structure
|
||||||
|
- Decide on chunk dimensions (e.g., 16×16×128).
|
||||||
|
- Create a simple structure to represent blocks (using enums or similar).
|
||||||
|
|
||||||
|
## 8. Generate Chunks Based on Noise
|
||||||
|
- For each (x, z) coordinate in a chunk:
|
||||||
|
- Calculate the noise value.
|
||||||
|
- Map it to a terrain height.
|
||||||
|
- Fill in blocks based on the height (e.g., surface, sub-surface, stone).
|
||||||
|
- Keep the code modular and avoid overcomplicating early on.
|
||||||
|
|
||||||
|
## 9. Test and Visualize the Generated Terrain
|
||||||
|
- Write unit tests for noise functions and terrain mapping.
|
||||||
|
- Create a simple visualization (e.g., a 2D height map printed to the console or exporting data for external tools).
|
||||||
|
- Verify that parameter adjustments produce the expected variations.
|
||||||
|
|
||||||
|
## 10. Integrate the Generator into Your Server Architecture
|
||||||
|
- Implement on-demand chunk generation as the player moves.
|
||||||
|
- Cache generated chunks (in memory or on disk) to avoid re-computation.
|
||||||
|
- Consider multithreading or asynchronous processing for parallel generation.
|
||||||
|
|
||||||
|
## 11. Optimize and Refine
|
||||||
|
- Profile the terrain generation for performance bottlenecks.
|
||||||
|
- Fine-tune noise parameters and mapping logic.
|
||||||
|
- Plan future enhancements (biomes, caves, advanced block types).
|
||||||
|
|
||||||
|
## 12. Document and Maintain the Codebase
|
||||||
|
- Document your functions, parameters, and overall architecture.
|
||||||
|
- Use version control to track changes and manage iterative improvements.
|
||||||
|
- Keep your code modular for easy future enhancements.
|
||||||
|
|
||||||
81
src/main.rs
81
src/main.rs
@@ -1,3 +1,80 @@
|
|||||||
fn main() {
|
// Example Code
|
||||||
println!("Hello, world!");
|
|
||||||
|
use noise::{NoiseFn, Perlin};
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum BlockType {
|
||||||
|
Air,
|
||||||
|
Grass,
|
||||||
|
Dirt,
|
||||||
|
Stone,
|
||||||
|
Water,
|
||||||
|
}
|
||||||
|
const CHUNK_SIZE: usize = 16;
|
||||||
|
const CHUNK_HEIGHT: usize = 128;
|
||||||
|
|
||||||
|
type Chunk = Vec<Vec<Vec<BlockType>>>;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let perlin = Perlin::new(42);
|
||||||
|
let scale = 0.1;
|
||||||
|
let x = 10.0 * scale;
|
||||||
|
let y = 20.0 * scale;
|
||||||
|
let noise_value = perlin.get([x, y]);
|
||||||
|
println!("Noise value: {}", noise_value);
|
||||||
|
}
|
||||||
|
fn fbm(perlin: &Perlin, x: f64, y: f64, octaves: u32, persistence: f64) -> f64 {
|
||||||
|
let mut total = 0.0;
|
||||||
|
let mut amplitude = 1.0;
|
||||||
|
let mut frequency = 1.0;
|
||||||
|
let mut max_value = 0.0;
|
||||||
|
|
||||||
|
for _ in 0..octaves {
|
||||||
|
total += perlin.get([x * frequency, y * frequency]) * amplitude;
|
||||||
|
max_value += amplitude;
|
||||||
|
amplitude *= persistence;
|
||||||
|
frequency *= 2.0;
|
||||||
|
}
|
||||||
|
total / max_value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_noise_to_height(noise_value: f64) -> usize {
|
||||||
|
let normalized = (noise_value + 1.0) / 2.0; // map from [-1, 1] to [0, 1]
|
||||||
|
let max_height = 128;
|
||||||
|
(normalized * max_height as f64) as usize
|
||||||
|
}
|
||||||
|
fn generate_chunk(perlin: &Perlin, chunk_x: i32, chunk_z: i32) -> Chunk {
|
||||||
|
let mut chunk = vec![vec![vec![BlockType::Air; CHUNK_HEIGHT]; CHUNK_SIZE]; CHUNK_SIZE];
|
||||||
|
let scale = 0.1;
|
||||||
|
|
||||||
|
for local_x in 0..CHUNK_SIZE {
|
||||||
|
for local_z in 0..CHUNK_SIZE {
|
||||||
|
let world_x = chunk_x * CHUNK_SIZE as i32 + local_x as i32;
|
||||||
|
let world_z = chunk_z * CHUNK_SIZE as i32 + local_z as i32;
|
||||||
|
let noise_value = fbm(
|
||||||
|
perlin,
|
||||||
|
world_x as f64 * scale,
|
||||||
|
world_z as f64 * scale,
|
||||||
|
4,
|
||||||
|
0.5,
|
||||||
|
);
|
||||||
|
let height = map_noise_to_height(noise_value);
|
||||||
|
|
||||||
|
for y in 0..CHUNK_HEIGHT {
|
||||||
|
if y > height {
|
||||||
|
chunk[local_x][local_z][y] = if y < 64 {
|
||||||
|
BlockType::Water
|
||||||
|
} else {
|
||||||
|
BlockType::Air
|
||||||
|
};
|
||||||
|
} else if y == height {
|
||||||
|
chunk[local_x][local_z][y] = BlockType::Grass;
|
||||||
|
} else if y > height.saturating_sub(3) {
|
||||||
|
chunk[local_x][local_z][y] = BlockType::Dirt;
|
||||||
|
} else {
|
||||||
|
chunk[local_x][local_z][y] = BlockType::Stone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chunk
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user