Fix map deserialization and remove old serialization code
authorPerttu Ahola <celeron55@gmail.com>
Mon, 23 Jul 2012 04:20:13 +0000 (07:20 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 23 Jul 2012 05:18:39 +0000 (08:18 +0300)
src/clientserver.h
src/content_mapnode.cpp
src/content_mapnode.h
src/mapblock.cpp
src/mapblock.h
src/mapnode.cpp
src/mapnode.h
src/nodedef.cpp
src/serialization.h

index 5214068441947b34306275fb4c89f36bb8e9109d..d432209627e46fe42ca8a1e509ab8388c07b9e3b 100644 (file)
@@ -61,10 +61,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
                (some dev snapshot)
                TOCLIENT_INVENTORY_FORMSPEC
                (0.4.0, 0.4.1)
+       PROTOCOL_VERSION 12:
                TOSERVER_INVENTORY_FIELDS
+               16-bit node ids
 */
 
-#define PROTOCOL_VERSION 11
+#define PROTOCOL_VERSION 12
 
 #define PROTOCOL_ID 0x4f457403
 
index 410aaa911b7e0ffc05357a33f607a4bf27e434f8..c3fdb4a42f91b6e8b7672df1d6341cb5e59688de 100644 (file)
@@ -102,23 +102,6 @@ content_t trans_table_19[21][2] = {
        {CONTENT_BOOKSHELF, 29},
 };
 
-MapNode mapnode_translate_from_internal(MapNode n_from, u8 version)
-{
-       MapNode result = n_from;
-       if(version <= 19)
-       {
-               content_t c_from = n_from.getContent();
-               for(u32 i=0; i<sizeof(trans_table_19)/sizeof(trans_table_19[0]); i++)
-               {
-                       if(trans_table_19[i][0] == c_from)
-                       {
-                               result.setContent(trans_table_19[i][1]);
-                               break;
-                       }
-               }
-       }
-       return result;
-}
 MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
 {
        MapNode result = n_from;
index cc11cd2241dba8f76e84a9ec561244f73a418262..45c2b0763db5b1beac0f8c10252ce36cb89b98d0 100644 (file)
@@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 // Backwards compatibility for non-extended content types in v19
 extern content_t trans_table_19[21][2];
-MapNode mapnode_translate_from_internal(MapNode n_from, u8 version);
 MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
 
 // Get legacy node name mapping for loading old blocks
index 571c2082d672474995b1ad2b4a195e14f96f7476..c7c820d42e7cfc6fa80ab0e00767f7c8c53857b3 100644 (file)
@@ -552,12 +552,12 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
                throw SerializationError("ERROR: Not writing dummy block.");
        }
        
-       if(version <= 21)
-       {
-               serialize_pre22(os, version, disk);
-               return;
-       }
-
+       // Can't do this anymore; we have 16-bit dynamically allocated node IDs
+       // in memory; conversion just won't work in this direction.
+       if(version < 24)
+               throw SerializationError("MapBlock::serialize: serialization to "
+                               "version < 24 not possible");
+               
        // First byte
        u8 flags = 0;
        if(is_underground)
@@ -582,7 +582,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
                        tmp_nodes[i] = data[i];
                getBlockNodeIdMapping(&nimap, tmp_nodes, m_gamedef->ndef());
 
-               u8 content_width = (version < 24) ? 1 : 2;
+               u8 content_width = 2;
                u8 params_width = 2;
                writeU8(os, content_width);
                writeU8(os, params_width);
@@ -604,10 +604,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
                Node metadata
        */
        std::ostringstream oss(std::ios_base::binary);
-       if(version >= 23)
-               m_node_metadata.serialize(oss);
-       else
-               content_nodemeta_serialize_legacy(oss, &m_node_metadata);
+       m_node_metadata.serialize(oss);
        compressZlib(oss.str(), os);
 
        /*
@@ -615,13 +612,8 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
        */
        if(disk)
        {
-               // Version 23 doesn't actually contain node timers
-               // (this field should have not been added)
-               if(version == 23)
-                       writeU8(os, 0);
-               // Node timers are in version 24
-               if(version >= 24)
-                       m_node_timers.serialize(os);
+               // Node timers
+               m_node_timers.serialize(os);
 
                // Static objects
                m_static_objects.serialize(os);
@@ -634,7 +626,6 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
        }
 }
 
