gzip compress/decompress + refactor
This commit is contained in:
parent
3837cdcf95
commit
b0165b1014
56
src/coders/gzip.cpp
Normal file
56
src/coders/gzip.cpp
Normal 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
12
src/coders/gzip.h
Normal 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_
|
||||
@ -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() {
|
||||
|
||||
@ -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(){
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -49,3 +49,7 @@ void Level::update() {
|
||||
chunks->resize(matrixSize, matrixSize);
|
||||
}
|
||||
}
|
||||
|
||||
World* Level::getWorld() {
|
||||
return world.get();
|
||||
}
|
||||
|
||||
@ -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_ */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user