void for_each_chunk_raw(regionfile* region, raw_chunk_func function, void* context) { if (!region || !function) return; FILE* f; if (region->keepopen == 1) { if (region->file) f = region->file; else { f = fopen(region->filename, "rb+"); region->file = f; } } else f = fopen(region->filename, "rb+"); size_t i; for (i = 0; i < SECTOR_INTS; i++) { uint32_t offset = region->offsets[i]; if (offset == 0) continue; uint32_t numSectors = offset & 0xff; if (numSectors == 0) continue; uint32_t sectorStart = offset >> 8; if (f && fseek(f, sectorStart*SECTOR_BYTES, SEEK_SET) == 0) { unsigned char buf[numSectors*SECTOR_BYTES]; if (fread(buf, 1, sizeof(buf), f) == sizeof(buf)) { size_t size = be32toh((uint32_t) (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24))); nbt_node* node = nbt_parse_compressed(buf+5, size); function(node, context); nbt_free(node); } } } if (region->file != f) fclose(f); };
void dump_nbt(const char *filename) { assert(errno == NBT_OK); FILE* f = fopen(filename, "rb"); nbt_node* root = nbt_parse_file(f); fclose(f); if(errno != NBT_OK) { fprintf(stderr, "Parsing error!\n"); return; } char* str = nbt_dump_ascii(root); nbt_free(root); if(str == NULL) fprintf(stderr, "Printing error!"); printf("%s", str); free(str); }
void Chunk::free() { if(nf != NULL) nbt_free(nf); //nbt_free_byte_array(blocks); }
int write_chunk(regionfile* region, int32_t cx, int32_t cz, chunk* chunk) { if (region == NULL) return -1; if (chunk == NULL) return -1; cx &= 0x1f; cz &= 0x1f; uint32_t offset = region->offsets[cx + cz * 32]; if (offset == 0) return -2; uint32_t numSectors = offset & 0xff; if (numSectors == 0) return -3; nbt_node* raw = new_chunk_data_to_nbt(chunk); if (raw == NULL) return -1; uint32_t sectorStart = offset >> 8; FILE* f; if (region->keepopen == 1) { if (region->file) f = region->file; else { f = fopen(region->filename, "rb+"); region->file = f; } } else f = fopen(region->filename, "rb+"); struct buffer buf = nbt_dump_compressed(raw, STRAT_INFLATE); uint16_t sectorsNeeded = (buf.len + 5) / SECTOR_BYTES + 1; if (sectorsNeeded >= 256) goto error; if (sectorStart != 0 && numSectors >= sectorsNeeded) { if (fseek(f, sectorStart*SECTOR_BYTES, SEEK_SET) != 0) goto error; uint32_t size = htobe32(buf.len); if (fwrite(&size, 1, sizeof(uint32_t), f) != sizeof(uint32_t)) goto error; static const char COMPRESSION = 2; if (fwrite(&COMPRESSION, 1, sizeof(COMPRESSION), f) != sizeof(COMPRESSION)) goto error; if (fwrite(buf.data, 1, buf.len, f) != buf.len) goto error; goto success; } else { size_t i; size_t runLength = 0; uint32_t runStart = 0; unsigned char* curSector = region->freeSectors; for (i = 0; curSector[i] != 0x00; i++) { if (runLength > 0) { if (curSector[i] == 0x01) runLength++; else runLength = 0; } else if (curSector[i] == 0x01) { runStart = i; runLength = 1; } if (runLength >= sectorsNeeded) break; } if (runLength >= sectorsNeeded) { region->offsets[cx + cz * 32] = runStart << 8 | sectorsNeeded; if (__region_write_offsets(region) != 0) goto error; if (fseek(f, runStart*SECTOR_BYTES, SEEK_SET) != 0) goto error; uint32_t size = htobe32(buf.len); if (fwrite(&size, 1, sizeof(uint32_t), f) != sizeof(uint32_t)) goto error; static const char COMPRESSION = 2; if (fwrite(&COMPRESSION, 1, sizeof(COMPRESSION), f) != sizeof(COMPRESSION)) goto error; if (fwrite(buf.data, 1, buf.len, f) != buf.len) goto error; goto success; } else { if (fseek(f, 0L, SEEK_END) != 0) goto error; long filesize = ftell(f); uint32_t sectorNumber = filesize/SECTOR_BYTES; filesize += sectorsNeeded * SECTOR_BYTES; if (ftruncate(fileno(f), filesize) != 0) goto error; region->offsets[cx + cz * 32] = sectorNumber << 8 | sectorsNeeded; if (__region_write_offsets(region) != 0) goto error; if (fseek(f, sectorNumber*SECTOR_BYTES, SEEK_SET) != 0) goto error; uint32_t size = htobe32(buf.len); if (fwrite(&size, 1, sizeof(uint32_t), f) != sizeof(uint32_t)) goto error; static const char COMPRESSION = 2; if (fwrite(&COMPRESSION, 1, sizeof(COMPRESSION), f) != sizeof(COMPRESSION)) goto error; if (fwrite(buf.data, 1, buf.len, f) != buf.len) goto error; uint32_t freeSectorsLength = filesize/SECTOR_BYTES; region->freeSectors = realloc(region->freeSectors, sizeof(unsigned char) * (freeSectorsLength+1)); region->freeSectors[freeSectorsLength] = 0x00; for (; sectorNumber < freeSectorsLength; sectorNumber++) region->freeSectors[sectorNumber] = 0x02; goto success; } } error: nbt_free(raw); if (f && region->file != f) fclose(f); buffer_free(&buf); return 1; success: nbt_free(raw); buffer_free(&buf); if (region->file != f) fclose(f); region->timestamps[cx + cz * 32] = time(NULL); __region_write_timestamps(region); return 0; };