<commit_before>#include "worldloader.h"

NBT minecraft_air(nbt::tag_type::tag_end);

void Terrain::scanWorldDirectory(const std::filesystem::path &regionDir,
                                 Terrain::Coordinates *savedWorld) {
  const char delimiter = '.';
  std::string index;
  char buffer[4];
  int32_t regionX, regionZ;
  savedWorld->setUndefined();

  for (auto &region : std::filesystem::directory_iterator(regionDir)) {
    // This loop parses files with name 'r.x.y.mca', extracting x and y. This is
    // done by creating a string stream and using `getline` with '.' as a
    // delimiter.
    std::stringstream ss(region.path().filename().c_str());
    std::getline(ss, index, delimiter); // This removes the 'r.'
    std::getline(ss, index, delimiter);

    regionX = atoi(index.c_str());

    std::getline(ss, index, delimiter);

    regionZ = atoi(index.c_str());

    std::ifstream regionData(region.path());
    for (uint16_t chunk = 0; chunk < REGIONSIZE * REGIONSIZE; chunk++) {
      regionData.read(buffer, 4);

      if (*((uint32_t *)&buffer) == 0) {
        continue;
      }

      savedWorld->minX =
          std::min(savedWorld->minX, int32_t((regionX << 5) + (chunk & 0x1f)));
      savedWorld->maxX =
          std::max(savedWorld->maxX, int32_t((regionX << 5) + (chunk & 0x1f)));
      savedWorld->minZ =
          std::min(savedWorld->minZ, int32_t((regionZ << 5) + (chunk >> 5)));
      savedWorld->maxZ =
          std::max(savedWorld->maxZ, int32_t((regionZ << 5) + (chunk >> 5)));
    }
  }

  // Convert region indexes to blocks
  savedWorld->minX = savedWorld->minX << 4;
  savedWorld->minZ = savedWorld->minZ << 4;
  savedWorld->maxX = ((savedWorld->maxX + 1) << 4) - 1;
  savedWorld->maxZ = ((savedWorld->maxZ + 1) << 4) - 1;

  logger::debug("World spans from {}.{} to {}.{}\n", savedWorld->minX,
                savedWorld->minZ, savedWorld->maxX, savedWorld->maxZ);
}

void Terrain::Data::load(const std::filesystem::path &regionDir) {
  this->regionDir = regionDir;
}

void Terrain::Data::inflateChunk(vector<NBT> *sections) {
  // Some chunks are "hollow", empty sections being present between blocks.
  // Internally, minecraft does not store those empty sections, instead relying
  // on the section index (key "Y"). This routine creates empty sections where
  // they should be, to save a lot of time when rendering.
  //
  // This method ensure all sections from index 0 to the highest existing<commit_msg>Default Y from 0 to 255<commit_after>#include "worldloader.h"

NBT minecraft_air(nbt::tag_type::tag_end);

void Terrain::scanWorldDirectory(const std::filesystem::path &regionDir,
                                 Terrain::Coordinates *savedWorld) {
  const char delimiter = '.';
  std::string index;
  char buffer[4];
  int32_t regionX, regionZ;
  savedWorld->setUndefined();

  for (auto &region : std::filesystem::directory_iterator(regionDir)) {
    // This loop parses files with name 'r.x.y.mca', extracting x and y. This is
    // done by creating a string stream and using `getline` with '.' as a
    // delimiter.
    std::stringstream ss(region.path().filename().c_str());
    std::getline(ss, index, delimiter); // This removes the 'r.'
    std::getline(ss, index, delimiter);

    regionX = atoi(index.c_str());

    std::getline(ss, index, delimiter);

    regionZ = atoi(index.c_str());

    std::ifstream regionData(region.path());
    for (uint16_t chunk = 0; chunk < REGIONSIZE * REGIONSIZE; chunk++) {
      regionData.read(buffer, 4);

      if (*((uint32_t *)&buffer) == 0) {
        continue;
      }

      savedWorld->minX =
          std::min(savedWorld->minX, int32_t((regionX << 5) + (chunk & 0x1f)));
      savedWorld->maxX =
          std::max(savedWorld->maxX, int32_t((regionX << 5) + (chunk & 0x1f)));
      savedWorld->minZ =
          std::min(savedWorld->minZ, int32_t((regionZ << 5) + (chunk >> 5)));
      savedWorld->maxZ =
          std::max(savedWorld->maxZ, int32_t((regionZ << 5) + (chunk >> 5)));
    }
  }

  // Convert region indexes to blocks
  savedWorld->minX = savedWorld->minX << 4;
  savedWorld->minZ = savedWorld->minZ << 4;
  savedWorld->maxX = ((savedWorld->maxX + 1) << 4) - 1;
  savedWorld->maxZ = ((savedWorld->maxZ + 1) << 4) - 1;

  savedWorld->minY = 0;
  savedWorld->maxY = 255;

  logger::debug("World spans from {}.{} to {}.{}\n", savedWorld->minX,
                savedWorld->minZ, savedWorld->maxX, savedWorld->maxZ);
}

void Terrain::Data::load(const std::filesystem::path &regionDir) {
  this->regionDir = regionDir;
}

void Terrain::Data::inflateChunk(vector<NBT> *sections) {
  // Some chunks are "hollow", empty sections being present between blocks.
  // Internally, minecraft does not store those empty sections, instead relying
  // on the section index (key "Y"). This routine creates empty sections where
  // they should be, to save a lot of time when rendering.
  //
  // This method ensure all sections from index 0 to the highest existing
{'fraction_non_alphanumeric': 0.15616824310726504, 'fraction_numerical': 0.016502314348963574, 'mean_word_length': 3.258783204798629, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6112304', 'n_tokens_mistral': 1689, 'n_tokens_neox': 1597, 'n_words': 418}