#include <stdbool.h>
#include <unistd.h>
#include <math.h>
-#include <endian.h>
#include <string.h>
#include "map.h"
#include "util.h"
Map *map = malloc(sizeof(Map));
pthread_rwlock_init(&map->rwlck, NULL);
pthread_rwlock_init(&map->cached_rwlck, NULL);
- map->sectors = bintree_create(sizeof(v2s32));
+ map->sectors = bintree_create(sizeof(v2s32), NULL);
map->cached = NULL;
map->callbacks = callbacks;
return map;
}
-static void free_block(void *value, void *arg)
+static void free_block(BintreeNode *node, void *arg)
{
Map *map = arg;
if (map->callbacks.delete_block)
- map->callbacks.delete_block(value);
+ map->callbacks.delete_block(node->value);
- map_free_block(value);
+ map_free_block(node->value);
}
-static void free_sector(void *value, void *arg)
+static void free_sector(BintreeNode *node, void *arg)
{
- MapSector *sector = value;
+ MapSector *sector = node->value;
bintree_clear(§or->blocks, &free_block, arg);
pthread_rwlock_destroy(§or->rwlck);
sector = malloc(sizeof(MapSector));
pthread_rwlock_init(§or->rwlck, NULL);
sector->pos = pos;
- sector->blocks = bintree_create(sizeof(s32));
+ sector->blocks = bintree_create(sizeof(s32), NULL);
bintree_add_node(&map->sectors, nodeptr, &pos, sector);
}
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&block->mtx, &attr);
- return block;
-}
-void map_clear_meta(MapBlock *block)
-{
- pthread_mutex_lock(&block->mtx);
- ITERATE_MAPBLOCK list_clear(&block->metadata[x][y][z]);
- pthread_mutex_unlock(&block->mtx);
+ ITERATE_MAPBLOCK block->data[x][y][z] = map_node_create(NODE_UNKNOWN, (Blob) {0, NULL});
+
+ return block;
}
void map_free_block(MapBlock *block)
{
- map_clear_meta(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)
+Blob map_serialize_block(MapBlock *block)
{
- Node type;
-
- if (! read_u32(fd, &type))
- return false;
-
- if (type >= NODE_UNLOADED)
- type = NODE_INVALID;
+ SerializedMapBlock block_data;
- *node = map_node_create(type);
-
- return true;
-}
-
-void map_serialize_block(MapBlock *block, char **dataptr, size_t *sizeptr)
-{
- MapBlockData uncompressed;
ITERATE_MAPBLOCK {
- MapNode node = block->data[x][y][z];
+ MapNode *node = &block->data[x][y][z];
+ SerializedMapNode *node_data = &block_data.raw.nodes[x][y][z];
- if (node_definitions[node.type].serialize)
- node_definitions[node.type].serialize(&node);
+ *node_data = (SerializedMapNode) {
+ .type = node->type,
+ .data = {
+ .siz = 0,
+ .data = NULL,
+ },
+ };
- node.type = htobe32(node.type);
- uncompressed[x][y][z] = node;
+ NodeDefinition *def = &node_definitions[node->type];
+
+ if (def->serialize)
+ def->serialize(&node_data->data, node->data);
}
- my_compress(&uncompressed, sizeof(MapBlockData), dataptr, sizeptr);
+ Blob buffer = {0, NULL};
+ SerializedMapBlock_write(&buffer, &block_data);
+ SerializedMapBlock_free(&block_data);
+
+ return buffer;
}
-bool map_deserialize_block(MapBlock *block, const char *data, size_t size)
+bool map_deserialize_block(MapBlock *block, Blob buffer)
{
- MapBlockData decompressed;
+ // it's important to copy Blobs that have been malloc'd before reading from them
+ // because reading from a Blob modifies its data and size pointer,
+ // but does not free anything
+ SerializedMapBlock block_data = {0};
+ bool success = SerializedMapBlock_read(&buffer, &block_data);
- if (! my_decompress(data, size, &decompressed, sizeof(MapBlockData)))
- return false;
-
- ITERATE_MAPBLOCK {
- MapNode node = decompressed[x][y][z];
- node.type = be32toh(node.type);
+ if (success) ITERATE_MAPBLOCK
+ block->data[x][y][z] = map_node_create(block_data.raw.nodes[x][y][z].type, block_data.raw.nodes[x][y][z].data);
- if (node.type >= NODE_UNLOADED)
- node.type = NODE_INVALID;
-
- if (node_definitions[node.type].deserialize)
- node_definitions[node.type].deserialize(&node);
-
- block->data[x][y][z] = node;
- block->metadata[x][y][z] = list_create(&list_compare_string);
- }
-
- return true;
+ SerializedMapBlock_free(&block_data);
+ return success;
}
v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset)
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, (Blob) {0, NULL});
return block->data[offset.x][offset.y][offset.z];
}
if (block) {
pthread_mutex_lock(&block->mtx);
if (! map->callbacks.set_node || map->callbacks.set_node(block, offset, &node, arg)) {
+ block->data[offset.x][offset.y][offset.z] = node;
if (map->callbacks.after_set_node)
map->callbacks.after_set_node(block, offset, arg);
- list_clear(&block->metadata[offset.x][offset.y][offset.z]);
- block->data[offset.x][offset.y][offset.z] = node;
+ } else {
+ map_node_delete(node);
}
pthread_mutex_unlock(&block->mtx);
}
}
-MapNode map_node_create(Node type)
+MapNode map_node_create(Node type, Blob buffer)
{
+ if (type >= NODE_UNLOADED)
+ type = NODE_UNKNOWN;
+
+ NodeDefinition *def = &node_definitions[type];
+
MapNode node;
node.type = type;
- memset(&node.state, 0, sizeof(NodeState));
+ 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)
+ def->deserialize(&buffer, node.data);
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);
+}