]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Add trees
authorElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 17 Jan 2022 11:55:27 +0000 (12:55 +0100)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 17 Jan 2022 11:55:27 +0000 (12:55 +0100)
64 files changed:
deps/dragontype
shaders/3d/fragment.glsl
src/CMakeLists.txt
src/client/blockmesh.c
src/client/client_commands.c
src/client/client_node.c
src/client/client_node.h
src/client/client_player.c
src/client/cube.c
src/client/font.c
src/client/game.c
src/client/object.c
src/client/object.h
src/client/scene.c
src/client/scene.h
src/client/sky.c
src/client/texture.c
src/client/texture.h
src/debug.sh
src/map.c
src/map.h
src/node.c
src/node.h
src/perlin.h
src/server/biomes.c
src/server/biomes.h
src/server/database.c
src/server/mapgen.c
src/server/server_commands.c
src/server/server_commands.h
src/server/server_map.c
src/server/server_map.h
src/server/trees.c [new file with mode: 0644]
src/server/trees.h [new file with mode: 0644]
src/server/voxelctx.c [new file with mode: 0644]
src/server/voxelctx.h [new file with mode: 0644]
src/util.c
src/util.h
textures/crosshair.png
textures/dirt.png
textures/grass.png
textures/lava.png
textures/lava_nt.png
textures/needles.png [new file with mode: 0644]
textures/oak_leaves.png [new file with mode: 0644]
textures/oak_wood.png [new file with mode: 0644]
textures/oak_wood_top.png [new file with mode: 0644]
textures/palm_leaves.png [new file with mode: 0644]
textures/palm_wood.png [new file with mode: 0644]
textures/palm_wood_top.png [new file with mode: 0644]
textures/pine_leaves.png [new file with mode: 0644]
textures/pine_wood.png [new file with mode: 0644]
textures/pine_wood_top.png [new file with mode: 0644]
textures/player.png
textures/sand.png
textures/snow.png
textures/stone.png
textures/sun.png
textures/unknown.png
textures/vulcano_stone.png
textures/water.png
textures/water_nt.png
textures/wood.png [deleted file]
textures/wood_top.png [deleted file]

index e2b7d38971a714300ae0edfc0af7e2ef89e433cc..5cb6a0956cd87981071f7e3dd5669f9698ac6682 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e2b7d38971a714300ae0edfc0af7e2ef89e433cc
+Subproject commit 5cb6a0956cd87981071f7e3dd5669f9698ac6682
index b419eaa1b256cf7fd86e36e5505c4132f277bf4b..dcfb212810f05672a9005d0669c2e79e31934538 100755 (executable)
@@ -11,13 +11,6 @@ uniform vec3 lightDir;
 uniform vec3 cameraPos;
 uniform sampler2D textures[MAX_TEXTURE_UNITS];
 
-vec3 hsv2rgb(vec3 c)
-{
-    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
-    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
-    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
-}
-
 void main()
 {
        vec3 lightColor = vec3(1.0);
@@ -30,6 +23,9 @@ void main()
 
        vec3 light = ambient + diffuse;
 
-       outColor = texture(textures[int(fragmentTextureIndex + 0.5)], fragmentTextureCoords) * vec4(hsv2rgb(vec3(fragmentColor)), 1.0) * vec4(light, 1.0);
+       outColor = texture(textures[int(fragmentTextureIndex + 0.5)], fragmentTextureCoords) * vec4(fragmentColor, 1.0) * vec4(light, 1.0);
        outColor.rgb = mix(outColor.rgb, ambientStrength * fogColor, clamp(length(fragmentPosition - cameraPos) / 255.0, 0.0, 1.0));
+
+       if (outColor.a == 0.0)
+               discard;
 }
