Node definition names
authorPerttu Ahola <celeron55@gmail.com>
Wed, 16 Nov 2011 11:03:28 +0000 (13:03 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 29 Nov 2011 17:13:46 +0000 (19:13 +0200)
18 files changed:
src/CMakeLists.txt
src/client.cpp
src/client.h
src/content_mapnode.cpp
src/content_mapnode.h
src/gamedef.h
src/map.cpp
src/mapblock.cpp
src/mapblock.h
src/mapnode.cpp
src/mapnode.h
src/nameidmapping.cpp [new file with mode: 0644]
src/nameidmapping.h [new file with mode: 0644]
src/nodedef.cpp
src/nodedef.h
src/serialization.h
src/server.cpp
src/server.h

index 85060ac705c8bcea218d121692506a302e571822..9c6419fcbef4fceccae257c62b6c28bbbf187796 100644 (file)
@@ -94,6 +94,7 @@ configure_file(
 )
 
 set(common_SRCS
+       nameidmapping.cpp
        tooldef.cpp
        nodedef.cpp
        luaentity_common.cpp
index 5c713e48640b9d190f60be3d88a9c48c13e6804a..661aecda59820e491b186d4e36d9c5977ef9b31a 100644 (file)
@@ -848,7 +848,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                //TimeTaker t1("TOCLIENT_ADDNODE");
 
                MapNode n;
-               n.deSerialize(&data[8], ser_version, m_nodedef);
+               n.deSerialize(&data[8], ser_version);
                
                addNode(p, n);
        }
@@ -2331,4 +2331,11 @@ ITextureSource* Client::getTextureSource()
 {
        return m_tsrc;
 }
+u16 Client::allocateUnknownNodeId(const std::string &name)
+{
+       errorstream<<"Client::allocateUnknownNodeId(): "
+                       <<"Client cannot allocate node IDs"<<std::endl;
+       assert(0);
+       return CONTENT_IGNORE;
+}
 
index 625170b174011382c5c099ad1a75a1ac4c682c4e..cd36c4858ab4cd6288a619248fb6c90894a73e66 100644 (file)
@@ -324,10 +324,10 @@ public:
        float getRTT(void);
 
        // IGameDef interface
-       // Under envlock
        virtual IToolDefManager* getToolDefManager();
        virtual INodeDefManager* getNodeDefManager();
        virtual ITextureSource* getTextureSource();
+       virtual u16 allocateUnknownNodeId(const std::string &name);
 
 private:
        
index b836cb493909562f2cf523b578b98febae7fcb0e..fdb75d46873e46e3252a41895b50cc8e1aed4612 100644 (file)
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "content_nodemeta.h"
 #include "nodedef.h"
 #include "utility.h"
+#include "nameidmapping.h"
 
 #define WATER_ALPHA 160
 
@@ -154,577 +155,665 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
        return result;
 }
 
