-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
#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);
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;
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()) {
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;
}
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];
.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);
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);
#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
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;
}
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
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);
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;
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])) {
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()
{
MapNode data[16][16][16];
v3s32 pos;
+ void *extra;
} MapBlock;
typedef struct
--- /dev/null
+#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
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;
}
#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));
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);
exit(EXIT_SUCCESS);
}
+#include "network.c"
+
static void *reciever_thread(void *clientptr)
{
Client *client = clientptr;
free(client->address);
- pthread_mutex_destroy(&client->mtx);
+ pthread_mutex_destroy(client->write_mtx);
free(client);
return NULL;
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);
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);
#include <netinet/in.h>
#include "clientcommands.h"
#include "servercommands.h"
-#include "linkedlist.h"
+#include "list.h"
#include "map.h"
#include "network.h"
{
int sockfd;
Map *map;
- LinkedList clients;
+ List clients;
} Server;
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
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);
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;
}
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;
}
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");
}