]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Redesign map handling 0.1.1
authorElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 29 Mar 2021 17:18:07 +0000 (19:18 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 29 Mar 2021 17:18:07 +0000 (19:18 +0200)
16 files changed:
src/Makefile
src/client.c
src/clientcommands.c
src/clientmap.c [new file with mode: 0644]
src/clientmap.h [new file with mode: 0644]
src/map.c
src/map.h
src/mapblock_meshgen.c [deleted file]
src/mapblock_meshgen.h [deleted file]
src/mapgen.c [deleted file]
src/mapgen.h [deleted file]
src/perlin.c [deleted file]
src/server.c
src/servercommands.c
src/servermap.c [new file with mode: 0644]
src/servermap.h [new file with mode: 0644]

index 0b6d0d8433e5bd44c24b09478de158cefb287938..e0bc214e7d097defaeed341d0982013ee48d8ac6 100644 (file)
@@ -1,6 +1,6 @@
 COMMON = array.o list.o map.o signal.o util.o types.o node.o
-SERVER = $(COMMON) server.o servercommands.o mapgen.o perlin.o
-CLIENT = $(COMMON) client.o clientcommands.o mesh.o scene.o mapblock_meshgen.o shaders.o
+SERVER = $(COMMON) server.o servercommands.o servermap.o
+CLIENT = $(COMMON) client.o clientcommands.o clientmap.o mesh.o scene.o shaders.o
 LIBRARIES = -lpthread -lm
 CLIENT_LIBRARIES = -lGL -lGLEW -lglfw
 FLAGS = -g -fmax-errors=4
index a2e197ecbeadcc9af71a9a469b92c14dae76cb4d..0d581c61a9c342370c8da6b15271dd928fa8c9ed 100644 (file)
@@ -10,7 +10,7 @@
 #include <GL/gl.h>
 #include <GLFW/glfw3.h>
 #include "client.h"
-#include "mapblock_meshgen.h"
+#include "clientmap.h"
 #include "signal.h"
 #include "shaders.h"
 #include "util.h"
@@ -200,7 +200,7 @@ static void client_start(int fd)
        client.scene = scene_create();
        client.pos = (v3f) {0.0f, 0.0f, 0.0f};
 
-       mapblock_meshgen_init(client.map, client.scene);
+       clientmap_init(&client);
 
        pthread_t recv_thread;
        pthread_create(&recv_thread, NULL, &reciever_thread, NULL);
@@ -214,7 +214,7 @@ static void client_start(int fd)
        if (client.name)
                free(client.name);
 
-       mapblock_meshgen_stop();
+       clientmap_deinit();
 
        map_delete(client.map);
        scene_delete(client.scene);
index 5b99d34a8b0e7f0601216ff4f16b1eefa478de16..d3d816bb2d2fb5d613e07a0343c4d963b4bcc817 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include "client.h"
+#include "clientmap.h"
 #include "types.h"
 
 static bool disconnect_handler(Client *client, bool good)
@@ -33,7 +34,12 @@ static bool auth_handler(Client *client, bool good)
 
 static bool block_handler(Client *client, bool good)
 {
-       return map_deserialize_block(client->fd, client->map, ! good);
+       MapBlock *block;
+       if (! map_deserialize_block(client->fd, client->map, &block, ! good))
+               return false;
+       if (good)
+               clientmap_block_changed(block);
+       return true;
 }
 
 CommandHandler command_handlers[CLIENT_COMMAND_COUNT] = {
diff --git a/src/clientmap.c b/src/clientmap.c
new file mode 100644 (file)
index 0000000..236785b
--- /dev/null
@@ -0,0 +1,178 @@
+#include <stdlib.h>
+#include "clientmap.h"
+
+static struct
+{
+       List queue;
+       pthread_mutex_t mtx;
+       pthread_t thread;
+       bool cancel;
+} meshgen;
+
+static Client *client = NULL;
+
+static v3f vpos[6][6] = {
+       {
+               {-0.5f, -0.5f, -0.5f},
+               {+0.5f, -0.5f, -0.5f},
+               {+0.5f, +0.5f, -0.5f},
+               {+0.5f, +0.5f, -0.5f},
+               {-0.5f, +0.5f, -0.5f},
+               {-0.5f, -0.5f, -0.5f},
+       },
+       {
+               {-0.5f, -0.5f, +0.5f},
+               {+0.5f, +0.5f, +0.5f},
+               {+0.5f, -0.5f, +0.5f},
+               {+0.5f, +0.5f, +0.5f},
+               {-0.5f, -0.5f, +0.5f},
+               {-0.5f, +0.5f, +0.5f},
+       },
+       {
+               {-0.5f, +0.5f, +0.5f},
+               {-0.5f, -0.5f, -0.5f},
+               {-0.5f, +0.5f, -0.5f},
+               {-0.5f, -0.5f, -0.5f},
+               {-0.5f, +0.5f, +0.5f},
+               {-0.5f, -0.5f, +0.5f},
+       },
+       {
+               {+0.5f, +0.5f, +0.5f},
+               {+0.5f, +0.5f, -0.5f},
+               {+0.5f, -0.5f, -0.5f},
+               {+0.5f, -0.5f, -0.5f},
+               {+0.5f, -0.5f, +0.5f},
+               {+0.5f, +0.5f, +0.5f},
+       },
+       {
+               {-0.5f, -0.5f, -0.5f},
+               {+0.5f, -0.5f, -0.5f},
+               {+0.5f, -0.5f, +0.5f},
+               {+0.5f, -0.5f, +0.5f},
+               {-0.5f, -0.5f, +0.5f},
+               {-0.5f, -0.5f, -0.5f},
+       },
+       {
+               {-0.5f, +0.5f, -0.5f},
+               {+0.5f, +0.5f, -0.5f},
+               {+0.5f, +0.5f, +0.5f},
+               {+0.5f, +0.5f, +0.5f},
+               {-0.5f, +0.5f, +0.5f},
+               {-0.5f, +0.5f, -0.5f},
+       },
+};
+
+static v3s8 fdir[6] = {
+       {+0, +0, -1},
+       {+0, +0, +1},
+       {-1, +0, +0},
+       {+1, +0, +0},
+       {+0, -1, +0},
+       {+0, +1, +0},
+};
+
+#define GNODDEF(block, x, y, z) node_definitions[block->data[x][y][z].type]
+#define VALIDPOS(pos) (pos.x >= 0 && pos.x < 16 && pos.y >= 0 && pos.y < 16 && pos.z >= 0 && pos.z < 16)
+
+static Array make_vertices(MapBlock *block)
+{
+       Array vertices = array_create(sizeof(Vertex));
+
+       ITERATE_MAPBLOCK {
+               NodeDefintion *def = &GNODDEF(block, x, y, z);
+               if (def->visible) {
+                       v3u8 pos = {x, y, z};
+                       v3f offset = {x + 8.5f, y + 8.5f, z + 8.5f};
+                       v3f color = get_node_color(def);
+                       for (int f = 0; f < 6; f++) {
+                               v3s8 *noff = &fdir[f];
+                               v3s8 npos = {
+                                       pos.x + noff->x,
+                                       pos.y + noff->y,
+                                       pos.z + noff->z,
+                               };
+                               if (! VALIDPOS(npos) || ! GNODDEF(block, npos.x, npos.y, npos.z).visible) {
+                                       for (int v = 0; v < 6; v++) {
+                                               Vertex vertex = {
+                                                       vpos[f][v].x + offset.x,
+                                                       vpos[f][v].y + offset.y,
+                                                       vpos[f][v].z + offset.z,
+                                                       color.x,
+                                                       color.y,
+                                                       color.z,
+                                               };
+                                               array_append(&vertices, &vertex);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return vertices;
+}
+
+#undef GNODDEF
+#undef VALIDPOS
+
+static void *meshgen_thread(void *unused)
+{
+       (void) unused;
+
+       while (! meshgen.cancel) {
+               ListPair **lptr = &meshgen.queue.first;
+               if (*lptr) {
+                       pthread_mutex_lock(&meshgen.mtx);
+                       MapBlock *block = (*lptr)->key;
+                       block->state = MBS_READY;
+                       ListPair *next = (*lptr)->next;
+                       free(*lptr);
+                       *lptr = next;
+                       pthread_mutex_unlock(&meshgen.mtx);
+
+                       Array vertices = make_vertices(block);
+                       Mesh *mesh = NULL;
+
+                       if (vertices.siz > 0) {
+                               mesh = mesh_create(vertices.ptr, vertices.siz);
+                               mesh->pos = (v3f) {block->pos.x * 16.0f - 8.0f, block->pos.y * 16.0f - 8.0f, block->pos.z * 16.0f - 8.0f};
+                               mesh_transform(mesh);
+                               scene_add_mesh(client->scene, mesh);
+                       }
+
+                       if (block->extra)
+                               ((Mesh *) block->extra)->remove = true;
+
+                       block->extra = mesh;
+               } else {
+                       sched_yield();
+               }
+       }
+
+       return NULL;
+}
+
+void clientmap_init(Client *cli)
+{
+       client = cli;
+       meshgen.queue = list_create(NULL);
+       pthread_mutex_init(&meshgen.mtx, NULL);
+       pthread_create(&meshgen.thread, NULL, &meshgen_thread, NULL);
+}
+
+void clientmap_deinit()
+{
+       meshgen.cancel = true;
+       pthread_join(meshgen.thread, NULL);
+       pthread_mutex_destroy(&meshgen.mtx);
+       list_clear(&meshgen.queue);
+}
+
+void clientmap_block_changed(MapBlock *block)
+{
+       pthread_mutex_lock(&meshgen.mtx);
+       if (block->state != MBS_PROCESSING) {
+               block->state = MBS_PROCESSING;
+               list_put(&meshgen.queue, block, NULL);
+       }
+       pthread_mutex_unlock(&meshgen.mtx);
+}
diff --git a/src/clientmap.h b/src/clientmap.h
new file mode 100644 (file)
index 0000000..e46c374
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _CLIENTMAP_H_
+#define _CLIENTMAP_H_
+
+#include "client.h"
+
+void clientmap_init(Client *cli);
+void clientmap_deinit();
+
+void clientmap_block_changed(MapBlock *block);
+
+#endif
index 94d5ea8612cbe7c1d32e407462628aa251e27259..840b6ac955fce0a301a512f31c6713cce2b46741 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -22,8 +22,9 @@ static MapBlock *allocate_block(v3s32 pos)
 {
        MapBlock *block = malloc(sizeof(MapBlock));
        block->pos = pos;
-       block->ready = false;
+       block->state = MBS_CREATED;
        block->extra = NULL;
+       pthread_mutex_init(&block->mtx, NULL);
        return block;
 }
 
@@ -96,19 +97,17 @@ MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
        } else if (create) {
                block = allocate_block(pos);
                array_insert(&sector->blocks, &block, res.index);
-
-               if (map->on_block_create)
-                       map->on_block_create(block);
        } else {
                return NULL;
        }
 
-       return block->ready ? block : NULL;
+       return (create || block->state == MBS_READY) ? block : NULL;
 }
 
 void map_free_block(MapBlock *block)
 {
        ITERATE_MAPBLOCK map_node_clear(&block->data[x][y][z]);
+       pthread_mutex_destroy(&block->mtx);
        free(block);
 }
 
@@ -140,7 +139,7 @@ bool map_serialize_block(int fd, MapBlock *block)
        return true;
 }
 
-bool map_deserialize_block(int fd, Map *map, bool dummy)
+bool map_deserialize_block(int fd, Map *map, MapBlock **blockptr, bool dummy)
 {
        v3s32 pos;
 
@@ -162,18 +161,17 @@ bool map_deserialize_block(int fd, Map *map, bool dummy)
        }
 
        ITERATE_MAPBLOCK {
-               if (! map_deserialize_node(fd, &block->data[x][y][z]))
+               if (! map_deserialize_node(fd, &block->data[x][y][z])) {
+                       if (dummy)
+                               map_free_block(block);
                        return false;
+               }
        }
 
-       if (dummy) {
+       if (dummy)
                map_free_block(block);
-       } else {
-               block->ready = true;
-
-               if (map->on_block_add)
-                       map->on_block_add(block);
-       }
+       else if (blockptr)
+               *blockptr = block;
 
        return true;
 }
@@ -191,7 +189,7 @@ bool map_serialize(int fd, Map *map)
 
 void map_deserialize(int fd, Map *map)
 {
-       while (map_deserialize_block(fd, map, false))
+       while (map_deserialize_block(fd, map, NULL, false))
                ;
 }
 
@@ -220,6 +218,8 @@ void map_set_node(Map *map, v3s32 pos, MapNode node)
                MapNode *current_node = &block->data[offset.x][offset.y][offset.z];
                map_node_clear(current_node);
                *current_node = node;
+
+               block->state = MBS_MODIFIED;
        }
 }
 
index 2341379b919125ac0404102cf97ba87e2936b2c1..f659e2f062550bc60639b84fa98d48e47479a14a 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -2,6 +2,7 @@
 #define _MAP_H_
 
 #include <stdbool.h>
+#include <pthread.h>
 #include "array.h"
 #include "list.h"
 #include "node.h"
@@ -15,11 +16,20 @@ typedef struct
        List meta;
 } MapNode;
 