+void content_mapnode_get_name_id_mapping(NameIdMapping *nimap)
+{
+       nimap->set(0, "stone");
+       nimap->set(2, "water_flowing");
+       nimap->set(3, "torch");
+       nimap->set(9, "water_source");
+       nimap->set(14, "sign_wall");
+       nimap->set(15, "chest");
+       nimap->set(16, "furnace");
+       nimap->set(17, "locked_chest");
+       nimap->set(21, "wooden_fence");
+       nimap->set(30, "rail");
+       nimap->set(31, "ladder");
+       nimap->set(32, "lava_flowing");
+       nimap->set(33, "lava_source");
+       nimap->set(0x800, "dirt_with_grass");
+       nimap->set(0x801, "tree");
+       nimap->set(0x802, "leaves");
+       nimap->set(0x803, "dirt_with_grass_footsteps");
+       nimap->set(0x804, "mese");
+       nimap->set(0x805, "dirt");
+       nimap->set(0x806, "cloud");
+       nimap->set(0x807, "coalstone");
+       nimap->set(0x808, "wood");
+       nimap->set(0x809, "sand");
+       nimap->set(0x80a, "cobble");
+       nimap->set(0x80b, "steel");
+       nimap->set(0x80c, "glass");
+       nimap->set(0x80d, "mossycobble");
+       nimap->set(0x80e, "gravel");
+       nimap->set(0x80f, "sandstone");
+       nimap->set(0x810, "cactus");
+       nimap->set(0x811, "brick");
+       nimap->set(0x812, "clay");
+       nimap->set(0x813, "papyrus");
+       nimap->set(0x814, "bookshelf");
+       nimap->set(0x815, "jungletree");
+       nimap->set(0x816, "junglegrass");
+       nimap->set(0x817, "nyancat");
+       nimap->set(0x818, "nyancat_rainbow");
+       nimap->set(0x819, "apple");
+       nimap->set(0x820, "sapling");
+       // Static types
+       nimap->set(CONTENT_IGNORE, "ignore");
+       nimap->set(CONTENT_AIR, "air");
+}
+
 // See header for description
 void content_mapnode_init(IWritableNodeDefManager *nodemgr)
 {
        content_t i;
-       ContentFeatures *f = NULL;
+       ContentFeatures f;
 
        i = CONTENT_STONE;
-       f = nodemgr->getModifiable(i);
-       f->name = "stone";
-       f->setAllTextures("stone.png");
-       f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->often_contains_mineral = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
-       setStoneLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "stone";
+       f.setAllTextures("stone.png");
+       f.setInventoryTextureCube("stone.png", "stone.png", "stone.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.often_contains_mineral = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
+       setStoneLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_GRASS;
-       f = nodemgr->getModifiable(i);
-       f->name = "grass";
-       f->setAllTextures("mud.png^grass_side.png");
-       f->setTexture(0, "grass.png");
-       f->setTexture(1, "mud.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
-       setDirtLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "dirt_with_grass";
+       f.setAllTextures("mud.png^grass_side.png");
+       f.setTexture(0, "grass.png");
+       f.setTexture(1, "mud.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
+       setDirtLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_GRASS_FOOTSTEPS;
-       f = nodemgr->getModifiable(i);
-       f->name = "grass_footsteps";
-       f->setAllTextures("mud.png^grass_side.png");
-       f->setTexture(0, "grass_footsteps.png");
-       f->setTexture(1, "mud.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
-       setDirtLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "dirt_with_grass_footsteps";
+       f.setAllTextures("mud.png^grass_side.png");
+       f.setTexture(0, "grass_footsteps.png");
+       f.setTexture(1, "mud.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
+       setDirtLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_MUD;
-       f = nodemgr->getModifiable(i);
-       f->name = "dirt";
-       f->setAllTextures("mud.png");
-       f->setInventoryTextureCube("mud.png", "mud.png", "mud.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setDirtLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "dirt";
+       f.setAllTextures("mud.png");
+       f.setInventoryTextureCube("mud.png", "mud.png", "mud.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setDirtLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_SAND;
-       f = nodemgr->getModifiable(i);
-       f->name = "sand";
-       f->setAllTextures("sand.png");
-       f->setInventoryTextureCube("sand.png", "sand.png", "sand.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->cookresult_item = std::string("MaterialItem2 ")+itos(CONTENT_GLASS)+" 1";
-       setDirtLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "sand";
+       f.setAllTextures("sand.png");
+       f.setInventoryTextureCube("sand.png", "sand.png", "sand.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.cookresult_item = std::string("MaterialItem2 ")+itos(CONTENT_GLASS)+" 1";
+       setDirtLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_GRAVEL;
-       f = nodemgr->getModifiable(i);
-       f->name = "gravel";
-       f->setAllTextures("gravel.png");
-       f->setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setGravelLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "gravel";
+       f.setAllTextures("gravel.png");
+       f.setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setGravelLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_SANDSTONE;
-       f = nodemgr->getModifiable(i);
-       f->name = "sandstone";
-       f->setAllTextures("sandstone.png");
-       f->setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 1";
-       setDirtLikeMaterialProperties(f->material, 1.0);
+       f = ContentFeatures();
+       f.name = "sandstone";
+       f.setAllTextures("sandstone.png");
+       f.setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 1";
+       setDirtLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
 
        i = CONTENT_CLAY;
-       f = nodemgr->getModifiable(i);
-       f->name = "clay";
-       f->setAllTextures("clay.png");
-       f->setInventoryTextureCube("clay.png", "clay.png", "clay.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("CraftItem lump_of_clay 4");
-       setDirtLikeMaterialProperties(f->material, 1.0);
+       f = ContentFeatures();
+       f.name = "clay";
+       f.setAllTextures("clay.png");
+       f.setInventoryTextureCube("clay.png", "clay.png", "clay.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("CraftItem lump_of_clay 4");
+       setDirtLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
 
        i = CONTENT_BRICK;
-       f = nodemgr->getModifiable(i);
-       f->name = "brick";
-       f->setAllTextures("brick.png");
-       f->setInventoryTextureCube("brick.png", "brick.png", "brick.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("CraftItem clay_brick 4");
-       setStoneLikeMaterialProperties(f->material, 1.0);
+       f = ContentFeatures();
+       f.name = "brick";
+       f.setAllTextures("brick.png");
+       f.setInventoryTextureCube("brick.png", "brick.png", "brick.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("CraftItem clay_brick 4");
+       setStoneLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
 
        i = CONTENT_TREE;
-       f = nodemgr->getModifiable(i);
-       f->name = "tree";
-       f->setAllTextures("tree.png");
-       f->setTexture(0, "tree_top.png");
-       f->setTexture(1, "tree_top.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->cookresult_item = "CraftItem lump_of_coal 1";
-       f->furnace_burntime = 30;
-       setWoodLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "tree";
+       f.setAllTextures("tree.png");
+       f.setTexture(0, "tree_top.png");
+       f.setTexture(1, "tree_top.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.cookresult_item = "CraftItem lump_of_coal 1";
+       f.furnace_burntime = 30;
+       setWoodLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_JUNGLETREE;
-       f = nodemgr->getModifiable(i);
-       f->name = "jungletree";
-       f->setAllTextures("jungletree.png");
-       f->setTexture(0, "jungletree_top.png");
-       f->setTexture(1, "jungletree_top.png");
-       f->param_type = CPT_MINERAL;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->furnace_burntime = 30;
-       setWoodLikeMaterialProperties(f->material, 1.0);
-       
+       f = ContentFeatures();
+       f.name = "jungletree";
+       f.setAllTextures("jungletree.png");
+       f.setTexture(0, "jungletree_top.png");
+       f.setTexture(1, "jungletree_top.png");
+       f.param_type = CPT_MINERAL;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.furnace_burntime = 30;
+       setWoodLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_JUNGLEGRASS;
-       f = nodemgr->getModifiable(i);
-       f->name = "junglegrass";
-       f->drawtype = NDT_PLANTLIKE;
-       f->visual_scale = 1.3;
-       f->setAllTextures("junglegrass.png");
-       f->setInventoryTexture("junglegrass.png");
-       f->light_propagates = true;
-       f->param_type = CPT_LIGHT;
-       f->air_equivalent = false; // grass grows underneath
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->walkable = false;
-       setLeavesLikeMaterialProperties(f->material, 1.0);
-       f->furnace_burntime = 2;
+       f = ContentFeatures();
+       f.name = "junglegrass";
+       f.drawtype = NDT_PLANTLIKE;
+       f.visual_scale = 1.3;
+       f.setAllTextures("junglegrass.png");
+       f.setInventoryTexture("junglegrass.png");
+       f.light_propagates = true;
+       f.param_type = CPT_LIGHT;
+       f.air_equivalent = false; // grass grows underneath
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.walkable = false;
+       setLeavesLikeMaterialProperties(f.material, 1.0);
+       f.furnace_burntime = 2;
+       nodemgr->set(i, f);
 
        i = CONTENT_LEAVES;
-       f = nodemgr->getModifiable(i);
-       f->name = "leaves";
-       f->drawtype = NDT_ALLFACES_OPTIONAL;
-       f->setAllTextures("leaves.png");
-       //f->setAllTextures("[noalpha:leaves.png");
-       f->light_propagates = true;
-       f->param_type = CPT_LIGHT;
-       f->extra_dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAPLING)+" 1";
-       f->extra_dug_item_rarity = 20;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setLeavesLikeMaterialProperties(f->material, 1.0);
-       f->furnace_burntime = 1.0;
+       f = ContentFeatures();
+       f.name = "leaves";
+       f.drawtype = NDT_ALLFACES_OPTIONAL;
+       f.setAllTextures("leaves.png");
+       //f.setAllTextures("[noalpha:leaves.png");
+       f.light_propagates = true;
+       f.param_type = CPT_LIGHT;
+       f.extra_dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAPLING)+" 1";
+       f.extra_dug_item_rarity = 20;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setLeavesLikeMaterialProperties(f.material, 1.0);
+       f.furnace_burntime = 1.0;
+       nodemgr->set(i, f);
 
        i = CONTENT_CACTUS;
-       f = nodemgr->getModifiable(i);
-       f->name = "cactus";
-       f->setAllTextures("cactus_side.png");
-       f->setTexture(0, "cactus_top.png");
-       f->setTexture(1, "cactus_top.png");
-       f->setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setWoodLikeMaterialProperties(f->material, 0.75);
-       f->furnace_burntime = 15;
+       f = ContentFeatures();
+       f.name = "cactus";
+       f.setAllTextures("cactus_side.png");
+       f.setTexture(0, "cactus_top.png");
+       f.setTexture(1, "cactus_top.png");
+       f.setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setWoodLikeMaterialProperties(f.material, 0.75);
+       f.furnace_burntime = 15;
+       nodemgr->set(i, f);
 
        i = CONTENT_PAPYRUS;
-       f = nodemgr->getModifiable(i);
-       f->name = "papyrus";
-       f->drawtype = NDT_PLANTLIKE;
-       f->setAllTextures("papyrus.png");
-       f->setInventoryTexture("papyrus.png");
-       f->light_propagates = true;
-       f->param_type = CPT_LIGHT;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->walkable = false;
-       setLeavesLikeMaterialProperties(f->material, 0.5);
-       f->furnace_burntime = 1;
+       f = ContentFeatures();
+       f.name = "papyrus";
+       f.drawtype = NDT_PLANTLIKE;
+       f.setAllTextures("papyrus.png");
+       f.setInventoryTexture("papyrus.png");
+       f.light_propagates = true;
+       f.param_type = CPT_LIGHT;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.walkable = false;
+       setLeavesLikeMaterialProperties(f.material, 0.5);
+       f.furnace_burntime = 1;
+       nodemgr->set(i, f);
 
        i = CONTENT_BOOKSHELF;
-       f = nodemgr->getModifiable(i);
-       f->name = "bookshelf";
-       f->setAllTextures("bookshelf.png");
-       f->setTexture(0, "wood.png");
-       f->setTexture(1, "wood.png");
+       f = ContentFeatures();
+       f.name = "bookshelf";
+       f.setAllTextures("bookshelf.png");
+       f.setTexture(0, "wood.png");
+       f.setTexture(1, "wood.png");
        // FIXME: setInventoryTextureCube() only cares for the first texture
-       f->setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png");
-       //f->setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png");
-       f->param_type = CPT_MINERAL;
-       f->is_ground_content = true;
-       setWoodLikeMaterialProperties(f->material, 0.75);
-       f->furnace_burntime = 30;
+       f.setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png");
+       //f.setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png");
+       f.param_type = CPT_MINERAL;
+       f.is_ground_content = true;
+       setWoodLikeMaterialProperties(f.material, 0.75);
+       f.furnace_burntime = 30;
+       nodemgr->set(i, f);
 
        i = CONTENT_GLASS;
-       f = nodemgr->getModifiable(i);
-       f->name = "glass";
-       f->drawtype = NDT_GLASSLIKE;
-       f->setAllTextures("glass.png");
-       f->light_propagates = true;
-       f->sunlight_propagates = true;
-       f->param_type = CPT_LIGHT;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
-       setGlassLikeMaterialProperties(f->material, 1.0);
+       f = ContentFeatures();
+       f.name = "glass";
+       f.drawtype = NDT_GLASSLIKE;
+       f.setAllTextures("glass.png");
+       f.light_propagates = true;
+       f.sunlight_propagates = true;
+       f.param_type = CPT_LIGHT;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.setInventoryTextureCube("glass.png", "glass.png", "glass.png");
+       setGlassLikeMaterialProperties(f.material, 1.0);
+       nodemgr->set(i, f);
 
        i = CONTENT_FENCE;
-       f = nodemgr->getModifiable(i);
-       f->name = "fence";
-       f->drawtype = NDT_FENCELIKE;
-       f->setInventoryTexture("fence.png");
-       f->setTexture(0, "wood.png");
-       f->light_propagates = true;
-       f->param_type = CPT_LIGHT;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->air_equivalent = true; // grass grows underneath
-       f->selection_box.type = NODEBOX_FIXED;
-       f->selection_box.fixed = core::aabbox3d<f32>(
+       f = ContentFeatures();
+       f.name = "wooden_fence";
+       f.drawtype = NDT_FENCELIKE;
+       f.setInventoryTexture("fence.png");
+       f.setTexture(0, "wood.png");
+       f.light_propagates = true;
+       f.param_type = CPT_LIGHT;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.air_equivalent = true; // grass grows underneath
+       f.selection_box.type = NODEBOX_FIXED;
+       f.selection_box.fixed = core::aabbox3d<f32>(
                        -BS/7, -BS/2, -BS/7, BS/7, BS/2, BS/7);
-       f->furnace_burntime = 30/2;
-       setWoodLikeMaterialProperties(f->material, 0.75);
+       f.furnace_burntime = 30/2;
+       setWoodLikeMaterialProperties(f.material, 0.75);
+       nodemgr->set(i, f);
 
        i = CONTENT_RAIL;
-       f = nodemgr->getModifiable(i);
-       f->name = "rail";
-       f->drawtype = NDT_RAILLIKE;
-       f->setInventoryTexture("rail.png");
-       f->setTexture(0, "rail.png");
-       f->setTexture(1, "rail_curved.png");
-       f->setTexture(2, "rail_t_junction.png");
-       f->setTexture(3, "rail_crossing.png");
-       f->light_propagates = true;
-       f->param_type = CPT_LIGHT;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->air_equivalent = true; // grass grows underneath
-       f->walkable = false;
-       f->selection_box.type = NODEBOX_FIXED;
-       f->furnace_burntime = 5;
-       setDirtLikeMaterialProperties(f->material, 0.75);
+       f = ContentFeatures();
+       f.name = "rail";
+       f.drawtype = NDT_RAILLIKE;
+       f.setInventoryTexture("rail.png");
+       f.setTexture(0, "rail.png");
+       f.setTexture(1, "rail_curved.png");
+       f.setTexture(2, "rail_t_junction.png");
+       f.setTexture(3, "rail_crossing.png");
+       f.light_propagates = true;
+       f.param_type = CPT_LIGHT;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.air_equivalent = true; // grass grows underneath
+       f.walkable = false;
+       f.selection_box.type = NODEBOX_FIXED;
+       f.furnace_burntime = 5;
+       setDirtLikeMaterialProperties(f.material, 0.75);
+       nodemgr->set(i, f);
 
        i = CONTENT_LADDER;
-       f = nodemgr->getModifiable(i);
-       f->name = "ladder";
-       f->drawtype = NDT_SIGNLIKE;
-       f->setAllTextures("ladder.png");
-       f->setInventoryTexture("ladder.png");
-       f->light_propagates = true;
-       f->param_type = CPT_LIGHT;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
-       f->wall_mounted = true;
-       f->air_equivalent = true;
-       f->walkable = false;
-       f->climbable = true;
-       f->selection_box.type = NODEBOX_WALLMOUNTED;
-       f->furnace_burntime = 5;
-       setWoodLikeMaterialProperties(f->material, 0.5);
-
-       // Deprecated
+       f = ContentFeatures();
+       f.name = "ladder";
+       f.drawtype = NDT_SIGNLIKE;
+       f.setAllTextures("ladder.png");
+       f.setInventoryTexture("ladder.png");
+       f.light_propagates = true;
+       f.param_type = CPT_LIGHT;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+       f.wall_mounted = true;
+       f.air_equivalent = true;
+       f.walkable = false;
+       f.climbable = true;
+       f.selection_box.type = NODEBOX_WALLMOUNTED;
+       f.furnace_burntime = 5;
+       setWoodLikeMaterialProperties(f.material, 0.5);
+
+       nodemgr->set(i, f);
+
        i = CONTENT_COALSTONE;
-       f = nodemgr->getModifiable(i);
-       f->name = "coalstone";
-       f->setAllTextures("stone.png^mineral_coal.png");
-       f->is_ground_content = true;
-       setStoneLikeMaterialProperties(f->material, 1.5);
-       
+       f = ContentFeatures();
+       f.name = "coalstone";
+       f.setAllTextures("stone.png^mineral_coal.png");
+       f.is_ground_content = true;
+       setStoneLikeMaterialProperties(f.material, 1.5);
+       nodemgr->set(i, f);
+
        i = CONTENT_WOOD;
-       f = nodemgr->getModifiable(i);
-       f->name = "wood";
-       f->setAllTextures("wood.png");
-       f->setInventoryTextureCube("wood.png", "wood.png", "wood.png");
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->furnace_burntime = 30/4;
-       setWoodLikeMaterialProperties(f->material, 0.75);
-       
+       f = ContentFeatures();
+       f.name = "wood";
+       f.setAllTextures("wood.png");
+       f.setInventoryTextureCube("wood.png", "wood.png", "wood.png");
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.furnace_burntime = 30/4;
+       setWoodLikeMaterialProperties(f.material, 0.75);
+       nodemgr->set(i, f);
+
        i = CONTENT_MESE;
-       f = nodemgr->getModifiable(i);
-       f->name = "mese";
-       f->setAllTextures("mese.png");
-       f->setInventoryTextureCube("mese.png", "mese.png", "mese.png");
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->furnace_burntime = 30;
-       setStoneLikeMaterialProperties(f->material, 0.5);
-       
+       f = ContentFeatures();
+       f.name = "mese";
+       f.setAllTextures("mese.png");
+       f.setInventoryTextureCube("mese.png", "mese.png", "mese.png");
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.furnace_burntime = 30;
+       setStoneLikeMaterialProperties(f.material, 0.5);
+       nodemgr->set(i, f);
+
        i = CONTENT_CLOUD;
-       f = nodemgr->getModifiable(i);
-       f->name = "cloud";
-       f->setAllTextures("cloud.png");
-       f->setInventoryTextureCube("cloud.png", "cloud.png", "cloud.png");
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       
+       f = ContentFeatures();
+       f.name = "cloud";
+       f.setAllTextures("cloud.png");
+       f.setInventoryTextureCube("cloud.png", "cloud.png", "cloud.png");
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       nodemgr->set(i, f);
+
        i = CONTENT_AIR;
-       f = nodemgr->getModifiable(i);
-       f->name = "air";
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = true;
-       f->sunlight_propagates = true;
-       f->walkable = false;
-       f->pointable = false;
-       f->diggable = false;
-       f->buildable_to = true;
-       f->air_equivalent = true;
-       
+       f = ContentFeatures();
+       f.name = "air";
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = true;
+       f.sunlight_propagates = true;
+       f.walkable = false;
+       f.pointable = false;
+       f.diggable = false;
+       f.buildable_to = true;
+       f.air_equivalent = true;
+       nodemgr->set(i, f);
+
        i = CONTENT_WATER;
-       f = nodemgr->getModifiable(i);
-       f->name = "water_flowing";
-       f->drawtype = NDT_FLOWINGLIQUID;
-       f->setAllTextures("water.png");
-       f->alpha = WATER_ALPHA;
-       f->setInventoryTextureCube("water.png", "water.png", "water.png");
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = true;
-       f->walkable = false;
-       f->pointable = false;
-       f->diggable = false;
-       f->buildable_to = true;
-       f->liquid_type = LIQUID_FLOWING;
-       f->liquid_alternative_flowing = CONTENT_WATER;
-       f->liquid_alternative_source = CONTENT_WATERSOURCE;
-       f->liquid_viscosity = WATER_VISC;
-       f->post_effect_color = video::SColor(64, 100, 100, 200);
-       f->setSpecialMaterial(0, MaterialSpec("water.png", false));
-       f->setSpecialMaterial(1, MaterialSpec("water.png", true));
+       f = ContentFeatures();
+       f.name = "water_flowing";
+       f.drawtype = NDT_FLOWINGLIQUID;
+       f.setAllTextures("water.png");
+       f.alpha = WATER_ALPHA;
+       f.setInventoryTextureCube("water.png", "water.png", "water.png");
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = true;
+       f.walkable = false;
+       f.pointable = false;
+       f.diggable = false;
+       f.buildable_to = true;
+       f.liquid_type = LIQUID_FLOWING;
+       f.liquid_alternative_flowing = CONTENT_WATER;
+       f.liquid_alternative_source = CONTENT_WATERSOURCE;
+       f.liquid_viscosity = WATER_VISC;
+       f.post_effect_color = video::SColor(64, 100, 100, 200);
+       f.setSpecialMaterial(0, MaterialSpec("water.png", false));
+       f.setSpecialMaterial(1, MaterialSpec("water.png", true));
+       nodemgr->set(i, f);
 
        i = CONTENT_WATERSOURCE;
-       f = nodemgr->getModifiable(i);
-       f->name = "water_source";
-       f->drawtype = NDT_LIQUID;
-       f->setAllTextures("water.png");
-       f->alpha = WATER_ALPHA;
-       f->setInventoryTextureCube("water.png", "water.png", "water.png");
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = true;
-       f->walkable = false;
-       f->pointable = false;
-       f->diggable = false;
-       f->buildable_to = true;
-       f->liquid_type = LIQUID_SOURCE;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->liquid_alternative_flowing = CONTENT_WATER;
-       f->liquid_alternative_source = CONTENT_WATERSOURCE;
-       f->liquid_viscosity = WATER_VISC;
-       f->post_effect_color = video::SColor(64, 100, 100, 200);
+       f = ContentFeatures();
+       f.name = "water_source";
+       f.drawtype = NDT_LIQUID;
+       f.setAllTextures("water.png");
+       f.alpha = WATER_ALPHA;
+       f.setInventoryTextureCube("water.png", "water.png", "water.png");
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = true;
+       f.walkable = false;
+       f.pointable = false;
+       f.diggable = false;
+       f.buildable_to = true;
+       f.liquid_type = LIQUID_SOURCE;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.liquid_alternative_flowing = CONTENT_WATER;
+       f.liquid_alternative_source = CONTENT_WATERSOURCE;
+       f.liquid_viscosity = WATER_VISC;
+       f.post_effect_color = video::SColor(64, 100, 100, 200);
        // New-style water source material (mostly unused)
-       f->setSpecialMaterial(0, MaterialSpec("water.png", false));
-       
+       f.setSpecialMaterial(0, MaterialSpec("water.png", false));
+       nodemgr->set(i, f);
+
        i = CONTENT_LAVA;
-       f = nodemgr->getModifiable(i);
-       f->name = "lava_flowing";
-       f->drawtype = NDT_FLOWINGLIQUID;
-       f->setAllTextures("lava.png");
-       f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = false;
-       f->light_source = LIGHT_MAX-1;
-       f->walkable = false;
-       f->pointable = false;
-       f->diggable = false;
-       f->buildable_to = true;
-       f->liquid_type = LIQUID_FLOWING;
-       f->liquid_alternative_flowing = CONTENT_LAVA;
-       f->liquid_alternative_source = CONTENT_LAVASOURCE;
-       f->liquid_viscosity = LAVA_VISC;
-       f->damage_per_second = 4*2;
-       f->post_effect_color = video::SColor(192, 255, 64, 0);
-       f->setSpecialMaterial(0, MaterialSpec("lava.png", false));
-       f->setSpecialMaterial(1, MaterialSpec("lava.png", true));
-       
+       f = ContentFeatures();
+       f.name = "lava_flowing";
+       f.drawtype = NDT_FLOWINGLIQUID;
+       f.setAllTextures("lava.png");
+       f.setInventoryTextureCube("lava.png", "lava.png", "lava.png");
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = false;
+       f.light_source = LIGHT_MAX-1;
+       f.walkable = false;
+       f.pointable = false;
+       f.diggable = false;
+       f.buildable_to = true;
+       f.liquid_type = LIQUID_FLOWING;
+       f.liquid_alternative_flowing = CONTENT_LAVA;
+       f.liquid_alternative_source = CONTENT_LAVASOURCE;
+       f.liquid_viscosity = LAVA_VISC;
+       f.damage_per_second = 4*2;
+       f.post_effect_color = video::SColor(192, 255, 64, 0);
+       f.setSpecialMaterial(0, MaterialSpec("lava.png", false));
+       f.setSpecialMaterial(1, MaterialSpec("lava.png", true));
+       nodemgr->set(i, f);
+
        i = CONTENT_LAVASOURCE;
-       f = nodemgr->getModifiable(i);
-       f->name = "lava_source";
-       f->drawtype = NDT_LIQUID;
-       f->setAllTextures("lava.png");
-       f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = false;
-       f->light_source = LIGHT_MAX-1;
-       f->walkable = false;
-       f->pointable = false;
-       f->diggable = false;
-       f->buildable_to = true;
-       f->liquid_type = LIQUID_SOURCE;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->liquid_alternative_flowing = CONTENT_LAVA;
-       f->liquid_alternative_source = CONTENT_LAVASOURCE;
-       f->liquid_viscosity = LAVA_VISC;
-       f->damage_per_second = 4*2;
-       f->post_effect_color = video::SColor(192, 255, 64, 0);
+       f = ContentFeatures();
+       f.name = "lava_source";
+       f.drawtype = NDT_LIQUID;
+       f.setAllTextures("lava.png");
+       f.setInventoryTextureCube("lava.png", "lava.png", "lava.png");
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = false;
+       f.light_source = LIGHT_MAX-1;
+       f.walkable = false;
+       f.pointable = false;
+       f.diggable = false;
+       f.buildable_to = true;
+       f.liquid_type = LIQUID_SOURCE;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.liquid_alternative_flowing = CONTENT_LAVA;
+       f.liquid_alternative_source = CONTENT_LAVASOURCE;
+       f.liquid_viscosity = LAVA_VISC;
+       f.damage_per_second = 4*2;
+       f.post_effect_color = video::SColor(192, 255, 64, 0);
        // New-style lava source material (mostly unused)
-       f->setSpecialMaterial(0, MaterialSpec("lava.png", false));
-       f->furnace_burntime = 60;
-       
+       f.setSpecialMaterial(0, MaterialSpec("lava.png", false));
+       f.furnace_burntime = 60;
+       nodemgr->set(i, f);
+
        i = CONTENT_TORCH;
-       f = nodemgr->getModifiable(i);
-       f->name = "torch";
-       f->drawtype = NDT_TORCHLIKE;
-       f->setTexture(0, "torch_on_floor.png");
-       f->setTexture(1, "torch_on_ceiling.png");
-       f->setTexture(2, "torch.png");
-       f->setInventoryTexture("torch_on_floor.png");
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = true;
-       f->sunlight_propagates = true;
-       f->walkable = false;
-       f->wall_mounted = true;
-       f->air_equivalent = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->light_source = LIGHT_MAX-1;
-       f->selection_box.type = NODEBOX_WALLMOUNTED;
-       f->selection_box.wall_top = core::aabbox3d<f32>(
+       f = ContentFeatures();
+       f.name = "torch";
+       f.drawtype = NDT_TORCHLIKE;
+       f.setTexture(0, "torch_on_floor.png");
+       f.setTexture(1, "torch_on_ceiling.png");
+       f.setTexture(2, "torch.png");
+       f.setInventoryTexture("torch_on_floor.png");
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = true;
+       f.sunlight_propagates = true;
+       f.walkable = false;
+       f.wall_mounted = true;
+       f.air_equivalent = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.light_source = LIGHT_MAX-1;
+       f.selection_box.type = NODEBOX_WALLMOUNTED;
+       f.selection_box.wall_top = core::aabbox3d<f32>(
                        -BS/10, BS/2-BS/3.333*2, -BS/10, BS/10, BS/2, BS/10);
-       f->selection_box.wall_bottom = core::aabbox3d<f32>(
+       f.selection_box.wall_bottom = core::aabbox3d<f32>(
                        -BS/10, -BS/2, -BS/10, BS/10, -BS/2+BS/3.333*2, BS/10);
-       f->selection_box.wall_side = core::aabbox3d<f32>(
+       f.selection_box.wall_side = core::aabbox3d<f32>(
                        -BS/2, -BS/3.333, -BS/10, -BS/2+BS/3.333, BS/3.333, BS/10);
-       setConstantMaterialProperties(f->material, 0.0);
-       f->furnace_burntime = 4;
-       
+       setConstantMaterialProperties(f.material, 0.0);
+       f.furnace_burntime = 4;
+       nodemgr->set(i, f);
+
        i = CONTENT_SIGN_WALL;
-       f = nodemgr->getModifiable(i);
-       f->name = "sign_wall";
-       f->drawtype = NDT_SIGNLIKE;
-       f->setAllTextures("sign_wall.png");
-       f->setInventoryTexture("sign_wall.png");
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = true;
-       f->sunlight_propagates = true;
-       f->walkable = false;
-       f->wall_mounted = true;
-       f->air_equivalent = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       if(f->initial_metadata == NULL)
-               f->initial_metadata = new SignNodeMetadata(NULL, "Some sign");
-       setConstantMaterialProperties(f->material, 0.5);
-       f->selection_box.type = NODEBOX_WALLMOUNTED;
-       f->furnace_burntime = 10;
-       
+       f = ContentFeatures();
+       f.name = "sign_wall";
+       f.drawtype = NDT_SIGNLIKE;
+       f.setAllTextures("sign_wall.png");
+       f.setInventoryTexture("sign_wall.png");
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = true;
+       f.sunlight_propagates = true;
+       f.walkable = false;
+       f.wall_mounted = true;
+       f.air_equivalent = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       if(f.initial_metadata == NULL)
+               f.initial_metadata = new SignNodeMetadata(NULL, "Some sign");
+       setConstantMaterialProperties(f.material, 0.5);
+       f.selection_box.type = NODEBOX_WALLMOUNTED;
+       f.furnace_burntime = 10;
+       nodemgr->set(i, f);
+
        i = CONTENT_CHEST;
-       f = nodemgr->getModifiable(i);
-       f->name = "chest";
-       f->param_type = CPT_FACEDIR_SIMPLE;
-       f->setAllTextures("chest_side.png");
-       f->setTexture(0, "chest_top.png");
-       f->setTexture(1, "chest_top.png");
-       f->setTexture(5, "chest_front.png"); // Z-
-       f->setInventoryTexture("chest_top.png");
-       //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       if(f->initial_metadata == NULL)
-               f->initial_metadata = new ChestNodeMetadata(NULL);
-       setWoodLikeMaterialProperties(f->material, 1.0);
-       f->furnace_burntime = 30;
-       
+       f = ContentFeatures();
+       f.name = "chest";
+       f.param_type = CPT_FACEDIR_SIMPLE;
+       f.setAllTextures("chest_side.png");
+       f.setTexture(0, "chest_top.png");
+       f.setTexture(1, "chest_top.png");
+       f.setTexture(5, "chest_front.png"); // Z-
+       f.setInventoryTexture("chest_top.png");
+       //f.setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       if(f.initial_metadata == NULL)
+               f.initial_metadata = new ChestNodeMetadata(NULL);
+       setWoodLikeMaterialProperties(f.material, 1.0);
+       f.furnace_burntime = 30;
+       nodemgr->set(i, f);
+
        i = CONTENT_LOCKABLE_CHEST;
-       f = nodemgr->getModifiable(i);
-       f->name = "locked_chest";
-       f->param_type = CPT_FACEDIR_SIMPLE;
-       f->setAllTextures("chest_side.png");
-       f->setTexture(0, "chest_top.png");
-       f->setTexture(1, "chest_top.png");
-       f->setTexture(5, "chest_lock.png"); // Z-
-       f->setInventoryTexture("chest_lock.png");
-       //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       if(f->initial_metadata == NULL)
-               f->initial_metadata = new LockingChestNodeMetadata(NULL);
-       setWoodLikeMaterialProperties(f->material, 1.0);
-       f->furnace_burntime = 30;
+       f = ContentFeatures();
+       f.name = "locked_chest";
+       f.param_type = CPT_FACEDIR_SIMPLE;
+       f.setAllTextures("chest_side.png");
+       f.setTexture(0, "chest_top.png");
+       f.setTexture(1, "chest_top.png");
+       f.setTexture(5, "chest_lock.png"); // Z-
+       f.setInventoryTexture("chest_lock.png");
+       //f.setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       if(f.initial_metadata == NULL)
+               f.initial_metadata = new LockingChestNodeMetadata(NULL);
+       setWoodLikeMaterialProperties(f.material, 1.0);
+       f.furnace_burntime = 30;
+       nodemgr->set(i, f);
 
        i = CONTENT_FURNACE;
-       f = nodemgr->getModifiable(i);
-       f->name = "furnace";
-       f->param_type = CPT_FACEDIR_SIMPLE;
-       f->setAllTextures("furnace_side.png");
-       f->setTexture(5, "furnace_front.png"); // Z-
-       f->setInventoryTexture("furnace_front.png");
-       //f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 6";
-       if(f->initial_metadata == NULL)
-               f->initial_metadata = new FurnaceNodeMetadata(NULL);
-       setStoneLikeMaterialProperties(f->material, 3.0);
-       
+       f = ContentFeatures();
+       f.name = "furnace";
+       f.param_type = CPT_FACEDIR_SIMPLE;
+       f.setAllTextures("furnace_side.png");
+       f.setTexture(5, "furnace_front.png"); // Z-
+       f.setInventoryTexture("furnace_front.png");
+       //f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 6";
+       if(f.initial_metadata == NULL)
+               f.initial_metadata = new FurnaceNodeMetadata(NULL);
+       setStoneLikeMaterialProperties(f.material, 3.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_COBBLE;
-       f = nodemgr->getModifiable(i);
-       f->name = "cobble";
-       f->setAllTextures("cobble.png");
-       f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
-       f->param_type = CPT_NONE;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->cookresult_item = std::string("MaterialItem2 ")+itos(CONTENT_STONE)+" 1";
-       setStoneLikeMaterialProperties(f->material, 0.9);
+       f = ContentFeatures();
+       f.name = "cobble";
+       f.setAllTextures("cobble.png");
+       f.setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
+       f.param_type = CPT_NONE;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.cookresult_item = std::string("MaterialItem2 ")+itos(CONTENT_STONE)+" 1";
+       setStoneLikeMaterialProperties(f.material, 0.9);
+       nodemgr->set(i, f);
 
        i = CONTENT_MOSSYCOBBLE;
-       f = nodemgr->getModifiable(i);
-       f->name = "mossycobble";
-       f->setAllTextures("mossycobble.png");
-       f->setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png");
-       f->param_type = CPT_NONE;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setStoneLikeMaterialProperties(f->material, 0.8);
-       
+       f = ContentFeatures();
+       f.name = "mossycobble";
+       f.setAllTextures("mossycobble.png");
+       f.setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png");
+       f.param_type = CPT_NONE;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setStoneLikeMaterialProperties(f.material, 0.8);
+       nodemgr->set(i, f);
+
        i = CONTENT_STEEL;
-       f = nodemgr->getModifiable(i);
-       f->name = "steelblock";
-       f->setAllTextures("steel_block.png");
-       f->setInventoryTextureCube("steel_block.png", "steel_block.png",
+       f = ContentFeatures();
+       f.name = "steelblock";
+       f.setAllTextures("steel_block.png");
+       f.setInventoryTextureCube("steel_block.png", "steel_block.png",
                        "steel_block.png");
-       f->param_type = CPT_NONE;
-       f->is_ground_content = true;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setStoneLikeMaterialProperties(f->material, 5.0);
-       
+       f.param_type = CPT_NONE;
+       f.is_ground_content = true;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setStoneLikeMaterialProperties(f.material, 5.0);
+       nodemgr->set(i, f);
+
        i = CONTENT_NC;
-       f = nodemgr->getModifiable(i);
-       f->name = "nyancat";
-       f->param_type = CPT_FACEDIR_SIMPLE;
-       f->setAllTextures("nc_side.png");
-       f->setTexture(5, "nc_front.png"); // Z-
-       f->setTexture(4, "nc_back.png"); // Z+
-       f->setInventoryTexture("nc_front.png");
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setStoneLikeMaterialProperties(f->material, 3.0);
-       f->furnace_burntime = 1;
-       
+       f = ContentFeatures();
+       f.name = "nyancat";
+       f.param_type = CPT_FACEDIR_SIMPLE;
+       f.setAllTextures("nc_side.png");
+       f.setTexture(5, "nc_front.png"); // Z-
+       f.setTexture(4, "nc_back.png"); // Z+
+       f.setInventoryTexture("nc_front.png");
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setStoneLikeMaterialProperties(f.material, 3.0);
+       f.furnace_burntime = 1;
+       nodemgr->set(i, f);
+
        i = CONTENT_NC_RB;
-       f = nodemgr->getModifiable(i);
-       f->name = "nyancat_rainbow";
-       f->setAllTextures("nc_rb.png");
-       f->setInventoryTexture("nc_rb.png");
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       setStoneLikeMaterialProperties(f->material, 3.0);
-       f->furnace_burntime = 1;
+       f = ContentFeatures();
+       f.name = "nyancat_rainbow";
+       f.setAllTextures("nc_rb.png");
+       f.setInventoryTexture("nc_rb.png");
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       setStoneLikeMaterialProperties(f.material, 3.0);
+       f.furnace_burntime = 1;
+       nodemgr->set(i, f);
 
        i = CONTENT_SAPLING;
-       f = nodemgr->getModifiable(i);
-       f->name = "sapling";
-       f->drawtype = NDT_PLANTLIKE;
-       f->visual_scale = 1.0;
-       f->setAllTextures("sapling.png");
-       f->setInventoryTexture("sapling.png");
-       f->param_type = CPT_LIGHT;
-       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->light_propagates = true;
-       f->air_equivalent = false;
-       f->walkable = false;
-       setConstantMaterialProperties(f->material, 0.0);
-       f->furnace_burntime = 10;
-       
+       f = ContentFeatures();
+       f.name = "sapling";
+       f.drawtype = NDT_PLANTLIKE;
+       f.visual_scale = 1.0;
+       f.setAllTextures("sapling.png");
+       f.setInventoryTexture("sapling.png");
+       f.param_type = CPT_LIGHT;
+       f.dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+       f.light_propagates = true;
+       f.air_equivalent = false;
+       f.walkable = false;
+       setConstantMaterialProperties(f.material, 0.0);
+       f.furnace_burntime = 10;
+       nodemgr->set(i, f);
+
        i = CONTENT_APPLE;
-       f = nodemgr->getModifiable(i);
-       f->name = "apple";
-       f->drawtype = NDT_PLANTLIKE;
-       f->visual_scale = 1.0;
-       f->setAllTextures("apple.png");
-       f->setInventoryTexture("apple.png");
-       f->param_type = CPT_LIGHT;
-       f->light_propagates = true;
-       f->sunlight_propagates = true;
-       f->walkable = false;
-       f->air_equivalent = true;
-       f->dug_item = std::string("CraftItem apple 1");
-       setConstantMaterialProperties(f->material, 0.0);
-       f->furnace_burntime = 3;
+       f = ContentFeatures();
+       f.name = "apple";
+       f.drawtype = NDT_PLANTLIKE;
+       f.visual_scale = 1.0;
+       f.setAllTextures("apple.png");
+       f.setInventoryTexture("apple.png");
+       f.param_type = CPT_LIGHT;
+       f.light_propagates = true;
+       f.sunlight_propagates = true;
+       f.walkable = false;
+       f.air_equivalent = true;
+       f.dug_item = std::string("CraftItem apple 1");
+       setConstantMaterialProperties(f.material, 0.0);
+       f.furnace_burntime = 3;
+       nodemgr->set(i, f);
 }
 
 
index 3140f2179936ee90b057d6ca2c00cb05b7d21d85..dea653901012441450f0e20bb4020d670653e28f 100644 (file)
@@ -42,6 +42,10 @@ 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
+class NameIdMapping;
+void content_mapnode_get_name_id_mapping(NameIdMapping *nimap);
+
 /*
        Node content type IDs
        Ranges:
index 79f5d188e304199269bda07c9bf7c0936e3ae708..6708f887db314ac61b1bae0290a953a9a801714e 100644 (file)
@@ -20,6 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef GAMEDEF_HEADER
 #define GAMEDEF_HEADER
 
+#include <string>
+
 class IToolDefManager;
 class INodeDefManager;
 //class IItemDefManager; //TODO
@@ -43,6 +45,9 @@ public:
        // This is always thread-safe, but referencing the irrlicht texture
        // pointers in other threads than main thread will make things explode.
        virtual ITextureSource* getTextureSource()=0;
+       
+       // Used for keeping track of names/ids of unknown nodes
+       virtual u16 allocateUnknownNodeId(const std::string &name)=0;
 
        // Shorthands
        IToolDefManager* tdef(){return getToolDefManager();}
index 0d64f01df143335de7bac5904f5db6e57826e888..2de4377d86eee9a2d3f1ee3339e13eb21bfe7d50 100644 (file)
@@ -3367,10 +3367,10 @@ void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool
                        Save blocks loaded in old format in new format
                */
 
-               if(version < SER_FMT_VER_HIGHEST || save_after_load)
-               {
+               //if(version < SER_FMT_VER_HIGHEST || save_after_load)
+               // Only save if asked to; no need to update version
+               if(save_after_load)
                        saveBlock(block);
-               }
                
                // We just loaded it from, so it's up-to-date.
                block->resetModified();
index f7cbda74be65f438934d538a05038eab7a0c80ef..06ce9282fbb02dd0c7b45478650f11239e930b94 100644 (file)
@@ -18,14 +18,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "mapblock.h"
+
+#include <sstream>
 #include "map.h"
 // For g_settings
 #include "main.h"
 #include "light.h"
-#include <sstream>
 #include "nodedef.h"
 #include "nodemetadata.h"
 #include "gamedef.h"
+#include "log.h"
+#include "nameidmapping.h"
+#include "content_mapnode.h" // For legacy name-id mapping
 
 /*
        MapBlock
@@ -188,13 +192,13 @@ void MapBlock::replaceMesh(scene::SMesh *mesh_new)
                        IMeshBuffer *buf = mesh_old->getMeshBuffer(i);
                }*/
                
-               /*dstream<<"mesh_old->getReferenceCount()="
+               /*infostream<<"mesh_old->getReferenceCount()="
                                <<mesh_old->getReferenceCount()<<std::endl;
                u32 c = mesh_old->getMeshBufferCount();
                for(u32 i=0; i<c; i++)
                {
                        scene::IMeshBuffer *buf = mesh_old->getMeshBuffer(i);
-                       dstream<<"buf->getReferenceCount()="
+                       infostream<<"buf->getReferenceCount()="
                                        <<buf->getReferenceCount()<<std::endl;
                }*/
 
@@ -519,6 +523,86 @@ s16 MapBlock::getGroundLevel(v2s16 p2d)
        Serialization
 */
 
+// List relevant id-name pairs for ids in the block using nodedef
+static void getBlockNodeIdMapping(NameIdMapping *nimap, MapBlock *block,
+               INodeDefManager *nodedef)
+{
+       std::set<content_t> unknown_contents;
+       for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
+       for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
+       for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
+       {
+               v3s16 p(x0,y0,z0);
+               MapNode n = block->getNode(p);
+               content_t id = n.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(): IGNORING ERROR: "
+                               <<"Name for node id "<<(*i)<<" not known"<<std::endl;
+       }
+}
+// Correct ids in the block to match nodedef based on names.
+// Unknown ones are added to nodedef.
+// Will not update itself to match id-name pairs in nodedef.
+void correctBlockNodeIds(const NameIdMapping *nimap, MapBlock *block,
+               IGameDef *gamedef)
+{
+       INodeDefManager *nodedef = gamedef->ndef();
+       // This means the block contains incorrect ids, and we contain
+       // the information to convert those to names.
+       // nodedef contains information to convert our names to globally
+       // correct ids.
+       std::set<content_t> unnamed_contents;
+       std::set<std::string> unallocatable_contents;
+       for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
+       for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
+       for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
+       {
+               v3s16 p(x0,y0,z0);
+               MapNode n = block->getNode(p);
+               content_t local_id = n.getContent();
+               std::string name;
+               bool found = nimap->getName(local_id, name);
+               if(!found){
+                       unnamed_contents.insert(local_id);
+                       continue;
+               }
+               content_t global_id;
+               found = nodedef->getId(name, global_id);
+               if(!found){
+                       global_id = gamedef->allocateUnknownNodeId(name);
+                       if(global_id == CONTENT_IGNORE){
+                               unallocatable_contents.insert(name);
+                               continue;
+                       }
+               }
+               n.setContent(global_id);
+               block->setNode(p, n);
+       }
+       for(std::set<content_t>::const_iterator
+                       i = unnamed_contents.begin();
+                       i != unnamed_contents.end(); i++){
+               errorstream<<"correctBlockNodeIds(): IGNORING ERROR: "
+                               <<"Block contains id "<<(*i)
+                               <<" with no name mapping"<<std::endl;
+       }
+       for(std::set<std::string>::const_iterator
+                       i = unallocatable_contents.begin();
+                       i != unallocatable_contents.end(); i++){
+               errorstream<<"correctBlockNodeIds(): IGNORING ERROR: "
+                               <<"Could not allocate global id for node name \""
+                               <<(*i)<<"\""<<std::endl;
+       }
+}
+
 void MapBlock::serialize(std::ostream &os, u8 version)
 {
        if(!ser_ver_supported(version))
@@ -602,7 +686,7 @@ void MapBlock::serialize(std::ostream &os, u8 version)
                                flags |= 0x08;
                }
                os.write((char*)&flags, 1);
-
+               
                u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
 
                /*
@@ -663,8 +747,6 @@ void MapBlock::serialize(std::ostream &os, u8 version)
 
 void MapBlock::deSerialize(std::istream &is, u8 version)
 {
-       INodeDefManager *nodemgr = m_gamedef->ndef();
-
        if(!ser_ver_supported(version))
                throw VersionMismatchException("ERROR: MapBlock format not supported");
 
@@ -698,7 +780,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                        if(is.gcount() != len)
                                throw SerializationError
                                                ("MapBlock::deSerialize: no enough input data");
-                       data[i].deSerialize(*d, version, nodemgr);
+                       data[i].deSerialize(*d, version);
                }
        }
        else if(version <= 10)
@@ -780,7 +862,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                        buf[0] = s[i];
                        buf[1] = s[i+nodecount];
                        buf[2] = s[i+nodecount*2];
-                       data[i].deSerialize(buf, version, m_gamedef->getNodeDefManager());
+                       data[i].deSerialize(buf, version);
                }
                
                /*
@@ -807,7 +889,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                        }
                        catch(SerializationError &e)
                        {
-                               dstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
+                               errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
                                                <<" while deserializing node metadata"<<std::endl;
                        }
                }
@@ -834,6 +916,13 @@ void MapBlock::serializeDiskExtra(std::ostream &os, u8 version)
        {
                writeU32(os, getTimestamp());
        }
+
+       // Scan and write node definition id mapping
+       if(version >= 21){
+               NameIdMapping nimap;
+               getBlockNodeIdMapping(&nimap, this, m_gamedef->ndef());
+               nimap.serialize(os);
+       }
 }
 
 void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
@@ -841,12 +930,11 @@ void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
        /*
                Versions up from 9 have block objects. (DEPRECATED)
        */
-       if(version >= 9)
-       {
+       if(version >= 9){
                u16 count = readU16(is);
                // Not supported and length not known if count is not 0
                if(count != 0){
-                       dstream<<"WARNING: MapBlock::deSerializeDiskExtra(): "
+                       errorstream<<"WARNING: MapBlock::deSerializeDiskExtra(): "
                                        <<"Ignoring stuff coming at and after MBOs"<<std::endl;
                        return;
                }
@@ -856,19 +944,24 @@ void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
                Versions up from 15 have static objects.
        */
        if(version >= 15)
-       {
                m_static_objects.deSerialize(is);
-       }
                
        // Timestamp
        if(version >= 17)
-       {
                setTimestamp(readU32(is));
-       }
        else
-       {
                setTimestamp(BLOCK_TIMESTAMP_UNDEFINED);
+       
+       // Dynamically re-set ids based on node names
+       NameIdMapping nimap;
+       // If supported, read node definition id mapping
+       if(version >= 21){
+               nimap.deSerialize(is);
+       // Else set the legacy mapping
+       } else {
+               content_mapnode_get_name_id_mapping(&nimap);
        }
+       correctBlockNodeIds(&nimap, this, m_gamedef);
 }
 
 /*
@@ -877,9 +970,7 @@ void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
 std::string analyze_block(MapBlock *block)
 {
        if(block == NULL)
-       {
                return "NULL";
-       }
 
        std::ostringstream desc;
        
index e7fd932b8e2395e7613a53a8f91bdc98fd69fefd..0866fc396fa19b217ce804db4faa2c9a9b683adc 100644 (file)
@@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 class Map;
 class NodeMetadataList;
 class IGameDef;
+class IWritableNodeDefManager;
 
 #define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
 
@@ -540,8 +541,11 @@ public:
        // These don't write or read version by itself
        void serialize(std::ostream &os, u8 version);
        void deSerialize(std::istream &is, u8 version);
+
        // Used after the basic ones when writing on disk (serverside)
        void serializeDiskExtra(std::ostream &os, u8 version);
+       // In addition to doing other things, will add unknown blocks from
+       // id-name mapping to wndef
        void deSerializeDiskExtra(std::istream &is, u8 version);
 
 private:
index 2fbc81dd28d4fc984b59f470ecb6adf5aa7cb272..c5756e8ba207871e3ee33aa47415cc6e57b2fdd3 100644 (file)
@@ -268,7 +268,7 @@ void MapNode::serialize(u8 *dest, u8 version)
                dest[2] = n_foreign.param2;
        }
 }
-void MapNode::deSerialize(u8 *source, u8 version, INodeDefManager *nodemgr)
+void MapNode::deSerialize(u8 *source, u8 version)
 {
        if(!ser_ver_supported(version))
                throw VersionMismatchException("ERROR: MapNode format not supported");
@@ -280,11 +280,6 @@ void MapNode::deSerialize(u8 *source, u8 version, INodeDefManager *nodemgr)
        else if(version == 1)
        {
                param0 = source[0];
-               // This version doesn't support saved lighting
-               if(nodemgr->get(*this).light_propagates || nodemgr->get(*this).light_source > 0)
-                       param1 = 0;
-               else
-                       param1 = source[1];
        }
        else if(version <= 9)
        {
index 12dbf45c52fe18b1b47e8a6b22cf86b71939fb76..285f197db995bd7a47dac0783b79736808e29d9e 100644 (file)
@@ -221,7 +221,7 @@ struct MapNode
 
        static u32 serializedLength(u8 version);
        void serialize(u8 *dest, u8 version);
-       void deSerialize(u8 *source, u8 version, INodeDefManager *nodemgr);
+       void deSerialize(u8 *source, u8 version);
        
 };
 
diff --git a/src/nameidmapping.cpp b/src/nameidmapping.cpp
new file mode 100644 (file)
index 0000000..0fb6632
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+Minetest-c55
+Copyright (C) 2011 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 General Public License as published by
+the Free Software Foundation; either version 2 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 General Public License for more details.
+
+You should have received a copy of the GNU 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 "nameidmapping.h"
+#include "utility.h"
+
+void NameIdMapping::serialize(std::ostream &os) const
+{
+       writeU8(os, 0); // version
+       writeU16(os, m_id_to_name.size());
+       for(std::map<u16, std::string>::const_iterator
+                       i = m_id_to_name.begin();
+                       i != m_id_to_name.end(); i++){
+               writeU16(os, i->first);
+               os<<serializeString(i->second);
+       }
+}
+
+void NameIdMapping::deSerialize(std::istream &is)
+{
+       int version = readU8(is);
+       if(version != 0)
+               throw SerializationError("unsupported NameIdMapping version");
+       u32 count = readU16(is);
+       m_id_to_name.clear();
+       m_name_to_id.clear();
+       for(u32 i=0; i<count; i++){
+               u16 id = readU16(is);
+               std::string name = deSerializeString(is);
+               m_id_to_name[id] = name;
+               m_name_to_id[name] = id;
+       }
+}
+
diff --git a/src/nameidmapping.h b/src/nameidmapping.h
new file mode 100644 (file)
index 0000000..071599e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+Minetest-c55
+Copyright (C) 2011 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 General Public License as published by
+the Free Software Foundation; either version 2 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 General Public License for more details.
+
+You should have received a copy of the GNU 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 NAMEIDMAPPING_HEADER
+#define NAMEIDMAPPING_HEADER
+
+#include <string>
+#include <iostream>
+#include <set>
+#include <map>
+#include "irrlichttypes.h"
+
+class NameIdMapping
+{
+public:
+       void serialize(std::ostream &os) const;
+       void deSerialize(std::istream &is);
+       
+       void clear(){
+               m_id_to_name.clear();
+               m_name_to_id.clear();
+       }
+       void set(u16 id, const std::string &name){
+               m_id_to_name[id] = name;
+               m_name_to_id[name] = id;
+       }
+       void removeId(u16 id){
+               std::string name;
+               bool found = getName(id, name);
+               if(!found) return;
+               m_id_to_name.erase(id);
+               m_name_to_id.erase(name);
+       }
+       void eraseName(const std::string &name){
+               u16 id;
+               bool found = getId(name, id);
+               if(!found) return;
+               m_id_to_name.erase(id);
+               m_name_to_id.erase(name);
+       }
+       bool getName(u16 id, std::string &result) const{
+               std::map<u16, std::string>::const_iterator i;
+               i = m_id_to_name.find(id);
+               if(i == m_id_to_name.end())
+                       return false;
+               result = i->second;
+               return true;
+       }
+       bool getId(const std::string &name, u16 &result) const{
+               std::map<std::string, u16>::const_iterator i;
+               i = m_name_to_id.find(name);
+               if(i == m_name_to_id.end())
+                       return false;
+               result = i->second;
+               return true;
+       }
+private:
+       std::map<u16, std::string> m_id_to_name;
+       std::map<std::string, u16> m_name_to_id;
+};
+
+#endif
+
index 166d9cba007000dd8065e8c5d672492decc0affc..baaaa1048ae987e8be1abc249d67b9dbb84d74d2 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #endif
 #include "log.h"
 #include "settings.h"
+#include "nameidmapping.h"
 
 /*
        NodeBox
@@ -318,20 +319,63 @@ class CNodeDefManager: public IWritableNodeDefManager
 public:
        void clear()
        {
+               m_name_id_mapping.clear();
                for(u16 i=0; i<=MAX_CONTENT; i++)
                {
-                       ContentFeatures *f = &m_content_features[i];
-                       f->reset(); // Reset to defaults
-                       if(i == CONTENT_IGNORE || i == CONTENT_AIR){
-                               f->drawtype = NDT_AIRLIKE;
-                               continue;
+                       ContentFeatures &f = m_content_features[i];
+                       f.reset(); // Reset to defaults
+                       f.setAllTextures("unknown_block.png");
+               }
+               
+               // Set CONTENT_AIR
+               {
+                       ContentFeatures f;
+                       f.name = "air";
+                       f.drawtype = NDT_AIRLIKE;
+                       f.param_type = CPT_LIGHT;
+                       f.light_propagates = true;
+                       f.sunlight_propagates = true;
+                       f.walkable = false;
+                       f.pointable = false;
+                       f.diggable = false;
+                       f.buildable_to = true;
+                       f.air_equivalent = true;
+                       set(CONTENT_AIR, f);
+               }
+               // Set CONTENT_IGNORE
+               {
+                       ContentFeatures f;
+                       f.name = "ignore";
+                       f.drawtype = NDT_AIRLIKE;
+                       f.param_type = CPT_LIGHT;
+                       f.light_propagates = true;
+                       f.sunlight_propagates = true;
+                       f.walkable = false;
+                       f.pointable = false;
+                       f.diggable = false;
+                       f.buildable_to = true;
+                       f.air_equivalent = true;
+                       set(CONTENT_AIR, f);
+               }
+       }
+       // CONTENT_IGNORE = not found
+       content_t getFreeId(bool require_full_param2)
+       {
+               // If allowed, first search in the large 4-byte-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;
                        }
-                       f->setAllTextures("unknown_block.png");
                }
-#ifndef SERVER
-               // Make CONTENT_IGNORE to not block the view when occlusion culling
-               m_content_features[CONTENT_IGNORE].solidness = 0;
-#endif
+               // Then search from the small 8-byte-param2 pool
+               for(u16 i=0; i<=125; i++){
+                       const ContentFeatures &f = m_content_features[i];
+                       if(f.name == "")
+                               return i;
+               }
+               return CONTENT_IGNORE;
        }
        CNodeDefManager()
        {
@@ -358,18 +402,54 @@ public:
        {
                return get(n.getContent());
        }
-       // Writable
+       virtual bool getId(const std::string &name, content_t &result) const
+       {
+               return m_name_id_mapping.getId(name, result);
+       }
+       // IWritableNodeDefManager
        virtual void set(content_t c, const ContentFeatures &def)
        {
                infostream<<"registerNode: registering content id \""<<c
                                <<"\": name=\""<<def.name<<"\""<<std::endl;
                assert(c <= MAX_CONTENT);
                m_content_features[c] = def;
+               if(def.name != "")
+                       m_name_id_mapping.set(c, def.name);
        }
-       virtual ContentFeatures* getModifiable(content_t c)
+       virtual content_t set(const std::string &name,
+                       const ContentFeatures &def)
        {
-               assert(c <= MAX_CONTENT);
-               return &m_content_features[c];
+               assert(name == def.name);
+               u16 id = CONTENT_IGNORE;
+               bool found = m_name_id_mapping.getId(name, id);
+               if(!found){
+                       // Determine if full param2 is required
+                       bool require_full_param2 = (
+                               def.liquid_type == LIQUID_FLOWING
+                               ||
+                               def.drawtype == NDT_FLOWINGLIQUID
+                               ||
+                               def.drawtype == NDT_TORCHLIKE
+                               ||
+                               def.drawtype == NDT_SIGNLIKE
+                       );
+                       // Get some id
+                       id = getFreeId(require_full_param2);
+                       if(id == CONTENT_IGNORE)
+                               return CONTENT_IGNORE;
+                       if(name != "")
+                               m_name_id_mapping.set(id, name);
+               }
+               set(id, def);
+               return id;
+       }
+       virtual content_t allocateDummy(const std::string &name)
+       {
+               assert(name != "");
+               ContentFeatures f;
+               f.name = name;
+               f.setAllTextures("unknown_block.png");
+               return set(name, f);
        }
        virtual void updateTextures(ITextureSource *tsrc)
        {
@@ -499,6 +579,8 @@ public:
                std::ostringstream tmp_os(std::ios::binary);
                for(u16 i=0; i<=MAX_CONTENT; i++)
                {
+                       if(i == CONTENT_IGNORE || i == CONTENT_AIR)
+                               continue;
                        ContentFeatures *f = &m_content_features[i];
                        if(f->name == "")
                                continue;
@@ -523,10 +605,13 @@ public:
                        }
                        ContentFeatures *f = &m_content_features[i];
                        f->deSerialize(tmp_is, gamedef);
+                       if(f->name != "")
+                               m_name_id_mapping.set(i, f->name);
                }
        }
 private:
        ContentFeatures m_content_features[MAX_CONTENT+1];
+       NameIdMapping m_name_id_mapping;
 };
 
 IWritableNodeDefManager* createNodeDefManager()
index a29626b10fff7ed1aaea3327231c811c3d1bde97..055ed7a4b46b571d52539388aa9232b665152077 100644 (file)
@@ -253,6 +253,7 @@ public:
        // Get node definition
        virtual const ContentFeatures& get(content_t c) const=0;
        virtual const ContentFeatures& get(const MapNode &n) const=0;
+       virtual bool getId(const std::string &name, content_t &result) const=0;
        
        virtual void serialize(std::ostream &os)=0;
 };
@@ -266,10 +267,16 @@ public:
        // Get node definition
        virtual const ContentFeatures& get(content_t c) const=0;
        virtual const ContentFeatures& get(const MapNode &n) const=0;
+       virtual bool getId(const std::string &name, content_t &result) const=0;
                
        // Register node definition
        virtual void set(content_t c, const ContentFeatures &def)=0;
-       virtual ContentFeatures* getModifiable(content_t c)=0;
+       // Register node definition by name (allocate an id)
+       // If returns CONTENT_IGNORE, could not allocate id
+       virtual content_t set(const std::string &name,
+                       const ContentFeatures &def)=0;
+       // If returns CONTENT_IGNORE, could not allocate id
+       virtual content_t allocateDummy(const std::string &name)=0;
 
        /*
                Update tile textures to latest return values of TextueSource.
index d93e6189299e5dd147e36756c89ef4d7ea0a9370..cc43811551ef6b35065cb76bdca92929e3d85865 100644 (file)
@@ -56,11 +56,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        18: new generator (not really necessary, but it's there)
        19: new content type handling
        20: many existing content types translated to extended ones
+       21: dynamic content type allocation
 */
 // This represents an uninitialized or invalid format
 #define SER_FMT_VER_INVALID 255
 // Highest supported serialization version
-#define SER_FMT_VER_HIGHEST 20
+#define SER_FMT_VER_HIGHEST 21
 // Lowest supported serialization version
 #define SER_FMT_VER_LOWEST 0
 
index 6a3421c0d9f6610709f445f2d7f84a161703f876..a488f3045f2170aa108583674300d55c8b5b546c 100644 (file)
@@ -4428,6 +4428,10 @@ ITextureSource* Server::getTextureSource()
 {
        return NULL;
 }
+u16 Server::allocateUnknownNodeId(const std::string &name)
+{
+       return m_nodemgr->allocateDummy(name);
+}
 
 IWritableToolDefManager* Server::getWritableToolDefManager()
 {
index 4ba28e3322fbb3c733b3f83ae9846a50395de23b..164cfe9cd91cc00a9c0a760f7821916cd002582b 100644 (file)
@@ -491,6 +491,7 @@ public:
        virtual IToolDefManager* getToolDefManager();
        virtual INodeDefManager* getNodeDefManager();
        virtual ITextureSource* getTextureSource();
+       virtual u16 allocateUnknownNodeId(const std::string &name);
        
        IWritableToolDefManager* getWritableToolDefManager();
        IWritableNodeDefManager* getWritableNodeDefManager();