index 012b7a2833829b13946f86e07089a05fae81c4a8..71daf3eb69f22f66d412a78f3313a3d2483142c4 100644 (file)
@@ -19,8 +19,6 @@ link_libraries(
 
 set(DEPS_DIR "${CMAKE_SOURCE_DIR}/../deps/")
 
-add_compile_definitions(DRAGONTYPE_ENDIAN_HEADER="${CMAKE_SOURCE_DIR}/../deps/endian.h/endian.h")
-
 include_directories(SYSTEM
        ${DEPS_DIR}
 )
@@ -29,9 +27,20 @@ include_directories(BEFORE
        ${CMAKE_SOURCE_DIR}
 )
 
-add_compile_options(-Wall -Wextra -Wpedantic -Werror)
+add_compile_options(-Wall -Wextra -Wpedantic -Werror -fmax-errors=4)
 
-set(SOURCES_COMMON
+set(DEPS_SOURCES
+       "${DEPS_DIR}/dragontype/array.c"
+       "${DEPS_DIR}/dragontype/bintree.c"
+       "${DEPS_DIR}/dragontype/list.c"
+       "${DEPS_DIR}/dragontype/number.c"
+       "${DEPS_DIR}/dragontype/queue.c"
+       "${DEPS_DIR}/dragonport/asprintf.c"
+       "${DEPS_DIR}/perlin/perlin.c"
+)
+
+set(COMMON_SOURCES
+       ${DEPS_SOURCES}
        day.c
        environment.c
        map.c
@@ -39,13 +48,10 @@ set(SOURCES_COMMON
        perlin.c
        signal_handlers.c
        util.c
-       "${DEPS_DIR}/dragontype/implementation.c"
-       "${DEPS_DIR}/dragonport/asprintf.c"
-       "${DEPS_DIR}/perlin/perlin.c"
 )
 
 add_executable(Dragonblocks
-       ${SOURCES_COMMON}
+       ${COMMON_SOURCES}
        client/blockmesh.c
        client/camera.c
        client/client.c
@@ -83,13 +89,15 @@ target_include_directories(Dragonblocks PUBLIC
 )
 
 add_executable(DragonblocksServer
-       ${SOURCES_COMMON}
+       ${COMMON_SOURCES}
        server/biomes.c
        server/database.c
        server/mapgen.c
        server/server.c
        server/server_commands.c
        server/server_map.c
+       server/trees.c
+       server/voxelctx.c
 )
 
 target_link_libraries(DragonblocksServer
index d98a1e3b61be222be599cfd91846b9496566df85..59b60c2aa47ebc9bc6ca5ee4d6166ea65ee6bff7 100644 (file)
@@ -25,7 +25,7 @@ static void make_vertices(Object *object, MapBlock *block, bool hide_edges)
 
        ITERATE_MAPBLOCK {
                MapNode *node = &block->data[x][y][z];
-               ClientNodeDefintion *def = &client_node_definitions[node->type];
+               ClientNodeDefinition *def = &client_node_definitions[node->type];
 
                if (def->visibility != NV_NONE) {
                        v3f32 offset = {
@@ -49,11 +49,11 @@ static void make_vertices(Object *object, MapBlock *block, bool hide_edges)
                                        ? block->data[npos.x][npos.y][npos.z]
                                        : map_get_node(client_map.map, (v3s32) {npos.x + node_bp.x, npos.y + node_bp.y, npos.z + node_bp.z});
 
-                               bool transparency_edge = def->visibility != NV_TRANSPARENT || neighbor.type != node->type;
+                               bool transparency_edge = def->visibility != NV_BLEND || neighbor.type != node->type;
 
-                               bool render_node = neighbor.type != NODE_UNLOADED
+                               bool render_node = def->visibility == NV_CLIP || (neighbor.type != NODE_UNLOADED
                                        && client_node_definitions[neighbor.type].visibility != NV_SOLID
-                                       && transparency_edge;
+                                       && transparency_edge);
 
                                object->visible = object->visible || render_node;
 
@@ -61,7 +61,7 @@ static void make_vertices(Object *object, MapBlock *block, bool hide_edges)
                                        render_node = transparency_edge;
 
                                if (render_node) {
-                                       object->transparent = object->transparent || def->visibility == NV_TRANSPARENT;
+                                       object->transparent = object->transparent || def->visibility == NV_BLEND;
                                        object_set_texture(object, def->tiles.textures[f]);
 
                                        for (int v = 0; v < 6; v++) {
@@ -104,7 +104,7 @@ void blockmesh_make(MapBlock *block)
        obj->pos = (v3f32) {block->pos.x * MAPBLOCK_SIZE + half_block_size + 0.5f, block->pos.y * MAPBLOCK_SIZE + half_block_size + 0.5f, block->pos.z * MAPBLOCK_SIZE + half_block_size + 0.5f};
        obj->scale = extra->obj ? extra->obj->scale : (v3f32) {0.1f, 0.1f, 0.1f};
        obj->frustum_culling = true;
-       obj->box = (aabb3f32) {{-half_block_size - 0.5f, -half_block_size - 0.5f, -half_block_size - 0.5f}, {half_block_size + 0.5f, half_block_size + 0.5f, half_block_size + 0.5f}};
+       obj->box = (aabb3f32) {{-half_block_size - 1.0f, -half_block_size - 1.0f, -half_block_size - 1.0f}, {half_block_size + 1.0f, half_block_size + 1.0f, half_block_size + 1.0f}};
        obj->on_render = (obj->scale.x == 1.0f) ? NULL : &animate_mapblock_mesh;
        obj->extra = block;
 
index cf13c0fde9b261154113fafa6929d5a59e88432a..63bce0dec6714b3880b0cc07c914eefb387c4345 100644 (file)
@@ -42,12 +42,17 @@ static bool block_handler(Client *client, bool good)
        if (! read_v3s32(client->fd, &pos))
                return false;
 
-       size_t size;
+       u64 size;
 
        if (! read_u64(client->fd, &size))
                return false;
 
-       if (size > sizeof(MapBlockData))        // guard to prevent malicious or malfunctioning packets from allocating huge unnecessary amounts of memory
+       if (size > 1 << 16)
+               return false;
+
+       u64 rawsize;
+
+       if (! read_u64(client->fd, &rawsize))
                return false;
 
        char data[size];
@@ -61,7 +66,7 @@ static bool block_handler(Client *client, bool good)
        else
                block = map_allocate_block(pos);
 
-       bool ret = map_deserialize_block(block, data, size);
+       bool ret = map_deserialize_block(block, data, size, rawsize);
 
        if (good)
                client_map_block_received(block);
index 832400dfbb38dd3cbfb35918846d7527b77df773..22b7c659a5982259e866a2ef5440626717289428 100644 (file)
@@ -7,6 +7,44 @@
 #define TILES_SIMPLE(path) {.paths = {path, NULL, NULL, NULL, NULL, NULL}, .indices = {0, 0, 0, 0, 0, 0}, .textures = {NULL}}
 #define TILES_NONE {.paths = {NULL}, .indices = {0}, .textures = {NULL}}
 
+static f32 hue_to_rgb(f32 p, f32 q, f32 t)
+{
+    if (t < 0.0f)
+        t += 1.0f;
+
+    if (t > 1.0f)
+        t -= 1.0f;
+
+    if (t < 1.0f / 6.0f)
+        return p + (q - p) * 6.0f * t;
+
+    if (t < 1.0f / 2.0f)
+        return q;
+
+    if (t < 2.0f / 3.0f)
+        return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
+
+    return p;
+}
+
+static Vertex3DColor hsl_to_rgb(v3f32 hsl)
+{
+       Vertex3DColor rgb;
+
+    if (hsl.y == 0.0f) {
+               rgb = (Vertex3DColor) {hsl.z, hsl.z, hsl.z};
+    } else {
+        f32 q = hsl.z < 0.5f ? hsl.z * (1.0f + hsl.y) : hsl.z + hsl.y - hsl.z * hsl.y;
+        f32 p = 2.0f * hsl.z - q;
+
+        rgb.r = hue_to_rgb(p, q, hsl.x + 1.0f / 3.0f);
+        rgb.g = hue_to_rgb(p, q, hsl.x);
+        rgb.b = hue_to_rgb(p, q, hsl.x - 1.0f / 3.0f);
+    }
+
+    return rgb;
+}
+
 static void render_grass(v3s32 pos, unused MapNode *node, Vertex3D *vertex, unused int f, unused int v)
 {
        f32 hum_min, hum_max, temp_max;
@@ -16,9 +54,7 @@ static void render_grass(v3s32 pos, unused MapNode *node, Vertex3D *vertex, unus
 
        f32 temp_f = clamp(0.3f - get_temperature(pos), 0.0f, 0.3f) / 0.3f;
 
-       vertex->color.h = (get_humidity(pos) * (hum_max - hum_min) + hum_min) * (1.0f - temp_f) + temp_max * temp_f;
-       vertex->color.s = 1.0f;
-       vertex->color.v = 1.0f;
+       vertex->color = hsl_to_rgb((v3f32) {(get_humidity(pos) * (hum_max - hum_min) + hum_min) * (1.0f - temp_f) + temp_max * temp_f, 1.0f, 0.5f});
 }
 
 static void render_stone(v3s32 pos, unused MapNode *node, Vertex3D *vertex, unused int f, unused int v)
@@ -27,82 +63,134 @@ static void render_stone(v3s32 pos, unused MapNode *node, Vertex3D *vertex, unus
        vertex->textureCoordinates.t += noise2d(pos.x, pos.z, 0, seed + SO_TEXTURE_OFFSET_T);
 }
 
-static void render_wood(unused v3s32 pos, unused MapNode *node, Vertex3D *vertex, int f, unused int v)
+static void render_hsl(unused v3s32 pos, MapNode *node, Vertex3D *vertex, unused int f, unused int v)
 {
-       vertex->color.h = f < 4 ? 0.1f : 0.11f;
-       vertex->color.s = 1.0f;
-       vertex->color.v = 1.0f;
+       vertex->color = hsl_to_rgb(((HSLData *) node->data)->color);
 }
 
-ClientNodeDefintion client_node_definitions[NODE_UNLOADED] = {
+ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
        // unknown
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/unknown.png"),
                .visibility = NV_SOLID,
+               .mipmap = true,
                .render = NULL,
        },
        // air
        {
                .tiles = TILES_NONE,
                .visibility = NV_NONE,
+               .mipmap = true,
                .render = NULL,
        },
        // grass
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/grass.png"),
                .visibility = NV_SOLID,
+               .mipmap = true,
                .render = &render_grass,
        },
        // dirt
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/dirt.png"),
                .visibility = NV_SOLID,
+               .mipmap = true,
                .render = NULL,
        },
        // stone
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/stone.png"),
                .visibility = NV_SOLID,
+               .mipmap = true,
                .render = &render_stone,
        },
        // snow
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/snow.png"),
                .visibility = NV_SOLID,
+               .mipmap = true,
                .render = NULL,
        },
-       // wood
+       // oak wood
+       {
+               .tiles = {
+                       .paths = {RESSOURCEPATH "textures/oak_wood.png", RESSOURCEPATH "textures/oak_wood_top.png", NULL, NULL, NULL, NULL},
+                       .indices = {0, 0, 0, 0, 1, 1},
+                       .textures = {NULL},
+               },
+               .visibility = NV_SOLID,
+               .mipmap = true,
+               .render = &render_hsl,
+       },
+       // oak leaves
+       {
+               .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/oak_leaves.png"),
+               .visibility = NV_SOLID,
+               .mipmap = true,
+               .render = &render_hsl,
+       },
+       // pine wood
+       {
+               .tiles = {
+                       .paths = {RESSOURCEPATH "textures/pine_wood.png", RESSOURCEPATH "textures/pine_wood_top.png", NULL, NULL, NULL, NULL},
+                       .indices = {0, 0, 0, 0, 1, 1},
+                       .textures = {NULL},
+               },
+               .visibility = NV_SOLID,
+               .mipmap = true,
+               .render = &render_hsl,
+       },
+       // pine leaves
+       {
+               .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/pine_leaves.png"),
+               .visibility = NV_CLIP,
+               .mipmap = true,
+               .render = &render_hsl,
+       },
+       // palm wood
        {
                .tiles = {
-                       .paths = {RESSOURCEPATH "textures/wood.png", RESSOURCEPATH "textures/wood_top.png", NULL, NULL, NULL, NULL},
+                       .paths = {RESSOURCEPATH "textures/palm_wood.png", RESSOURCEPATH "textures/palm_wood_top.png", NULL, NULL, NULL, NULL},
                        .indices = {0, 0, 0, 0, 1, 1},
                        .textures = {NULL},
                },
                .visibility = NV_SOLID,
-               .render = &render_wood,
+               .mipmap = true,
+               .render = &render_hsl,
+       },
+       // palm leaves
+       {
+               .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/palm_leaves.png"),
+               .visibility = NV_SOLID,
+               .mipmap = true,
+               .render = &render_hsl,
        },
        // sand
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/sand.png"),
                .visibility = NV_SOLID,
+               .mipmap = true,
                .render = NULL,
        },
        // water
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/water.png"),
-               .visibility = NV_TRANSPARENT,
+               .visibility = NV_BLEND,
+               .mipmap = true,
                .render = NULL,
        },
        // lava
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/lava.png"),
-               .visibility = NV_TRANSPARENT,
+               .visibility = NV_BLEND,
+               .mipmap = true,
                .render = NULL,
        },
        // vulcano_stone
        {
                .tiles = TILES_SIMPLE(RESSOURCEPATH "textures/vulcano_stone.png"),
                .visibility = NV_SOLID,
+               .mipmap = true,
                .render = NULL,
        },
 };
@@ -110,16 +198,16 @@ ClientNodeDefintion client_node_definitions[NODE_UNLOADED] = {
 void client_node_init()
 {
        for (Node node = NODE_UNKNOWN; node < NODE_UNLOADED; node++) {
-               ClientNodeDefintion *def = &client_node_definitions[node];
+               ClientNodeDefinition *def = &client_node_definitions[node];
 
-               if (client_node_definitions[node].visibility != NV_NONE) {
+               if (def->visibility != NV_NONE) {
                        Texture *textures[6];
 
                        for (int i = 0; i < 6; i++) {
                                char *path = def->tiles.paths[i];
 
                                if (path)
-                                       textures[i] = texture_get(path);
+                                       textures[i] = texture_load(path, def->mipmap);
                                else
                                        break;
                        }
index e3884f13091d69180406fbf6719d4cc629b662d5..91ef338715404404a2aba3921accb064403b491b 100644 (file)
@@ -8,7 +8,8 @@
 typedef enum
 {
        NV_NONE,
-       NV_TRANSPARENT,
+       NV_CLIP,
+       NV_BLEND,
        NV_SOLID,
 } NodeVisibility;
 
@@ -21,10 +22,11 @@ typedef struct
                Texture *textures[6];   // output
        } tiles;
        NodeVisibility visibility;
+       bool mipmap;
        void (*render)(v3s32 pos, MapNode *node, Vertex3D *vertex, int f, int v);
-} ClientNodeDefintion;
+} ClientNodeDefinition;
 
-extern ClientNodeDefintion client_node_definitions[];
+extern ClientNodeDefinition client_node_definitions[];
 void client_node_init();
 
 #endif
index b964f9e2d7f84ed41d5e7f92fb8b1c3636ca7add..d0418db5dabbd56fa7978e4fcb3d12bcffb9a29f 100644 (file)
@@ -100,7 +100,7 @@ void client_player_add_to_scene()
        client_player.obj->scale = (v3f32) {0.6, 1.75, 0.6};
        client_player.obj->visible = false;
 
-       object_set_texture(client_player.obj, texture_get(RESSOURCEPATH "textures/player.png"));
+       object_set_texture(client_player.obj, texture_load(RESSOURCEPATH "textures/player.png", true));
 
        for (int f = 0; f < 6; f++) {
                for (int v = 0; v < 6; v++) {
index 42413796b34a1e33313c116e24d44c76022b99d0..738407614a8b921265c00a8354a0f40e99418ca3 100644 (file)
@@ -2,52 +2,52 @@
 
 Vertex3D cube_vertices[6][6] = {
        {
-               {{-0.5, -0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, -0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, +0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
+               {{-0.5, -0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, -0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, +0.5, -0.5}, {+0.0, +0.0, -1.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
        },
        {
-               {{-0.5, -0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, +0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, -0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
+               {{-0.5, -0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, +0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, -0.5, +0.5}, {+0.0, +0.0, +1.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
        },
        {
-               {{-0.5, +0.5, +0.5}, {-1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, +0.5, -0.5}, {-1.0, +0.0, +0.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, -0.5, -0.5}, {-1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, -0.5, -0.5}, {-1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, -0.5, +0.5}, {-1.0, +0.0, +0.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, +0.5, +0.5}, {-1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
+               {{-0.5, +0.5, +0.5}, {-1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, +0.5, -0.5}, {-1.0, +0.0, +0.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, -0.5, -0.5}, {-1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, -0.5, -0.5}, {-1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, -0.5, +0.5}, {-1.0, +0.0, +0.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, +0.5, +0.5}, {-1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
        },
        {
-               {{+0.5, +0.5, +0.5}, {+1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, -0.5}, {+1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, -0.5}, {+1.0, +0.0, +0.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, -0.5}, {+1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, +0.5}, {+1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, +0.5}, {+1.0, +0.0, +0.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
+               {{+0.5, +0.5, +0.5}, {+1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, -0.5}, {+1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, -0.5}, {+1.0, +0.0, +0.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, -0.5}, {+1.0, +0.0, +0.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, +0.5}, {+1.0, +0.0, +0.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, +0.5}, {+1.0, +0.0, +0.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
        },
        {
-               {{-0.5, -0.5, -0.5}, {+0.0, -1.0, +0.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, -0.5}, {+0.0, -1.0, +0.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, +0.5}, {+0.0, -1.0, +0.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, -0.5, +0.5}, {+0.0, -1.0, +0.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, -0.5, +0.5}, {+0.0, -1.0, +0.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, -0.5, -0.5}, {+0.0, -1.0, +0.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
+               {{-0.5, -0.5, -0.5}, {+0.0, -1.0, +0.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, -0.5}, {+0.0, -1.0, +0.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, +0.5}, {+0.0, -1.0, +0.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, -0.5, +0.5}, {+0.0, -1.0, +0.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, -0.5, +0.5}, {+0.0, -1.0, +0.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, -0.5, -0.5}, {+0.0, -1.0, +0.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
        },
        {
-               {{-0.5, +0.5, -0.5}, {+0.0, +1.0, +0.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, +0.5}, {+0.0, +1.0, +0.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, -0.5}, {+0.0, +1.0, +0.0}, +0.0, {+1.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{+0.5, +0.5, +0.5}, {+0.0, +1.0, +0.0}, +0.0, {+1.0, +0.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, +0.5, -0.5}, {+0.0, +1.0, +0.0}, +0.0, {+0.0, +1.0}, {+0.0, +0.0, +1.0}},
-               {{-0.5, +0.5, +0.5}, {+0.0, +1.0, +0.0}, +0.0, {+0.0, +0.0}, {+0.0, +0.0, +1.0}},
+               {{-0.5, +0.5, -0.5}, {+0.0, +1.0, +0.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, +0.5}, {+0.0, +1.0, +0.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, -0.5}, {+0.0, +1.0, +0.0}, +0.0, {+1.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{+0.5, +0.5, +0.5}, {+0.0, +1.0, +0.0}, +0.0, {+1.0, +0.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, +0.5, -0.5}, {+0.0, +1.0, +0.0}, +0.0, {+0.0, +1.0}, {+1.0, +1.0, +1.0}},
+               {{-0.5, +0.5, +0.5}, {+0.0, +1.0, +0.0}, +0.0, {+0.0, +0.0}, {+1.0, +1.0, +1.0}},
        },
 };
 
index 3fa6002dcbcef2997e5f8aa60f53f84e22f9dfc8..1c7684d45091467df5b1b8331adc8b824d81d85c 100644 (file)
@@ -85,7 +85,7 @@ bool font_init()
                        };
                } else {
                        font.chars[c] = (Character) {
-                               .texture = texture_create(font.face->glyph->bitmap.buffer, font.face->glyph->bitmap.width, font.face->glyph->bitmap.rows, GL_RED),
+                               .texture = texture_create(font.face->glyph->bitmap.buffer, font.face->glyph->bitmap.width, font.face->glyph->bitmap.rows, GL_RED, false),
                                .bearing = {font.face->glyph->bitmap_left, font.face->glyph->bitmap_top},
                                .advance = font.face->glyph->advance.x,
                        };
index 979b25420041d1c5912bc77eb6d5470d446997f8..182bae751810f2cf834f8e73f573c803c7ed9229 100644 (file)
@@ -33,7 +33,7 @@ static void crosshair_init()
                .scale_type = GST_IMAGE,
                .affect_parent_scale = false,
                .text = NULL,
-               .image = texture_get(RESSOURCEPATH "textures/crosshair.png"),
+               .image = texture_load(RESSOURCEPATH "textures/crosshair.png", false),
                .text_color = (v4f32) {0.0f, 0.0f, 0.0f, 0.0f},
                .bg_color = (v4f32) {0.0f, 0.0f, 0.0f, 0.0f},
        });
@@ -48,7 +48,7 @@ static void render(f64 dtime)
        glEnable(GL_CULL_FACE);
 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glAlphaFunc(GL_GREATER, 0.0f);
+       glAlphaFunc(GL_GREATER, 0.1f);
        glCullFace(GL_BACK);
        glFrontFace(GL_CCW);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
index 009ca1bdf65344ab51f004f77a4135ab5581c653..e7f3c85b370e50ca471ae7d6d5c4d3ddeec234bf 100644 (file)
@@ -192,7 +192,7 @@ bool object_before_render(Object *obj, f64 dtime)
                return false;
 
        if (obj->frustum_culling) {
-               aabb3f32 box = {v3f32_add(obj->box.min, obj->pos), v3f32_add(obj->box.max, obj->pos)};
+               aabb3f32 box = {v3f32_add(obj->box.min, obj->pos), v3f32_add(obj->box.max, obj->pos)};
 
                 if (! frustum_is_visible(box))
                        return false;
index 13fb1d9f7dc3fdc22b7a493067e7068493e43d7d..549db74734ae97facf9011ca874f098e61bec0cc 100644 (file)
@@ -27,7 +27,7 @@ typedef struct {
 } __attribute__((packed)) Vertex3DTextureCoordinates;
 
 typedef struct {
-       GLfloat h, s, v;
+       GLfloat r, g, b;
 } __attribute__((packed)) Vertex3DColor;
 
 typedef struct
index 70109d06b155ed99df473432c0524f6fe6fdeab1..9339b0691ff3e9174830984fe7c1d939eb4fad99 100644 (file)
@@ -19,7 +19,7 @@ static int bintree_compare_f32(void *v1, void *v2, unused Bintree *tree)
 bool scene_init()
 {
        scene.objects = list_create(NULL);
-       scene.render_objects = bintree_create(sizeof(f32), &bintree_compare_f32);
+       scene.transparent_objects = bintree_create(sizeof(f32), &bintree_compare_f32);
        pthread_mutex_init(&scene.mtx, NULL);
 
        glGetIntegerv(GL_MAX_TEXTURE_UNITS, &scene.max_texture_units);
@@ -113,7 +113,7 @@ void scene_render(f64 dtime)
                        f32 distance = sqrt(pow(obj->pos.x - camera.eye[0], 2) + pow(obj->pos.y - camera.eye[1], 2) + pow(obj->pos.z - camera.eye[2], 2));
                        if (distance < scene.render_distance && object_before_render(obj, dtime)) {
                                if (obj->transparent)
-                                       bintree_insert(&scene.render_objects, &distance, obj);
+                                       bintree_insert(&scene.transparent_objects, &distance, obj);
                                else
                                        object_render(obj);
                        }
@@ -121,8 +121,8 @@ void scene_render(f64 dtime)
                }
        }
 
-       bintree_traverse(&scene.render_objects, BTT_INORDER, &bintree_render_object, NULL);
-       bintree_clear(&scene.render_objects, NULL, NULL);
+       bintree_traverse(&scene.transparent_objects, BTT_INORDER, &bintree_render_object, NULL);
+       bintree_clear(&scene.transparent_objects, NULL, NULL);
 }
 
 void scene_on_resize(int width, int height)
index 1a27162fd345fda502842417c636523afb8a3268..2941db0f906ad487f9b9a90e196f098f2cde9456 100644 (file)
@@ -12,7 +12,7 @@
 extern struct Scene
 {
        List objects;
-       Bintree render_objects;
+       Bintree transparent_objects;
        pthread_mutex_t mtx;
        GLuint prog;
        GLint loc_model;
index 5d9635e57382f1444e0cedbaa81ba4f736e1a14c..30e161229217d05162b71bab8f762cff8a1692b3 100644 (file)
@@ -149,7 +149,7 @@ bool sky_init()
 
        sky.sun_loc_MVP = glGetUniformLocation(sky.sun_prog, "MVP");
 
-       sky.sun_texture = texture_get(RESSOURCEPATH "textures/sun.png");
+       sky.sun_texture = texture_load(RESSOURCEPATH "textures/sun.png", false);
 
        sky.sun_mesh = mesh_create();
        sky.sun_mesh->textures = &sky.sun_texture->id;
index 2fa16803218947a498d7cd9b7a75c3c62773b6fb..2e3e461ddbe6e35128160d9b212c4daf14cc1288 100644 (file)
@@ -22,7 +22,7 @@ __attribute((destructor)) static void textures_deinit()
        list_clear_func(&textures, &list_delete_texture, NULL);
 }
 
-Texture *texture_create(unsigned char *data, int width, int height, GLenum format)
+Texture *texture_create(unsigned char *data, int width, int height, GLenum format, bool mipmap)
 {
        Texture *texture = malloc(sizeof(Texture));
        texture->width = width;
@@ -32,7 +32,7 @@ Texture *texture_create(unsigned char *data, int width, int height, GLenum forma
 
        glBindTexture(GL_TEXTURE_2D, texture->id);
 
-       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipmap ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
@@ -91,24 +91,21 @@ void texture_delete(Texture *texture)
        free(texture);
 }
 
-static void *create_image_texture(void *key)
+Texture *texture_load(char *path, bool mipmap)
 {
        int width, height, channels;
 
-       unsigned char *data = stbi_load(key, &width, &height, &channels, 0);
+       unsigned char *data = stbi_load(path, &width, &height, &channels, 0);
        if (! data) {
-               fprintf(stderr, "Failed to load texture %s\n", (char *) key);
-               return 0;
+               fprintf(stderr, "Failed to load texture %s\n", path);
+               return NULL;
        }
 
-       Texture *texture = texture_create(data, width, height, GL_RGBA);
+       Texture *texture = texture_create(data, width, height, GL_RGBA, mipmap);
 
        stbi_image_free(data);
 
-       return texture;
-}
+       list_put(&textures, texture, NULL);
 
-Texture *texture_get(char *path)
-{
-       return list_get_cached(&textures, path, &create_image_texture);
+       return texture;
 }
index c339c7037e91c4ab827d7bc1675f4eab55f985cf..77375752ffef545265d95e3194a20f41ce83c019 100644 (file)
@@ -10,9 +10,9 @@ typedef struct
        int width, height;
 } Texture;
 
-Texture *texture_create(unsigned char *data, int width, int height, GLenum format);
+Texture *texture_create(unsigned char *data, int width, int height, GLenum format, bool mipmap);
 GLuint texture_create_cubemap(char *path);
 void texture_delete(Texture *texture);
-Texture *texture_get(char *path);
+Texture *texture_load(char *path, bool mipmap);
 
 #endif
index 400d2143c4c14d7bd182743b6aa96eaa5aaf8c92..32fa0c1abd9c8585753d82aaddf55d2cd6b364a1 100755 (executable)
@@ -25,13 +25,15 @@ run ::1 4000 < $DEBUG_DIR/name
 " > $DEBUG_DIR/client_script
 
 echo "$COMMON
+set print thread-events off
 run 4000
 " > $DEBUG_DIR/server_script
 
-konsole -e bash -c "
+kitty --detach -e bash -c "
        echo \$\$ > $DEBUG_DIR/server_pid
        exec gdb --command $DEBUG_DIR/server_script ./DragonblocksServer
-" & sleep 0.5
+"
+sleep 0.5
 
 gdb --command $DEBUG_DIR/client_script ./Dragonblocks
 
index 5da5acd8d58b8a1e3d535cd4aa7b8ca6faebcb61..59097b86260f0167153ab1f0c6a4f7086b2c0f0a 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -130,64 +130,88 @@ MapBlock *map_allocate_block(v3s32 pos)
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&block->mtx, &attr);
+
+       ITERATE_MAPBLOCK block->data[x][y][z] = map_node_create(NODE_UNKNOWN, NULL, 0);
+
        return block;
 }
 
 void map_free_block(MapBlock *block)
 {
+       ITERATE_MAPBLOCK map_node_delete(block->data[x][y][z]);
+
        pthread_mutex_destroy(&block->mtx);
        free(block);
 }
 
-bool map_deserialize_node(int fd, MapNode *node)
+void map_serialize_block(MapBlock *block, char **dataptr, size_t *sizeptr, size_t *rawsizeptr)
 {
-       Node type;
-
-       if (! read_u32(fd, &type))
-               return false;
+       unsigned char *uncompressed = NULL;
+       size_t uncompressed_size = 0;
 
-       if (type >= NODE_UNLOADED)
-               type = NODE_UNKNOWN;
+       ITERATE_MAPBLOCK {
+               MapNode node = block->data[x][y][z];
+               NodeDefinition *def = &node_definitions[node.type];
 
-       *node = map_node_create(type);
+               u32 type = htobe32(node.type);
+               buffer_write(&uncompressed, &uncompressed_size, &type, sizeof(u32));
 
-       return true;
-}
+               unsigned char *data_buffer = NULL;
+               size_t data_bufsiz = 0;
 
-void map_serialize_block(MapBlock *block, char **dataptr, size_t *sizeptr)
-{
-       MapBlockData uncompressed;
-       ITERATE_MAPBLOCK {
-               MapNode node = block->data[x][y][z];
+               if (def->serialize)
+                       def->serialize(&node, &data_buffer, &data_bufsiz);
 
-               if (node_definitions[node.type].serialize)
-                       node_definitions[node.type].serialize(&node);
+               u16 data_size = htobe16(data_bufsiz);
+               buffer_write(&uncompressed, &uncompressed_size, &data_size, sizeof(u16));
+               buffer_write(&uncompressed, &uncompressed_size, data_buffer, data_bufsiz);
 
-               node.type = htobe32(node.type);
-               uncompressed[x][y][z] = node;
+               if (data_buffer)
+                       free(data_buffer);
        }
 
-       my_compress(&uncompressed, sizeof(MapBlockData), dataptr, sizeptr);
+       my_compress(uncompressed, uncompressed_size, dataptr, sizeptr);
+       *rawsizeptr = uncompressed_size;
+
+       if (uncompressed)
+               free(uncompressed);
 }
 
-bool map_deserialize_block(MapBlock *block, const char *data, size_t size)
+bool map_deserialize_block(MapBlock *block, const char *data, size_t size, size_t rawsize)
 {
-       MapBlockData decompressed;
+       unsigned char decompressed[rawsize];
+       size_t decompressed_size = rawsize;
 
-       if (! my_decompress(data, size, &decompressed, sizeof(MapBlockData)))
+       if (! my_decompress(data, size, decompressed, decompressed_size))
                return false;
 
+       unsigned char *ptr = decompressed;
+
        ITERATE_MAPBLOCK {
-               MapNode node = decompressed[x][y][z];
-               node.type = be32toh(node.type);
+               // node type
+               u32 *type_ptr = buffer_read(&ptr, &decompressed_size, sizeof(u32));
 
-               if (node.type >= NODE_UNLOADED)
-                       node.type = NODE_UNKNOWN;
+               if (! type_ptr)
+                       return false;
 
-               if (node_definitions[node.type].deserialize)
-                       node_definitions[node.type].deserialize(&node);
+               u32 type = be32toh(*type_ptr);
 
-               block->data[x][y][z] = node;
+               // data size
+               u16 *data_size_ptr = buffer_read(&ptr, &decompressed_size, sizeof(u16));
+
+               if (! data_size_ptr)
+                       return false;
+
+               u16 data_size = be16toh(*data_size_ptr);
+
+               // data
+               void *data = buffer_read(&ptr, &decompressed_size, data_size);
+
+               if (! data && data_size)
+                       return false;
+
+               // set node
+               block->data[x][y][z] = map_node_create(type, data, data_size);
        }
 
        return true;
@@ -206,7 +230,7 @@ MapNode map_get_node(Map *map, v3s32 pos)
        v3s32 blockpos = map_node_to_block_pos(pos, &offset);
        MapBlock *block = map_get_block(map, blockpos, false);
        if (! block)
-               return map_node_create(NODE_UNLOADED);
+               return map_node_create(NODE_UNLOADED, NULL, 0);
        return block->data[offset.x][offset.y][offset.z];
 }
 
@@ -220,18 +244,40 @@ void map_set_node(Map *map, v3s32 pos, MapNode node, bool create, void *arg)
                        block->data[offset.x][offset.y][offset.z] = node;
                        if (map->callbacks.after_set_node)
                                map->callbacks.after_set_node(block, offset, arg);
+               } else {
+                       map_node_delete(node);
                }
                pthread_mutex_unlock(&block->mtx);
        }
 }
 
-MapNode map_node_create(Node type)
+MapNode map_node_create(Node type, void *data, size_t size)
 {
+       if (type >= NODE_UNLOADED)
+               type = NODE_UNKNOWN;
+
+       NodeDefinition *def = &node_definitions[type];
+
        MapNode node;
        node.type = type;
+       node.data = def->data_size ? malloc(def->data_size) : NULL;
 
-       if (node.type != NODE_UNLOADED && node_definitions[node.type].create)
-               node_definitions[node.type].create(&node);
+       if (def->create)
+               def->create(&node);
+
+       if (def->deserialize && size)
+               def->deserialize(&node, data, size);
 
        return node;
 }
+
+void map_node_delete(MapNode node)
+{
+       NodeDefinition *def = &node_definitions[node.type];
+
+       if (def->delete)
+               def->delete(&node);
+
+       if (node.data)
+               free(node.data);
+}
index 25827f07702a751e9bafccdf885658db129ee20d..c8eb97269e2996357ffd5fe0d752ef156f405da7 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -14,6 +14,7 @@
 typedef struct MapNode
 {
        Node type;
+       void *data;
 } MapNode;
 
 typedef MapNode MapBlockData[MAPBLOCK_SIZE][MAPBLOCK_SIZE][MAPBLOCK_SIZE];
@@ -60,15 +61,15 @@ MapBlock *map_get_block(Map *map, v3s32 pos, bool create);
 MapBlock *map_allocate_block(v3s32 pos);
 void map_free_block(MapBlock *block);
 
-bool map_deserialize_node(int fd, MapNode *buf);
-void map_serialize_block(MapBlock *block, char **dataptr, size_t *sizeptr);
-bool map_deserialize_block(MapBlock *block, const char *data, size_t size);
+void map_serialize_block(MapBlock *block, char **dataptr, size_t *sizeptr, size_t *rawsizeptr);
+bool map_deserialize_block(MapBlock *block, const char *data, size_t size, size_t rawsize);
 
 v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset);
 
 MapNode map_get_node(Map *map, v3s32 pos);
 void map_set_node(Map *map, v3s32 pos, MapNode node, bool create, void *arg);
-MapNode map_node_create(Node type);
-void map_node_clear(MapNode *node);
+
+MapNode map_node_create(Node type, void *data, size_t size);
+void map_node_delete(MapNode node);
 
 #endif
index 0fe7ce9944e33655e9eb7eacb94069567cd79827..39e60ac7f4684955c31685ff26eca2a77bb6b0b2 100644 (file)
 #include "map.h"
 #include "node.h"
 #include "util.h"
+#include <stdio.h>
 
-NodeDefintion node_definitions[NODE_UNLOADED] = {
+static void serialize_hsl(MapNode *node, unsigned char **buffer, size_t *bufsiz)
+{
+       HSLData *node_data = node->data;
+       buffer_write(buffer, bufsiz, (f32 []) {node_data->color.x, node_data->color.y, node_data->color.z}, sizeof(f32) * 3);
+}
+
+static void deserialize_hsl(MapNode *node, unsigned char *data, size_t size)
+{
+       HSLData *node_data = node->data;
+
+       f32 *color = buffer_read(&data, &size, sizeof(f32) * 3);
+
+       if (! color)
+               return;
+
+       *node_data = (HSLData) {.color = {color[0], color[1], color[2]}};
+}
+
+NodeDefinition node_definitions[NODE_UNLOADED] = {
        // unknown
        {
                .solid = true,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // air
        {
                .solid = false,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // grass
        {
                .solid = true,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // dirt
        {
                .solid = true,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // stone
        {
                .solid = true,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // snow
        {
                .solid = true,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
-       // wood
+       // oak wood
        {
                .solid = true,
+               .data_size = sizeof(HSLData),
                .create = NULL,
-               .serialize = NULL,
-               .deserialize = NULL,
+               .delete = NULL,
+               .serialize = &serialize_hsl,
+               .deserialize = &deserialize_hsl,
+       },
+       // oak leaves
+       {
+               .solid = true,
+               .data_size = sizeof(HSLData),
+               .create = NULL,
+               .delete = NULL,
+               .serialize = &serialize_hsl,
+               .deserialize = &deserialize_hsl,
+       },
+       // pine wood
+       {
+               .solid = true,
+               .data_size = sizeof(HSLData),
+               .create = NULL,
+               .delete = NULL,
+               .serialize = &serialize_hsl,
+               .deserialize = &deserialize_hsl,
+       },
+       // pine leaves
+       {
+               .solid = true,
+               .data_size = sizeof(HSLData),
+               .create = NULL,
+               .delete = NULL,
+               .serialize = &serialize_hsl,
+               .deserialize = &deserialize_hsl,
+       },
+       // palm wood
+       {
+               .solid = true,
+               .data_size = sizeof(HSLData),
+               .create = NULL,
+               .delete = NULL,
+               .serialize = &serialize_hsl,
+               .deserialize = &deserialize_hsl,
+       },
+       // palm leaves
+       {
+               .solid = true,
+               .data_size = sizeof(HSLData),
+               .create = NULL,
+               .delete = NULL,
+               .serialize = &serialize_hsl,
+               .deserialize = &deserialize_hsl,
        },
        // sand
        {
                .solid = true,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // water
        {
                .solid = false,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // lava
        {
                .solid = false,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
        // vulcanostone
        {
                .solid = true,
+               .data_size = 0,
                .create = NULL,
+               .delete = NULL,
                .serialize = NULL,
                .deserialize = NULL,
        },
index bf668449a03784f5be050f1d18313b0021b01122..0c513482aaf0a1aacaf8286928c4bbf46652cf57 100644 (file)
@@ -4,6 +4,8 @@
 #include <stdbool.h>
 #include <dragontype/number.h>
 
+#define NODE_DEFINITION(type) ((type) < NODE_UNLOADED ? &node_definitions[NODE_UNKNOWN] : &node_definitions[(type)]);
+
 typedef enum
 {
        NODE_UNKNOWN,           // Used for unknown nodes received from server (caused by outdated clients)
@@ -12,7 +14,12 @@ typedef enum
        NODE_DIRT,
        NODE_STONE,
        NODE_SNOW,
-       NODE_WOOD,
+       NODE_OAK_WOOD,
+       NODE_OAK_LEAVES,
+       NODE_PINE_WOOD,
+       NODE_PINE_LEAVES,
+       NODE_PALM_WOOD,
+       NODE_PALM_LEAVES,
        NODE_SAND,
        NODE_WATER,
        NODE_LAVA,
@@ -25,11 +32,17 @@ struct MapNode;
 typedef struct
 {
        bool solid;
+       size_t data_size;
        void (*create)(struct MapNode *node);
-       void (*serialize)(struct MapNode *node);
-       void (*deserialize)(struct MapNode *node);
-} NodeDefintion;
+       void (*delete)(struct MapNode *node);
+       void (*serialize)(struct MapNode *node, unsigned char **buffer, size_t *bufsiz);
+       void (*deserialize)(struct MapNode *node, unsigned char *data, size_t size);
+} NodeDefinition;
+
+typedef struct {
+       v3f32 color;
+} HSLData;
 
-extern NodeDefintion node_definitions[];
+extern NodeDefinition node_definitions[];
 
 #endif
index dd099514f338c619cf231583e5288b8e71e0cf75..366a4d93b3bc0fff47bba3e4e6efad1f7cc93153 100644 (file)
@@ -21,6 +21,16 @@ typedef enum
        SO_VULCANO_STONE,
        SO_VULCANO_CRATER_TOP,
        SO_HILLYNESS,
+       SO_VOXELCTX,
+       SO_OAKTREE,
+       SO_OAKTREE_AREA,
+       SO_PINETREE,
+       SO_PINETREE_AREA,
+       SO_PINETREE_HEIGHT,
+       SO_PINETREE_BRANCH,
+       SO_PINETREE_BRANCH_DIR,
+       SO_PALMTREE,
+       SO_PALMTREE_AREA,
 } SeedOffset;
 
 extern s32 seed;
index 18c5a383b3336f52c76c90898aa6dc63cc3546c9..082c85c92dc75f32a035921c26f7208d3d67fa98 100644 (file)
@@ -22,7 +22,7 @@ Biome get_biome(v2s32 pos, f64 *factor)
 
 // mountain biome
 
-static s32 height_mountain(v2s32 pos, f64 factor, s32 height, unused void *row_data, unused void *block_data)
+static s32 height_mountain(v2s32 pos, f64 factor, f32 height, unused void *row_data, unused void *block_data)
 {
        return pow((height + 96) * pow(((smooth2d(U32(pos.x) / 48.0, U32(pos.y) / 48.0, 0, seed + SO_MOUNTAIN_HEIGHT) + 1.0) * 256.0 + 128.0), factor), 1.0 / (factor + 1.0)) - 96;
 }
@@ -173,7 +173,7 @@ static void preprocess_block_ocean(MapBlock *block, unused List *changed_blocks,
                data->vulcano_pos = (v2s32) {vulcano_pos.x * MAPBLOCK_SIZE, vulcano_pos.y * MAPBLOCK_SIZE};
 }
 
-static void preprocess_row_ocean(v2s32 pos, unused s32 height, unused f64 factor, void *row_data, void *block_data)
+static void preprocess_row_ocean(v2s32 pos, unused f64 factor, void *row_data, void *block_data)
 {
        OceanRowData *rdata = row_data;
        OceanBlockData *bdata = block_data;
@@ -202,7 +202,7 @@ static void preprocess_row_ocean(v2s32 pos, unused s32 height, unused f64 factor
        }
 }
 
-static s32 height_ocean(unused v2s32 pos, f64 factor, s32 height, void *row_data, unused void *block_data)
+static s32 height_ocean(unused v2s32 pos, f64 factor, f32 height, void *row_data, unused void *block_data)
 {
        OceanRowData *rdata = row_data;
        s32 ocean_floor = calculate_ocean_floor(factor, height);
@@ -210,7 +210,7 @@ static s32 height_ocean(unused v2s32 pos, f64 factor, s32 height, void *row_data
        return rdata->vulcano ? max(ocean_floor, rdata->vulcano_height) : ocean_floor;
 }
 
-static Node generate_ocean(v3s32 pos, s32 diff, unused f64 humidity, unused f64 temperature, unused f64 factor, unused MapBlock *block, unused List *changed_blocks, void *row_data, unused void *block_data)
+Node ocean_get_node_at(v3s32 pos, s32 diff, void *row_data)
 {
        OceanRowData *rdata = row_data;
 
@@ -233,6 +233,11 @@ static Node generate_ocean(v3s32 pos, s32 diff, unused f64 humidity, unused f64
        return NODE_AIR;
 }
 
+static Node generate_ocean(v3s32 pos, s32 diff, unused f64 humidity, unused f64 temperature, unused f64 factor, unused MapBlock *block, unused List *changed_blocks, void *row_data, unused void *block_data)
+{
+       return ocean_get_node_at(pos, diff, row_data);
+}
+
 // hills biome
 
 static bool boulder_touching_ground(v3s32 pos, s32 diff)
@@ -245,7 +250,7 @@ static bool boulder_touching_ground(v3s32 pos, s32 diff)
        return true;
 }
 
-static s32 height_hills(unused v2s32 pos, unused f64 factor, s32 height, unused void *row_data, unused void *block_data)
+static s32 height_hills(unused v2s32 pos, unused f64 factor, f32 height, unused void *row_data, unused void *block_data)
 {
        return height;
 }
index 0cf488105648575de4ff7f3aa1d820bbc4c0517a..46155632f79bb5176b460bea98e7500fcbee9167 100644 (file)
@@ -19,16 +19,17 @@ typedef struct
        SeedOffset offset;
        f64 threshold;
        bool snow;
-       s32 (*height)(v2s32 pos, f64 factor, s32 height, void *row_data, void *block_data);
+       s32 (*height)(v2s32 pos, f64 factor, f32 height, void *row_data, void *block_data);
        Node (*generate)(v3s32 pos, s32 diff, f64 humidity, f64 temperature, f64 factor, MapBlock *block, List *changed_blocks, void *row_data, void *block_data);
        size_t block_data_size;
        void (*preprocess_block)(MapBlock *block, List *changed_blocks, void *block_data);
        size_t row_data_size;
-       void (*preprocess_row)(v2s32 pos, s32 height, f64 factor, void *row_data, void *block_data);
+       void (*preprocess_row)(v2s32 pos, f64 factor, void *row_data, void *block_data);
 } BiomeDef;
 
-extern BiomeDef biomes[BIOME_COUNT];
+extern BiomeDef biomes[];
 
 Biome get_biome(v2s32 pos, f64 *factor);
+Node ocean_get_node_at(v3s32 pos, s32 diff, void *row_data);
 
 #endif
index 9c8bd23c72e7f393e404d8579eb1d1afb1db00bd..d205a88ffab090de3a65728b7ea8548ca166c580 100644 (file)
@@ -72,7 +72,7 @@ void database_init()
        }
 
        const char *init_stmts[3]= {
-               "CREATE TABLE IF NOT EXISTS map (pos BLOB PRIMARY KEY, generated INTEGER, size INTEGER, data BLOB, mgsb_size INTEGER, mgsb_data BLOB);",
+               "CREATE TABLE IF NOT EXISTS map (pos BLOB PRIMARY KEY, generated INTEGER, size INTEGER, rawsize INTEGER, data BLOB, mgsb_size INTEGER, mgsb_data BLOB);",
                "CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INTEGER);",
                "CREATE TABLE IF NOT EXISTS players (name TEXT PRIMARY KEY, pos BLOB);"
        };
@@ -115,7 +115,7 @@ bool database_load_block(MapBlock *block)
 {
        sqlite3_stmt *stmt;
 
-       if (! (stmt = prepare_block_statement(block, "loading", "SELECT generated, size, data, mgsb_size, mgsb_data FROM map WHERE pos=?")))
+       if (! (stmt = prepare_block_statement(block, "loading", "SELECT generated, size, rawsize, data, mgsb_size, mgsb_data FROM map WHERE pos=?")))
                return false;
 
        int rc = sqlite3_step(stmt);
@@ -126,15 +126,16 @@ bool database_load_block(MapBlock *block)
 
                extra->state = sqlite3_column_int(stmt, 0) ? MBS_READY : MBS_CREATED;
                extra->size = sqlite3_column_int64(stmt, 1);
+               extra->rawsize = sqlite3_column_int64(stmt, 2);
                extra->data = malloc(extra->size);
-               memcpy(extra->data, sqlite3_column_blob(stmt, 2), extra->size);
+               memcpy(extra->data, sqlite3_column_blob(stmt, 3), extra->size);
 
                MapgenStageBuffer decompressed_mgsb;
-               my_decompress(sqlite3_column_blob(stmt, 4), sqlite3_column_int64(stmt, 3), &decompressed_mgsb, sizeof(MapgenStageBuffer));
+               my_decompress(sqlite3_column_blob(stmt, 5), sqlite3_column_int64(stmt, 4), &decompressed_mgsb, sizeof(MapgenStageBuffer));
 
                ITERATE_MAPBLOCK extra->mgs_buffer[x][y][z] = be32toh(decompressed_mgsb[x][y][z]);
 
-               if (! map_deserialize_block(block, extra->data, extra->size))
+               if (! map_deserialize_block(block, extra->data, extra->size, extra->rawsize))
                        printf("Error with deserializing block at (%d, %d, %d)\n", block->pos.x, block->pos.y, block->pos.z);
        } else if (rc != SQLITE_DONE) {
                print_block_error(block, "loading");
@@ -149,7 +150,7 @@ void database_save_block(MapBlock *block)
 {
        sqlite3_stmt *stmt;
 
-       if (! (stmt = prepare_block_statement(block, "saving", "REPLACE INTO map (pos, generated, size, data, mgsb_size, mgsb_data) VALUES(?1, ?2, ?3, ?4, ?5, ?6)")))
+       if (! (stmt = prepare_block_statement(block, "saving", "REPLACE INTO map (pos, generated, size, rawsize, data, mgsb_size, mgsb_data) VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7)")))
                return;
 
        MapBlockExtraData *extra = block->extra;
@@ -164,9 +165,10 @@ void database_save_block(MapBlock *block)
 
        sqlite3_bind_int(stmt, 2, extra->state > MBS_CREATED);
        sqlite3_bind_int64(stmt, 3, extra->size);
-       sqlite3_bind_blob(stmt, 4, extra->data, extra->size, SQLITE_TRANSIENT);
-       sqlite3_bind_int64(stmt, 5, mgsb_size);
-       sqlite3_bind_blob(stmt, 6, mgsb_data, mgsb_size, &free);
+       sqlite3_bind_int64(stmt, 4, extra->rawsize);
+       sqlite3_bind_blob(stmt, 5, extra->data, extra->size, SQLITE_TRANSIENT);
+       sqlite3_bind_int64(stmt, 6, mgsb_size);
+       sqlite3_bind_blob(stmt, 7, mgsb_data, mgsb_size, &free);
 
        if (sqlite3_step(stmt) != SQLITE_DONE)
                print_block_error(block, "saving");
index 22e54e09ffebd1f9f9f9397a749b7dfc1005f037..bfaaf0d0ba98ed01a5ccfe0d16f293a4f528dbf4 100644 (file)
@@ -1,10 +1,12 @@
 #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)
@@ -32,9 +34,9 @@ void mapgen_generate_block(MapBlock *block, List *changed_blocks)
                for (u8 z = 0; z < MAPBLOCK_SIZE; z++) {
                        v2s32 pos_horizontal = {pos_x, block_node_pos.z + z};
 
-                       s32 height = (pnoise2d(U32(pos_horizontal.x) / 32.0, U32(pos_horizontal.y) / 32.0, 0.45, 5, seed + SO_HEIGHT) * 16.0)
+                       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;
+                               + 32.0;
 
                        f64 factor;
                        Biome biome = get_biome(pos_horizontal, &factor);
@@ -51,9 +53,9 @@ void mapgen_generate_block(MapBlock *block, List *changed_blocks)
                        char row_data[biome_def->row_data_size];
 
                        if (biome_def->preprocess_row)
-                               biome_def->preprocess_row(pos_horizontal, height, factor, row_data, block_data[biome]);
+                               biome_def->preprocess_row(pos_horizontal, factor, row_data, block_data[biome]);
 
-                       height = biome_def->height(pos_horizontal, factor, height, 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++) {
                                v3s32 pos = {pos_horizontal.x, block_node_pos.y + y, pos_horizontal.y};
@@ -68,9 +70,22 @@ void mapgen_generate_block(MapBlock *block, List *changed_blocks)
                                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);
+                                       block->data[x][y][z] = map_node_create(node, NULL, 0);
                                        extra->mgs_buffer[x][y][z] = MGS_TERRAIN;
                                }
                                pthread_mutex_unlock(&block->mtx);
index 1d48fa07e5cfae9ff845bf2bbadac1eb2b6067b6..2a437ffdaca76ea2cb7652f440dea810b040a6c5 100644 (file)
@@ -70,13 +70,13 @@ static bool setnode_handler(Client *client, bool good)
        if (! read_v3s32(client->fd, &pos))
                return false;
 
-       MapNode node;
+       Node node;
 
-       if (! map_deserialize_node(client->fd, &node))
+       if (! read_u32(client->fd, &node))
                return false;
 
        if (good)
-               map_set_node(server_map.map, pos, node, false, NULL);
+               map_set_node(server_map.map, pos, map_node_create(node, NULL, 0), false, NULL);
 
        return true;
 }
index 35025d5ff690adde274b2b5f1292b3199600184a..2f5d7a9056efeb04b266255fe993751795676a62 100644 (file)
@@ -8,7 +8,7 @@ typedef enum
        SERVER_COMMAND_NULL,    // invalid command
        SC_DISCONNECT,                  // client notifies server about disconnecting
        SC_AUTH,                                // client wants to authentify [body: name (zero terminated string)]
-       SC_SETNODE,                             // player placed a node [body: pos (v3s32), node (MapNode)]
+       SC_SETNODE,                             // player placed a node [body: pos (v3s32), node (Node)]
        SC_POS,                                 // player moved [body: pos (v3f)]
        SC_REQUEST_BLOCK,               // request to send a block [body: pos (v3s32)]
        SERVER_COMMAND_COUNT,   // count of available commands
index 83b81f7c30966000ee0fda871d0985c1dea96880..f7cb57d16d136d0e76621361ca2aa1400eb0a265 100644 (file)
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -21,7 +22,11 @@ static void send_block(Client *client, MapBlock *block)
 
        pthread_mutex_lock(&client->mtx);
        if (client->state == CS_ACTIVE)
-               (void) (write_u32(client->fd, CC_BLOCK) && write_v3s32(client->fd, block->pos) && write_u64(client->fd, extra->size) && write(client->fd, extra->data, extra->size) != -1);
+               (void) (write_u32(client->fd, CC_BLOCK)
+                       && write_v3s32(client->fd, block->pos)
+                       && write_u64(client->fd, extra->size)
+                       && write_u64(client->fd, extra->rawsize)
+                       && write(client->fd, extra->data, extra->size) != -1);
        pthread_mutex_unlock(&client->mtx);
 }
 
@@ -37,7 +42,7 @@ static void send_block_to_near(MapBlock *block)
        if (extra->data)
                free(extra->data);
 
-       map_serialize_block(block, &extra->data, &extra->size);
+       map_serialize_block(block, &extra->data, &extra->size, &extra->rawsize);
        database_save_block(block);
 
        if (extra->state == MBS_CREATED)
@@ -126,7 +131,7 @@ static void on_create_block(MapBlock *block)
                extra->data = NULL;
 
                ITERATE_MAPBLOCK {
-                       block->data[x][y][z] = map_node_create(NODE_AIR);
+                       block->data[x][y][z] = map_node_create(NODE_AIR, NULL, 0);
                        extra->mgs_buffer[x][y][z] = MGS_VOID;
                }
        }
@@ -215,29 +220,29 @@ static void generate_spawn_hut()
        for (s32 x = -4; x <= +4; x++) {
                for (s32 y = 0; y <= 3; y++) {
                        for (s32 z = -3; z <= +2; z++) {
-                               mapgen_set_node((v3s32) {x, server_map.spawn_height + y, z}, (MapNode) {NODE_AIR}, MGS_PLAYER, &changed_blocks);
+                               mapgen_set_node((v3s32) {x, server_map.spawn_height + y, z}, map_node_create(NODE_AIR, NULL, 0), MGS_PLAYER, &changed_blocks);
                        }
                }
        }
 
        for (s32 x = -5; x <= +5; x++) {
                for (s32 z = -4; z <= +3; z++) {
-                       mapgen_set_node((v3s32) {x, server_map.spawn_height - 1, z}, (MapNode) {NODE_WOOD}, MGS_PLAYER, &changed_blocks);
-                       mapgen_set_node((v3s32) {x, server_map.spawn_height + 4, z}, (MapNode) {NODE_WOOD}, MGS_PLAYER, &changed_blocks);
+                       mapgen_set_node((v3s32) {x, server_map.spawn_height - 1, z}, map_node_create(NODE_OAK_WOOD, NULL, 0), MGS_PLAYER, &changed_blocks);
+                       mapgen_set_node((v3s32) {x, server_map.spawn_height + 4, z}, map_node_create(NODE_OAK_WOOD, NULL, 0), MGS_PLAYER, &changed_blocks);
                }
        }
 
        for (s32 y = 0; y <= 3; y++) {
                for (s32 x = -5; x <= +5; x++) {
-                       mapgen_set_node((v3s32) {x, server_map.spawn_height + y, -4}, (MapNode) {((y == 1 || y == 2) && ((x >= -3 && x <= -1) || (x >= +1 && x <= +2))) ? NODE_AIR : NODE_WOOD}, MGS_PLAYER, &changed_blocks);
-                       mapgen_set_node((v3s32) {x, server_map.spawn_height + y, +3}, (MapNode) {((y == 1 || y == 2) && ((x >= -3 && x <= -2) || (x >= +1 && x <= +3))) ? NODE_AIR : NODE_WOOD}, MGS_PLAYER, &changed_blocks);
+                       mapgen_set_node((v3s32) {x, server_map.spawn_height + y, -4}, map_node_create(((y == 1 || y == 2) && ((x >= -3 && x <= -1) || (x >= +1 && x <= +2))) ? NODE_AIR : NODE_OAK_WOOD, NULL, 0), MGS_PLAYER, &changed_blocks);
+                       mapgen_set_node((v3s32) {x, server_map.spawn_height + y, +3}, map_node_create(((y == 1 || y == 2) && ((x >= -3 && x <= -2) || (x >= +1 && x <= +3))) ? NODE_AIR : NODE_OAK_WOOD, NULL, 0), MGS_PLAYER, &changed_blocks);
                }
        }
 
        for (s32 y = 0; y <= 3; y++) {
                for (s32 z = -3; z <= +2; z++) {
-                       mapgen_set_node((v3s32) {-5, server_map.spawn_height + y, z}, (MapNode) {NODE_WOOD}, MGS_PLAYER, &changed_blocks);
-                       mapgen_set_node((v3s32) {+5, server_map.spawn_height + y, z}, (MapNode) {((y != 3) && (z == -1 || z == +0)) ? NODE_AIR : NODE_WOOD}, MGS_PLAYER, &changed_blocks);
+                       mapgen_set_node((v3s32) {-5, server_map.spawn_height + y, z}, map_node_create(NODE_OAK_WOOD, NULL, 0), MGS_PLAYER, &changed_blocks);
+                       mapgen_set_node((v3s32) {+5, server_map.spawn_height + y, z}, map_node_create(((y != 3) && (z == -1 || z == +0)) ? NODE_AIR : NODE_OAK_WOOD, NULL, 0), MGS_PLAYER, &changed_blocks);
                }
        }
 
@@ -265,7 +270,7 @@ static void generate_spawn_hut()
                        if (node_definitions[node].solid)
                                break;
 
-                       mapgen_set_node(pos, (MapNode) {node == NODE_LAVA ? NODE_VULCANO_STONE : NODE_WOOD}, MGS_PLAYER, &changed_blocks);
+                       mapgen_set_node(pos, map_node_create(node == NODE_LAVA ? NODE_VULCANO_STONE : NODE_OAK_WOOD, NULL, 0), MGS_PLAYER, &changed_blocks);
                }
        }
 
index d4049fb1ef0f0aeb43cb882ccd5516be96eacb74..0cddb3e4757f85267e27e3c8021235f3324a63bd 100644 (file)
@@ -33,6 +33,7 @@ typedef struct
 {
        char *data;                                             // cached serialized data
        size_t size;                                    // size of data
+       size_t rawsize;                                 // size of decompressed data
        MapBlockState state;                    // generation state of the block
        pthread_t mapgen_thread;                // thread that is generating block
        MapgenStageBuffer mgs_buffer;   // buffer to make sure mapgen only overrides things it should
diff --git a/src/server/trees.c b/src/server/trees.c
new file mode 100644 (file)
index 0000000..b5d0ee1
--- /dev/null
@@ -0,0 +1,246 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "server/biomes.h"
+#include "server/mapgen.h"
+#include "server/trees.h"
+#include "server/voxelctx.h"
+#include "util.h"
+
+// oak
+
+static bool oak_condition(unused v3s32 pos, unused f64 humidity, unused f64 temperature, Biome biome, unused f64 factor, unused MapBlock *block, unused void *row_data, unused void *block_data)
+{
+       return biome == BIOME_HILLS;
+}
+
+static void oak_tree_leaf(Voxelctx *ctx)
+{
+       if (! voxelctx_is_alive(ctx))
+               return;
+
+       voxelctx_push(ctx);
+               voxelctx_cube(ctx, NODE_OAK_LEAVES, true);
+       voxelctx_pop(ctx);
+
+       voxelctx_push(ctx);
+               voxelctx_x(ctx, 0.5f);
+               voxelctx_sx(ctx, 0.9f);
+               voxelctx_sy(ctx, 0.9f);
+               voxelctx_sz(ctx, 0.8f);
+               voxelctx_ry(ctx, 25.0f);
+               voxelctx_x(ctx, 0.4f);
+               oak_tree_leaf(ctx);
+       voxelctx_pop(ctx);
+}
+
+static void oak_tree_top(Voxelctx *ctx)
+{
+       if (! voxelctx_is_alive(ctx))
+               return;
+
+       voxelctx_push(ctx);
+       for (int i = 0; i < 8; i++) {
+               voxelctx_rz(ctx, 360.0f / 8.0f);
+               voxelctx_push(ctx);
+                       voxelctx_life(ctx, 8);
+                       voxelctx_sy(ctx, 2.0f);
+                       voxelctx_z(ctx, voxelctx_random(ctx, 0.0f, 5.0f));
+                       voxelctx_s(ctx, 5.0f);
+                       voxelctx_light(ctx, -0.4f);
+                       voxelctx_sat(ctx, 0.5f);
+                       voxelctx_hue(ctx, voxelctx_random(ctx, 60.0f, 20.0f));
+                       voxelctx_ry(ctx, -45.0f);
+                       oak_tree_leaf(ctx);
+               voxelctx_pop(ctx);
+       }
+       voxelctx_pop(ctx);
+}
+
+static void oak_tree_part(Voxelctx *ctx, f32 n)
+{
+       if (! voxelctx_is_alive(ctx))
+               return;
+
+       voxelctx_push(ctx);
+       for (int i = 1; i <= n; i++) {
+               voxelctx_z(ctx, 1.0f);
+               voxelctx_rz(ctx, voxelctx_random(ctx, 30.0f, 10.0f));
+               voxelctx_rx(ctx, voxelctx_random(ctx, 0.0f, 10.0f));
+
+               voxelctx_push(ctx);
+                       voxelctx_s(ctx, 4.0f);
+                       voxelctx_x(ctx, 0.1f);
+                       voxelctx_light(ctx, voxelctx_random(ctx, 0.0f, 0.1f));
+                       //voxelctx_cylinder(ctx, NODE_OAK_WOOD, true);
+                       voxelctx_cube(ctx, NODE_OAK_WOOD, true);
+               voxelctx_pop(ctx);
+
+               if (i == (int) (n - 2.0f)) {
+                       voxelctx_push(ctx);
+                               oak_tree_top(ctx);
+                       voxelctx_pop(ctx);
+               }
+       }
+       voxelctx_pop(ctx);
+}
+
+static void oak_tree(v3s32 pos, List *changed_blocks)
+{
+       Voxelctx *ctx = voxelctx_create(changed_blocks, MGS_TREES, pos);
+
+       voxelctx_hue(ctx, 40.0f);
+       voxelctx_light(ctx, -0.5f);
+       voxelctx_sat(ctx, 0.5f);
+
+       /*voxelctx_s(ctx, 50);
+       voxelctx_ry(ctx, 45);
+
+       voxelctx_push(ctx);
+               voxelctx_cube(ctx, NODE_OAK_LEAVES, true);
+       voxelctx_pop(ctx);
+
+       voxelctx_delete(ctx);
+       if (true)
+               return;*/
+
+       f32 n = voxelctx_random(ctx, 40.0f, 10.0f);
+
+       voxelctx_push(ctx);
+       for (int i = 1; i <= 3; i++) {
+               voxelctx_rz(ctx, voxelctx_random(ctx, 120.0f, 45.0f));
+               voxelctx_push(ctx);
+                       voxelctx_y(ctx, 0.5f);
+                       voxelctx_light(ctx, voxelctx_random(ctx, -0.3f, 0.05f));
+                       oak_tree_part(ctx, n);
+               voxelctx_pop(ctx);
+       }
+       voxelctx_pop(ctx);
+
+       voxelctx_delete(ctx);
+}
+
+// pine
+
+static bool pine_condition(unused v3s32 pos, unused f64 humidity, unused f64 temperature, Biome biome, unused f64 factor, unused MapBlock *block, unused void *row_data, unused void *block_data)
+{
+       return biome == BIOME_MOUNTAIN;
+}
+
+static void pine_tree(v3s32 pos, List *changed_blocks)
+{
+       s32 tree_top = (noise2d(pos.x, pos.z, 0, seed + SO_PINETREE_HEIGHT) * 0.5 + 0.5) * (35.0 - 20.0) + 20.0 + pos.y;
+       for (v3s32 tree_pos = pos; tree_pos.y < tree_top; tree_pos.y++) {
+               f64 branch_length = noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + SO_PINETREE_BRANCH) * 3.0;
+
+               v3s32 dirs[4] = {
+                       {+0, +0, +1},
+                       {+1, +0, +0},
+                       {+0, +0, -1},
+                       {-1, +0, +0},
+               };
+
+               s32 dir = (noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + SO_PINETREE_BRANCH_DIR) * 0.5 + 0.5) * 4.0;
+
+               for (v3s32 branch_pos = tree_pos; branch_length > 0; branch_length--, branch_pos = v3s32_add(branch_pos, dirs[dir]))
+                       mapgen_set_node(branch_pos, map_node_create(NODE_PINE_WOOD, NULL, 0), MGS_TREES, changed_blocks);
+
+               mapgen_set_node(tree_pos, map_node_create(NODE_PINE_WOOD, NULL, 0), MGS_TREES, changed_blocks);
+       }
+}
+
+// palm
+
+static bool palm_condition(v3s32 pos, unused f64 humidity, unused f64 temperature, Biome biome, unused f64 factor, unused MapBlock *block, void *row_data, unused void *block_data)
+{
+       return biome == BIOME_OCEAN
+               && ocean_get_node_at((v3s32) {pos.x, pos.y - 0, pos.z}, 1, row_data) == NODE_AIR
+               && ocean_get_node_at((v3s32) {pos.x, pos.y - 1, pos.z}, 0, row_data) == NODE_SAND;
+}
+
+static void palm_branch(Voxelctx *ctx)
+{
+       if (! voxelctx_is_alive(ctx))
+               return;
+
+       voxelctx_cube(ctx, NODE_PALM_LEAVES, true);
+       voxelctx_push(ctx);
+               voxelctx_z(ctx, 0.5f);
+               voxelctx_s(ctx, 0.8f);
+               voxelctx_rx(ctx, voxelctx_random(ctx, 20.0f, 4.0f));
+               voxelctx_z(ctx, 0.5f);
+               palm_branch(ctx);
+       voxelctx_pop(ctx);
+}
+
+static void palm_tree(v3s32 pos, List *changed_blocks)
+{
+       Voxelctx *ctx = voxelctx_create(changed_blocks, MGS_TREES, (v3s32) {pos.x, pos.y - 1, pos.z});
+
+       f32 s = voxelctx_random(ctx, 8.0f, 2.0f);
+
+       voxelctx_push(ctx);
+       for (int i = 1; i <= s; i++) {
+               voxelctx_z(ctx, 1.0f);
+               voxelctx_push(ctx);
+                       voxelctx_s(ctx, 1.0f);
+                       voxelctx_light(ctx, voxelctx_random(ctx, -0.8f, 0.1f));
+                       voxelctx_sat(ctx, 0.5f);
+                       voxelctx_cube(ctx, NODE_PALM_WOOD, true);
+               voxelctx_pop(ctx);
+       }
+       voxelctx_pop(ctx);
+
+       voxelctx_z(ctx, s);
+       voxelctx_sat(ctx, 1.0f),
+       voxelctx_light(ctx, -0.5f);
+       voxelctx_hue(ctx, voxelctx_random(ctx, 50.0f, 30.0f));
+
+       voxelctx_push(ctx);
+       for (int i = 0; i < 6; i++) {
+               voxelctx_rz(ctx, 360.0f / 6.0f);
+               voxelctx_rz(ctx, voxelctx_random(ctx, 0.0f, 10.0f));
+               voxelctx_push(ctx);
+                       voxelctx_light(ctx, voxelctx_random(ctx, 0.0f, 0.3f));
+                       voxelctx_rx(ctx, 90.0f);
+                       voxelctx_s(ctx, 2.0f);
+                       palm_branch(ctx);
+               voxelctx_pop(ctx);
+       }
+       voxelctx_pop(ctx);
+
+       voxelctx_delete(ctx);
+}
+
+TreeDef tree_definitions[NUM_TREES] = {
+       // oak
+       {
+               .spread = 64.0f,
+               .probability = 0.0005f,
+               .area_probability = 0.3f,
+               .offset = SO_OAKTREE,
+               .area_offset = SO_OAKTREE_AREA,
+               .condition = &oak_condition,
+               .generate = &oak_tree,
+       },
+       // pine
+       {
+               .spread = 256.0f,
+               .probability = 0.01f,
+               .area_probability = 0.1f,
+               .offset = SO_PINETREE,
+               .area_offset = SO_PINETREE_AREA,
+               .condition = &pine_condition,
+               .generate = &pine_tree,
+       },
+       // palm
+       {
+               .spread = 16.0f,
+               .probability = 0.005f,
+               .area_probability = 0.5f,
+               .offset = SO_PALMTREE,
+               .area_offset = SO_PALMTREE_AREA,
+               .condition = &palm_condition,
+               .generate = &palm_tree,
+       },
+};
+
diff --git a/src/server/trees.h b/src/server/trees.h
new file mode 100644 (file)
index 0000000..439d37e
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _TREES_H_
+#define _TREES_H_
+
+#include <dragontype/list.h>
+#include <dragontype/number.h>
+#include "perlin.h"
+
+#define NUM_TREES 3
+
+typedef struct
+{
+       f32 spread;
+       f32 probability;
+       f32 area_probability;
+       SeedOffset offset;
+       SeedOffset area_offset;
+       bool (*condition)(v3s32 pos, f64 humidity, f64 temperature, Biome biome, f64 factor, MapBlock *block, void *row_data, void *block_data);
+       void (*generate)(v3s32 pos, List *changed_blocks);
+} TreeDef;
+
+extern TreeDef tree_definitions[];
+
+#endif
diff --git a/src/server/voxelctx.c b/src/server/voxelctx.c
new file mode 100644 (file)
index 0000000..3e8999e
--- /dev/null
@@ -0,0 +1,311 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include "server/mapgen.h"
+#include "server/voxelctx.h"
+#include "perlin.h"
+#include "util.h"
+
+#define CREATE_NODE map_node_create(node, use_color ? (f32[]) {VOXELCTXSTATE(ctx).h / 360.0, VOXELCTXSTATE(ctx).s, VOXELCTXSTATE(ctx).l} : NULL, use_color ? sizeof(f32) * 3 : 0)
+
+static VoxelctxState *create_state(VoxelctxState *old)
+{
+       VoxelctxState *state = malloc(sizeof(VoxelctxState));
+
+       if (old) {
+               *state = *old;
+               state->strs = array_create(sizeof(char *));
+
+               for (size_t i = 0; i < old->strs.siz; i++) {
+                       char *s = strdup(((char **) old->strs.ptr)[i]);
+                       array_append(&state->strs, &s);
+               }
+       } else {
+               state->pos[0] = 0.0f;
+               state->pos[1] = 0.0f;
+               state->pos[2] = 0.0f;
+               state->pos[3] = 1.0f;
+               state->scale[0] = 1.0f;
+               state->scale[1] = 1.0f;
+               state->scale[2] = 1.0f;
+               mat4x4_identity(state->mat);
+               state->h = 0.0f;
+               state->s = 0.0f;
+               state->l = 1.0f;
+               state->life = 0;
+
+               state->strs = array_create(sizeof(char *));
+               char *s = format_string("glm.mat4()\n");
+               array_append(&state->strs, &s);
+       }
+
+       return state;
+}
+
+Voxelctx *voxelctx_create(List *changed_blocks, MapgenStage mgs, v3s32 pos)
+{
+       Voxelctx *ctx = malloc(sizeof(Voxelctx));
+
+       ctx->changed_blocks = changed_blocks;
+       ctx->mgs = mgs;
+       ctx->pos = pos;
+       ctx->statestack = list_create(NULL);
+       ctx->random = 0;
+
+       list_put(&ctx->statestack, create_state(NULL), NULL);
+
+       return ctx;
+}
+
+static void delete_state(VoxelctxState *state)
+{
+       for (size_t i = 0; i < state->strs.siz; i++)
+               free(((char **) state->strs.ptr)[i]);
+
+       free(state->strs.ptr);
+}
+
+static void list_delete_state(void *key, unused void *value, unused void *arg)
+{
+       delete_state(key);
+       free(key);
+}
+
+void voxelctx_delete(Voxelctx *ctx)
+{
+       list_clear_func(&ctx->statestack, &list_delete_state, NULL);
+       free(ctx);
+}
+
+static inline f32 mix(f32 x, f32 y, f32 t)
+{
+    return (1.0 - t) * x + t * y;
+}
+
+static void move_value(f32 *x, f32 v, f32 range)
+{
+    f32 dst = v >= 0 ? range : 0;
+    v = fabs(v);
+    *x = mix(*x, dst, v);
+}
+
+void voxelctx_hue(Voxelctx *ctx, f32 value)
+{
+       VOXELCTXSTATE(ctx).h += value;
+}
+
+void voxelctx_sat(Voxelctx *ctx, f32 value)
+{
+       move_value(&VOXELCTXSTATE(ctx).s, value, 1.0f);
+}
+
+void voxelctx_light(Voxelctx *ctx, f32 value)
+{
+       move_value(&VOXELCTXSTATE(ctx).l, value, 1.0f);
+}
+
+void voxelctx_life(Voxelctx *ctx, s32 value)
+{
+       VOXELCTXSTATE(ctx).life += value;
+}
+
+static void apply_translation(Voxelctx *ctx, v3f32 translate)
+{
+       vec4 translate_vec;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+       mat4x4_mul_vec4(translate_vec, VOXELCTXSTATE(ctx).mat, (vec4) {translate.x, translate.y, translate.z, 0.0f});
+#pragma GCC diagnostic pop
+       vec4_add(VOXELCTXSTATE(ctx).pos, VOXELCTXSTATE(ctx).pos, translate_vec);
+}
+
+void voxelctx_x(Voxelctx *ctx, f32 value)
+{
+       apply_translation(ctx, (v3f32) {value, 0.0f, 0.0f});
+}
+
+// swap y and z
+void voxelctx_z(Voxelctx *ctx, f32 value)
+{
+       apply_translation(ctx, (v3f32) {0.0f, value, 0.0f});
+}
+
+void voxelctx_y(Voxelctx *ctx, f32 value)
+{
+       apply_translation(ctx, (v3f32) {0.0f, 0.0f, value});
+}
+
+void voxelctx_rx(Voxelctx *ctx, f32 value)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+       mat4x4_rotate_X(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
+#pragma GCC diagnostic pop
+}
+
+// swap y and z
+void voxelctx_rz(Voxelctx *ctx, f32 value)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+
+       mat4x4_rotate_Y(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
+#pragma GCC diagnostic pop
+}
+
+void voxelctx_ry(Voxelctx *ctx, f32 value)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+       mat4x4_rotate_Z(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
+#pragma GCC diagnostic pop
+}
+
+static void apply_scale(Voxelctx *ctx, v3f32 scale)
+{
+       VOXELCTXSTATE(ctx).scale[0] *= scale.x;
+       VOXELCTXSTATE(ctx).scale[1] *= scale.y;
+       VOXELCTXSTATE(ctx).scale[2] *= scale.z;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+       mat4x4_scale_aniso(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, scale.x, scale.y, scale.z);
+#pragma GCC diagnostic pop
+}
+
+void voxelctx_sx(Voxelctx *ctx, f32 value)
+{
+       apply_scale(ctx, (v3f32) {value, 1.0f, 1.0f});
+}
+
+// swap y and z
+void voxelctx_sz(Voxelctx *ctx, f32 value)
+{
+       apply_scale(ctx, (v3f32) {1.0f, value, 1.0f});
+}
+
+void voxelctx_sy(Voxelctx *ctx, f32 value)
+{
+       apply_scale(ctx, (v3f32) {1.0f, 1.0f, value});
+}
+
+void voxelctx_s(Voxelctx *ctx, f32 value)
+{
+       apply_scale(ctx, (v3f32) {value, value, value});
+}
+
+void voxelctx_pop(Voxelctx *ctx)
+{
+       ListPair *next = ctx->statestack.first->next;
+       delete_state(ctx->statestack.first->key);
+       free(ctx->statestack.first->key);
+       free(ctx->statestack.first);
+       ctx->statestack.first = next;
+}
+
+void voxelctx_push(Voxelctx *ctx)
+{
+       ListPair *pair = malloc(sizeof(ListPair));
+       pair->key = create_state(&VOXELCTXSTATE(ctx));
+       pair->value = NULL;
+       pair->next = ctx->statestack.first;
+
+       ctx->statestack.first = pair;
+}
+
+bool voxelctx_is_alive(Voxelctx *ctx)
+{
+       if (VOXELCTXSTATE(ctx).life > 0) {
+               VOXELCTXSTATE(ctx).life--;
+               if (VOXELCTXSTATE(ctx).life <= 0)
+                       return false;
+       }
+
+       return VOXELCTXSTATE(ctx).scale[0] >= 1.0f && VOXELCTXSTATE(ctx).scale[1] >= 1.0f && VOXELCTXSTATE(ctx).scale[2] >= 1.0f;
+}
+
+void voxelctx_cube(Voxelctx *ctx, Node node, bool use_color)
+{
+       if (! voxelctx_is_alive(ctx))
+               return;
+
+       vec4 base_corners[8] = {
+               {0.0f, 0.0f, 0.0f, 0.0f},
+               {0.0f, 0.0f, 1.0f, 0.0f},
+               {0.0f, 1.0f, 0.0f, 0.0f},
+               {0.0f, 1.0f, 1.0f, 0.0f},
+               {1.0f, 0.0f, 0.0f, 0.0f},
+               {1.0f, 0.0f, 1.0f, 0.0f},
+               {1.0f, 1.0f, 0.0f, 0.0f},
+               {1.0f, 1.0f, 1.0f, 0.0f},
+       };
+
+       vec4 corners[8];
+
+       s32 max_len = 0;
+
+       vec4 center;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+       mat4x4_mul_vec4(center, VOXELCTXSTATE(ctx).mat, (vec4) {0.5f, 0.5f, 0.5f});
+#pragma GCC diagnostic pop
+
+       for (int i = 0; i < 8; i++) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+               mat4x4_mul_vec4(corners[i], VOXELCTXSTATE(ctx).mat, base_corners[i]);
+#pragma GCC diagnostic pop
+
+               vec3 from_center;
+               vec3_sub(from_center, corners[i], center);
+
+               s32 len = ceil(vec3_len(from_center));
+
+               if (max_len < len)
+                       max_len = len;
+       }
+
+       for (s32 x = -max_len; x <= +max_len; x++)
+       for (s32 y = -max_len; y <= +max_len; y++)
+       for (s32 z = -max_len; z <= +max_len; z++) {
+               s32 v[3];
+
+               for (int i = 0; i < 3; i++)
+                       v[i] = floor(VOXELCTXSTATE(ctx).pos[0] + 0.5f
+                               + mix(corners[0][i], corners[4][i], (f32) x / (f32) max_len / 2.0f)
+                               + mix(corners[0][i], corners[2][i], (f32) y / (f32) max_len / 2.0f)
+                               + mix(corners[0][i], corners[1][i], (f32) z / (f32) max_len / 2.0f));
+
+               mapgen_set_node(v3s32_add(ctx->pos, (v3s32) {v[0], v[1], v[2]}), CREATE_NODE, ctx->mgs, ctx->changed_blocks);
+       }
+}
+
+/*
+void voxelctx_cylinder(Voxelctx *ctx, Node node, bool use_color)
+{
+       if (! voxelctx_is_alive(ctx))
+               return;
+
+       return;
+
+       f32 xf = VOXELCTXSTATE(ctx).scale[0] / 2.0f;
+       for (s32 x = round(-xf + 0.5f); x <= round(xf); x++) {
+               f32 yf = cos(x / VOXELCTXSTATE(ctx).scale[0] * M_PI) * VOXELCTXSTATE(ctx).scale[1] / 2.0f;
+               for (s32 y = round(-yf); y <= round(yf); y++) {
+                       f32 zf = VOXELCTXSTATE(ctx).scale[2] / 2.0f;
+                       for (s32 z = round(-zf + 0.5f); z <= round(zf); z++) {
+                               mapgen_set_node((v3s32) {
+                                       ctx->pos.x + round(VOXELCTXSTATE(ctx).pos[0] + x),
+                                       ctx->pos.y + round(VOXELCTXSTATE(ctx).pos[2] + z),
+                                       ctx->pos.z + round(VOXELCTXSTATE(ctx).pos[1] + y),
+                               }, CREATE_NODE, ctx->mgs, ctx->changed_blocks);
+                       }
+               }
+       }
+}
+*/
+
+f32 voxelctx_random(Voxelctx *ctx, f32 base, f32 vary)
+{
+       return base + noise3d(ctx->pos.x, ctx->pos.y, ctx->pos.z, ctx->random++, seed + SO_VOXELCTX) * vary;
+}
diff --git a/src/server/voxelctx.h b/src/server/voxelctx.h
new file mode 100644 (file)
index 0000000..1da3d1c
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _VOXELCTX_H_
+#define _VOXELCTX_H_
+
+#define VOXELCTXSTATE(ctx) (*((VoxelctxState *) (ctx)->statestack.first->key))
+
+#include <linmath.h/linmath.h>
+#include <dragontype/list.h>
+#include <dragontype/number.h>
+#include "server/server_map.h"
+
+
+
+#include <dragontype/array.h>
+
+
+typedef struct
+{
+       vec4 pos;
+       vec3 scale;
+       mat4x4 mat;
+       f32 h, s, l;
+       s32 life;
+       Array strs;
+} VoxelctxState;
+
+typedef struct
+{
+       v3s32 pos;
+       List *changed_blocks;
+       MapgenStage mgs;
+       List statestack;
+       s32 random;
+} Voxelctx;
+
+Voxelctx *voxelctx_create(List *changed_blocks, MapgenStage mgs, v3s32 pos);
+void voxelctx_delete(Voxelctx *ctx);
+void voxelctx_hue(Voxelctx *ctx, f32 value);
+void voxelctx_sat(Voxelctx *ctx, f32 value);
+void voxelctx_light(Voxelctx *ctx, f32 value);
+void voxelctx_life(Voxelctx *ctx, s32 value);
+void voxelctx_x(Voxelctx *ctx, f32 value);
+void voxelctx_y(Voxelctx *ctx, f32 value);
+void voxelctx_z(Voxelctx *ctx, f32 value);
+void voxelctx_rx(Voxelctx *ctx, f32 value);
+void voxelctx_ry(Voxelctx *ctx, f32 value);
+void voxelctx_rz(Voxelctx *ctx, f32 value);
+void voxelctx_sx(Voxelctx *ctx, f32 value);
+void voxelctx_sy(Voxelctx *ctx, f32 value);
+void voxelctx_sz(Voxelctx *ctx, f32 value);
+void voxelctx_s(Voxelctx *ctx, f32 value);
+void voxelctx_pop(Voxelctx *ctx);
+void voxelctx_push(Voxelctx *ctx);
+bool voxelctx_is_alive(Voxelctx *ctx);
+void voxelctx_cube(Voxelctx *ctx, Node node, bool use_hsl);
+void voxelctx_cylinder(Voxelctx *ctx, Node node, bool use_hsl);
+f32 voxelctx_random(Voxelctx *ctx, f32 base, f32 vary);
+
+#endif
index c1c1c2dc37ee3d1667240a9b3b6889128d35bdf1..56640171f958c2cac5c934c75c4c704ae8e208fa 100644 (file)
@@ -122,3 +122,32 @@ char *format_string(const char *format, ...)
        va_end(args);
        return ptr;
 }
+
+void *buffer_read(unsigned char **buffer, size_t *bufsiz, size_t size)
+{
+       if (size == 0)
+               return NULL;
+
+       if (*bufsiz < size)
+               return NULL;
+
+       void *old_buffer = *buffer;
+
+       *bufsiz -= size;
+       *buffer += size;
+
+       return old_buffer;
+}
+
+void buffer_write(unsigned char **buffer, size_t *bufsiz, void *data, size_t size)
+{
+       if (size == 0)
+               return;
+
+       size_t old_bufsiz = *bufsiz;
+
+       *bufsiz += size;
+       *buffer = realloc(*buffer, *bufsiz);
+
+       memcpy(*buffer + old_bufsiz, data, size);
+}
index ddcec815003b2ad81d14be5096b5bb74369a5d90..cdb99657afe8c8eea12fd80f95fa28c847a61bc1 100644 (file)
@@ -28,5 +28,7 @@ bool my_decompress(const char *compressed, size_t compressed_size, void *decompr
 bool within_simulation_distance(v3f64 player_pos, v3s32 block_pos, u32 simulation_distance);                                                           // return true if a player is close enough to a block to access it
 f64 clamp(f64 v, f64 min, f64 max);
 char *format_string(const char *format, ...);
+void *buffer_read(unsigned char **buffer, size_t *bufsiz, size_t size);
+void buffer_write(unsigned char **buffer, size_t *bufsiz, void *data, size_t size);
 
 #endif
index 8e94dcc6bef47196a2f5cd93226eec0e8a8c3a24..8f03d32bdba0c7e5e467062c82dcab8b0a613242 100644 (file)
Binary files a/textures/crosshair.png and b/textures/crosshair.png differ
index 5cc6e8639556cfa826aa5e5079ff318de48de4ff..9a64b490f0b3c9708eb552679d4278daf15800da 100644 (file)
Binary files a/textures/dirt.png and b/textures/dirt.png differ
index 88a8b45abb14d87bd8a5af2648e69688117545aa..70a3522d6c39413d4a05bc689b358000ef028064 100644 (file)
Binary files a/textures/grass.png and b/textures/grass.png differ
index a88d91d865983ae3035bbb4e0a50b40ddc411d99..48aaccfadca12948f5f66fe6846eaf1ca0957069 100644 (file)
Binary files a/textures/lava.png and b/textures/lava.png differ
index 1a0bdc5903f71157e5fc845a465955c991bb9614..e44018f39c22eef104571b073701aae5e9e41faa 100644 (file)
Binary files a/textures/lava_nt.png and b/textures/lava_nt.png differ
diff --git a/textures/needles.png b/textures/needles.png
new file mode 100644 (file)
index 0000000..24e3ed4
Binary files /dev/null and b/textures/needles.png differ
diff --git a/textures/oak_leaves.png b/textures/oak_leaves.png
new file mode 100644 (file)
index 0000000..a29369a
Binary files /dev/null and b/textures/oak_leaves.png differ
diff --git a/textures/oak_wood.png b/textures/oak_wood.png
new file mode 100644 (file)
index 0000000..55cb954
Binary files /dev/null and b/textures/oak_wood.png differ
diff --git a/textures/oak_wood_top.png b/textures/oak_wood_top.png
new file mode 100644 (file)
index 0000000..cf8ed6f
Binary files /dev/null and b/textures/oak_wood_top.png differ
diff --git a/textures/palm_leaves.png b/textures/palm_leaves.png
new file mode 100644 (file)
index 0000000..9d44925
Binary files /dev/null and b/textures/palm_leaves.png differ
diff --git a/textures/palm_wood.png b/textures/palm_wood.png
new file mode 100644 (file)
index 0000000..5f0295d
Binary files /dev/null and b/textures/palm_wood.png differ
diff --git a/textures/palm_wood_top.png b/textures/palm_wood_top.png
new file mode 100644 (file)
index 0000000..276ae1e
Binary files /dev/null and b/textures/palm_wood_top.png differ
diff --git a/textures/pine_leaves.png b/textures/pine_leaves.png
new file mode 100644 (file)
index 0000000..24e3ed4
Binary files /dev/null and b/textures/pine_leaves.png differ
diff --git a/textures/pine_wood.png b/textures/pine_wood.png
new file mode 100644 (file)
index 0000000..fae7da1
Binary files /dev/null and b/textures/pine_wood.png differ
diff --git a/textures/pine_wood_top.png b/textures/pine_wood_top.png
new file mode 100644 (file)
index 0000000..276ae1e
Binary files /dev/null and b/textures/pine_wood_top.png differ
index c04d569a6dadb82b2431bb6804493f5e3c9ef10b..f403dc3b2f53b63ebec320a8ae47be4110a8606d 100644 (file)
Binary files a/textures/player.png and b/textures/player.png differ
index 63ca7d3c289c6bbb7d42e3fa9f1977a89a386330..3899f4b2679363fc443d846b4f957bdd9bb3f4f4 100644 (file)
Binary files a/textures/sand.png and b/textures/sand.png differ
index 17481035e94d0c1fd92e59660e5e8371a94dd287..359335ea0b17cc5c604625e3f45e189a83999bfe 100644 (file)
Binary files a/textures/snow.png and b/textures/snow.png differ
index a641ceb677542fbf9a78417ba1cee614bbc9ab00..3af8ac97cc7d5d5a1f7c5ab623c3450d15ca87f3 100644 (file)
Binary files a/textures/stone.png and b/textures/stone.png differ
index c94a9a2be43fa9e4f15aadc7ff0dcb7274aa8269..fb3b88dbc92c2fc0c12011afca73518dc3bc0101 100644 (file)
Binary files a/textures/sun.png and b/textures/sun.png differ
index c04d569a6dadb82b2431bb6804493f5e3c9ef10b..bbea82c42df2bc86c99e534def9edb22b51f35f7 100644 (file)
Binary files a/textures/unknown.png and b/textures/unknown.png differ
index 530fd3447e461ea6bf0d2b2779d3806df2aa7de0..c35971359226f213ca2e8579bb1f29e2c595877f 100644 (file)
Binary files a/textures/vulcano_stone.png and b/textures/vulcano_stone.png differ
index 175639e61a2848b5785cebe27b977bd66aa89d1d..b9a66fda818ea94141045e7c50d66a840bb62a28 100644 (file)
Binary files a/textures/water.png and b/textures/water.png differ
index 0c071f376e9b17477ce2b95d7adab432ef4de0f4..f4575669d27a4d451bb75922d5ccbb7039d94c99 100644 (file)
Binary files a/textures/water_nt.png and b/textures/water_nt.png differ
diff --git a/textures/wood.png b/textures/wood.png
deleted file mode 100644 (file)
index 63250fa..0000000
Binary files a/textures/wood.png and /dev/null differ
diff --git a/textures/wood_top.png b/textures/wood_top.png
deleted file mode 100644 (file)
index 505e6a0..0000000
Binary files a/textures/wood_top.png and /dev/null differ