]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Graphics (WIP)
authorElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 24 Mar 2021 19:05:42 +0000 (20:05 +0100)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 24 Mar 2021 19:05:42 +0000 (20:05 +0100)
16 files changed:
src/Makefile
src/client.c
src/client.h
src/clientcommands.c
src/linkedlist.c [deleted file]
src/linkedlist.h [deleted file]
src/list.c [new file with mode: 0644]
src/list.h [new file with mode: 0644]
src/map.c
src/map.h
src/mesh.c [new file with mode: 0644]
src/mesh.h [new file with mode: 0644]
src/network.c
src/server.c
src/server.h
src/servercommands.c

index 33139cf4ab27df0a1fe93cdb2e1fd4ccf37b70db..84067ac86c8f5815c94b7df47640b2831eccfebe 100644 (file)
@@ -1,6 +1,6 @@
-COMMON = array.o binsearch.o linkedlist.o map.o signal.o util.o types.o
+COMMON = array.o binsearch.o list.o map.o signal.o util.o types.o
 SERVER = $(COMMON) server.o servercommands.o
-CLIENT = $(COMMON) client.o clientcommands.o
+CLIENT = $(COMMON) client.o clientcommands.o mesh.o
 LIBRARIES = -lpthread -lm
 CLIENT_LIBRARIES = -lGL -lGLEW -lglfw
 FLAGS = -g
index 3b30040d618104ba158fc713487a1e74d0e46796..328dffcd1e7883c7c0606cfb1e86861da6e78746 100644 (file)
@@ -5,19 +5,42 @@
 #include <unistd.h>
 #include <errno.h>
 #include <netdb.h>
+#include <GLFW/glfw3.h>
 #include <GL/glew.h>
 #include <GL/gl.h>
-#include <GLFW/glfw3.h>
-#include <linmath.h/linmath.h>
 #include "client.h"
+#include "mesh.h"
 #include "signal.h"
 #include "util.h"
 
-#include "network.c"
+void client_create_mesh(Client *client, Mesh *mesh);
+{
+       pthread_mutex_lock(client->meshlist_mtx);
+       list_put(&client->meshlist, mesh, NULL);
+       pthread_mutex_unlock(client->meshlist_mtx);
+}
+
+void client_remove_mesh(Client *client, Mesh *mesh);
+{
+       pthread_mutex_lock(client->meshlist_mtx);
+       list_delete(&client->meshlist, mesh);
+       pthread_mutex_unlock(client->meshlist_mtx);
+       delete_mesh(mesh);
+}
+
+void client_mapblock_changed(Client *client, v3s32 pos)
+{
+       v3s32 *posptr = malloc(sizeof(v3s32));
+       *posptr = pos;
+       pthread_mutex_lock(client->mapblock_meshgen_mtx);
+       if (! list_put(&client->mapblock_meshgen_queue, posptr, NULL))
+               free(posptr);
+       pthread_mutex_unlock(client->mapblock_meshgen_mtx);
+}
 
 void client_disconnect(Client *client, bool send, const char *detail)
 {
-       pthread_mutex_lock(&client->mtx);
+       pthread_mutex_lock(client->write_mtx);
        if (client->state != CS_DISCONNECTED) {
                if (send)
                        write_u32(client->fd, SC_DISCONNECT);
@@ -26,9 +49,11 @@ void client_disconnect(Client *client, bool send, const char *detail)
                printf("Disconnected %s%s%s\n", INBRACES(detail));
                close(client->fd);
        }
-       pthread_mutex_unlock(&client->mtx);
+       pthread_mutex_unlock(client->write_mtx);
 }
 
+#include "network.c"
+
 static void *reciever_thread(void *cliptr)
 {
        Client *client = cliptr;
@@ -43,12 +68,40 @@ static void *reciever_thread(void *cliptr)
        if (client->name)
                free(client->name);
 
-       pthread_mutex_destroy(&client->mtx);
+       pthread_mutex_lock(client->meshlist_mtx);
+       ITERATE_LIST(&client->meshes, pair) delete_mesh(pair->value);
+       list_clear(&client->meshes);
+       pthread_mutex_unlock(client->meshlist_mtx);
+
+       for (int i = 0; i < CLIENT_MTX_COUNT; i++)
+               pthread_mutex_destroy(&client.mutexes[i]);
 
        exit(EXIT_SUCCESS);
        return NULL;
 }
 