-
 void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
 {
        if(!ser_ver_supported(version))
@@ -738,219 +729,6 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
        Legacy serialization
 */
 
-// List relevant id-name pairs for ids in the block using nodedef
-// Before serialization version 22
-static void getBlockNodeIdMapping_pre22(NameIdMapping *nimap, MapNode *nodes,
-               INodeDefManager *nodedef)
-{
-       std::set<content_t> unknown_contents;
-       for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
-       {
-               content_t id = nodes[i].getContent();
-               const ContentFeatures &f = nodedef->get(id);
-               const std::string &name = f.name;
-               if(name == "")
-                       unknown_contents.insert(id);
-               else
-                       nimap->set(id, name);
-       }
-       for(std::set<content_t>::const_iterator
-                       i = unknown_contents.begin();
-                       i != unknown_contents.end(); i++){
-               errorstream<<"getBlockNodeIdMapping_pre22(): IGNORING ERROR: "
-                               <<"Name for node id "<<(*i)<<" not known"<<std::endl;
-       }
-}
-void MapBlock::serialize_pre22(std::ostream &os, u8 version, bool disk)
-{
-       u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
-
-       MapNode *tmp_data = new MapNode[nodecount];
-       
-       // Legacy data changes
-       // This code has to change from post-22 to pre-22 format.
-       INodeDefManager *nodedef = m_gamedef->ndef();
-       for(u32 i=0; i<nodecount; i++)
-       {
-               const ContentFeatures &f = nodedef->get(tmp_data[i].getContent());
-               // Mineral
-               if(nodedef->getId("default:stone_with_coal") == tmp_data[i].getContent())
-               {
-                       tmp_data[i].setContent(nodedef->getId("default:stone"));
-                       tmp_data[i].setParam1(1);  // MINERAL_COAL
-               }
-               else if(nodedef->getId("default:stone_with_iron") == tmp_data[i].getContent())
-               {
-                       tmp_data[i].setContent(nodedef->getId("default:stone"));
-                       tmp_data[i].setParam1(2);  // MINERAL_IRON
-               }
-               // facedir_simple
-               if(f.legacy_facedir_simple)
-               {
-                       tmp_data[i].setParam1(tmp_data[i].getParam2());
-                       tmp_data[i].setParam2(0);
-               }
-               // wall_mounted
-               if(f.legacy_wallmounted)
-               {
-                       u8 wallmounted_new_to_old[8] = {0x04, 0x08, 0x01, 0x02, 0x10, 0x20, 0, 0};
-                       u8 dir_new_format = tmp_data[i].getParam2() & 7; // lowest 3 bits
-                       u8 dir_old_format = wallmounted_new_to_old[dir_new_format];
-                       tmp_data[i].setParam2(dir_old_format);
-               }
-       }
-
-       // Serialize nodes
-       u32 ser_length = MapNode::serializedLength(version);
-       SharedBuffer<u8> databuf_nodelist(nodecount * ser_length);
-       for(u32 i=0; i<nodecount; i++)
-       {
-               tmp_data[i].serialize(&databuf_nodelist[i*ser_length], version);
-       }
-
-       delete[] tmp_data;
-               
-       // These have no compression
-       if(version <= 3 || version == 5 || version == 6)
-       {
-               writeU8(os, is_underground);
-               os.write((char*)*databuf_nodelist, databuf_nodelist.getSize());
-       }
-       else if(version <= 10)
-       {
-               /*
-                       With compression.
-                       Compress the materials and the params separately.
-               */
-               
-               // First byte
-               writeU8(os, is_underground);
-
-               // Get and compress materials
-               SharedBuffer<u8> materialdata(nodecount);
-               for(u32 i=0; i<nodecount; i++)
-               {
-                       materialdata[i] = databuf_nodelist[i*ser_length];
-               }
-               compress(materialdata, os, version);
-
-               // Get and compress lights
-               SharedBuffer<u8> lightdata(nodecount);
-               for(u32 i=0; i<nodecount; i++)
-               {
-                       lightdata[i] = databuf_nodelist[i*ser_length+1];
-               }
-               compress(lightdata, os, version);
-               
-               if(version >= 10)
-               {
-                       // Get and compress param2
-                       SharedBuffer<u8> param2data(nodecount);
-                       for(u32 i=0; i<nodecount; i++)
-                       {
-                               param2data[i] = databuf_nodelist[i*ser_length+2];
-                       }
-                       compress(param2data, os, version);
-               }
-       }
-       // All other versions (newest)
-       else
-       {
-               // First byte
-               u8 flags = 0;
-               if(is_underground)
-                       flags |= 0x01;
-               if(getDayNightDiff())
-                       flags |= 0x02;
-               if(m_lighting_expired)
-                       flags |= 0x04;
-               if(version >= 18)
-               {
-                       if(m_generated == false)
-                               flags |= 0x08;
-               }
-               writeU8(os, flags);
-               
-               /*
-                       Get data
-               */
-
-               // Create buffer with different parameters sorted
-               SharedBuffer<u8> databuf(nodecount*3);
-               for(u32 i=0; i<nodecount; i++)
-               {
-                       databuf[i] = databuf_nodelist[i*ser_length];
-                       databuf[i+nodecount] = databuf_nodelist[i*ser_length+1];
-                       databuf[i+nodecount*2] = databuf_nodelist[i*ser_length+2];
-               }
-
-               /*
-                       Compress data to output stream
-               */
-
-               compress(databuf, os, version);
-               
-               /*
-                       NodeMetadata
-               */
-               if(version >= 14)
-               {
-                       if(version <= 15)
-                       {
-                               try{
-                                       std::ostringstream oss(std::ios_base::binary);
-                                       content_nodemeta_serialize_legacy(oss, &m_node_metadata);
-                                       os<<serializeString(oss.str());
-                               }
-                               // This will happen if the string is longer than 65535
-                               catch(SerializationError &e)
-                               {
-                                       // Use an empty string
-                                       os<<serializeString("");
-                               }
-                       }
-                       else
-                       {
-                               std::ostringstream oss(std::ios_base::binary);
-                               content_nodemeta_serialize_legacy(oss, &m_node_metadata);
-                               compressZlib(oss.str(), os);
-                               //os<<serializeLongString(oss.str());
-                       }
-               }
-       }
-
-
-       if(disk)
-       {
-               // Versions up from 9 have block objects. (DEPRECATED)
-               if(version >= 9)
-               {
-                       // count=0
-                       writeU16(os, 0);
-               }
-
-               // Versions up from 15 have static objects.
-               if(version >= 15)
-               {
-                       m_static_objects.serialize(os);
-               }
-
-               // Timestamp
-               if(version >= 17)
-               {
-                       writeU32(os, getTimestamp());
-               }
-
-               // Scan and write node definition id mapping
-               if(version >= 21)
-               {
-                       NameIdMapping nimap;
-                       getBlockNodeIdMapping_pre22(&nimap, data, m_gamedef->ndef());
-                       nimap.serialize(os);
-               }
-       }
-}
-
 void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
 {
        u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
index adb3324f6e6f5ec06f789ad4a14974b7444a0101..7f901e5d35ec24ca48663f6556e7021310383c4e 100644 (file)
@@ -467,7 +467,6 @@ private:
                Private methods
        */
 
-       void serialize_pre22(std::ostream &os, u8 version, bool disk);
        void deSerialize_pre22(std::istream &is, u8 version, bool disk);
 
        /*
index 0479d2e55e9e00a3f670c507c1ea8e7c9c055f1f..c616e011755a2adaa4b26d603cbedae38f76d70d 100644 (file)
@@ -241,28 +241,16 @@ void MapNode::serialize(u8 *dest, u8 version)
 {
        if(!ser_ver_supported(version))
                throw VersionMismatchException("ERROR: MapNode format not supported");
-
-       if(version <= 21)
-       {
-               serialize_pre22(dest, version);
-               return;
-       }
-
-       if(version >= 24){
-               writeU16(dest+0, param0);
-               writeU8(dest+2, param1);
-               writeU8(dest+3, param2);
-       }
-       else{
-               writeU8(dest+0, (param0&0xFF));
-               writeU8(dest+1, param1);
-               if (param0 > 0x7F){
-                       writeU8(dest+2, ((param2&0x0F) | ((param0&0x0F00)>>4)));
-               }
-               else{
-                       writeU8(dest+2, param2);
-               }
-       }
+       
+       // Can't do this anymore; we have 16-bit dynamically allocated node IDs
+       // in memory; conversion just won't work in this direction.
+       if(version < 24)
+               throw SerializationError("MapNode::serialize: serialization to "
+                               "version < 24 not possible");
+               
+       writeU16(dest+0, param0);
+       writeU8(dest+2, param1);
+       writeU8(dest+3, param2);
 }
 void MapNode::deSerialize(u8 *source, u8 version)
 {
@@ -297,22 +285,20 @@ void MapNode::serializeBulk(std::ostream &os, int version,
        if(!ser_ver_supported(version))
                throw VersionMismatchException("ERROR: MapNode format not supported");
 
-       assert(version >= 22);
-       assert(content_width == 1 || content_width == 2);
+       assert(content_width == 2);
        assert(params_width == 2);
 
+       // Can't do this anymore; we have 16-bit dynamically allocated node IDs
+       // in memory; conversion just won't work in this direction.
+       if(version < 24)
+               throw SerializationError("MapNode::serializeBulk: serialization to "
+                               "version < 24 not possible");
+
        SharedBuffer<u8> databuf(nodecount * (content_width + params_width));
 
        // Serialize content
-       if(content_width == 1)
-       {
-               for(u32 i=0; i<nodecount; i++)
-                       writeU8(&databuf[i], (nodes[i].param0&0x00FF));
-       }else if(content_width == 2)
-       {
-               for(u32 i=0; i<nodecount; i++)
-                       writeU16(&databuf[i*2], nodes[i].param0);
-       }
+       for(u32 i=0; i<nodecount; i++)
+               writeU16(&databuf[i*2], nodes[i].param0);
 
        // Serialize param1
        u32 start1 = content_width * nodecount;
@@ -321,21 +307,8 @@ void MapNode::serializeBulk(std::ostream &os, int version,
 
        // Serialize param2
        u32 start2 = (content_width + 1) * nodecount;
-       if(content_width == 1)
-       {
-               for(u32 i=0; i<nodecount; i++) {
-                       if(nodes[i].param0 > 0x7F){
-                               writeU8(&databuf[start2 + i], ((nodes[i].param2&0x0F) | ((nodes[i].param0&0x0F00)>>4)));
-                       }
-                       else{
-                               writeU8(&databuf[start2 + i], nodes[i].param2);
-                       }
-               }
-       }else if(content_width == 2)
-       {
-               for(u32 i=0; i<nodecount; i++)
-                       writeU8(&databuf[start2 + i], nodes[i].param2);
-       }
+       for(u32 i=0; i<nodecount; i++)
+               writeU8(&databuf[start2 + i], nodes[i].param2);
 
        /*
                Compress data to output stream
@@ -408,7 +381,8 @@ void MapNode::deSerializeBulk(std::istream &is, int version,
                for(u32 i=0; i<nodecount; i++) {
                        nodes[i].param2 = readU8(&databuf[start2 + i]);
                        if(nodes[i].param0 > 0x7F){
-                               nodes[i].param0 |= ((nodes[i].param2&0xF0)<<4);
+                               nodes[i].param0 <<= 4;
+                               nodes[i].param0 |= (nodes[i].param2&0xF0)>>4;
                                nodes[i].param2 &= 0x0F;
                        }
                }
@@ -423,40 +397,6 @@ void MapNode::deSerializeBulk(std::istream &is, int version,
 /*
        Legacy serialization
 */
-void MapNode::serialize_pre22(u8 *dest, u8 version)
-{
-       // Translate to wanted version
-       MapNode n_foreign = mapnode_translate_from_internal(*this, version);
-
-       u8 actual_param0 = n_foreign.param0;
-
-       // Convert special values from new version to old
-       if(version <= 18)
-       {
-               // In these versions, CONTENT_IGNORE and CONTENT_AIR
-               // are 255 and 254
-               if(actual_param0 == CONTENT_IGNORE)
-                       actual_param0 = 255;
-               else if(actual_param0 == CONTENT_AIR)
-                       actual_param0 = 254;
-       }
-
-       if(version == 0)
-       {
-               dest[0] = actual_param0;
-       }
-       else if(version <= 9)
-       {
-               dest[0] = actual_param0;
-               dest[1] = n_foreign.param1;
-       }
-       else
-       {
-               dest[0] = actual_param0;
-               dest[1] = n_foreign.param1;
-               dest[2] = n_foreign.param2;
-       }
-}
 void MapNode::deSerialize_pre22(u8 *source, u8 version)
 {
        if(version <= 1)
@@ -473,6 +413,11 @@ void MapNode::deSerialize_pre22(u8 *source, u8 version)
                param0 = source[0];
                param1 = source[1];
                param2 = source[2];
+               if(param0 > 0x7f){
+                       param0 <<= 4;
+                       param0 |= (param2&0xf0)>>4;
+                       param2 &= 0x0f;
+               }
        }
        
        // Convert special values from old version to new
index fe656fa5cd53f4c41c49a201f51462ba07995cc6..a95497ef5c3c50e3202838299146d46c28e6e89c 100644 (file)
@@ -33,10 +33,6 @@ class INodeDefManager;
        - Material = irrlicht's Material class
        - Content = (content_t) content of a node
        - Tile = TileSpec at some side of a node of some content type
-
-       Content ranges:
-         0x000...0x07f: param2 is fully usable
-         0x800...0xfff: param2 lower 4 bits are free
 */
 typedef u16 content_t;
 #define MAX_CONTENT 0xfff
@@ -84,8 +80,6 @@ struct MapNode
 {
        /*
                Main content
-               0x00-0x7f: Short content type
-               0x80-0xff: Long content type
        */
        u16 param0;
 
@@ -208,7 +202,6 @@ struct MapNode
 
 private:
        // Deprecated serialization methods
-       void serialize_pre22(u8 *dest, u8 version);
        void deSerialize_pre22(u8 *source, u8 version);
 };
 
index 47a29a6fcdd922ae488848378550354ddaa8056a..e38061e30d1b9231b6a850235db91b6ef400e9ad 100644 (file)
@@ -377,18 +377,9 @@ public:
                }
        }
        // CONTENT_IGNORE = not found
