]> git.lizzy.rs Git - dragonblocks_alpha.git/blobdiff - src/server/mapgen.c
Use thread pool for map generation
[dragonblocks_alpha.git] / src / server / mapgen.c
index 04f4f57adff08f7ab4363d63a7153263088d38ae..767c19ec767b0703915fdd9537438cfce258b682 100644 (file)
@@ -1,10 +1,12 @@
-#include <stdio.h>
 #include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
 #include "environment.h"
 #include "perlin.h"
 #include "server/biomes.h"
 #include "server/mapgen.h"
 #include "server/server_map.h"
+#include "server/trees.h"
 #include "util.h"
 
 void mapgen_set_node(v3s32 pos, MapNode node, MapgenStage mgs, List *changed_blocks)
@@ -13,52 +15,87 @@ void mapgen_set_node(v3s32 pos, MapNode node, MapgenStage mgs, List *changed_blo
                .mgs = mgs,
                .changed_blocks = changed_blocks,
        };
+
        map_set_node(server_map.map, pos, node, true, &arg);
 }
 
 // generate a block (does not manage block state or threading)
 void mapgen_generate_block(MapBlock *block, List *changed_blocks)
 {
-       printf("Generating block at (%d, %d, %d)\n", block->pos.x, block->pos.y, block->pos.z);
-
        MapBlockExtraData *extra = block->extra;
 
        v3s32 block_node_pos = {block->pos.x * MAPBLOCK_SIZE, block->pos.y * MAPBLOCK_SIZE, block->pos.z * MAPBLOCK_SIZE};
-       v3s32 pos;
+
+       char *block_data[BIOME_COUNT] = {NULL};
+       bool preprocessed_block[BIOME_COUNT] = {false};
 
        for (u8 x = 0; x < MAPBLOCK_SIZE; x++) {
-               pos.x = block_node_pos.x + x;
+               s32 pos_x = block_node_pos.x + x;
 
                for (u8 z = 0; z < MAPBLOCK_SIZE; z++) {
-                       pos.z = block_node_pos.z + z;
+                       v2s32 pos_horizontal = {pos_x, block_node_pos.z + z};
+
+                       s32 default_height = (pnoise2d(U32(pos_horizontal.x) / 32.0, U32(pos_horizontal.y) / 32.0, 0.45, 5, seed + SO_HEIGHT) * 16.0)
+                               * (pnoise2d(U32(pos_horizontal.x) / 256.0, U32(pos_horizontal.y) / 256.0, 0.45, 5, seed + SO_HILLYNESS) * 0.5 + 0.5)
+                               + 32.0;
 
-                       s32 height = pnoise2d(U32(pos.x) / 32.0, U32(pos.z) / 32.0, 0.45, 5, seed + SO_HEIGHT) * 16.0 + 32;
+                       f64 factor;
+                       Biome biome = get_biome(pos_horizontal, &factor);
+                       BiomeDef *biome_def = &biomes[biome];
 
-                       f64 biome_factor;
-                       BiomeDef *biome_def = get_biome(pos, &biome_factor);
+                       if (biome_def->block_data_size > 0 && ! block_data[biome])
+                               block_data[biome] = malloc(biome_def->block_data_size);
+
+                       if (biome_def->preprocess_block && ! preprocessed_block[biome]) {
+                               biome_def->preprocess_block(block, changed_blocks, block_data[biome]);
+                               preprocessed_block[biome] = true;
+                       }
 
-                       height = biome_def->height(pos, biome_factor, height);
+                       char row_data[biome_def->row_data_size];
+
+                       if (biome_def->preprocess_row)
+                               biome_def->preprocess_row(pos_horizontal, factor, row_data, block_data[biome]);
+
+                       s32 height = biome_def->height(pos_horizontal, factor, default_height, row_data, block_data[biome]);
 
                        for (u8 y = 0; y < MAPBLOCK_SIZE; y++) {
-                               pos.y = block_node_pos.y + y;
+                               v3s32 pos = {pos_horizontal.x, block_node_pos.y + y, pos_horizontal.y};
 
-                               f64 wetness = get_wetness(pos);
+                               f64 humidity = get_humidity(pos);
                                f64 temperature = get_temperature(pos);
 
                                s32 diff = pos.y - height;
 
-                               Node node = biome_def->generate(pos, diff, wetness, temperature, biome_factor, block, changed_blocks);
+                               Node node = biome_def->generate(pos, diff, humidity, temperature, factor, block, changed_blocks, row_data, block_data[biome]);
 
-                               if (diff <= 1 && temperature < 0.0 && node == NODE_AIR)
+                               if (biome_def->snow && diff <= 1 && temperature < 0.0 && node == NODE_AIR)
                                        node = NODE_SNOW;
 
+                               if (diff == 1) {
+                                       for (int i = 0; i < NUM_TREES; i++) {
+                                               TreeDef *def = &tree_definitions[i];
+
+                                               if (def->condition(pos, humidity, temperature, biome, factor, block, row_data, block_data)
+                                                       && noise2d(pos.x, pos.z, 0, seed + def->offset) * 0.5 + 0.5 < def->probability
+                                                       && smooth2d(U32(pos.x) / def->spread, U32(pos.z) / def->spread, 0, seed + def->area_offset) * 0.5 + 0.5 < def->area_probability) {
+                                                       def->generate(pos, changed_blocks);
+                                                       break;
+                                               }
+                                       }
+                               }
+
                                pthread_mutex_lock(&block->mtx);
-                               if (extra->mgs_buffer[x][y][z] <= MGS_TERRAIN) {
-                                       block->data[x][y][z] = map_node_create(node);
-                                       extra->mgs_buffer[x][y][z] = MGS_TERRAIN;
+                               if (extra->mgsb.raw.nodes[x][y][z] <= MGS_TERRAIN) {
+                                       block->data[x][y][z] = map_node_create(node, (Blob) {0, NULL});
+                                       extra->mgsb.raw.nodes[x][y][z] = MGS_TERRAIN;
                                }
                                pthread_mutex_unlock(&block->mtx);
                        }
                }
        }
+
+       for (Biome i = 0; i < BIOME_COUNT; i++) {
+               if (block_data[i])
+                       free(block_data[i]);
+       }
 }