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() {
std::cout << "-- writing world" << std::endl;
World* world = level->world;
auto world = level->getWorld();
world->write(level.get());
delete world;
}
void LevelScreen::updateHotkeys() {

View File

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

View File

@ -18,11 +18,6 @@ struct voxel;
class Lightmap;
class ContentLUT;
struct RenderData {
float* vertices;
size_t size;
};
class Chunk {
public:
int x, z;
@ -31,7 +26,6 @@ public:
Lightmap* lightmap;
int flags = 0;
int surrounding = 0;
RenderData renderData;
Chunk(int x, int z);
~Chunk();
@ -44,7 +38,7 @@ public:
// flags getters/setters below
void SETFLAGS(int mask, bool value){
inline void setFlags(int mask, bool value){
if (value)
flags |= mask;
else
@ -63,17 +57,17 @@ public:
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;
bool decode(ubyte* data);

View File

@ -16,10 +16,6 @@
#include <math.h>
#include <limits.h>
using glm::vec3;
using glm::ivec3;
using std::shared_ptr;
Chunks::Chunks(int w, int d,
int ox, int oz,
WorldFiles* wfile,
@ -27,25 +23,16 @@ Chunks::Chunks(int w, int d,
const Content* content)
: content(content),
contentIds(content->indices),
chunks(w*d),
chunksSecond(w*d),
w(w), d(d), ox(ox), oz(oz),
worldFiles(wfile),
events(events) {
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;
}
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){
@ -56,7 +43,7 @@ voxel* Chunks::get(int x, int y, int z){
int cz = floordiv(z, CHUNK_D);
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
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)
return nullptr;
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);
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return 0;
shared_ptr<Chunk> chunk = chunks[(cy * d + cz) * w + cx];
auto chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr)
return 0;
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);
if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d)
return 0;
shared_ptr<Chunk> chunk = chunks[(cy * d + cz) * w + cx];
auto chunk = chunks[(cy * d + cz) * w + cx];
if (chunk == nullptr)
return 0;
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);
}
voxel* Chunks::rayCast(vec3 start,
vec3 dir,
voxel* Chunks::rayCast(glm::vec3 start,
glm::vec3 dir,
float maxDist,
vec3& end,
ivec3& norm,
ivec3& iend) {
glm::vec3& end,
glm::ivec3& norm,
glm::ivec3& iend) {
float px = start.x;
float py = start.y;
float pz = start.z;
@ -256,7 +243,7 @@ voxel* Chunks::rayCast(vec3 start,
scalar_t distance;
Ray ray(start, dir);
if (ray.intersectAABB(iend, box, maxDist, norm, distance) > RayRelation::None){
end = start + (dir * vec3(distance));
end = start + (dir * glm::vec3(distance));
return voxel;
}
@ -309,7 +296,7 @@ voxel* Chunks::rayCast(vec3 start,
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 py = start.y;
float pz = start.z;
@ -343,7 +330,7 @@ vec3 Chunks::rayCastToObstacle(vec3 start, vec3 dir, float maxDist) {
while (t <= maxDist) {
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);
if (def->obstacle) {
@ -352,15 +339,15 @@ vec3 Chunks::rayCastToObstacle(vec3 start, vec3 dir, float maxDist) {
? def->rt.hitboxes[voxel->rotation()]
: def->hitbox;
scalar_t distance;
ivec3 norm;
glm::ivec3 norm;
Ray ray(start, dir);
// norm is dummy now, can be inefficient
if (ray.intersectAABB(ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) {
return start + (dir * vec3(distance));
if (ray.intersectAABB(glm::ivec3(ix, iy, iz), box, maxDist, norm, distance) > RayRelation::None) {
return start + (dir * glm::vec3(distance));
}
}
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) {
@ -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 x = 0; x < w; x++){
shared_ptr<Chunk> chunk = chunks[z * w + x];
auto chunk = chunks[z * w + x];
int nx = x - dx;
int nz = z - dz;
if (chunk == nullptr)
@ -443,20 +430,18 @@ void Chunks::resize(int newW, int newD) {
translate(0, delta);
}
const int newVolume = newW * newD;
auto newChunks = new shared_ptr<Chunk>[newVolume] {};
auto newChunksSecond = new shared_ptr<Chunk>[newVolume] {};
std::vector<std::shared_ptr<Chunk>> newChunks(newVolume);
std::vector<std::shared_ptr<Chunk>> newChunksSecond(newVolume);
for (int z = 0; z < d && z < newD; z++) {
for (int x = 0; x < w && x < newW; x++) {
newChunks[z * newW + x] = chunks[z * w + x];
}
}
delete[] chunks;
delete[] chunksSecond;
w = newW;
d = newD;
volume = newVolume;
chunks = newChunks;
chunksSecond = newChunksSecond;
w = newW;
d = newD;
volume = newVolume;
chunks = std::move(newChunks);
chunksSecond = std::move(newChunksSecond);
}
void Chunks::_setOffset(int x, int z){
@ -464,7 +449,7 @@ void Chunks::_setOffset(int x, int z){
oz = z;
}
bool Chunks::putChunk(shared_ptr<Chunk> chunk) {
bool Chunks::putChunk(std::shared_ptr<Chunk> chunk) {
int x = chunk->x;
int z = chunk->z;
x -= ox;

View File

@ -21,8 +21,8 @@ class Chunks {
const Content* const content;
const ContentIndices* const contentIds;
public:
std::shared_ptr<Chunk>* chunks;
std::shared_ptr<Chunk>* chunksSecond;
std::vector<std::shared_ptr<Chunk>> chunks;
std::vector<std::shared_ptr<Chunk>> chunksSecond;
size_t volume;
size_t chunksCount;
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++) {
blockid_t id = chunk->voxels[i].id;
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) {
World* world = level->world;
World* world = level->getWorld();
WorldFiles* wfile = world->wfile;
auto chunk = std::make_shared<Chunk>(x, z);
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) {
chunk->decode(data.get());
chunk->setLoaded(true);
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) {
chunk->lightmap->set(lights);
chunk->setLoadedLights(true);

View File

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

View File

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