diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/content_mapnode.cpp | 169 | ||||
-rw-r--r-- | src/content_mapnode.h | 37 | ||||
-rw-r--r-- | src/inventory.cpp | 163 | ||||
-rw-r--r-- | src/mapblock.cpp | 8 | ||||
-rw-r--r-- | src/mapnode.cpp | 70 | ||||
-rw-r--r-- | src/server.cpp | 1 | ||||
-rw-r--r-- | src/unittest/test_mapnode.cpp | 1 |
8 files changed, 416 insertions, 34 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba531cb64..6963d0306 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -371,6 +371,7 @@ set(common_SRCS clientiface.cpp collision.cpp content_abm.cpp + content_mapnode.cpp content_nodemeta.cpp content_sao.cpp convert_json.cpp diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp new file mode 100644 index 000000000..a6bf0a82d --- /dev/null +++ b/src/content_mapnode.cpp @@ -0,0 +1,169 @@ +/* +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "content_mapnode.h" + +#include "irrlichttypes_bloated.h" +#include "mapnode.h" +#include "nodedef.h" +#include "nameidmapping.h" +#include "util/string.h" + +/* + Legacy node content type IDs + Ranges: + 0x000...0x07f (0...127): param2 is fully usable + 126 and 127 are reserved (CONTENT_AIR and CONTENT_IGNORE). + 0x800...0xfff (2048...4095): higher 4 bits of param2 are not usable +*/ +#define CONTENT_STONE 0 +#define CONTENT_WATER 2 +#define CONTENT_TORCH 3 +#define CONTENT_WATERSOURCE 9 +#define CONTENT_SIGN_WALL 14 +#define CONTENT_CHEST 15 +#define CONTENT_FURNACE 16 +#define CONTENT_LOCKABLE_CHEST 17 +#define CONTENT_FENCE 21 +#define CONTENT_RAIL 30 +#define CONTENT_LADDER 31 +#define CONTENT_LAVA 32 +#define CONTENT_LAVASOURCE 33 +#define CONTENT_GRASS 0x800 //1 +#define CONTENT_TREE 0x801 //4 +#define CONTENT_LEAVES 0x802 //5 +#define CONTENT_GRASS_FOOTSTEPS 0x803 //6 +#define CONTENT_MESE 0x804 //7 +#define CONTENT_MUD 0x805 //8 +#define CONTENT_CLOUD 0x806 //10 +#define CONTENT_COALSTONE 0x807 //11 +#define CONTENT_WOOD 0x808 //12 +#define CONTENT_SAND 0x809 //13 +#define CONTENT_COBBLE 0x80a //18 +#define CONTENT_STEEL 0x80b //19 +#define CONTENT_GLASS 0x80c //20 +#define CONTENT_MOSSYCOBBLE 0x80d //22 +#define CONTENT_GRAVEL 0x80e //23 +#define CONTENT_SANDSTONE 0x80f //24 +#define CONTENT_CACTUS 0x810 //25 +#define CONTENT_BRICK 0x811 //26 +#define CONTENT_CLAY 0x812 //27 +#define CONTENT_PAPYRUS 0x813 //28 +#define CONTENT_BOOKSHELF 0x814 //29 +#define CONTENT_JUNGLETREE 0x815 +#define CONTENT_JUNGLEGRASS 0x816 +#define CONTENT_NC 0x817 +#define CONTENT_NC_RB 0x818 +#define CONTENT_APPLE 0x819 +#define CONTENT_SAPLING 0x820 + +/* + A conversion table for backwards compatibility. + Maps <=v19 content types to current ones. + Should never be touched. +*/ +content_t trans_table_19[21][2] = { + {CONTENT_GRASS, 1}, + {CONTENT_TREE, 4}, + {CONTENT_LEAVES, 5}, + {CONTENT_GRASS_FOOTSTEPS, 6}, + {CONTENT_MESE, 7}, + {CONTENT_MUD, 8}, + {CONTENT_CLOUD, 10}, + {CONTENT_COALSTONE, 11}, + {CONTENT_WOOD, 12}, + {CONTENT_SAND, 13}, + {CONTENT_COBBLE, 18}, + {CONTENT_STEEL, 19}, + {CONTENT_GLASS, 20}, + {CONTENT_MOSSYCOBBLE, 22}, + {CONTENT_GRAVEL, 23}, + {CONTENT_SANDSTONE, 24}, + {CONTENT_CACTUS, 25}, + {CONTENT_BRICK, 26}, + {CONTENT_CLAY, 27}, + {CONTENT_PAPYRUS, 28}, + {CONTENT_BOOKSHELF, 29}, +}; + +MapNode mapnode_translate_to_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][1] == c_from) + { + result.setContent(trans_table_19[i][0]); + break; + } + } + } + return result; +} + +void content_mapnode_get_name_id_mapping(NameIdMapping *nimap) +{ + nimap->set(0, "default:stone"); + nimap->set(2, "default:water_flowing"); + nimap->set(3, "default:torch"); + nimap->set(9, "default:water_source"); + nimap->set(14, "default:sign_wall"); + nimap->set(15, "default:chest"); + nimap->set(16, "default:furnace"); + nimap->set(17, "default:chest_locked"); + nimap->set(21, "default:fence_wood"); + nimap->set(30, "default:rail"); + nimap->set(31, "default:ladder"); + nimap->set(32, "default:lava_flowing"); + nimap->set(33, "default:lava_source"); + nimap->set(0x800, "default:dirt_with_grass"); + nimap->set(0x801, "default:tree"); + nimap->set(0x802, "default:leaves"); + nimap->set(0x803, "default:dirt_with_grass_footsteps"); + nimap->set(0x804, "default:mese"); + nimap->set(0x805, "default:dirt"); + nimap->set(0x806, "default:cloud"); + nimap->set(0x807, "default:coalstone"); + nimap->set(0x808, "default:wood"); + nimap->set(0x809, "default:sand"); + nimap->set(0x80a, "default:cobble"); + nimap->set(0x80b, "default:steelblock"); + nimap->set(0x80c, "default:glass"); + nimap->set(0x80d, "default:mossycobble"); + nimap->set(0x80e, "default:gravel"); + nimap->set(0x80f, "default:sandstone"); + nimap->set(0x810, "default:cactus"); + nimap->set(0x811, "default:brick"); + nimap->set(0x812, "default:clay"); + nimap->set(0x813, "default:papyrus"); + nimap->set(0x814, "default:bookshelf"); + nimap->set(0x815, "default:jungletree"); + nimap->set(0x816, "default:junglegrass"); + nimap->set(0x817, "default:nyancat"); + nimap->set(0x818, "default:nyancat_rainbow"); + nimap->set(0x819, "default:apple"); + nimap->set(0x820, "default:sapling"); + // Static types + nimap->set(CONTENT_IGNORE, "ignore"); + nimap->set(CONTENT_AIR, "air"); +} + diff --git a/src/content_mapnode.h b/src/content_mapnode.h new file mode 100644 index 000000000..9fa4e6d13 --- /dev/null +++ b/src/content_mapnode.h @@ -0,0 +1,37 @@ +/* +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef CONTENT_MAPNODE_HEADER +#define CONTENT_MAPNODE_HEADER + +#include "mapnode.h" + +/* + Legacy node definitions +*/ + +// Backwards compatibility for non-extended content types in v19 +extern content_t trans_table_19[21][2]; +MapNode mapnode_translate_to_internal(MapNode n_from, u8 version); + +// Get legacy node name mapping for loading old blocks +class NameIdMapping; +void content_mapnode_get_name_id_mapping(NameIdMapping *nimap); + +#endif diff --git a/src/inventory.cpp b/src/inventory.cpp index b4d1b4dd9..8617f7263 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "itemdef.h" #include "util/strfnd.h" +#include "content_mapnode.h" // For loading legacy MaterialItems +#include "nameidmapping.h" // For loading legacy MaterialItems #include "util/serialize.h" #include "util/string.h" @@ -31,6 +33,18 @@ with this program; if not, write to the Free Software Foundation, Inc., ItemStack */ +static content_t content_translate_from_19_to_internal(content_t c_from) +{ + for(u32 i=0; i<sizeof(trans_table_19)/sizeof(trans_table_19[0]); i++) + { + if(trans_table_19[i][1] == c_from) + { + return trans_table_19[i][0]; + } + } + return c_from; +} + ItemStack::ItemStack(const std::string &name_, u16 count_, u16 wear_, IItemDefManager *itemdef) : name(itemdef->getAlias(name_)), @@ -85,35 +99,140 @@ void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef) if(!tmp.empty()) throw SerializationError("Unexpected text after item name"); - do { // This loop is just to allow "break;" - // The real thing - - // Apply item aliases + if(name == "MaterialItem") + { + // Obsoleted on 2011-07-30 + + u16 material; + is>>material; + u16 materialcount; + is>>materialcount; + // Convert old materials + if(material <= 0xff) + material = content_translate_from_19_to_internal(material); + if(material > 0xfff) + throw SerializationError("Too large material number"); + // Convert old id to name + NameIdMapping legacy_nimap; + content_mapnode_get_name_id_mapping(&legacy_nimap); + legacy_nimap.getName(material, name); + if(name == "") + name = "unknown_block"; if (itemdef) name = itemdef->getAlias(name); - - // Read the count - std::string count_str; - std::getline(is, count_str, ' '); - if (count_str.empty()) { + count = materialcount; + } + else if(name == "MaterialItem2") + { + // Obsoleted on 2011-11-16 + + u16 material; + is>>material; + u16 materialcount; + is>>materialcount; + if(material > 0xfff) + throw SerializationError("Too large material number"); + // Convert old id to name + NameIdMapping legacy_nimap; + content_mapnode_get_name_id_mapping(&legacy_nimap); + legacy_nimap.getName(material, name); + if(name == "") + name = "unknown_block"; + if (itemdef) + name = itemdef->getAlias(name); + count = materialcount; + } + else if(name == "node" || name == "NodeItem" || name == "MaterialItem3" + || name == "craft" || name == "CraftItem") + { + // Obsoleted on 2012-01-07 + + std::string all; + std::getline(is, all, '\n'); + // First attempt to read inside "" + Strfnd fnd(all); + fnd.next("\""); + // If didn't skip to end, we have ""s + if(!fnd.at_end()){ + name = fnd.next("\""); + } else { // No luck, just read a word then + fnd.start(all); + name = fnd.next(" "); + } + fnd.skip_over(" "); + if (itemdef) + name = itemdef->getAlias(name); + count = stoi(trim(fnd.next(""))); + if(count == 0) count = 1; - break; - } else { - count = stoi(count_str); + } + else if(name == "MBOItem") + { + // Obsoleted on 2011-10-14 + throw SerializationError("MBOItem not supported anymore"); + } + else if(name == "tool" || name == "ToolItem") + { + // Obsoleted on 2012-01-07 + + std::string all; + std::getline(is, all, '\n'); + // First attempt to read inside "" + Strfnd fnd(all); + fnd.next("\""); + // If didn't skip to end, we have ""s + if(!fnd.at_end()){ + name = fnd.next("\""); + } else { // No luck, just read a word then + fnd.start(all); + name = fnd.next(" "); } + count = 1; + // Then read wear + fnd.skip_over(" "); + if (itemdef) + name = itemdef->getAlias(name); + wear = stoi(trim(fnd.next(""))); + } + else + { + do // This loop is just to allow "break;" + { + // The real thing + + // Apply item aliases + if (itemdef) + name = itemdef->getAlias(name); + + // Read the count + std::string count_str; + std::getline(is, count_str, ' '); + if(count_str.empty()) + { + count = 1; + break; + } + else + count = stoi(count_str); - // Read the wear - std::string wear_str; - std::getline(is, wear_str, ' '); - if (wear_str.empty()) - break; - else - wear = stoi(wear_str); + // Read the wear + std::string wear_str; + std::getline(is, wear_str, ' '); + if(wear_str.empty()) + break; + else + wear = stoi(wear_str); - // Read metadata - metadata.deSerialize(is); + // Read metadata + metadata.deSerialize(is); - } while(false); + // In case fields are added after metadata, skip space here: + //std::getline(is, tmp, ' '); + //if(!tmp.empty()) + // throw SerializationError("Unexpected text after metadata"); + + } while(false); + } if (name.empty() || count == 0) clear(); diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 07912b9a2..ec10a49bb 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gamedef.h" #include "log.h" #include "nameidmapping.h" +#include "content_mapnode.h" // For legacy name-id mapping #include "content_nodemeta.h" // For legacy deserialization #include "serialization.h" #ifndef SERVER @@ -930,7 +931,12 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) // Dynamically re-set ids based on node names NameIdMapping nimap; // If supported, read node definition id mapping - nimap.deSerialize(is); + if (version >= 21) { + nimap.deSerialize(is); + // Else set the legacy mapping + } else { + content_mapnode_get_name_id_mapping(&nimap); + } correctBlockNodeIds(&nimap, data, m_gamedef); } diff --git a/src/mapnode.cpp b/src/mapnode.cpp index cae3d0b14..d835daba2 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "nodedef.h" #include "map.h" +#include "content_mapnode.h" // For mapnode_translate_*_internal #include "serialization.h" // For ser_ver_supported #include "util/serialize.h" #include "log.h" @@ -630,19 +631,25 @@ void MapNode::serialize(u8 *dest, u8 version) } void MapNode::deSerialize(u8 *source, u8 version) { - if (!ser_ver_supported(version)) + if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapNode format not supported"); - if (version >= 24) { - param0 = readU16(source + 0); - param1 = readU8(source + 2); - param2 = readU8(source + 3); - } else { - param0 = readU8(source + 0); - param1 = readU8(source + 1); - param2 = readU8(source + 2); - if (param0 > 0x7F) { - param0 |= ((param2 & 0xF0) << 4); + if(version <= 21) + { + deSerialize_pre22(source, version); + return; + } + + if(version >= 24){ + param0 = readU16(source+0); + param1 = readU8(source+2); + param2 = readU8(source+3); + }else{ + param0 = readU8(source+0); + param1 = readU8(source+1); + param2 = readU8(source+2); + if(param0 > 0x7F){ + param0 |= ((param2&0xF0)<<4); param2 &= 0x0F; } } @@ -764,3 +771,44 @@ void MapNode::deSerializeBulk(std::istream &is, int version, } } +/* + Legacy serialization +*/ +void MapNode::deSerialize_pre22(u8 *source, u8 version) +{ + if(version <= 1) + { + param0 = source[0]; + } + else if(version <= 9) + { + param0 = source[0]; + param1 = source[1]; + } + else + { + 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 + if(version <= 19) + { + // In these versions, CONTENT_IGNORE and CONTENT_AIR + // are 255 and 254 + // Version 19 is fucked up with sometimes the old values and sometimes not + if(param0 == 255) + param0 = CONTENT_IGNORE; + else if(param0 == 254) + param0 = CONTENT_AIR; + } + + // Translate to our known version + *this = mapnode_translate_to_internal(*this, version); +} diff --git a/src/server.cpp b/src/server.cpp index 46176c667..b2fdecfa9 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -45,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "emerge.h" #include "mapgen.h" #include "mg_biome.h" +#include "content_mapnode.h" #include "content_nodemeta.h" #include "content_abm.h" #include "content_sao.h" diff --git a/src/unittest/test_mapnode.cpp b/src/unittest/test_mapnode.cpp index 145d16465..70e7d42cf 100644 --- a/src/unittest/test_mapnode.cpp +++ b/src/unittest/test_mapnode.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gamedef.h" #include "nodedef.h" +#include "content_mapnode.h" class TestMapNode : public TestBase { |