5 #include <endian.h/endian.h>
10 Map *map_create(MapCallbacks callbacks)
12 Map *map = malloc(sizeof(Map));
13 pthread_rwlock_init(&map->rwlck, NULL);
14 pthread_rwlock_init(&map->cached_rwlck, NULL);
15 map->sectors = bintree_create(sizeof(v2s32), NULL);
17 map->callbacks = callbacks;
21 static void free_block(BintreeNode *node, void *arg)
25 if (map->callbacks.delete_block)
26 map->callbacks.delete_block(node->value);
28 map_free_block(node->value);
31 static void free_sector(BintreeNode *node, void *arg)
33 MapSector *sector = node->value;
35 bintree_clear(§or->blocks, &free_block, arg);
36 pthread_rwlock_destroy(§or->rwlck);
40 void map_delete(Map *map)
42 pthread_rwlock_destroy(&map->rwlck);
43 pthread_rwlock_destroy(&map->cached_rwlck);
44 bintree_clear(&map->sectors, &free_sector, map);
48 MapSector *map_get_sector(Map *map, v2s32 pos, bool create)
51 pthread_rwlock_wrlock(&map->rwlck);
53 pthread_rwlock_rdlock(&map->rwlck);
55 BintreeNode **nodeptr = bintree_search(&map->sectors, &pos);
57 MapSector *sector = NULL;
60 sector = (*nodeptr)->value;
62 sector = malloc(sizeof(MapSector));
63 pthread_rwlock_init(§or->rwlck, NULL);
65 sector->blocks = bintree_create(sizeof(s32), NULL);
67 bintree_add_node(&map->sectors, nodeptr, &pos, sector);
70 pthread_rwlock_unlock(&map->rwlck);
75 MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
77 MapBlock *cached = NULL;
79 pthread_rwlock_rdlock(&map->cached_rwlck);
81 pthread_rwlock_unlock(&map->cached_rwlck);
83 if (cached && v3s32_equals(cached->pos, pos))
86 MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
91 pthread_rwlock_wrlock(§or->rwlck);
93 pthread_rwlock_rdlock(§or->rwlck);
95 BintreeNode **nodeptr = bintree_search(§or->blocks, &pos.y);
97 MapBlock *block = NULL;
100 block = (*nodeptr)->value;
102 pthread_mutex_lock(&block->mtx);
103 if (map->callbacks.get_block && ! map->callbacks.get_block(block, create)) {
104 pthread_mutex_unlock(&block->mtx);
107 pthread_mutex_unlock(&block->mtx);
108 pthread_rwlock_wrlock(&map->cached_rwlck);
110 pthread_rwlock_unlock(&map->cached_rwlck);
113 bintree_add_node(§or->blocks, nodeptr, &pos.y, block = map_allocate_block(pos));
115 if (map->callbacks.create_block)
116 map->callbacks.create_block(block);
119 pthread_rwlock_unlock(§or->rwlck);
124 MapBlock *map_allocate_block(v3s32 pos)
126 MapBlock *block = malloc(sizeof(MapBlock));
129 pthread_mutexattr_t attr;
130 pthread_mutexattr_init(&attr);
131 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
132 pthread_mutex_init(&block->mtx, &attr);
134 ITERATE_MAPBLOCK block->data[x][y][z] = map_node_create(NODE_UNKNOWN, NULL, 0);
139 void map_free_block(MapBlock *block)
141 ITERATE_MAPBLOCK map_node_delete(block->data[x][y][z]);
143 pthread_mutex_destroy(&block->mtx);
147 void map_serialize_block(MapBlock *block, char **dataptr, size_t *sizeptr, size_t *rawsizeptr)
149 unsigned char *uncompressed = NULL;
150 size_t uncompressed_size = 0;
153 MapNode node = block->data[x][y][z];
154 NodeDefinition *def = &node_definitions[node.type];
156 u32 type = htobe32(node.type);
157 buffer_write(&uncompressed, &uncompressed_size, &type, sizeof(u32));
159 unsigned char *data_buffer = NULL;
160 size_t data_bufsiz = 0;
163 def->serialize(&node, &data_buffer, &data_bufsiz);
165 u16 data_size = htobe16(data_bufsiz);
166 buffer_write(&uncompressed, &uncompressed_size, &data_size, sizeof(u16));
167 buffer_write(&uncompressed, &uncompressed_size, data_buffer, data_bufsiz);
173 my_compress(uncompressed, uncompressed_size, dataptr, sizeptr);
174 *rawsizeptr = uncompressed_size;
180 bool map_deserialize_block(MapBlock *block, const char *data, size_t size, size_t rawsize)
182 unsigned char decompressed[rawsize];
183 size_t decompressed_size = rawsize;
185 if (! my_decompress(data, size, decompressed, decompressed_size))
188 unsigned char *ptr = decompressed;
192 u32 *type_ptr = buffer_read(&ptr, &decompressed_size, sizeof(u32));
197 u32 type = be32toh(*type_ptr);
200 u16 *data_size_ptr = buffer_read(&ptr, &decompressed_size, sizeof(u16));
205 u16 data_size = be16toh(*data_size_ptr);
208 void *data = buffer_read(&ptr, &decompressed_size, data_size);
210 if (! data && data_size)
214 block->data[x][y][z] = map_node_create(type, data, data_size);
220 v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset)
223 *offset = (v3u8) {(u32) pos.x % MAPBLOCK_SIZE, (u32) pos.y % MAPBLOCK_SIZE, (u32) pos.z % MAPBLOCK_SIZE};
224 return (v3s32) {floor((double) pos.x / (double) MAPBLOCK_SIZE), floor((double) pos.y / (double) MAPBLOCK_SIZE), floor((double) pos.z / (double) MAPBLOCK_SIZE)};
227 MapNode map_get_node(Map *map, v3s32 pos)
230 v3s32 blockpos = map_node_to_block_pos(pos, &offset);
231 MapBlock *block = map_get_block(map, blockpos, false);
233 return map_node_create(NODE_UNLOADED, NULL, 0);
234 return block->data[offset.x][offset.y][offset.z];
237 void map_set_node(Map *map, v3s32 pos, MapNode node, bool create, void *arg)
240 MapBlock *block = map_get_block(map, map_node_to_block_pos(pos, &offset), create);
242 pthread_mutex_lock(&block->mtx);
243 if (! map->callbacks.set_node || map->callbacks.set_node(block, offset, &node, arg)) {
244 block->data[offset.x][offset.y][offset.z] = node;
245 if (map->callbacks.after_set_node)
246 map->callbacks.after_set_node(block, offset, arg);
248 map_node_delete(node);
250 pthread_mutex_unlock(&block->mtx);
254 MapNode map_node_create(Node type, void *data, size_t size)
256 if (type >= NODE_UNLOADED)
259 NodeDefinition *def = &node_definitions[type];
263 node.data = def->data_size ? malloc(def->data_size) : NULL;
268 if (def->deserialize && size)
269 def->deserialize(&node, data, size);
274 void map_node_delete(MapNode node)
276 NodeDefinition *def = &node_definitions[node.type];