9 Map *map_create(MapCallbacks callbacks)
11 Map *map = malloc(sizeof(Map));
12 pthread_rwlock_init(&map->rwlck, NULL);
13 pthread_rwlock_init(&map->cached_rwlck, NULL);
14 map->sectors = bintree_create(sizeof(v2s32), NULL);
16 map->callbacks = callbacks;
20 static void free_block(BintreeNode *node, void *arg)
24 if (map->callbacks.delete_block)
25 map->callbacks.delete_block(node->value);
27 map_free_block(node->value);
30 static void free_sector(BintreeNode *node, void *arg)
32 MapSector *sector = node->value;
34 bintree_clear(§or->blocks, &free_block, arg);
35 pthread_rwlock_destroy(§or->rwlck);
39 void map_delete(Map *map)
41 pthread_rwlock_destroy(&map->rwlck);
42 pthread_rwlock_destroy(&map->cached_rwlck);
43 bintree_clear(&map->sectors, &free_sector, map);
47 MapSector *map_get_sector(Map *map, v2s32 pos, bool create)
50 pthread_rwlock_wrlock(&map->rwlck);
52 pthread_rwlock_rdlock(&map->rwlck);
54 BintreeNode **nodeptr = bintree_search(&map->sectors, &pos);
56 MapSector *sector = NULL;
59 sector = (*nodeptr)->value;
61 sector = malloc(sizeof(MapSector));
62 pthread_rwlock_init(§or->rwlck, NULL);
64 sector->blocks = bintree_create(sizeof(s32), NULL);
66 bintree_add_node(&map->sectors, nodeptr, &pos, sector);
69 pthread_rwlock_unlock(&map->rwlck);
74 MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
76 MapBlock *cached = NULL;
78 pthread_rwlock_rdlock(&map->cached_rwlck);
80 pthread_rwlock_unlock(&map->cached_rwlck);
82 if (cached && v3s32_equals(cached->pos, pos))
85 MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
90 pthread_rwlock_wrlock(§or->rwlck);
92 pthread_rwlock_rdlock(§or->rwlck);
94 BintreeNode **nodeptr = bintree_search(§or->blocks, &pos.y);
96 MapBlock *block = NULL;
99 block = (*nodeptr)->value;
101 pthread_mutex_lock(&block->mtx);
102 if (map->callbacks.get_block && ! map->callbacks.get_block(block, create)) {
103 pthread_mutex_unlock(&block->mtx);
106 pthread_mutex_unlock(&block->mtx);
107 pthread_rwlock_wrlock(&map->cached_rwlck);
109 pthread_rwlock_unlock(&map->cached_rwlck);
112 bintree_add_node(§or->blocks, nodeptr, &pos.y, block = map_allocate_block(pos));
114 if (map->callbacks.create_block)
115 map->callbacks.create_block(block);
118 pthread_rwlock_unlock(§or->rwlck);
123 MapBlock *map_allocate_block(v3s32 pos)
125 MapBlock *block = malloc(sizeof(MapBlock));
128 pthread_mutexattr_t attr;
129 pthread_mutexattr_init(&attr);
130 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
131 pthread_mutex_init(&block->mtx, &attr);
133 ITERATE_MAPBLOCK block->data[x][y][z] = map_node_create(NODE_UNKNOWN, (Blob) {0, NULL});
138 void map_free_block(MapBlock *block)
140 ITERATE_MAPBLOCK map_node_delete(block->data[x][y][z]);
142 pthread_mutex_destroy(&block->mtx);
146 Blob map_serialize_block(MapBlock *block)
151 if (block->data[x][y][z].type != NODE_AIR) {
158 return (Blob) {0, NULL};
160 SerializedMapBlock block_data;
163 MapNode *node = &block->data[x][y][z];
164 SerializedMapNode *node_data = &block_data.raw.nodes[x][y][z];
166 *node_data = (SerializedMapNode) {
174 NodeDefinition *def = &node_definitions[node->type];
177 def->serialize(&node_data->data, node->data);
180 Blob buffer = {0, NULL};
181 SerializedMapBlock_write(&buffer, &block_data);
182 SerializedMapBlock_free(&block_data);
187 bool map_deserialize_block(MapBlock *block, Blob buffer)
189 if (buffer.siz == 0) {
191 block->data[x][y][z] = map_node_create(NODE_AIR, (Blob) {0, NULL});
196 // it's important to copy Blobs that have been malloc'd before reading from them
197 // because reading from a Blob modifies its data and size pointer,
198 // but does not free anything
199 SerializedMapBlock block_data = {0};
200 bool success = SerializedMapBlock_read(&buffer, &block_data);
202 if (success) ITERATE_MAPBLOCK
203 block->data[x][y][z] = map_node_create(block_data.raw.nodes[x][y][z].type, block_data.raw.nodes[x][y][z].data);
205 SerializedMapBlock_free(&block_data);
209 v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset)
212 *offset = (v3u8) {(u32) pos.x % MAPBLOCK_SIZE, (u32) pos.y % MAPBLOCK_SIZE, (u32) pos.z % MAPBLOCK_SIZE};
213 return (v3s32) {floor((double) pos.x / (double) MAPBLOCK_SIZE), floor((double) pos.y / (double) MAPBLOCK_SIZE), floor((double) pos.z / (double) MAPBLOCK_SIZE)};
216 MapNode map_get_node(Map *map, v3s32 pos)
219 v3s32 blockpos = map_node_to_block_pos(pos, &offset);
220 MapBlock *block = map_get_block(map, blockpos, false);
222 return map_node_create(NODE_UNLOADED, (Blob) {0, NULL});
223 return block->data[offset.x][offset.y][offset.z];
226 void map_set_node(Map *map, v3s32 pos, MapNode node, bool create, void *arg)
229 MapBlock *block = map_get_block(map, map_node_to_block_pos(pos, &offset), create);
231 pthread_mutex_lock(&block->mtx);
232 if (! map->callbacks.set_node || map->callbacks.set_node(block, offset, &node, arg)) {
233 block->data[offset.x][offset.y][offset.z] = node;
234 if (map->callbacks.after_set_node)
235 map->callbacks.after_set_node(block, offset, arg);
237 map_node_delete(node);
239 pthread_mutex_unlock(&block->mtx);
243 MapNode map_node_create(Node type, Blob buffer)
245 if (type >= NODE_UNLOADED)
248 NodeDefinition *def = &node_definitions[type];
252 node.data = def->data_size ? malloc(def->data_size) : NULL;
257 if (def->deserialize)
258 def->deserialize(&buffer, node.data);
263 void map_node_delete(MapNode node)
265 NodeDefinition *def = &node_definitions[node.type];