diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index b5be5568..459cdb5b 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -14,6 +14,7 @@ #include "../maths/voxmaths.h" #include "../world/World.h" +#include "../util/data_io.h" #include "../coders/json.h" #include "../constants.h" @@ -39,23 +40,10 @@ using glm::vec3; using std::ios; using std::string; using std::unique_ptr; +using std::unordered_map; using std::filesystem::path; namespace fs = std::filesystem; -int bytes2Int(const ubyte* src, size_t offset){ - return (src[offset] << 24) | - (src[offset+1] << 16) | - (src[offset+2] << 8) | - (src[offset+3]); -} - -void int2Bytes(int value, ubyte* dest, size_t offset){ - dest[offset] = (char) (value >> 24 & 255); - dest[offset+1] = (char) (value >> 16 & 255); - dest[offset+2] = (char) (value >> 8 & 255); - dest[offset+3] = (char) (value >> 0 & 255); -} - WorldRegion::WorldRegion() { chunksData = new ubyte*[REGION_VOL]{}; sizes = new uint32_t[REGION_VOL]{}; @@ -112,7 +100,8 @@ WorldFiles::~WorldFiles(){ regions.clear(); } -WorldRegion* WorldFiles::getRegion(int x, int z) { +WorldRegion* WorldFiles::getRegion(unordered_map& regions, + int x, int z) { auto found = regions.find(ivec2(x, z)); if (found == regions.end()) return nullptr; @@ -140,7 +129,7 @@ void WorldFiles::put(Chunk* chunk){ int regionX = floordiv(chunk->x, REGION_SIZE); int regionZ = floordiv(chunk->z, REGION_SIZE); - WorldRegion* region = getRegion(regionX, regionZ); + WorldRegion* region = getRegion(regions, regionX, regionZ); if (region == nullptr) { region = new WorldRegion(); regions[ivec2(regionX, regionZ)] = region; @@ -192,7 +181,7 @@ ubyte* WorldFiles::getChunk(int x, int z){ int localX = x - (regionX * REGION_SIZE); int localZ = z - (regionZ * REGION_SIZE); - WorldRegion* region = getRegion(regionX, regionZ); + WorldRegion* region = getRegion(regions, regionX, regionZ); if (region == nullptr) { region = new WorldRegion(); regions[ivec2(regionX, regionZ)] = region; @@ -218,10 +207,8 @@ ubyte* WorldFiles::readChunkData(int x, int z, uint32_t& length, path filename){ int regionX = floordiv(x, REGION_SIZE); int regionZ = floordiv(z, REGION_SIZE); - int localX = x - (regionX * REGION_SIZE); int localZ = z - (regionZ * REGION_SIZE); - int chunkIndex = localZ * REGION_SIZE + localX; std::ifstream input(filename, std::ios::binary); @@ -235,14 +222,14 @@ ubyte* WorldFiles::readChunkData(int x, int z, uint32_t& length, path filename){ uint32_t offset; input.seekg(table_offset + chunkIndex * 4); input.read((char*)(&offset), 4); - offset = bytes2Int((const ubyte*)(&offset), 0); + offset = dataio::read_int32_big((const ubyte*)(&offset), 0); if (offset == 0){ input.close(); return nullptr; } input.seekg(offset); input.read((char*)(&offset), 4); - length = bytes2Int((const ubyte*)(&offset), 0); + length = dataio::read_int32_big((const ubyte*)(&offset), 0); ubyte* data = new ubyte[length]; input.read((char*)data, length); input.close(); @@ -278,7 +265,7 @@ void WorldFiles::writeRegion(int x, int y, WorldRegion* entry, path filename){ offsets[i] = offset; size_t compressedSize = sizes[i]; - int2Bytes(compressedSize, (ubyte*)intbuf, 0); + dataio::write_int32_big(compressedSize, (ubyte*)intbuf, 0); offset += 4 + compressedSize; file.write(intbuf, 4); @@ -286,7 +273,7 @@ void WorldFiles::writeRegion(int x, int y, WorldRegion* entry, path filename){ } } for (size_t i = 0; i < REGION_VOL; i++) { - int2Bytes(offsets[i], (ubyte*)intbuf, 0); + dataio::write_int32_big(offsets[i], (ubyte*)intbuf, 0); file.write(intbuf, 4); } } diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index 341b0acf..d556547c 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -61,7 +61,8 @@ class WorldFiles { bool readOldPlayer(Player* player); // -------------------- - WorldRegion* getRegion(int x, int z); + WorldRegion* getRegion(std::unordered_map& regions, + int x, int z); /* Compress buffer with extrle @param src source buffer @@ -75,8 +76,13 @@ class WorldFiles { @param dstlen max expected length of source buffer */ ubyte* decompress(ubyte* src, size_t srclen, size_t dstlen); + + ubyte* readChunkData(int x, int y, + uint32_t& length, + std::filesystem::path file); public: std::unordered_map regions; + std::unordered_map lights; std::filesystem::path directory; ubyte* compressionBuffer; bool generatorTestMode; @@ -89,9 +95,7 @@ public: bool readWorldInfo(World* world); bool readPlayer(Player* player); - ubyte* readChunkData(int x, int y, - uint32_t& length, - std::filesystem::path file); + void writeRegion(int x, int y, WorldRegion* entry, std::filesystem::path file); diff --git a/src/lighting/Lightmap.cpp b/src/lighting/Lightmap.cpp index fd5cec4e..544d700c 100644 --- a/src/lighting/Lightmap.cpp +++ b/src/lighting/Lightmap.cpp @@ -1,8 +1,11 @@ #include "Lightmap.h" +#include + +#include "../util/data_io.h" Lightmap::Lightmap(){ - map = new unsigned short[CHUNK_VOL]; - for (unsigned int i = 0; i < CHUNK_VOL; i++){ + map = new light_t[CHUNK_VOL]; + for (uint i = 0; i < CHUNK_VOL; i++){ map[i] = 0x0000; } } @@ -16,3 +19,13 @@ void Lightmap::set(const Lightmap* lightmap) { map[i] = lightmap->map[i]; } } + +static_assert(sizeof(light_t) == 2, "replace dataio calls to new light_t"); + +ubyte* Lightmap::encode() const { + ubyte* buffer = new ubyte[CHUNK_VOL * sizeof(light_t)]; + for (uint i = 0; i < CHUNK_VOL; i++) { + dataio::write_int16_big(map[i], buffer, i * sizeof(light_t)); + } + return buffer; +} diff --git a/src/lighting/Lightmap.h b/src/lighting/Lightmap.h index 2e774dc1..c4077807 100644 --- a/src/lighting/Lightmap.h +++ b/src/lighting/Lightmap.h @@ -2,6 +2,7 @@ #define LIGHTING_LIGHTMAP_H_ #include "../constants.h" +#include "../typedefs.h" #include "../voxels/Chunk.h" // Lichtkarte @@ -78,6 +79,8 @@ public: static inline light_t extract(light_t light, ubyte channel) { return (light >> (channel << 2)) & 0xF; } + + ubyte* encode() const; }; #endif /* LIGHTING_LIGHTMAP_H_ */ diff --git a/src/util/data_io.h b/src/util/data_io.h new file mode 100644 index 00000000..634e0cea --- /dev/null +++ b/src/util/data_io.h @@ -0,0 +1,56 @@ +#ifndef UTIL_DATA_IO_H_ +#define UTIL_DATA_IO_H_ + +#include "../typedefs.h" + +namespace dataio { + /* Read big-endian 16 bit signed integer from bytes */ + inline int16_t read_int16_big(const ubyte* src, size_t offset) { + return (src[offset] << 8) | + (src[offset+1]); + } + /* Read big-endian 32 bit signed integer from bytes */ + inline int32_t read_int32_big(const ubyte* src, size_t offset) { + return (src[offset] << 24) | + (src[offset+1] << 16) | + (src[offset+2] << 8) | + (src[offset+3]); + } + /* Read big-endian 64 bit signed integer from bytes */ + inline int64_t read_int64_big(const ubyte* src, size_t offset) { + return (int64_t(src[offset]) << 56) | + (int64_t(src[offset+1]) << 48) | + (int64_t(src[offset+2]) << 40) | + (int64_t(src[offset+3]) << 32) | + (int64_t(src[offset+4]) << 24) | + (int64_t(src[offset+5]) << 16) | + (int64_t(src[offset+6]) << 8) | + (int64_t(src[offset+7])); + } + /* Write big-endian 16 bit signed integer to bytes */ + inline void write_int16_big(int16_t value, ubyte* dest, size_t offset) { + dest[offset] = (char) (value >> 8 & 255); + dest[offset+1] = (char) (value >> 0 & 255); + } + /* Write big-endian 32 bit signed integer to bytes */ + inline void write_int32_big(int32_t value, ubyte* dest, size_t offset) { + dest[offset] = (char) (value >> 24 & 255); + dest[offset+1] = (char) (value >> 16 & 255); + dest[offset+2] = (char) (value >> 8 & 255); + dest[offset+3] = (char) (value >> 0 & 255); + } + /* Write big-endian 64 bit signed integer to bytes */ + inline void write_int64_big(int64_t value, ubyte* dest, size_t offset) { + dest[offset] = (char) (value >> 56 & 255); + dest[offset+1] = (char) (value >> 48 & 255); + dest[offset+2] = (char) (value >> 40 & 255); + dest[offset+3] = (char) (value >> 32 & 255); + + dest[offset+4] = (char) (value >> 24 & 255); + dest[offset+5] = (char) (value >> 16 & 255); + dest[offset+6] = (char) (value >> 8 & 255); + dest[offset+7] = (char) (value >> 0 & 255); + } +} + +#endif // UTIL_DATA_IO_H_ \ No newline at end of file