gzip compress/decompress + refactor

This commit is contained in:
MihailRis 2024-01-17 00:52:55 +03:00
parent 3837cdcf95
commit b0165b1014
10 changed files with 119 additions and 65 deletions

56
src/coders/gzip.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "gzip.h"
#define ZLIB_CONST
#include <zlib.h>
#include <math.h>
#include <memory>
#include "byte_utils.h"
std::vector<ubyte> gzip::compress(const ubyte* src, size_t size) {
size_t buffer_size = 23+size*1.01;
std::vector<ubyte> buffer;
buffer.resize(buffer_size);
// zlib struct
z_stream defstream {};
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = size;
defstream.next_in = src;
defstream.avail_out = buffer_size;
defstream.next_out = buffer.data();
// compression
deflateInit2(&defstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
16 + MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
deflate(&defstream, Z_FINISH);
deflateEnd(&defstream);
size_t compressed_size = defstream.next_out - buffer.data();
buffer.resize(compressed_size);
return buffer;
}
std::vector<ubyte> gzip::decompress(const ubyte* src, size_t size) {
// getting uncompressed data length from gzip footer
size_t decompressed_size = *(uint32_t*)(src+size-4);
std::vector<ubyte> buffer;
buffer.resize(decompressed_size);
// zlib struct
z_stream infstream;
infstream.zalloc = Z_NULL;
infstream.zfree = Z_NULL;
infstream.opaque = Z_NULL;
infstream.avail_in = size;
infstream.next_in = src;
infstream.avail_out = decompressed_size;
infstream.next_out = buffer.data();
inflateInit2(&infstream, 16+MAX_WBITS);
inflate(&infstream, Z_NO_FLUSH);
inflateEnd(&infstream);
return buffer;
}

12
src/coders/gzip.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef CODERS_GZIP_H_
#define CODERS_GZIP_H_
#include <vector>
#include "../typedefs.h"
namespace gzip {
std::vector<ubyte> compress(const ubyte* src, size_t size);
std::vector<ubyte> decompress(const ubyte* src, size_t size);
}
#endif // CODERS_GZIP_H_

View File

@ -96,9 +96,8 @@ LevelScreen::LevelScreen(Engine* engine, Level* level)
LevelScreen::~LevelScreen() { LevelScreen::~LevelScreen() {
std::cout << "-- writing world" << std::endl; std::cout << "-- writing world" << std::endl;
World* world = level->world; auto world = level->getWorld();
world->write(level.get()); world->write(level.get());
delete world;
} }
void LevelScreen::updateHotkeys() { void LevelScreen::updateHotkeys() {

View File

@ -15,7 +15,6 @@ Chunk::Chunk(int xpos, int zpos) : x(xpos), z(zpos){
voxels[i].states = 0; voxels[i].states = 0;
} }
lightmap = new Lightmap(); lightmap = new Lightmap();
renderData.vertices = nullptr;
} }
Chunk::~Chunk(){ Chunk::~Chunk(){

View File

@ -18,11 +18,6 @@ struct voxel;
class Lightmap; class Lightmap;
class ContentLUT; class ContentLUT;
struct RenderData {
float* vertices;
size_t size;
};
class Chunk { class Chunk {
public: public:
int x, z; int x, z;
@ -31,7 +26,6 @@ public:
Lightmap* lightmap; Lightmap* lightmap;
int flags = 0; int flags = 0;
int surrounding = 0; int surrounding = 0;
RenderData renderData;
Chunk(int x, int z); Chunk(int x, int z);
~Chunk(); ~Chunk();
@ -44,7 +38,7 @@ public:
// flags getters/setters below // flags getters/setters below
void SETFLAGS(int mask, bool value){ inline void setFlags(int mask, bool value){
if (value) if (value)
flags |= mask; flags |= mask;
else else
@ -63,17 +57,17 @@ public:
inline bool isReady() const {return flags & ChunkFlag::READY;} inline bool isReady() const {return flags & ChunkFlag::READY;}
inline void setUnsaved(bool newState) {SETFLAGS(ChunkFlag::UNSAVED, newState);} inline void setUnsaved(bool newState) {setFlags(ChunkFlag::UNSAVED, newState);}
inline void setModified(bool newState) {SETFLAGS(ChunkFlag::MODIFIED, newState);} inline void setModified(bool newState) {setFlags(ChunkFlag::MODIFIED, newState);}
inline void setLoaded(bool newState) {SETFLAGS(ChunkFlag::LOADED, newState);} inline void setLoaded(bool newState) {setFlags(ChunkFlag::LOADED, newState);}
inline void setLoadedLights(bool newState) {SETFLAGS(ChunkFlag::LOADED_LIGHTS, newState);} inline void setLoadedLights(bool newState) {setFlags(ChunkFlag::LOADED_LIGHTS, newState);}
inline void setLighted(bool newState) {SETFLAGS(ChunkFlag::LIGHTED, newState);} inline void setLighted(bool newState) {setFlags(ChunkFlag::LIGHTED, newState);}
inline void setReady(bool newState) {SETFLAGS(ChunkFlag::READY, newState);} inline void setReady(bool newState) {setFlags(ChunkFlag::READY, newState);}
ubyte* encode() const; ubyte* encode() const;
bool decode(ubyte* data); bool decode(ubyte* data);

View File

@ -16,10 +16,6 @@
#include <math.h> #include <math.h>
#include <limits.h> #include <limits.h>
using glm::vec3;
using glm::ivec3;
using std::shared_ptr;
Chunks::Chunks(int w, int d, Chunks::Chunks(int w, int d,
int ox, int oz, int ox, int oz,
WorldFiles* wfile, WorldFiles* wfile,
@ -27,25 +23,16 @@ Chunks::Chunks(int w, int d,
const Content* content) const Content* content)
: content(content), : content(content),
contentIds(content->indices), contentIds(content->indices),
chunks(w*d),
chunksSecond(w*d),
w(w), d(d), ox(ox), oz(oz), w(w), d(d), ox(ox), oz(oz),
worldFiles(wfile), worldFiles(wfile),
events(events) { events(events) {
volume = (size_t)w*(size_t)d; volume = (size_t)w*(size_t)d;
chunks = new shared_ptr<Chunk>[volume];
chunksSecond = new shared_ptr<Chunk>[volume];
for (size_t i = 0; i < volume; i++){
chunks[i] = nullptr;
}
chunksCount = 0; chunksCount = 0;
} }
Chunks::~Chunks(){ Chunks::~Chunks(){
for (size_t i = 0; i < volume; i++){
chunks[i] = nullptr;
}
delete[] chunks;
delete[] chunksSecond;
} }
voxel* Chunks::get(int x, int y, int z){ voxel* Chunks::get(int x, int y, int z){
@ -56,7 +43,7 @@ voxel* Chunks::get(int x, int y, int z){
int cz = floordiv(z, CHUNK_D); int cz = floordiv(z, CHUNK_D);
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return nullptr; return nullptr;
shared_ptr<Chunk> chunk = chunks[cz * w + cx]; // chunks is 2D-array std::shared_ptr<Chunk> chunk = chunks[cz * w + cx];
if (chunk == nullptr) if (chunk == nullptr)
return nullptr; return nullptr;
int lx = x - cx * CHUNK_W; int lx = x - cx * CHUNK_W;
@ -117,7 +104,7 @@ ubyte Chunks::getLight(int x, int y, int z, int channel){
int cz = floordiv(z, CHUNK_D); int cz = floordiv(z, CHUNK_D);
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return 0; return 0;
shared_ptr<Chunk> chunk = chunks[(cy * d + cz) * w + cx]; auto chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr) if (chunk == nullptr)
return 0; return 0;
int lx = x - cx * CHUNK_W; int lx = x - cx * CHUNK_W;
@ -134,7 +121,7 @@ light_t Chunks::getLight(int x, int y, int z){
int cz = floordiv(z, CHUNK_D); int cz = floordiv(z, CHUNK_D);
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return 0; return 0;
shared_ptr<Chunk> chunk = chunks[(cy * d + cz) * w + cx]; auto chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr) if (chunk == nullptr)
return 0; return 0;
int lx = x - cx * CHUNK_W; int lx = x - cx * CHUNK_W;
@ -197,12 +184,12 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){
chunk->setModified(true); chunk->setModified(true);
} }
voxel* Chunks::rayCast(vec3 start, voxel* Chunks::rayCast(glm::vec3 start,
vec3 dir, glm::vec3 dir,
float maxDist, float maxDist,
vec3& end, glm::vec3& end,
ivec3& norm, glm::ivec3& norm,
ivec3& iend) { glm::ivec3& iend) {
float px = start.x; float px = start.x;
float py = start.y; float py = start.y;
float pz = start.z; float pz = start.z;
@ -256,7 +243,7 @@ voxel* Chunks::rayCast(vec3 start,
scalar_t distance; scalar_t distance;
Ray ray(start, dir); Ray ray(start, dir);
if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None){ if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None){
end = start + (dir * vec3(distance)); end = start + (dir * glm::vec3(distance));
return voxel; return voxel;
} }
@ -309,7 +296,7 @@ voxel* Chunks::rayCast(vec3 start,
return nullptr; return nullptr;
} }
vec3 Chunks::rayCastToObstacle(vec3 start, vec3 dir, float maxDist) { glm::vec3 Chunks::rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist) {
float px = start.x; float px = start.x;
float py = start.y; float py = start.y;
float pz = start.z; float pz = start.z;
@ -343,7 +330,7 @@ vec3 Chunks::rayCastToObstacle(vec3 start, vec3 dir, float maxDist) {
while (t <= maxDist) { while (t <= maxDist) {
voxel* voxel = get(ix, iy, iz); voxel* voxel = get(ix, iy, iz);
if (voxel == nullptr) { return vec3(px + t * dx, py + t * dy, pz + t * dz); } if (voxel == nullptr) { return glm::vec3(px + t * dx, py + t * dy, pz + t * dz); }
const Block* def = contentIds->getBlockDef(voxel->id); const Block* def = contentIds->getBlockDef(voxel->id);
if (def->obstacle) { if (def->obstacle) {
@ -352,15 +339,15 @@ vec3 Chunks::rayCastToObstacle(vec3 start, vec3 dir, float maxDist) {
? def->rt.hitboxes[voxel->rotation()] ? def->rt.hitboxes[voxel->rotation()]
: def->hitbox; : def->hitbox;
scalar_t distance; scalar_t distance;
ivec3 norm; glm::ivec3 norm;
Ray ray(start, dir); Ray ray(start, dir);
// norm is dummy now, can be inefficient // norm is dummy now, can be inefficient
if (ray.intersectAABB(ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) { if (ray.intersectAABB(glm::ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) {
return start + (dir * vec3(distance)); return start + (dir * glm::vec3(distance));
} }
} }
else { else {
return vec3(px + t * dx, py + t * dy, pz + t * dz); return glm::vec3(px + t * dx, py + t * dy, pz + t * dz);
} }
} }
if (txMax < tyMax) { if (txMax < tyMax) {
@ -388,7 +375,7 @@ vec3 Chunks::rayCastToObstacle(vec3 start, vec3 dir, float maxDist) {
} }
} }
} }
return vec3(px + maxDist * dx, py + maxDist * dy, pz + maxDist * dz); return glm::vec3(px + maxDist * dx, py + maxDist * dy, pz + maxDist * dz);
} }
@ -408,7 +395,7 @@ void Chunks::translate(int dx, int dz){
} }
for (int z = 0; z < d; z++){ for (int z = 0; z < d; z++){
for (int x = 0; x < w; x++){ for (int x = 0; x < w; x++){
shared_ptr<Chunk> chunk = chunks[z * w + x]; auto chunk = chunks[z * w + x];
int nx = x - dx; int nx = x - dx;
int nz = z - dz; int nz = z - dz;
if (chunk == nullptr) if (chunk == nullptr)
@ -443,20 +430,18 @@ void Chunks::resize(int newW, int newD) {
translate(0, delta); translate(0, delta);
} }
const int newVolume = newW * newD; const int newVolume = newW * newD;
auto newChunks = new shared_ptr<Chunk>[newVolume] {}; std::vector<std::shared_ptr<Chunk>> newChunks(newVolume);
auto newChunksSecond = new shared_ptr<Chunk>[newVolume] {}; std::vector<std::shared_ptr<Chunk>> newChunksSecond(newVolume);
for (int z = 0; z < d && z < newD; z++) { for (int z = 0; z < d && z < newD; z++) {
for (int x = 0; x < w && x < newW; x++) { for (int x = 0; x < w && x < newW; x++) {
newChunks[z * newW + x] = chunks[z * w + x]; newChunks[z * newW + x] = chunks[z * w + x];
} }
} }
delete[] chunks;
delete[] chunksSecond;
w = newW; w = newW;
d = newD; d = newD;
volume = newVolume; volume = newVolume;
chunks = newChunks; chunks = std::move(newChunks);
chunksSecond = newChunksSecond; chunksSecond = std::move(newChunksSecond);
} }
void Chunks::_setOffset(int x, int z){ void Chunks::_setOffset(int x, int z){
@ -464,7 +449,7 @@ void Chunks::_setOffset(int x, int z){
oz = z; oz = z;
} }
bool Chunks::putChunk(shared_ptr<Chunk> chunk) { bool Chunks::putChunk(std::shared_ptr<Chunk> chunk) {
int x = chunk->x; int x = chunk->x;
int z = chunk->z; int z = chunk->z;
x -= ox; x -= ox;

View File

@ -21,8 +21,8 @@ class Chunks {
const Content* const content; const Content* const content;
const ContentIndices* const contentIds; const ContentIndices* const contentIds;
public: public:
std::shared_ptr<Chunk>* chunks; std::vector<std::shared_ptr<Chunk>> chunks;
std::shared_ptr<Chunk>* chunksSecond; std::vector<std::shared_ptr<Chunk>> chunksSecond;
size_t volume; size_t volume;
size_t chunksCount; size_t chunksCount;
size_t visible; size_t visible;

View File

@ -39,7 +39,7 @@ void ChunksStorage::remove(int x, int z) {
} }
} }
void verifyLoadedChunk(ContentIndices* indices, Chunk* chunk) { static void verifyLoadedChunk(ContentIndices* indices, Chunk* chunk) {
for (size_t i = 0; i < CHUNK_VOL; i++) { for (size_t i = 0; i < CHUNK_VOL; i++) {
blockid_t id = chunk->voxels[i].id; blockid_t id = chunk->voxels[i].id;
if (indices->getBlockDef(id) == nullptr) { if (indices->getBlockDef(id) == nullptr) {
@ -52,18 +52,19 @@ void verifyLoadedChunk(ContentIndices* indices, Chunk* chunk) {
} }
std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) { std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
World* world = level->world; World* world = level->getWorld();
WorldFiles* wfile = world->wfile;
auto chunk = std::make_shared<Chunk>(x, z); auto chunk = std::make_shared<Chunk>(x, z);
store(chunk); store(chunk);
std::unique_ptr<ubyte[]> data(world->wfile->getChunk(chunk->x, chunk->z)); std::unique_ptr<ubyte[]> data(wfile->getChunk(chunk->x, chunk->z));
if (data) { if (data) {
chunk->decode(data.get()); chunk->decode(data.get());
chunk->setLoaded(true); chunk->setLoaded(true);
verifyLoadedChunk(level->content->indices, chunk.get()); verifyLoadedChunk(level->content->indices, chunk.get());
} }
light_t* lights = world->wfile->getLights(chunk->x, chunk->z); light_t* lights = wfile->getLights(chunk->x, chunk->z);
if (lights) { if (lights) {
chunk->lightmap->set(lights); chunk->lightmap->set(lights);
chunk->setLoadedLights(true); chunk->setLoadedLights(true);

View File

@ -49,3 +49,7 @@ void Level::update() {
chunks->resize(matrixSize, matrixSize); chunks->resize(matrixSize, matrixSize);
} }
} }
World* Level::getWorld() {
return world.get();
}

View File

@ -1,6 +1,8 @@
#ifndef WORLD_LEVEL_H_ #ifndef WORLD_LEVEL_H_
#define WORLD_LEVEL_H_ #define WORLD_LEVEL_H_
#include <memory>
#include "../typedefs.h" #include "../typedefs.h"
#include "../settings.h" #include "../settings.h"
@ -15,7 +17,7 @@ class ChunksStorage;
class Level { class Level {
public: public:
World* world; std::unique_ptr<World> world;
const Content* const content; const Content* const content;
Player* player; Player* player;
Chunks* chunks; Chunks* chunks;
@ -34,6 +36,8 @@ public:
~Level(); ~Level();
void update(); void update();
World* getWorld();
}; };
#endif /* WORLD_LEVEL_H_ */ #endif /* WORLD_LEVEL_H_ */