-       content_t getFreeId(bool require_full_param2)
+       content_t getFreeId()
        {
-               // If allowed, first search in the large 4-bit-param2 pool
-               if(!require_full_param2){
-                       for(u16 i=0x800; i<=0xfff; i++){
-                               const ContentFeatures &f = m_content_features[i];
-                               if(f.name == "")
-                                       return i;
-                       }
-               }
-               // Then search from the small 8-bit-param2 pool
-               for(u16 i=0; i<=125; i++){
+               for(u32 i=0; i<=0xffff; i++){
                        const ContentFeatures &f = m_content_features[i];
                        if(f.name == "")
                                return i;
@@ -492,16 +483,8 @@ public:
                u16 id = CONTENT_IGNORE;
                bool found = m_name_id_mapping.getId(name, id);  // ignore aliases
                if(!found){
-                       // Determine if full param2 is required
-                       bool require_full_param2 = (
-                               def.param_type_2 == CPT2_FULL
-                               ||
-                               def.param_type_2 == CPT2_FLOWINGLIQUID
-                               ||
-                               def.legacy_wallmounted
-                       );
                        // Get some id
-                       id = getFreeId(require_full_param2);
+                       id = getFreeId();
                        if(id == CONTENT_IGNORE)
                                return CONTENT_IGNORE;
                        if(name != "")
index 266eada1786e7a1cc8cd8416b67d75b55db0bd7c..0d74ccf48fb7ba280ce101416dfa992180638022 100644 (file)
@@ -59,7 +59,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        21: dynamic content type allocation
        22: minerals removed, facedir & wallmounted changed
        23: new node metadata format
-       24: NodeTimers
+       24: 16-bit node ids and node timers
 */
 // This represents an uninitialized or invalid format
 #define SER_FMT_VER_INVALID 255