+static void *mapblock_meshgen_thread(void *cliptr)
+{
+       Client *client = cliptr;
+
+       for ever {
+               ListPair **lptr = &client->mapblock_meshgen_queue.first;
+               if (*lptr) {
+                       MapBlock *block = map_get_block(client->map, *(v3s32 *)(*lptr)->key, false);
+                       Array vertices(sizeof(GLfloat));
+
+                       // ToDo: Actual vertices generation code
+
+                       client_create_mesh(client, create_mesh(vertices.ptr, vertices.siz));
+                       pthread_mutex_lock(client->mapblock_meshgen_mtx);
+                       *lptr = (*lptr)->next;
+                       pthread_mutex_unlock(client->mapblock_meshgen_mtx);
+               } else {
+                       sched_yield();
+               }
+       }
+}
+
 static void client_loop(Client *client)
 {
        if(! glfwInit()) {
@@ -92,12 +145,12 @@ static bool client_name_prompt(Client *client)
        if (scanf("%s", name) == EOF)
                return false;
        client->name = strdup(name);
-       pthread_mutex_lock(&client->mtx);
+       pthread_mutex_lock(client->write_mtx);
        if (write_u32(client->fd, SC_AUTH) && write(client->fd, client->name, strlen(name) + 1)) {
                client->state = CS_AUTH;
                printf("Authenticating...\n");
        }
-       pthread_mutex_unlock(&client->mtx);
+       pthread_mutex_unlock(client->write_mtx);
        return true;
 }
 
@@ -125,6 +178,13 @@ static bool client_authenticate(Client *client)
        return false;
 }
 
+static bool compare_positions(void *p1, void *p2)
+{
+       v3s32 *pos1 = p1;
+       v3s32 *pos2 = p2;
+       return pos1->x == pos2->x && pos1->y == pos2->y && pos->z == pos2->z;
+}
+
 int main(int argc, char **argv)
 {
        program_name = argv[0];
@@ -151,9 +211,16 @@ int main(int argc, char **argv)
                .map = NULL,
                .name = NULL,
                .state = CS_CREATED,
+               .meshlist = list_create(NULL),
+               .mapblock_meshgen_queue = list_create(&compare_positions),
        };
 
-       pthread_mutex_init(&client.mtx, NULL);
+       for (int i = 0; i < CLIENT_MTX_COUNT; i++)
+               pthread_mutex_init(&client.mutexes[i], NULL);
+
+       client.write_mtx = &client.mutexes[0];
+       client.meshlist_mtx = &client.mutexes[1];
+       client.mapblock_meshgen_mtx = &client.mutexes[2];
 
        client.fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
 
@@ -174,7 +241,9 @@ int main(int argc, char **argv)
        client.map = map_create();
 
        pthread_t recv_thread;
+       pthread_t mmg_thread;
        pthread_create(&recv_thread, NULL, &reciever_thread, &client);
+       pthread_create(&mmg_thread, NULL, &mapblock_meshgen_thread, &client);
 
        if (client_authenticate(&client))
                client_loop(&client);
index 2b8c43181c9bb51e09a2d4dc1f1c0afa0149e890..d2c001a2075707ca785958e4081ca759c1c9b293 100644 (file)
@@ -6,17 +6,28 @@
 #include "servercommands.h"
 #include "clientcommands.h"
 #include "network.h"
+#include "list.h"
 #include "map.h"
 
+#define CLIENT_MTX_COUNT 3
+
 typedef struct Client
 {
        int fd;
        char *name;
        Map *map;
        ClientState state;
-       pthread_mutex_t mtx;
+       pthread_mutex_t *write_mtx;
+       pthread_mutex_t *meshlist_mtx;
+       pthread_mutex_t *mapblock_meshgen_mtx;
+       pthread_mutex_t mutexes[CLIENT_MTX_COUNT];
+       List meshlist;
+       List mapblock_meshgen_queue;
 } Client;
 