+typedef enum
+{
+       MBS_CREATED,
+       MBS_PROCESSING,
+       MBS_READY,
+       MBS_MODIFIED,
+} MapBlockState;
+
 typedef struct
 {
        MapNode data[16][16][16];
        v3s32 pos;
-       bool ready;
+       MapBlockState state;
+       pthread_mutex_t mtx;
        void *extra;
 } MapBlock;
 
@@ -30,14 +40,9 @@ typedef struct
        u64 hash;
 } MapSector;
 
-typedef void (*MapBlockCallback)(MapBlock *block);
-
 typedef struct
 {
        Array sectors;
-       MapBlockCallback on_block_create;
-       MapBlockCallback on_block_add;
-       MapBlockCallback on_block_change;
 } Map;
 
 Map *map_create();
@@ -52,7 +57,7 @@ void map_free_block(MapBlock *block);
 
 bool map_deserialize_node(int fd, MapNode *buf);
 bool map_serialize_block(int fd, MapBlock *block);
-bool map_deserialize_block(int fd, Map *map, bool dummy);
+bool map_deserialize_block(int fd, Map *map, MapBlock **blockptr, bool dummy);
 bool map_serialize(int fd, Map *map);
 void map_deserialize(int fd, Map *map);
 
diff --git a/src/mapblock_meshgen.c b/src/mapblock_meshgen.c
deleted file mode 100644 (file)
index 10bf853..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-#include <stdlib.h>
-#include "node.h"
-#include "mapblock_meshgen.h"
-
-static struct
-{
-       Map *map;
-       Scene *scene;
-       List queue;
-       pthread_mutex_t mtx;
-       pthread_t thread;
-       bool cancel;
-} meshgen;
-
-static v3f vpos[6][6] = {
-       {
-               {-0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {-0.5f, +0.5f, -0.5f},
-               {-0.5f, -0.5f, -0.5f},
-       },
-       {
-               {-0.5f, -0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {-0.5f, -0.5f, +0.5f},
-               {-0.5f, +0.5f, +0.5f},
-       },
-       {
-               {-0.5f, +0.5f, +0.5f},
-               {-0.5f, -0.5f, -0.5f},
-               {-0.5f, +0.5f, -0.5f},
-               {-0.5f, -0.5f, -0.5f},
-               {-0.5f, +0.5f, +0.5f},
-               {-0.5f, -0.5f, +0.5f},
-       },
-       {
-               {+0.5f, +0.5f, +0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
-       },
-       {
-               {-0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, -0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {+0.5f, -0.5f, +0.5f},
-               {-0.5f, -0.5f, +0.5f},
-               {-0.5f, -0.5f, -0.5f},
-       },
-       {
-               {-0.5f, +0.5f, -0.5f},
-               {+0.5f, +0.5f, -0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {+0.5f, +0.5f, +0.5f},
-               {-0.5f, +0.5f, +0.5f},
-               {-0.5f, +0.5f, -0.5f},
-       },
-};
-
-static v3s8 fdir[6] = {
-       {+0, +0, -1},
-       {+0, +0, +1},
-       {-1, +0, +0},
-       {+1, +0, +0},
-       {+0, -1, +0},
-       {+0, +1, +0},
-};
-
-#define GNODDEF(block, x, y, z) node_definitions[block->data[x][y][z].type]
-#define VALIDPOS(pos) (pos.x >= 0 && pos.x < 16 && pos.y >= 0 && pos.y < 16 && pos.z >= 0 && pos.z < 16)
-
-static Array make_vertices(MapBlock *block)
-{
-       Array vertices = array_create(sizeof(Vertex));
-
-       ITERATE_MAPBLOCK {
-               NodeDefintion *def = &GNODDEF(block, x, y, z);
-               if (def->visible) {
-                       v3u8 pos = {x, y, z};
-                       v3f offset = {x + 8.5f, y + 8.5f, z + 8.5f};
-                       v3f color = get_node_color(def);
-                       for (int f = 0; f < 6; f++) {
-                               v3s8 *noff = &fdir[f];
-                               v3s8 npos = {
-                                       pos.x + noff->x,
-                                       pos.y + noff->y,
-                                       pos.z + noff->z,
-                               };
-                               if (! VALIDPOS(npos) || ! GNODDEF(block, npos.x, npos.y, npos.z).visible) {
-                                       for (int v = 0; v < 6; v++) {
-                                               Vertex vertex = {
-                                                       vpos[f][v].x + offset.x,
-                                                       vpos[f][v].y + offset.y,
-                                                       vpos[f][v].z + offset.z,
-                                                       color.x,
-                                                       color.y,
-                                                       color.z,
-                                               };
-                                               array_append(&vertices, &vertex);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       return vertices;
-}
-
-#undef GNODDEF
-#undef VALIDPOS
-
-static void *meshgen_thread(void *unused)
-{
-       (void) unused;
-
-       while (! meshgen.cancel) {
-               ListPair **lptr = &meshgen.queue.first;
-               if (*lptr) {
-                       MapBlock *block = (*lptr)->key;
-
-                       pthread_mutex_lock(&meshgen.mtx);
-                       ListPair *next = (*lptr)->next;
-                       free(*lptr);
-                       *lptr = next;
-                       pthread_mutex_unlock(&meshgen.mtx);
-
-                       Array vertices = make_vertices(block);
-                       Mesh *mesh = NULL;
-
-                       if (vertices.siz > 0) {
-                               mesh = mesh_create(vertices.ptr, vertices.siz);
-                               mesh->pos = (v3f) {block->pos.x * 16.0f - 8.0f, block->pos.y * 16.0f - 8.0f, block->pos.z * 16.0f - 8.0f};
-                               mesh_transform(mesh);
-                               scene_add_mesh(meshgen.scene, mesh);
-                       }
-
-                       if (block->extra)
-                               ((Mesh *) block->extra)->remove = true;
-
-                       block->extra = mesh;
-               } else {
-                       sched_yield();
-               }
-       }
-
-       return NULL;
-}
-
-static void enqueue_block(MapBlock *block)
-{
-       pthread_mutex_lock(&meshgen.mtx);
-       list_put(&meshgen.queue, block, NULL);
-       pthread_mutex_unlock(&meshgen.mtx);
-}
-
-void mapblock_meshgen_init(Map *map, Scene *scene)
-{
-       meshgen.map = map;
-       meshgen.scene = scene;
-       meshgen.queue = list_create(NULL);
-       pthread_mutex_init(&meshgen.mtx, NULL);
-       map->on_block_add = &enqueue_block;
-       map->on_block_change = &enqueue_block;
-       pthread_create(&meshgen.thread, NULL, &meshgen_thread, NULL);
-}
-
-void mapblock_meshgen_stop()
-{
-       meshgen.cancel = true;
-       pthread_join(meshgen.thread, NULL);
-       pthread_mutex_destroy(&meshgen.mtx);
-       ITERATE_LIST(&meshgen.queue, pair) free(pair->key);
-       list_clear(&meshgen.queue);
-}
diff --git a/src/mapblock_meshgen.h b/src/mapblock_meshgen.h
deleted file mode 100644 (file)
index 2be1016..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _MAPBLOCK_MESHGEN_H_
-#define _MAPBLOCK_MESHGEN_H_
-
-#include "map.h"
-#include "scene.h"
-
-void mapblock_meshgen_init(Map *map, Scene *scene);
-void mapblock_meshgen_stop();
-
-#endif
diff --git a/src/mapgen.c b/src/mapgen.c
deleted file mode 100644 (file)
index b25f58e..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <stdlib.h>
-#include <perlin/perlin.h>
-#include "mapgen.h"
-
-int seed = 0;
-static Server *server = NULL;
-
-// mapgen prototype
-static void generate_block(MapBlock *block)
-{
-       for (u8 x = 0; x < 16; x++) {
-               u32 ux = x + block->pos.x * 16 + ((u32) 1 << 31);
-               for (u8 z = 0; z < 16; z++) {
-                       u32 uz = z + block->pos.z * 16 + ((u32) 1 << 31);
-                       s32 height = smooth2d((double) ux / 32.0f, (double) uz / 32.0f, 0, seed) * 16.0f;
-                       for (u8 y = 0; y < 16; y++) {
-                               s32 ay = y + block->pos.y * 16;
-                               Node type;
-                               if (ay > height)
-                                       type = NODE_AIR;
-                               else if (ay == height)
-                                       type = NODE_GRASS;
-                               else if (ay >= height - 4)
-                                       type = NODE_DIRT;
-                               else
-                                       type = NODE_STONE;
-                               block->data[x][y][z] = map_node_create(type);
-                       }
-               }
-       }
-       ITERATE_LIST(&server->clients, pair) {
-               Client *client = pair->value;
-               if (client->state == CS_ACTIVE) {
-                       pthread_mutex_lock(&client->mtx);
-                       (void) (write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, block));
-                       pthread_mutex_unlock(&client->mtx);
-               }
-       }
-       block->ready = true;
-}
-
-void mapgen_init(Server *srv)
-{
-       server = srv;
-       server->map->on_block_create = &generate_block;
-}
-
-#define RANGE 3
-
-static void *mapgen_thread(void *cliptr)
-{
-       Client *client = cliptr;
-
-       while (client->state != CS_DISCONNECTED) {
-               v3s32 pos = map_node_to_block_pos((v3s32) {client->pos.x, client->pos.y, client->pos.z}, NULL);
-               for (s32 x = pos.x - RANGE; x <= pos.x + RANGE; x++)
-                       for (s32 y = pos.y - RANGE; y <= pos.y + RANGE; y++)
-                               for (s32 z = pos.z - RANGE; z <= pos.z + RANGE; z++)
-                                       map_get_block(client->server->map, (v3s32) {x, y, z}, true);
-       }
-
-       return NULL;
-}
-
-void mapgen_start_thread(Client *client)
-{
-       (void) client;
-       (void) mapgen_thread;
-       pthread_t thread;
-       pthread_create(&thread, NULL, &mapgen_thread, client);
-}
diff --git a/src/mapgen.h b/src/mapgen.h
deleted file mode 100644 (file)
index 0c686c0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _MAPGEN_H_
-#define _MAPGEN_H_
-
-#include "server.h"
-#include "map.h"
-
-void mapgen_init(Server *srv);
-void mapgen_start_thread(Client *client);
-
-#endif
diff --git a/src/perlin.c b/src/perlin.c
deleted file mode 100644 (file)
index 47aa06c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <perlin/perlin.c>
index ee5a06836022fdffb26f8e6eea5e24a6d86cc34d..0816dba291854357fa7f3d4926bb213326659916 100644 (file)
@@ -3,8 +3,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <netdb.h>
-#include "mapgen.h"
 #include "server.h"
+#include "servermap.h"
 #include "signal.h"
 #include "util.h"
 
@@ -91,7 +91,7 @@ void server_start(int fd)
                perror("fopen");
        }
 
-       mapgen_init(&server);
+       servermap_init(&server);
 
        while (! interrupted)
                server_accept_client();
index 8975d6a39599d31cbec62dfe7d258d1b8ee262a0..f8b4dd762ce3df63a9b506cb798f7b4058f2684d 100644 (file)
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include "mapgen.h"
 #include "server.h"
+#include "servermap.h"
 #include "util.h"
 
 static bool disconnect_handler(Client *client, bool good)
@@ -11,17 +11,6 @@ static bool disconnect_handler(Client *client, bool good)
        return true;
 }
 
-static bool send_map(Client *client)
-{
-       for (size_t s = 0; s < client->server->map->sectors.siz; s++) {
-               MapSector *sector = map_get_sector_raw(client->server->map, s);
-               for (size_t b = 0; b < sector->blocks.siz; b++)
-                       if (! (write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, map_get_block_raw(sector, b))))
-                               return false;
-       }
-       return true;
-}
-
 static bool auth_handler(Client *client, bool good)
 {
        char *name = read_string(client->fd, NAME_MAX);
@@ -41,13 +30,13 @@ static bool auth_handler(Client *client, bool good)
        if (success) {
                client->name = name;
                client->state = CS_ACTIVE;
-               mapgen_start_thread(client);
+               servermap_add_client(client);
        } else {
                free(name);
        }
 
        pthread_mutex_lock(&client->mtx);
-       bool ret = write_u32(client->fd, CC_AUTH) && write_u8(client->fd, success) && (success ? send_map(client) : true);
+       bool ret = write_u32(client->fd, CC_AUTH) && write_u8(client->fd, success);
        pthread_mutex_unlock(&client->mtx);
 
        return ret;
diff --git a/src/servermap.c b/src/servermap.c
new file mode 100644 (file)
index 0000000..3a93885
--- /dev/null
@@ -0,0 +1,152 @@
+#include <stdlib.h>
+#include <perlin/perlin.h>
+#include "servermap.h"
+
+int seed = 0;
+static Server *server = NULL;
+
+static void generate_block(MapBlock *block)
+{
+       pthread_mutex_lock(&block->mtx);
+       if (block->state != MBS_CREATED)
+               return;
+       block->state = MBS_PROCESSING;
+       pthread_mutex_unlock(&block->mtx);
+       for (u8 x = 0; x < 16; x++) {
+               u32 ux = x + block->pos.x * 16 + ((u32) 1 << 31);
+               for (u8 z = 0; z < 16; z++) {
+                       u32 uz = z + block->pos.z * 16 + ((u32) 1 << 31);
+                       s32 height = smooth2d((double) ux / 32.0f, (double) uz / 32.0f, 0, seed) * 16.0f;
+                       for (u8 y = 0; y < 16; y++) {
+                               s32 ay = y + block->pos.y * 16;
+                               Node type;
+                               if (ay > height)
+                                       type = NODE_AIR;
+                               else if (ay == height)
+                                       type = NODE_GRASS;
+                               else if (ay >= height - 4)
+                                       type = NODE_DIRT;
+                               else
+                                       type = NODE_STONE;
+                               block->data[x][y][z] = map_node_create(type);
+                       }
+               }
+       }
+       block->state = MBS_READY;
+}
+
+static void send_block(MapBlock *block)
+{
+       pthread_mutex_lock(&block->mtx);
+       block->state = MBS_READY;
+       // ToDo: only send to near clients
+       ITERATE_LIST(&server->clients, pair) {
+               if (block->state != MBS_READY)
+                       break;
+               Client *client = pair->value;
+               if (client->state == CS_ACTIVE) {
+                       pthread_mutex_lock(&client->mtx);
+                       (void) (write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, block));
+                       pthread_mutex_unlock(&client->mtx);
+               }
+       }
+       pthread_mutex_unlock(&block->mtx);
+}
+
+#define RANGE 3
+#define POS_CACHE_COUNT ((1 + RANGE * 2) * (1 + RANGE * 2) * (1 + RANGE * 2))
+static size_t pos_chache_count = POS_CACHE_COUNT;
+static v3s32 pos_cache[POS_CACHE_COUNT];
+
+static void create_pos_cache()
+{
+       size_t i = -1;
+#define ADDPOS(a, b, c, va, vb, vc) \
+       *(s32 *) ((char *) &pos_cache[++i] + offsetof(v3s32, a)) = va; \
+       *(s32 *) ((char *) &pos_cache[i] + offsetof(v3s32, b)) = vb; \
+       *(s32 *) ((char *) &pos_cache[i] + offsetof(v3s32, c)) = vc;
+       ADDPOS(x, y, z, 0, 0, 0)
+       for (s32 l = 1; l <= RANGE ; l++) {
+#define SQUARES(a, b, c) \
+               for (s32 va = -l + 1; va < l; va++) { \
+                       for (s32 vb = -l + 1; vb < l; vb++) { \
+                               ADDPOS(a, b, c, va, vb,  l) \
+                               ADDPOS(a, b, c, va, vb, -l) \
+                       } \
+               }
+               SQUARES(x, z, y)
+               SQUARES(x, y, z)
+               SQUARES(z, y, x)
+#undef SQUARES
+#define EDGES(a, b, c) \
+               for (s32 va = -l + 1; va < l; va++) { \
+                       ADDPOS(a, b, c, va,  l,  l) \
+                       ADDPOS(a, b, c, va,  l, -l) \
+                       ADDPOS(a, b, c, va, -l,  l) \
+                       ADDPOS(a, b, c, va, -l, -l) \
+               }
+               EDGES(x, y, z)
+               EDGES(z, x, y)
+               EDGES(y, x, z)
+#undef EDGES
+               ADDPOS(x, y, z,  l,  l,  l)
+               ADDPOS(x, y, z,  l,  l, -l)
+               ADDPOS(x, y, z,  l, -l,  l)
+               ADDPOS(x, y, z,  l, -l, -l)
+               ADDPOS(x, y, z, -l,  l,  l)
+               ADDPOS(x, y, z, -l,  l, -l)
+               ADDPOS(x, y, z, -l, -l,  l)
+               ADDPOS(x, y, z, -l, -l, -l)
+#undef ADDPOS
+       }
+}
+
+static void send_blocks(Client *client, bool init)
+{
+       v3s32 pos = map_node_to_block_pos((v3s32) {client->pos.x, client->pos.y, client->pos.z}, NULL);
+       for (size_t i = 0; i < pos_chache_count; i++) {
+               MapBlock *block = map_get_block(client->server->map, (v3s32) {pos.x + pos_cache[i].x, pos.y + pos_cache[i].y, pos.z + pos_cache[i].z}, ! init);
+               if (init)
+                       (void) (block && write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, block));
+               else switch (block->state) {
+                       case MBS_CREATED:
+                               generate_block(block);
+                               __attribute__ ((fallthrough));
+                       case MBS_MODIFIED:
+                               send_block(block);
+                               __attribute__ ((fallthrough));
+                       case MBS_PROCESSING:
+                               i = -1;
+                               sched_yield();
+                               __attribute__ ((fallthrough));
+                       case MBS_READY:
+                               break;
+               }
+       }
+}
+
+static void *block_send_thread(void *cli)
+{
+       Client *client = cli;
+
+       send_blocks(client, true);
+
+       while (client->state != CS_DISCONNECTED)
+               send_blocks(client, false);
+
+       return NULL;
+}
+
+void servermap_init(Server *srv)
+{
+       server = srv;
+       create_pos_cache();
+}
+
+void servermap_add_client(Client *client)
+{
+       pthread_t thread;
+       pthread_create(&thread, NULL, &block_send_thread, client);
+}
+
+#include <perlin/perlin.c>
diff --git a/src/servermap.h b/src/servermap.h
new file mode 100644 (file)
index 0000000..c40b9f9
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _MAPGEN_H_
+#define _MAPGEN_H_
+
+#include "server.h"
+#include "map.h"
+
+void servermap_init(Server *srv);
+
+void servermap_add_client(Client *client);
+
+#endif