Skip to content

Commit

Permalink
Compress node data and metadata together.
Browse files Browse the repository at this point in the history
  • Loading branch information
lhofhansl committed Jan 7, 2021
1 parent 6e6d36e commit db12ec6
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 31 deletions.
84 changes: 61 additions & 23 deletions src/mapblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,9 +378,26 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk, int compressio
writeU16(os, m_lighting_complete);
}

/*
Node metadata
*/
std::ostringstream oss(std::ios_base::binary);
m_node_metadata.serialize(oss, version, disk);
std::string metadata = oss.str();

/*
Bulk node data
*/
u8 content_width = 2;
u8 params_width = 2;

u32 node_len = nodecount * (content_width + params_width);
u32 len = node_len;
if (version >= 29)
len += metadata.size();

SharedBuffer<u8> databuf(len);

NameIdMapping nimap;
if(disk)
{
Expand All @@ -389,30 +406,32 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk, int compressio
tmp_nodes[i] = data[i];
getBlockNodeIdMapping(&nimap, tmp_nodes, m_gamedef->ndef());

u8 content_width = 2;
u8 params_width = 2;
writeU8(os, content_width);
writeU8(os, params_width);
MapNode::serializeBulk(os, version, tmp_nodes, nodecount,
content_width, params_width, compression_level);
MapNode::serializeBulk(databuf, version, tmp_nodes, nodecount,
content_width, params_width);
delete[] tmp_nodes;
}
else
{
u8 content_width = 2;
u8 params_width = 2;
writeU8(os, content_width);
writeU8(os, params_width);
MapNode::serializeBulk(os, version, data, nodecount,
content_width, params_width, compression_level);
MapNode::serializeBulk(databuf, version, data, nodecount,
content_width, params_width);
}

/*
Node metadata
*/
std::ostringstream oss(std::ios_base::binary);
m_node_metadata.serialize(oss, version, disk);
compress(oss.str(), os, version, compression_level);
if (version >= 29) {
const char *src = metadata.c_str();
for (u32 i = 0; i < len - node_len; i++) {
databuf[i + node_len] = src[i];
}
}
// compress everything at once
compress(databuf, os, version, compression_level);

if (version < 29)
// prior to 29 metadata was compressed separately
compress(metadata, os, version, compression_level);

/*
Data that goes to disk, but not the network
Expand Down Expand Up @@ -484,7 +503,20 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
throw SerializationError("MapBlock::deSerialize(): invalid content_width");
if(params_width != 2)
throw SerializationError("MapBlock::deSerialize(): invalid params_width");
MapNode::deSerializeBulk(is, version, data, nodecount,

u32 node_len = nodecount * (content_width + params_width);

// decompress
std::ostringstream os(std::ios_base::binary);
decompress(is, os, version);
std::string s = os.str();
if(s.size() < node_len)
throw SerializationError("deSerializeBulkNodes: "
"decompress resulted in invalid size");

const u8 *databuf = reinterpret_cast<const u8*>(s.c_str());

MapNode::deSerializeBulk(databuf, data, nodecount,
content_width, params_width);

/*
Expand All @@ -494,15 +526,21 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
<<": Node metadata"<<std::endl);
// Ignore errors
try {
std::ostringstream oss(std::ios_base::binary);
decompress(is, oss, version);
std::istringstream iss(oss.str(), std::ios_base::binary);
if (version >= 23)
if (version >= 29) {
std::istringstream iss(s.substr(node_len), std::ios_base::binary);
m_node_metadata.deSerialize(iss, m_gamedef->idef());
else
content_nodemeta_deserialize_legacy(iss,
&m_node_metadata, &m_node_timers,
m_gamedef->idef());
} else {
// prior to 29 metadata was compressed separately
std::ostringstream oss(std::ios_base::binary);
decompress(is, oss, version);
std::istringstream iss(oss.str(), std::ios_base::binary);
if (version >= 23)
m_node_metadata.deSerialize(iss, m_gamedef->idef());
else
content_nodemeta_deserialize_legacy(iss,
&m_node_metadata, &m_node_timers,
m_gamedef->idef());
}
} catch(SerializationError &e) {
warningstream<<"MapBlock::deSerialize(): Ignoring an error"
<<" while deserializing node metadata at ("
Expand Down
29 changes: 21 additions & 8 deletions src/mapnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,19 @@ void MapNode::deSerialize(u8 *source, u8 version)
void MapNode::serializeBulk(std::ostream &os, int version,
const MapNode *nodes, u32 nodecount,
u8 content_width, u8 params_width, int compression_level)
{
SharedBuffer<u8> databuf(nodecount * (content_width + params_width));

serializeBulk(databuf, version, nodes, nodecount, content_width, params_width);
/*
Compress data to output stream
*/
compress(databuf, os, version, compression_level);
}

void MapNode::serializeBulk(SharedBuffer<u8> & databuf, int version,
const MapNode *nodes, u32 nodecount,
u8 content_width, u8 params_width)
{
if (!ser_ver_supported(version))
throw VersionMismatchException("ERROR: MapNode format not supported");
Expand All @@ -720,8 +733,6 @@ void MapNode::serializeBulk(std::ostream &os, int version,
throw SerializationError("MapNode::serializeBulk: serialization to "
"version < 24 not possible");

SharedBuffer<u8> databuf(nodecount * (content_width + params_width));

u32 start1 = content_width * nodecount;
u32 start2 = (content_width + 1) * nodecount;

Expand All @@ -731,12 +742,6 @@ void MapNode::serializeBulk(std::ostream &os, int version,
writeU8(&databuf[start1 + i], nodes[i].param1);
writeU8(&databuf[start2 + i], nodes[i].param2);
}

/*
Compress data to output stream
*/

compress(databuf, os, version, compression_level);
}

// Deserialize bulk node data
Expand All @@ -760,8 +765,16 @@ void MapNode::deSerializeBulk(std::istream &is, int version,
if(s.size() != len)
throw SerializationError("deSerializeBulkNodes: "
"decompress resulted in invalid size");

const u8 *databuf = reinterpret_cast<const u8*>(s.c_str());
deSerializeBulk(databuf, nodes, nodecount, content_width, params_width);
}

// Deserialize bulk node data
void MapNode::deSerializeBulk(const u8 *databuf,
MapNode *nodes, u32 nodecount,
u8 content_width, u8 params_width)
{
// Deserialize content
if(content_width == 1)
{
Expand Down
7 changes: 7 additions & 0 deletions src/mapnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#include "irrlichttypes_bloated.h"
#include "light.h"
#include "util/pointer.h"
#include <string>
#include <vector>

Expand Down Expand Up @@ -293,9 +294,15 @@ struct MapNode
static void serializeBulk(std::ostream &os, int version,
const MapNode *nodes, u32 nodecount,
u8 content_width, u8 params_width, int compression_level);
static void serializeBulk(SharedBuffer<u8> & databuf, int version,
const MapNode *nodes, u32 nodecount,
u8 content_width, u8 params_width);
static void deSerializeBulk(std::istream &is, int version,
MapNode *nodes, u32 nodecount,
u8 content_width, u8 params_width);
static void deSerializeBulk(const u8 *databuf,
MapNode *nodes, u32 nodecount,
u8 content_width, u8 params_width);

private:
// Deprecated serialization methods
Expand Down

0 comments on commit db12ec6

Please sign in to comment.