]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/server/biomes.c
Add oceans and toggle keys for flight & collision
[dragonblocks_alpha.git] / src / server / biomes.c
1 #include <math.h>
2 #include "server/biomes.h"
3 #include "server/mapgen.h"
4 #include "server/server_map.h"
5 #include "util.h"
6 #define NUM_BIOMES 3
7
8 static s32 height_mountain(v3s32 pos, f64 factor, s32 height)
9 {
10         return pow((height + 96) * pow(((smooth2d(U32(pos.x) / 48.0, U32(pos.z) / 48.0, 0, seed + SO_MOUNTAIN_HEIGHT) + 1.0) * 256.0 + 128.0), factor), 1.0 / (factor + 1.0)) - 96;
11 }
12
13 static Node generate_mountain(unused v3s32 pos, s32 diff, unused f64 wetness, unused f64 temperature, unused f64 factor, unused MapBlock *block, unused List *changed_blocks)
14 {
15         return diff <= 0 ? NODE_STONE : NODE_AIR;
16 }
17
18 typedef enum
19 {
20         OL_BEACH_EDGE,
21         OL_BEACH,
22         OL_OCEAN,
23         OL_DEEP_OCEAN,
24         OL_COUNT
25 } OceanLevel;
26
27 static f64 ocean_level_start[OL_COUNT] = {
28         0.0,
29         0.2,
30         0.3,
31         0.8,
32 };
33
34 static OceanLevel get_ocean_level(f64 factor)
35 {
36         if (factor >= ocean_level_start[OL_DEEP_OCEAN])
37                 return OL_DEEP_OCEAN;
38         else if (factor >= ocean_level_start[OL_OCEAN])
39                 return OL_OCEAN;
40         else if (factor >= ocean_level_start[OL_BEACH])
41                 return OL_BEACH;
42
43         return OL_BEACH_EDGE;
44 }
45
46 static s32 mix(s32 a, s32 b, f64 f)
47 {
48         return (a * (1.0 - f) + b * f);
49 }
50
51 static f64 get_ocean_level_factor(f64 factor, OceanLevel level)
52 {
53         f64 start, end;
54         start = ocean_level_start[level];
55         end = ++level == OL_COUNT ? 1.0 : ocean_level_start[level];
56
57         return (factor - start) / (end - start);
58 }
59
60 static s32 height_ocean(unused v3s32 pos, f64 factor, s32 height)
61 {
62         switch (get_ocean_level(factor)) {
63                 case OL_BEACH_EDGE:
64                         return mix(height + 1, 0, get_ocean_level_factor(factor, OL_BEACH_EDGE));
65
66                 case OL_BEACH:
67                         return 0;
68
69                 case OL_OCEAN:
70                         return mix(0, -10, get_ocean_level_factor(factor, OL_OCEAN));
71
72                 case OL_DEEP_OCEAN:
73                         return mix(-10, -50, get_ocean_level_factor(factor, OL_DEEP_OCEAN));
74
75                 default:
76                         break;
77         }
78
79         return height;
80 }
81
82 static Node generate_ocean(unused v3s32 pos, s32 diff, unused f64 wetness, unused f64 temperature, unused f64 factor, unused MapBlock *block, unused List *changed_blocks)
83 {
84         if (diff <= -5)
85                 return NODE_STONE;
86         else if (diff <= 0)
87                 return NODE_SAND;
88         else if (pos.y <= 0)
89                 return NODE_WATER;
90
91         return NODE_AIR;
92 }
93
94 static s32 height_hills(unused v3s32 pos, unused f64 factor, s32 height)
95 {
96         return height;
97 }
98
99 static Node generate_hills(v3s32 pos, s32 diff, unused f64 wetness, unused f64 temperature, unused f64 factor, unused MapBlock *block, List *changed_blocks)
100 {
101         if (diff == 2 && smooth2d(U32(pos.x), U32(pos.z), 0, seed + SO_BOULDER_CENTER) > 0.999) {
102                 for (s8 bx = -1; bx <= 1; bx++) {
103                         for (s8 by = -1; by <= 1; by++) {
104                                 for (s8 bz = -1; bz <= 1; bz++) {
105                                         v3s32 bpos = {pos.x + bx, pos.y + by, pos.z + bz};
106                                         if (smooth3d(bpos.x, bpos.y, bpos.z, 0, seed + SO_BOULDER) > 0.0)
107                                                 mapgen_set_node(bpos, map_node_create(NODE_STONE), MGS_BOULDERS, changed_blocks);
108                                 }
109                         }
110                 }
111         }
112
113         if (diff <= -5)
114                 return NODE_STONE;
115         else if (diff <= -1)
116                 return NODE_DIRT;
117         else if (diff <= 0)
118                 return NODE_GRASS;
119
120         return NODE_AIR;
121 }
122
123 static BiomeDef biomes[NUM_BIOMES] = {
124         {
125                 .probability = 0.2,
126                 .offset = SO_MOUNTAIN,
127                 .height = &height_mountain,
128                 .generate = &generate_mountain,
129         },
130         {
131                 .probability = 0.2,
132                 .offset = SO_OCEAN,
133                 .height = &height_ocean,
134                 .generate = &generate_ocean,
135         },
136         {
137                 .probability = 1.0,
138                 .offset = SO_NONE,
139                 .height = &height_hills,
140                 .generate = &generate_hills,
141         },
142 };
143
144 BiomeDef *get_biome(v3s32 pos, f64 *factor)
145 {
146         for (int i = 0; i < NUM_BIOMES; i++) {
147                 BiomeDef *def = &biomes[i];
148                 f64 f = (smooth2d(U32(pos.x) / 1024.0, U32(pos.z) / 1024.0, 0, seed + def->offset) * 0.5 - 0.5 + def->probability) / def->probability;
149
150                 if (f > 0.0) {
151                         if (factor)
152                                 *factor = f;
153                         return def;
154                 }
155         }
156
157         return NULL;
158 }