+void client_add_mesh(Client *client, Mesh *mesh);
+void client_remove_mesh(Client *client, Mesh *mesh);
+void client_mapblock_changed(Client *client, v3s32 pos);
 void client_disconnect(Client *client, bool send, const char *detail);
 
 #endif
index 574a18eb5eaebf001ae6304110040c5b018fecd3..3f0f224ecb157da989c0b8ee8120c4d7bcc7f851 100644 (file)
@@ -36,10 +36,12 @@ static bool block_handler(Client *client, bool good)
        if (! block)
                return false;
 
-       if (good)
+       if (good) {
+               client_mapblock_changed(client, block->pos);
                map_add_block(client->map, block);
-       else
+       } else {
                map_free_block(block);
+       }
 
        return true;
 }
diff --git a/src/linkedlist.c b/src/linkedlist.c
deleted file mode 100644 (file)
index 5618c65..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include "linkedlist.h"
-
-LinkedList linked_list_create()
-{
-       return (LinkedList) {NULL};
-}
-
-void linked_list_clear(LinkedList *list)
-{
-       for (LinkedListPair *pair = list->first; pair != NULL;) {
-               LinkedListPair *next = pair->next;
-               free(pair);
-               pair = next;
-       }
-       list->first = NULL;
-}
-
-static LinkedListPair *make_pair(const char *key, void *value)
-{
-       LinkedListPair *pair = malloc(sizeof(LinkedListPair));
-       pair->key = key;
-       pair->value = value;
-       pair->next = NULL;
-       return pair;
-}
-
-bool linked_list_put(LinkedList *list, const char *key, void *value)
-{
-       LinkedListPair **pairptr;
-       for (pairptr = &list->first; *pairptr != NULL; pairptr = &(*pairptr)->next) {
-               if (strcmp((*pairptr)->key, key) == 0)
-                       return false;
-       }
-       *pairptr = make_pair(key, value);
-       return true;
-}
-
-void linked_list_set(LinkedList *list, const char *key, void *value)
-{
-       LinkedListPair **pairptr;
-       for (pairptr = &list->first; *pairptr != NULL; pairptr = &(*pairptr)->next) {
-               if (strcmp((*pairptr)->key, key) == 0)
-                       break;
-       }
-       *pairptr = make_pair(key, value);
-}
-
-void linked_list_delete(LinkedList *list, const char *key)
-{
-       for (LinkedListPair **pairptr = &list->first; *pairptr != NULL; pairptr = &(*pairptr)->next) {
-               if (strcmp((*pairptr)->key, key) == 0) {
-                       LinkedListPair *pair = *pairptr;
-                       *pairptr = pair->next;
-                       free(pair);
-                       return;
-               }
-       }
-}
-
-void *linked_list_get(LinkedList *list, const char *key)
-{
-       for (LinkedListPair *pair = list->first; pair != NULL; pair = pair->next)
-               if (strcmp(pair->key, key) == 0)
-                       return pair->value;
-       return NULL;
-}
diff --git a/src/linkedlist.h b/src/linkedlist.h
deleted file mode 100644 (file)
index a3604c2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _LINKEDLIST_H_
-#define _LINKEDLIST_H_
-
-#include <stdbool.h>
-
-#define ITERATE_LINKEDLIST(list, pair) for (LinkedListPair *pair = (list)->first; pair != NULL; pair = pair->next)
-
-typedef struct LinkedListPair
-{
-       struct LinkedListPair *next;
-       const char *key;
-       void *value;
-} LinkedListPair;
-
-typedef struct
-{
-       LinkedListPair *first;
-} LinkedList;
-
-LinkedList linked_list_create();
-void linked_list_clear(LinkedList *list);
-
-bool linked_list_put(LinkedList *list, const char *key, void *value);
-void linked_list_set(LinkedList *list, const char *key, void *value);
-void *linked_list_get(LinkedList *list, const char *key);
-void linked_list_delete(LinkedList *list, const char *key);
-
-void linked_list_serialize(int fd); // ToDo
-void linked_list_deserialize(int fd, LinkedList *); // ToDo
-
-#endif
diff --git a/src/list.c b/src/list.c
new file mode 100644 (file)
index 0000000..93163f7
--- /dev/null
@@ -0,0 +1,83 @@
+#include <stdlib.h>
+#include <string.h>
+#include "List.h"
+
+int list_compare_default(void *v1, void *v2)
+{
+       return v1 == v2;
+}
+
+int list_compare_string(void *v1, void *v2)
+{
+       return strcmp(v1, v2) == 0;
+}
+
+List list_create(ListComparator cmp)
+{
+       return (List) {
+               .cmp = cmp ? cmp : list_compare_default;
+               .first = NULL,
+       };
+}
+
+void list_clear(List *list)
+{
+       for (ListPair *pair = list->first; pair != NULL;) {
+               ListPair *next = pair->next;
+               free(pair);
+               pair = next;
+       }
+       list->first = NULL;
+}
+
+static ListPair *make_pair(void *key, void *value)
+{
+       ListPair *pair = malloc(sizeof(ListPair));
+       pair->key = key;
+       pair->value = value;
+       pair->next = NULL;
+       return pair;
+}
+
+bool list_put(List *list, void *key, void *value)
+{
+       ListPair **pairptr;
+       for (pairptr = &list->first; *pairptr != NULL; pairptr = &(*pairptr)->next) {
+               if (list->cmp((*pairptr)->key, key))
+                       return false;
+       }
+       *pairptr = make_pair(key, value);
+       return true;
+}
+
+void list_set(List *list, void *key, void *value)
+{
+       ListPair **pairptr;
+       for (pairptr = &list->first; *pairptr != NULL; pairptr = &(*pairptr)->next) {
+               if (strcmp((*pairptr)->key, key) == 0)
+                       break;
+       }
+       *pairptr = make_pair(key, value);
+}
+
+void *list_delete(List *list, void *key)
+{
+       for (ListPair **pairptr = &list->first; *pairptr != NULL; pairptr = &(*pairptr)->next) {
+               if (list->cmp((*pairptr)->key, key)) {
+                       ListPair *pair = *pairptr;
+                       void *value = (*pairptr)->value;
+                       *pairptr = pair->next;
+                       free(pair);
+                       return value;
+               }
+       }
+       return NULL;
+}
+
+void *list_get(List *list, void *key)
+{
+       for (ListPair *pair = list->first; pair != NULL; pair = pair->next)
+               if (list->cmp(pair->key, key))
+                       return pair->value;
+       return NULL;
+}
diff --git a/src/list.h b/src/list.h
new file mode 100644 (file)
index 0000000..3097062
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _List_H_
+#define _List_H_
+
+#include <stdbool.h>
+
+#define ITERATE_LIST(list, pair) for (ListPair *pair = (list)->first; pair != NULL; pair = pair->next)
+
+typedef struct ListPair
+{
+       struct ListPair *next;
+       void *key;
+       void *value;
+} ListPair;
+
+typedef bool (*ListComparator)(void *v1, void *v2);
+
+typedef struct
+{
+       ListComparator cmp;
+       ListPair *first;
+} List;
+
+bool list_compare_default(void *v1, void *v2);
+bool list_compare_string(void *v1, void *v2);
+
+List list_create(ListComparator cmp);
+void list_clear(List *list);
+
+bool list_put(List *list, void *key, void *value);
+void list_set(List *list, void *key, void *value);
+void *list_get(List *list, void *key);
+void *list_delete(List *list, void *key);
+
+bool list_serialize(int fd, List *list); // ToDo
+bool list_deserialize(int fd, List *list); // ToDo
+
+#endif
index 7830d8dae943fbd26bf4cb8d0cad3ba86c7132b3..79f5aa127a57b0b8e407280aabf6053dc11da2c8 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -39,6 +39,14 @@ static s8 block_compare(void *level, void *block)
        return CMPBOUNDS(d);
 }
 
