10 Map *map = malloc(sizeof(Map));
11 map->sectors = array_create(sizeof(MapSector *));
15 static MapBlock **get_block_ptr(MapSector *sector, size_t idx)
17 return (MapBlock **) sector->blocks.ptr + idx;
20 static MapSector **get_sector_ptr(Map *map, size_t idx)
22 return (MapSector **) map->sectors.ptr + idx;
25 void map_delete(Map *map)
27 for (size_t s = 0; s < map->sectors.siz; s++) {
28 MapSector *sector = *get_sector_ptr(map, s);
29 for (size_t b = 0; b < sector->blocks.siz; b++)
30 map_free_block(*get_block_ptr(sector, b));
31 if (sector->blocks.ptr)
32 free(sector->blocks.ptr);
36 free(map->sectors.ptr);
40 #define CMPBOUNDS(x) x == 0 ? 0 : x > 0 ? 1 : -1
42 static s8 sector_compare(void *hash, void *sector)
44 s64 d = *((u64 *) hash) - ((MapSector *) sector)->hash;
48 MapSector *map_get_sector(Map *map, v2s32 pos, bool create)
50 u64 hash = ((u64) pos.x << 32) + (u64) pos.y;
51 BinsearchResult res = binsearch(&hash, map->sectors.ptr, map->sectors.siz, §or_compare);
54 return *get_sector_ptr(map, res.index);
58 MapSector *sector = malloc(sizeof(MapSector));
61 sector->blocks = array_create(sizeof(MapBlock *));
63 array_insert(&map->sectors, §or, res.index);
68 static s8 block_compare(void *level, void *block)
70 s32 d = *((s32 *) level) - ((MapBlock *) block)->pos.y;
74 static MapBlock *allocate_block(v3s32 pos)
76 MapBlock *block = malloc(sizeof(MapBlock));
82 MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
84 MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, create);
88 BinsearchResult res = binsearch(&pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
90 MapBlock *block = NULL;
93 block = *get_block_ptr(sector, res.index);
95 block = allocate_block(pos);
97 if (map->on_block_create)
98 map->on_block_create(block);
100 array_insert(§or->blocks, &block, res.index);
105 return block->ready ? block : NULL;
108 void map_add_block(Map *map, MapBlock *block)
110 MapSector *sector = map_get_sector(map, (v2s32) {block->pos.x, block->pos.z}, true);
111 BinsearchResult res = binsearch(&block->pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
113 MapBlock **ptr = get_block_ptr(sector, res.index);
114 map_free_block(*ptr);
117 array_insert(§or->blocks, &block, res.index);
119 if (map->on_block_add)
120 map->on_block_add(block);
123 void map_clear_block(MapBlock *block, v3u8 init_state)
125 for (u8 x = 0; x <= init_state.x; x++)
126 for (u8 y = 0; y <= init_state.y; y++)
127 for (u8 z = 0; z <= init_state.z; z++)
128 map_node_clear(&block->data[x][y][z]);
131 void map_free_block(MapBlock *block)
133 map_clear_block(block, (v3u8) {15, 15, 15});
137 bool map_deserialize_node(int fd, MapNode *node)
141 if (! read_u32(fd, &type))
144 if (type > NODE_INVALID)
147 *node = map_node_create(type);
152 bool map_serialize_block(int fd, MapBlock *block)
154 if (! write_v3s32(fd, block->pos))
158 if (! write_u32(fd, block->data[x][y][z].type))
165 MapBlock *map_deserialize_block(int fd)
169 if (! read_v3s32(fd, &pos))
172 MapBlock *block = allocate_block(pos);
175 if (! map_deserialize_node(fd, &block->data[x][y][z])) {
176 map_clear_block(block, (v3u8) {x, y, z});
185 bool map_serialize(int fd, Map *map)
187 for (size_t s = 0; s < map->sectors.siz; s++) {
188 MapSector *sector = *get_sector_ptr(map, s);
189 for (size_t b = 0; b < sector->blocks.siz; b++)
190 if (! map_serialize_block(fd, *get_block_ptr(sector, b)))
196 void map_deserialize(int fd, Map *map)
200 while ((block = map_deserialize_block(fd)) != NULL)
201 map_add_block(map, block);
204 v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset)
207 *offset = (v3u8) {(u32) pos.x % 16, (u32) pos.y % 16, (u32) pos.z % 16};
208 return (v3s32) {floor((double) pos.x / 16.0), floor((double) pos.y / 16.0), floor((double) pos.z / 16.0)};
211 MapNode map_get_node(Map *map, v3s32 pos)
214 v3s32 blockpos = map_node_to_block_pos(pos, &offset);
215 MapBlock *block = map_get_block(map, blockpos, false);
217 return map_node_create(NODE_UNLOADED);
218 return block->data[offset.x][offset.y][offset.z];
221 void map_set_node(Map *map, v3s32 pos, MapNode node)
224 MapBlock *block = map_get_block(map, map_node_to_block_pos(pos, &offset), false);
226 MapNode *current_node = &block->data[offset.x][offset.y][offset.z];
227 map_node_clear(current_node);
228 *current_node = node;
232 MapNode map_node_create(Node type)
234 return (MapNode) {type, list_create(&list_compare_string)};
237 void map_node_clear(MapNode *node)
239 list_clear(&node->meta);