]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Initial commit
authorElias Fleckenstein <eliasfleckenstein@web.de>
Fri, 19 Mar 2021 14:43:59 +0000 (15:43 +0100)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Fri, 19 Mar 2021 14:43:59 +0000 (15:43 +0100)
13 files changed:
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
array.c [new file with mode: 0644]
array.h [new file with mode: 0644]
binsearch.c [new file with mode: 0644]
binsearch.h [new file with mode: 0644]
linkedlist.c [new file with mode: 0644]
linkedlist.h [new file with mode: 0644]
map.c [new file with mode: 0644]
map.h [new file with mode: 0644]
node.h [new file with mode: 0644]
server.c [new file with mode: 0644]
types.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..26ec5bd
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+DragonblocksServer
+Dragonblocks
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e18d035
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+COMMON = array.o binsearch.o linkedlist.o map.o
+SERVER = $(COMMON) server.o
+
+all: DragonblocksServer
+
+DragonblocksServer: $(SERVER)
+       gcc -o DragonblocksServer $(SERVER)
+
+%.o: %.c
+       gcc -c -o $@ -Wall -Wextra -Wpedantic $<
diff --git a/array.c b/array.c
new file mode 100644 (file)
index 0000000..604201c
--- /dev/null
+++ b/array.c
@@ -0,0 +1,40 @@
+#include <string.h>
+#include <stdlib.h>
+#include "array.h"
+
+static void array_realloc(Array *array)
+{
+       if (array->siz > array->cap) {
+               array->cap = array->siz + ARRAY_REALLOC_EXTRA;
+               array->ptr = realloc(array->ptr, array->cap * sizeof(void *));
+       }
+}
+
+static void array_alloc(Array *array, size_t siz)
+{
+       array->siz += siz;
+       array_realloc(array);
+}
+
+void array_insert(Array *array, void *elem, size_t idx)
+{
+       size_t oldsiz = array->siz;
+       array_alloc(array, 1);
+
+       void **iptr = array->ptr + idx;
+       memmove(iptr + 1, iptr, oldsiz - idx);
+       *iptr = elem;
+}
+
+void array_append(Array *array, void *elem)
+{
+       size_t oldsiz = array->siz;
+       array_alloc(array, 1);
+
+       array->ptr[oldsiz] = elem;
+}
+
+Array array_create()
+{
+       return (Array) {0, 0, NULL};
+}
diff --git a/array.h b/array.h
new file mode 100644 (file)
index 0000000..c0b42b5
--- /dev/null
+++ b/array.h
@@ -0,0 +1,18 @@
+#ifndef _ARRAY_H_
+#define _ARRAY_H_
+
+#define ARRAY_REALLOC_EXTRA 25
+
+#include <stddef.h>
+
+typedef struct
+{
+       size_t siz, cap;
+       void **ptr;
+} Array;
+
+void array_insert(Array *array, void *elem, size_t idx);
+void array_append(Array *array, void *elem);
+Array array_create();
+
+#endif
diff --git a/binsearch.c b/binsearch.c
new file mode 100644 (file)
index 0000000..efc6a1a
--- /dev/null
@@ -0,0 +1,25 @@
+#include "binsearch.h"
+
+BinsearchResult binsearch(void *search, void **array, size_t size, BinsearchComparator cmp)
+{
+       size_t min, max, index;
+
+       min = index = 0;
+       max = size;
+
+       while (min < max) {
+               index = min;
+
+               size_t mid = (max + min) / 2;
+               s8 state = cmp(search, array[mid]);
+
+               if (state == 0)
+                       return (BinsearchResult) {true, mid};
+               else if (state < 0)
+                       max = mid;
+               else
+                       min = mid;
+       }
+
+       return (BinsearchResult) {false, index};
+}
diff --git a/binsearch.h b/binsearch.h
new file mode 100644 (file)
index 0000000..f6337a2
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _BINSEARCH_H_
+#define _BINSEARCH_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "types.h"
+
+typedef s8 (*BinsearchComparator)(void *search, void *element);
+
+typedef struct {
+       bool success;
+       size_t index;
+} BinsearchResult;
+
+BinsearchResult binsearch(void *search, void **array, size_t size, BinsearchComparator cmp);
+
+#endif
diff --git a/linkedlist.c b/linkedlist.c
new file mode 100644 (file)
index 0000000..3a4f1e5
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdlib.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;
+}
diff --git a/linkedlist.h b/linkedlist.h
new file mode 100644 (file)
index 0000000..a216989
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _LINKEDLIST_H_
+#define _LINKEDLIST_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;
+       const char *value;
+} LinkedListPair;
+
+typedef struct
+{
+       LinkedListPair *first;
+} LinkedList;
+
+LinkedList linked_list_create();
+void linked_list_clear(LinkedList *list);
+
+void linked_list_put(LinkedList *list, const char *key, const char *value); // ToDo
+void linked_list_get(LinkedList *list, const char *key); // ToDo
+void linked_list_delete(LinkedList *list, const char *key); // ToDo
+
+void linked_list_serialize(int fd); // ToDo
+void linked_list_deserialize(int fd, LinkedList *); // ToDo
+
+#endif
diff --git a/map.c b/map.c
new file mode 100644 (file)
index 0000000..9568363
--- /dev/null
+++ b/map.c
@@ -0,0 +1,118 @@
+#include <stdlib.h>
+#include <stdbool.h>
+#include "map.h"
+#include "binsearch.h"
+
+#define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
+
+static void map_raw_delete_block(MapBlock *block)
+{
+       ITERATE_MAPBLOCK map_node_clear(&block->data[x][y][z]);
+       free(block);
+}
+
+static s8 sector_compare(void *hash, void *sector)
+{
+       s64 d = *((u64 *) hash) - ((MapSector *) sector)->hash;
+       return CMPBOUNDS(d);
+}
+
+MapSector *map_get_sector(Map *map, v2s32 pos, bool create)
+{
+       u64 hash = ((u64) pos.x << 32) + (u64) pos.y;
+       BinsearchResult res = binsearch(&hash, map->sectors.ptr, map->sectors.siz, &sector_compare);
+
+       if (res.success)
+               return map->sectors.ptr[res.index];
+       if (! create)
+               return NULL;
+
+       MapSector *sector = malloc(sizeof(MapSector));
+       sector->pos = pos;
+       sector->hash = hash;
+       sector->blocks = array_create();
+
+       array_insert(&map->sectors, sector, res.index);
+
+       return sector;
+}
+
+static s8 block_compare(void *level, void *block)
+{
+       s32 d = *((s32 *) level) - ((MapSector *) block)->pos.y;
+       return CMPBOUNDS(d);
+}
+
+MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
+{
+       MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
+       if (! sector)
+               return NULL;
+
+       BinsearchResult res = binsearch(&pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
+
+       if (res.success)
+               return sector->blocks.ptr[res.index];
+       if (! create)
+               return NULL;
+
+       MapBlock *block = malloc(sizeof(MapBlock));
+       block->pos = pos;
+
+       MapNode air = map_node_create(NODE_AIR);
+       ITERATE_MAPBLOCK block->data[x][y][z] = air;
+
+       array_insert(&sector->blocks, block, res.index);
+
+       return block;
+}
+
+MapNode map_get_node(Map *map, v3s32 pos)
+{
+       MapBlock *block = map_get_block(map, (v3s32) {pos.x / 16, pos.y / 16, pos.z / 16}, false);
+       if (! block)
+               return map_node_create(NODE_UNLOADED);
+       return block->data[pos.x % 16][pos.y % 16][pos.z % 16];
+}
+
+void map_set_node(Map *map, v3s32 pos, MapNode node)
+{
+       MapBlock *block = map_get_block(map, (v3s32) {pos.x / 16, pos.y / 16, pos.z / 16}, true);
+       MapNode *current_node = &block->data[pos.x % 16][pos.y % 16][pos.z % 16];
+       map_node_clear(current_node);
+       *current_node = node;
+}
+
+MapNode map_node_create(Node type)
+{
+       return (MapNode) {type, linked_list_create()};
+}
+
+void map_node_clear(MapNode *node)
+{
+       linked_list_clear(&node->meta);
+}
+
+Map *map_create(FILE *file)
+{
+       Map *map = malloc(sizeof(Map));
+       map->file = file;
+       map->sectors = array_create();
+
+       return map;
+}
+
+void map_delete(Map *map)
+{
+       for (size_t s = 0; s < map->sectors.siz; s++) {
+               MapSector *sector = map->sectors.ptr[s];
+               for (size_t b = 0; b < sector->blocks.siz; b++)
+                       map_raw_delete_block(sector->blocks.ptr[b]);
+               if (sector->blocks.ptr)
+                       free(sector->blocks.ptr);
+               free(sector);
+       }
+       if (map->sectors.ptr)
+               free(map->sectors.ptr);
+       free(map);
+}
diff --git a/map.h b/map.h
new file mode 100644 (file)
index 0000000..606cb93
--- /dev/null
+++ b/map.h
@@ -0,0 +1,56 @@
+#ifndef _MAP_H_
+#define _MAP_H_
+
+#include <stdio.h>
+#include <stdbool.h>
+#include "array.h"
+#include "linkedlist.h"
+#include "node.h"
+#include "types.h"
+
+#define ITERATE_MAPBLOCK for (u8 x = 0; x < 16; x++) for (u8 y = 0; y < 16; y++) for (u8 z = 0; z < 16; z++)
+
+typedef struct
+{
+       Node type;
+       LinkedList meta;
+} MapNode;
+
+typedef struct
+{
+       MapNode data[16][16][16];
+       v3s32 pos;
+} MapBlock;
+
+typedef struct
+{
+       Array blocks;
+       v2s32 pos;
+       u64 hash;
+} MapSector;
+
+typedef struct
+{
+       Array sectors;
+       FILE *file;
+} Map;
+
+MapSector *map_get_sector(Map *map, v2s32 pos, bool create);
+MapBlock *map_get_block(Map *map, v3s32 pos, bool create);
+void map_create_block(Map *map, v3s32 pos, MapBlock *block);
+
+void map_serialize_block(int fd, MapBlock *); // ToDo
+MapBlock *map_deserialize_block(int fd); // ToDo
+
+void map_delete_block(MapBlock *); // ToDo
+void map_unload_block(MapBlock *); // ToDo
+
+MapNode map_get_node(Map *map, v3s32 pos);
+void map_set_node(Map *map, v3s32 pos, MapNode node);
+MapNode map_node_create(Node type);
+void map_node_clear(MapNode *node);
+
+Map *map_create(FILE *file);
+void map_delete(Map *map);
+
+#endif
diff --git a/node.h b/node.h
new file mode 100644 (file)
index 0000000..602837a
--- /dev/null
+++ b/node.h
@@ -0,0 +1,13 @@
+#ifndef _NODE_H_
+#define _NODE_H_
+
+typedef enum
+{
+       NODE_UNLOADED,          // Used for nodes in unloaded blocks
+       NODE_AIR,
+       NODE_GRASS,
+       NODE_DIRT,
+       NODE_STONE,
+} Node;
+
+#endif
diff --git a/server.c b/server.c
new file mode 100644 (file)
index 0000000..c4b97a4
--- /dev/null
+++ b/server.c
@@ -0,0 +1,14 @@
+#include "map.h"
+
+int main()
+{
+       Map *map = map_create(NULL);
+       map_set_node(map, (v3s32) {0, 0, 0}, map_node_create(NODE_STONE));
+       MapBlock *block = map_get_block(map, (v3s32) {0, 0, 0}, false);
+       if (! block) {
+               fprintf(stderr, "Map error\n");
+               return 1;
+       }
+       ITERATE_MAPBLOCK printf("%d", block->data[x][y][z].type);
+       map_delete(map);
+}
diff --git a/types.h b/types.h
new file mode 100644 (file)
index 0000000..885791b
--- /dev/null
+++ b/types.h
@@ -0,0 +1,28 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#include <stdint.h>
+
+#define DEFVEC(type) typedef struct {type x, y;} v2 ## type; typedef struct {type x, y, z;} v3 ## type;
+#define DEFTYP(from, to) typedef from to; DEFVEC(to)
+#define DEFTYPES(bytes) DEFTYP(int ## bytes ## _t, s ## bytes) DEFTYP(uint ## bytes ## _t, u ## bytes)
+
+DEFTYPES(8)
+DEFTYPES(16)
+DEFTYPES(32)
+DEFTYPES(64)
+
+typedef float f32;
+typedef double f64;
+
+DEFVEC(f32)
+DEFVEC(f64)
+
+typedef v2f32 v2f;
+typedef v3f32 v3f;
+
+#undef DEFVEC
+#undef DEFTYP
+#undef DEFTYPES
+
+#endif