+static void allocate_block(v3s23 pos)
+{
+       MapBlock *block = malloc(sizeof(MapBlock));
+       block->pos = pos;
+       block->extra = NULL;
+       return block;
+}
+
 MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
 {
        MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
@@ -52,8 +60,7 @@ MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
        if (! create)
                return NULL;
 
-       MapBlock *block = malloc(sizeof(MapBlock));
-       block->pos = pos;
+       MapBlock *block = allocate_block(pos);
 
        MapNode air = map_node_create(NODE_AIR);
        ITERATE_MAPBLOCK block->data[x][y][z] = air;
@@ -124,8 +131,7 @@ MapBlock *map_deserialize_block(int fd)
        if (! read_v3s32(fd, &pos))
                return NULL;
 
-       MapBlock *block = malloc(sizeof(MapBlock));
-       block->pos = pos;
+       MapBlock *block = allocate_block(pos);
 
        ITERATE_MAPBLOCK {
                if (! map_deserialize_node(fd, &block->data[x][y][z])) {
@@ -185,12 +191,12 @@ void map_set_node(Map *map, v3s32 pos, MapNode node)
 
 MapNode map_node_create(Node type)
 {
-       return (MapNode) {type, linked_list_create()};
+       return (MapNode) {type, list_create(&list_compare_string)};
 }
 
 void map_node_clear(MapNode *node)
 {
-       linked_list_clear(&node->meta);
+       list_clear(&node->meta);
 }
 
 Map *map_create()
index 1355a369d9d7408360bd00ad15ecfe640e3351ec..925b60f4710bcc2a294f7e397cbc7dd2b89c47cc 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -19,6 +19,7 @@ typedef struct
 {
        MapNode data[16][16][16];
        v3s32 pos;
+       void *extra;
 } MapBlock;
 
 typedef struct
diff --git a/src/mesh.c b/src/mesh.c
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/src/mesh.h b/src/mesh.h
new file mode 100644 (file)
index 0000000..bfb8079
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _MESH_H_
+#define _MESH_H_
+
+#include <GL/glew.h>
+#include <GL/gl.h>
+#include <linmath.h/linmath.h>
+
+typedef struct
+{
+       vec3 pos, rot, scale;
+       float angle;
+       mat4x4 transform;
+       GLuint VAO, VBO;
+} Mesh;
+
+Mesh *create_mesh(const GLvoid *vertices, GLsizei size);
+void delete_mesh(Mesh *mesh);
+
+#endif
index 27bc5ed591dd3dc3c7c7abc771306a6d680d3655..7c585b797bd1d91bf11bb2a1134adcde66f5dd50 100644 (file)
@@ -2,9 +2,9 @@
 
 bool send_command(Client *client, RemoteCommand cmd)
 {
-       pthread_mutex_lock(&client->mtx);
+       pthread_mutex_lock(client->write_mtx);
        bool ret = write_u32(client->fd, cmd);
-       pthread_mutex_unlock(&client->mtx);
+       pthread_mutex_unlock(client->write_mtx);
        return ret;
 }
 
index 93cdd19ffaaeb3915d671534319b2ccdd2dd3aad..c160dd72f36479b208104276bba77a23507aa708 100644 (file)
@@ -8,14 +8,12 @@
 #include "signal.h"
 #include "util.h"
 
-#include "network.c"
-
 void server_disconnect_client(Client *client, int flags, const char *detail)
 {
        client->state = CS_DISCONNECTED;
 
        if (client->name && ! (flags & DISCO_NO_REMOVE))
-               linked_list_delete(&client->server->clients, client->name);
+               list_delete(&client->server->clients, client->name);
 
        if (! (flags & DISCO_NO_MESSAGE))
                printf("Disconnected %s %s%s%s\n", client->name, INBRACES(detail));
@@ -23,17 +21,17 @@ void server_disconnect_client(Client *client, int flags, const char *detail)
        if (! (flags & DISCO_NO_SEND))
                send_command(client, CC_DISCONNECT);
 
-       pthread_mutex_lock(&client->mtx);
+       pthread_mutex_lock(client->write_mtx);
        close(client->fd);
-       pthread_mutex_unlock(&client->mtx);
+       pthread_mutex_unlock(client->write_mtx);
 }
 
 void server_shutdown(Server *srv)
 {
        printf("Shutting down\n");
 
-       ITERATE_LINKEDLIST(&srv->clients, pair) server_disconnect_client(pair->value, DISCO_NO_REMOVE | DISCO_NO_MESSAGE, "");
-       linked_list_clear(&srv->clients);
+       ITERATE_LIST(&srv->clients, pair) server_disconnect_client(pair->value, DISCO_NO_REMOVE | DISCO_NO_MESSAGE, "");
+       list_clear(&srv->clients);
 
        shutdown(srv->sockfd, SHUT_RDWR);
        close(srv->sockfd);
@@ -54,6 +52,8 @@ void server_shutdown(Server *srv)
        exit(EXIT_SUCCESS);
 }
 
+#include "network.c"
+
 static void *reciever_thread(void *clientptr)
 {
        Client *client = clientptr;
@@ -68,7 +68,7 @@ static void *reciever_thread(void *clientptr)
 
        free(client->address);
 
-       pthread_mutex_destroy(&client->mtx);
+       pthread_mutex_destroy(client->write_mtx);
        free(client);
 
        return NULL;
@@ -97,7 +97,8 @@ static void accept_client(Server *srv)
 
        printf("Connected %s\n", client->address);
 
-       pthread_mutex_init(&client->mtx, NULL);
+       client->write_mtx = &client->mutex;
+       pthread_mutex_init(client->write_mtx, NULL);
 
        pthread_t thread;
        pthread_create(&thread, NULL, &reciever_thread, client);
@@ -127,7 +128,7 @@ int main(int argc, char **argv)
        Server server = {
                .sockfd = -1,
                .map = NULL,
-               .clients = linked_list_create(),
+               .clients = list_create(&list_compare_string),
        };
 
        server.sockfd = socket(info->ai_family, info->ai_socktype, 0);
index 8cb9921185e6c340ea7768bf26428d738fc59671..736cc74dc30edc403cf9f778c96f881a6c178f37 100644 (file)
@@ -5,7 +5,7 @@
 #include <netinet/in.h>
 #include "clientcommands.h"
 #include "servercommands.h"
-#include "linkedlist.h"
+#include "list.h"
 #include "map.h"
 #include "network.h"
 
@@ -13,7 +13,7 @@ typedef struct
 {
        int sockfd;
        Map *map;
-       LinkedList clients;
+       List clients;
 } Server;
 
 typedef struct Client
@@ -23,7 +23,8 @@ typedef struct Client
        char *address;
        Server *server;
        ClientState state;
-       pthread_mutex_t mtx;
+       pthread_mutex_t *write_mtx;
+       pthread_mutex_t mutex;
 } Client;
 
 typedef enum
index 89742db0ba9712415d4b32899e918cbcc6ec1fec..bdb8a6d8e1dc7f38443e84228f807d797345f5a9 100644 (file)
@@ -22,7 +22,7 @@ static bool auth_handler(Client *client, bool good)
                return true;
        }
 
-       u8 success = linked_list_put(&client->server->clients, name, client);
+       u8 success = list_put(&client->server->clients, name, client);
 
        printf("Authentication %s: %s -> %s\n", success ? "success" : "failure", client->address, name);
 
@@ -33,9 +33,9 @@ static bool auth_handler(Client *client, bool good)
                free(name);
        }
 
-       pthread_mutex_lock(&client->mtx);
+       pthread_mutex_lock(client->write_mtx);
        bool ret = write_u32(client->fd, CC_AUTH) && write_u8(client->fd, success);
-       pthread_mutex_unlock(&client->mtx);
+       pthread_mutex_unlock(client->write_mtx);
 
        return ret;
 }
@@ -52,9 +52,9 @@ static bool getblock_handler(Client *client, bool good)
 
        MapBlock *block = map_get_block(client->server->map, pos, false);
        if (block) {
-               pthread_mutex_lock(&client->mtx);
+               pthread_mutex_lock(client->write_mtx);
                bool ret = write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, block);
-               pthread_mutex_unlock(&client->mtx);
+               pthread_mutex_unlock(client->write_mtx);
 
                return ret;
        }
@@ -88,7 +88,7 @@ static bool kick_handler(Client *client, bool good)
                return false;
 
        if (good) {
-               Client *target = linked_list_get(&client->server->clients, target_name);
+               Client *target = list_get(&client->server->clients, target_name);
                if (target)
                        server_disconnect_client(target, 0, "kicked");
        }