7 #define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
9 static s8 sector_compare(void *hash, void *sector)
11 s64 d = *((u64 *) hash) - (*(MapSector **) sector)->hash;
15 static s8 block_compare(void *level, void *block)
17 s32 d = *((s32 *) level) - (*(MapBlock **) block)->pos.y;
21 static MapBlock *allocate_block(v3s32 pos)
23 MapBlock *block = malloc(sizeof(MapBlock));
32 Map *map = malloc(sizeof(Map));
33 map->sectors = array_create(sizeof(MapSector *));
34 map->sectors.cmp = §or_compare;
38 void map_delete(Map *map)
40 for (size_t s = 0; s < map->sectors.siz; s++) {
41 MapSector *sector = map_get_sector_raw(map, s);
42 for (size_t b = 0; b < sector->blocks.siz; b++)
43 map_free_block(map_get_block_raw(sector, b));
44 if (sector->blocks.ptr)
45 free(sector->blocks.ptr);
49 free(map->sectors.ptr);
53 MapSector *map_get_sector_raw(Map *map, size_t idx)
55 return ((MapSector **) map->sectors.ptr)[idx];
58 MapBlock *map_get_block_raw(MapSector *sector, size_t idx)
60 return ((MapBlock **) sector->blocks.ptr)[idx];
63 MapSector *map_get_sector(Map *map, v2s32 pos, bool create)
65 u64 hash = ((u64) pos.x << 32) + (u64) pos.y;
66 ArraySearchResult res = array_search(&map->sectors, &hash);
69 return map_get_sector_raw(map, res.index);
73 MapSector *sector = malloc(sizeof(MapSector));
76 sector->blocks = array_create(sizeof(MapBlock *));
77 sector->blocks.cmp = &block_compare;
79 array_insert(&map->sectors, §or, res.index);
84 MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
86 MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
90 ArraySearchResult res = array_search(§or->blocks, &pos.y);
92 MapBlock *block = NULL;
95 block = map_get_block_raw(sector, res.index);
97 block = allocate_block(pos);
98 array_insert(§or->blocks, &block, res.index);
100 if (map->on_block_create)
101 map->on_block_create(block);
106 return block->ready ? block : NULL;
109 void map_free_block(MapBlock *block)
111 ITERATE_MAPBLOCK map_node_clear(&block->data[x][y][z]);
115 bool map_deserialize_node(int fd, MapNode *node)
119 if (! read_u32(fd, &type))
122 if (type >= NODE_UNLOADED)
125 *node = map_node_create(type);
130 bool map_serialize_block(int fd, MapBlock *block)
132 if (! write_v3s32(fd, block->pos))
136 if (! write_u32(fd, block->data[x][y][z].type))
143 bool map_deserialize_block(int fd, Map *map, bool dummy)
147 if (! read_v3s32(fd, &pos))
150 MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, true);
151 ArraySearchResult res = array_search(§or->blocks, &pos.y);
156 block = allocate_block(pos);
157 } else if (res.success) {
158 block = map_get_block_raw(sector, res.index);
160 block = allocate_block(pos);
161 array_insert(§or->blocks, &block, res.index);
165 if (! map_deserialize_node(fd, &block->data[x][y][z]))
170 map_free_block(block);
174 if (map->on_block_add)
175 map->on_block_add(block);
181 bool map_serialize(int fd, Map *map)
183 for (size_t s = 0; s < map->sectors.siz; s++) {
184 MapSector *sector = map_get_sector_raw(map, s);
185 for (size_t b = 0; b < sector->blocks.siz; b++)
186 if (! map_serialize_block(fd, map_get_block_raw(sector, b)))
192 void map_deserialize(int fd, Map *map)
194 while (map_deserialize_block(fd, map, false))
198 v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset)
201 *offset = (v3u8) {(u32) pos.x % 16, (u32) pos.y % 16, (u32) pos.z % 16};
202 return (v3s32) {floor((double) pos.x / 16.0), floor((double) pos.y / 16.0), floor((double) pos.z / 16.0)};
205 MapNode map_get_node(Map *map, v3s32 pos)
208 v3s32 blockpos = map_node_to_block_pos(pos, &offset);
209 MapBlock *block = map_get_block(map, blockpos, false);
211 return map_node_create(NODE_UNLOADED);
212 return block->data[offset.x][offset.y][offset.z];
215 void map_set_node(Map *map, v3s32 pos, MapNode node)
218 MapBlock *block = map_get_block(map, map_node_to_block_pos(pos, &offset), false);
220 MapNode *current_node = &block->data[offset.x][offset.y][offset.z];
221 map_node_clear(current_node);
222 *current_node = node;
226 MapNode map_node_create(Node type)
228 return (MapNode) {type, list_create(&list_compare_string)};
231 void map_node_clear(MapNode *node)
233 list_clear(&node->meta);