10 #define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
12 static s8 sector_compare(void *hash, void *sector)
14 s64 d = *((u64 *) hash) - (*(MapSector **) sector)->hash;
18 static s8 block_compare(void *level, void *block)
20 s32 d = *((s32 *) level) - (*(MapBlock **) block)->pos.y;
24 static MapBlock *allocate_block(v3s32 pos)
26 MapBlock *block = malloc(sizeof(MapBlock));
28 block->state = MBS_CREATED;
30 pthread_mutex_init(&block->mtx, NULL);
36 Map *map = malloc(sizeof(Map));
37 map->sectors = array_create(sizeof(MapSector *));
38 map->sectors.cmp = §or_compare;
42 void map_delete(Map *map)
44 for (size_t s = 0; s < map->sectors.siz; s++) {
45 MapSector *sector = map_get_sector_raw(map, s);
46 for (size_t b = 0; b < sector->blocks.siz; b++)
47 map_free_block(map_get_block_raw(sector, b));
48 if (sector->blocks.ptr)
49 free(sector->blocks.ptr);
53 free(map->sectors.ptr);
57 MapSector *map_get_sector_raw(Map *map, size_t idx)
59 return ((MapSector **) map->sectors.ptr)[idx];
62 MapBlock *map_get_block_raw(MapSector *sector, size_t idx)
64 return ((MapBlock **) sector->blocks.ptr)[idx];
67 MapSector *map_get_sector(Map *map, v2s32 pos, bool create)
69 u64 hash = ((u64) pos.x << 32) + (u64) pos.y;
70 ArraySearchResult res = array_search(&map->sectors, &hash);
73 return map_get_sector_raw(map, res.index);
77 MapSector *sector = malloc(sizeof(MapSector));
80 sector->blocks = array_create(sizeof(MapBlock *));
81 sector->blocks.cmp = &block_compare;
83 array_insert(&map->sectors, §or, res.index);
88 MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
90 MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
94 ArraySearchResult res = array_search(§or->blocks, &pos.y);
96 MapBlock *block = NULL;
99 block = map_get_block_raw(sector, res.index);
101 block = allocate_block(pos);
102 array_insert(§or->blocks, &block, res.index);
107 return (create || block->state == MBS_READY) ? block : NULL;
110 void map_free_block(MapBlock *block)
112 ITERATE_MAPBLOCK list_clear(&block->metadata[x][y][z]);
113 pthread_mutex_destroy(&block->mtx);
117 bool map_deserialize_node(int fd, MapNode *node)
121 if (! read_u32(fd, &type))
124 if (type >= NODE_UNLOADED)
127 *node = map_node_create(type);
132 bool map_serialize_block(FILE *file, MapBlock *block)
135 htobe32(block->pos.x),
136 htobe32(block->pos.y),
137 htobe32(block->pos.z),
139 if (fwrite(pos, 1, sizeof(pos), file) != sizeof(pos))
145 MapNode node = block->data[x][y][z];
146 node.type = htobe32(node.type);
147 data[x][y][z] = node;
150 if (fwrite(data, 1, sizeof(MapBlockData), file) != sizeof(MapBlockData))
158 bool map_deserialize_block(int fd, Map *map, MapBlock **blockptr, bool dummy)
162 if (! read_v3s32(fd, &pos))
165 MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, true);
166 ArraySearchResult res = array_search(§or->blocks, &pos.y);
171 block = allocate_block(pos);
172 } else if (res.success) {
173 block = map_get_block_raw(sector, res.index);
175 block = allocate_block(pos);
176 array_insert(§or->blocks, &block, res.index);
180 size_t n_read_total = 0;
184 while (n_read_total < sizeof(MapBlockData)) {
185 if ((n_read = read(fd, (char *) data + n_read_total, sizeof(MapBlockData) - n_read_total)) == -1) {
191 n_read_total += n_read;
196 MapNode node = data[x][y][z];
197 node.type = be32toh(node.type);
199 if (node.type >= NODE_UNLOADED)
200 node.type = NODE_INVALID;
202 block->data[x][y][z] = node;
203 block->metadata[x][y][z] = list_create(&list_compare_string);
207 // ToDo: Deserialize meta
210 map_free_block(block);
211 else if (blockptr && ret)
217 bool map_serialize(FILE *file, Map *map)
219 for (size_t s = 0; s < map->sectors.siz; s++) {
220 MapSector *sector = map_get_sector_raw(map, s);
221 for (size_t b = 0; b < sector->blocks.siz; b++)
222 if (! map_serialize_block(file, map_get_block_raw(sector, b)))
228 void map_deserialize(int fd, Map *map)
230 while (map_deserialize_block(fd, map, NULL, false))
234 v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset)
237 *offset = (v3u8) {(u32) pos.x % 16, (u32) pos.y % 16, (u32) pos.z % 16};
238 return (v3s32) {floor((double) pos.x / 16.0), floor((double) pos.y / 16.0), floor((double) pos.z / 16.0)};
241 MapNode map_get_node(Map *map, v3s32 pos)
244 v3s32 blockpos = map_node_to_block_pos(pos, &offset);
245 MapBlock *block = map_get_block(map, blockpos, false);
247 return map_node_create(NODE_UNLOADED);
248 return block->data[offset.x][offset.y][offset.z];
251 void map_set_node(Map *map, v3s32 pos, MapNode node)
254 MapBlock *block = map_get_block(map, map_node_to_block_pos(pos, &offset), false);
256 list_clear(&block->metadata[offset.x][offset.y][offset.z]);
257 block->data[offset.x][offset.y][offset.z] = node;
259 block->state = MBS_MODIFIED;
263 MapNode map_node_create(Node type)
265 return (MapNode) {type};