]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/server/mapgen.c
Speed up logistics of all air mapblocks
[dragonblocks_alpha.git] / src / server / mapgen.c
1 #include <math.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include "environment.h"
5 #include "perlin.h"
6 #include "server/biomes.h"
7 #include "server/mapgen.h"
8 #include "server/server_map.h"
9 #include "server/trees.h"
10 #include "util.h"
11
12 void mapgen_set_node(v3s32 pos, MapNode node, MapgenStage mgs, List *changed_blocks)
13 {
14         MapgenSetNodeArg arg = {
15                 .mgs = mgs,
16                 .changed_blocks = changed_blocks,
17         };
18
19         map_set_node(server_map.map, pos, node, true, &arg);
20 }
21
22 // generate a block (does not manage block state or threading)
23 void mapgen_generate_block(MapBlock *block, List *changed_blocks)
24 {
25         MapBlockExtraData *extra = block->extra;
26
27         v3s32 block_node_pos = {block->pos.x * MAPBLOCK_SIZE, block->pos.y * MAPBLOCK_SIZE, block->pos.z * MAPBLOCK_SIZE};
28
29         char *block_data[BIOME_COUNT] = {NULL};
30         bool preprocessed_block[BIOME_COUNT] = {false};
31
32         for (u8 x = 0; x < MAPBLOCK_SIZE; x++) {
33                 s32 pos_x = block_node_pos.x + x;
34
35                 for (u8 z = 0; z < MAPBLOCK_SIZE; z++) {
36                         v2s32 pos_horizontal = {pos_x, block_node_pos.z + z};
37
38                         s32 default_height = (pnoise2d(U32(pos_horizontal.x) / 32.0, U32(pos_horizontal.y) / 32.0, 0.45, 5, seed + SO_HEIGHT) * 16.0)
39                                 * (pnoise2d(U32(pos_horizontal.x) / 256.0, U32(pos_horizontal.y) / 256.0, 0.45, 5, seed + SO_HILLYNESS) * 0.5 + 0.5)
40                                 + 32.0;
41
42                         f64 factor;
43                         Biome biome = get_biome(pos_horizontal, &factor);
44                         BiomeDef *biome_def = &biomes[biome];
45
46                         if (biome_def->block_data_size > 0 && ! block_data[biome])
47                                 block_data[biome] = malloc(biome_def->block_data_size);
48
49                         if (biome_def->preprocess_block && ! preprocessed_block[biome]) {
50                                 biome_def->preprocess_block(block, changed_blocks, block_data[biome]);
51                                 preprocessed_block[biome] = true;
52                         }
53
54                         char row_data[biome_def->row_data_size];
55
56                         if (biome_def->preprocess_row)
57                                 biome_def->preprocess_row(pos_horizontal, factor, row_data, block_data[biome]);
58
59                         s32 height = biome_def->height(pos_horizontal, factor, default_height, row_data, block_data[biome]);
60
61                         for (u8 y = 0; y < MAPBLOCK_SIZE; y++) {
62                                 v3s32 pos = {pos_horizontal.x, block_node_pos.y + y, pos_horizontal.y};
63
64                                 f64 humidity = get_humidity(pos);
65                                 f64 temperature = get_temperature(pos);
66
67                                 s32 diff = pos.y - height;
68
69                                 Node node = biome_def->generate(pos, diff, humidity, temperature, factor, block, changed_blocks, row_data, block_data[biome]);
70
71                                 if (biome_def->snow && diff <= 1 && temperature < 0.0 && node == NODE_AIR)
72                                         node = NODE_SNOW;
73
74                                 if (diff == 1) {
75                                         for (int i = 0; i < NUM_TREES; i++) {
76                                                 TreeDef *def = &tree_definitions[i];
77
78                                                 if (def->condition(pos, humidity, temperature, biome, factor, block, row_data, block_data)
79                                                         && noise2d(pos.x, pos.z, 0, seed + def->offset) * 0.5 + 0.5 < def->probability
80                                                         && smooth2d(U32(pos.x) / def->spread, U32(pos.z) / def->spread, 0, seed + def->area_offset) * 0.5 + 0.5 < def->area_probability) {
81                                                         def->generate(pos, changed_blocks);
82                                                         break;
83                                                 }
84                                         }
85                                 }
86
87                                 pthread_mutex_lock(&block->mtx);
88                                 if (extra->mgsb.raw.nodes[x][y][z] <= MGS_TERRAIN) {
89                                         block->data[x][y][z] = map_node_create(node, (Blob) {0, NULL});
90                                         extra->mgsb.raw.nodes[x][y][z] = MGS_TERRAIN;
91                                 }
92                                 pthread_mutex_unlock(&block->mtx);
93                         }
94                 }
95         }
96
97         for (Biome i = 0; i < BIOME_COUNT; i++) {
98                 if (block_data[i])
99                         free(block_data[i]);
100         }
101 }