void hex_grid_t::load_from_file(std::string const& filepath) { SDL_RWops* io = SDL_RWFromFile(filepath.c_str(), "rb"); if (!io) { EXPLODE("hex_grid_t::load_to_file()"); //todo: handle errors better } hxm_header_t header; size_t num_read = SDL_RWread(io, &header, sizeof (hxm_header_t), 1); ASSERT(num_read > 0, "Error reading file header"); init(header.map_size, header.chunk_size); for_each_chunk([&](hex_grid_chunk_t& chunk) { SDL_RWread(io, &(chunk.size), sizeof(glm::uvec2), 1); for(auto& column : chunk.cells) { size_t num_r = SDL_RWread(io, column.data(), sizeof(hex_grid_cell_t), column.size()); ASSERT(num_r == column.size(), ""); LOG("read %d cells", num_r); } }); SDL_RWclose(io); }
void World::update(const glm::vec3& center) { update_loaded_chunks(center); for_each_chunk([this](Chunk* chunk, int x, int y, int z) { if (!chunk->update_queued() && (!chunk->filled() || !chunk->up_to_date())) { auto chunk_update_slot = get_chunk_update_slot(chunk->low_priority_update()); if (!chunk_update_slot) { // No free slots. End the for_each_chunk loop. return false; } auto chunk_update = std::make_unique<ChunkUpdate>(chunk->get_block_data(), x, y, z, !chunk->filled()); { std::lock_guard<decltype(chunk_update_slot->second)> chunk_update_lock(chunk_update_slot->second); chunk_update_slot->first = std::move(chunk_update); } chunk->set_update_queued(true); } return true; }, false); // Limit to prevent stuttering int mesh_updates = MAX_CHUNK_MESH_UPDATES_PER_FRAME; auto process_completed_chunk_updates = [this, &mesh_updates](ChunkUpdateArray& chunk_updates) { for (auto& chunk_update : chunk_updates) { if (chunk_update.first && chunk_update.first->finished()) { process_completed_chunk_update(chunk_update.first); { std::lock_guard<decltype(chunk_update.second)> chunk_update_lock(chunk_update.second); chunk_update.first.reset(); } if (--mesh_updates <= 0) { break; } } } }; process_completed_chunk_updates(m_chunk_updates); if (mesh_updates > 0) { process_completed_chunk_updates(m_chunk_updates_low_priority); } }
void World::render() { for_each_chunk([](Chunk* chunk, int x, int y, int z) { chunk->render(); return true; }); }
World::World(int render_distance) : m_render_distance{render_distance}, m_run_chunk_updates{true} { ChunkUpdate::set_world(this); update_loaded_chunks(WorldGen::get_spawn_pos()); // pre-generate world for_each_chunk([](Chunk* chunk, int x, int y, int z) { WorldGen::fill_chunk(*chunk->get_block_data(), x * WorldConstants::CHUNK_SIZE, y * WorldConstants::CHUNK_SIZE, z * WorldConstants::CHUNK_SIZE); chunk->set_filled(true); return true; }, false); m_chunk_update_thread = std::thread{std::bind(&World::chunk_update_thread, this)}; }
// https://wiki.libsdl.org/SDL_RWops?highlight=%28%5CbCategoryStruct%5Cb%29%7C%28CategoryIO%29 // https://wiki.libsdl.org/SDL_RWwrite?highlight=%28%5CbCategoryIO%5Cb%29%7C%28CategoryEnum%29%7C%28CategoryStruct%29 void hex_grid_t::save_to_file(std::string const& filepath) { WARN_IF(!chunks.empty(), "Saving an empty map"); SDL_RWops* io = SDL_RWFromFile(filepath.c_str(), "wb"); if(!io) { EXPLODE("hex_grid_t::save_to_file() error"); //todo: handle errors better } hxm_header_t header; header.version = 0; header.chunk_size = chunk_size(); header.map_size = size; size_t num_written = SDL_RWwrite(io, (void*)&header, sizeof(hxm_header_t), 1); if(num_written != 1) { EXPLODE("error writing hxm header"); } for_each_chunk([&](hex_grid_chunk_t const& chunk) { SDL_RWwrite(io, (void*)&chunk.size, sizeof(glm::uvec2), 1); for(auto column : chunk.cells) { size_t num_w = SDL_RWwrite(io, column.data(), sizeof(hex_grid_cell_t), column.size()); ASSERT(num_w == column.size(), "chunk save error"); LOG("wrote %d cells", num_w); } }); SDL_RWclose(io); }