Completely generalized mesh generation; ContentFeatures serialization
authorPerttu Ahola <celeron55@gmail.com>
Tue, 15 Nov 2011 17:58:36 +0000 (19:58 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 29 Nov 2011 17:13:44 +0000 (19:13 +0200)
18 files changed:
minetest.conf.example
src/common_irrlicht.h
src/content_mapblock.cpp
src/content_mapnode.cpp
src/content_mapnode.h
src/defaultsettings.cpp
src/game.cpp
src/irrlichttypes.h
src/mapnode.cpp
src/mapnode.h
src/materials.cpp
src/materials.h
src/nodedef.cpp
src/nodedef.h
src/server.cpp
src/test.cpp
src/tile.cpp
src/utility.h

index 30adc5e601cb472ce85232c65d44001bafcb3445..e0c43d72854aa91b70ae971b89b334fe2e981cc4 100644 (file)
 #farmesh_distance = 40
 # Enable/disable clouds
 #enable_clouds = true
-# Don't draw stone (for testing)
-#invisible_stone = false
 # Path for screenshots
 #screenshot_path = .
 # Amount of view bobbing (0 = no view bobbing, 1.0 = normal, 2.0 = double)
index 379c2d15a6fb101279402c390bf0bcdd9ea4e204..0a2ed0be1bc3db8ff0d5825637bb3ec3b37f082c 100644 (file)
@@ -26,7 +26,6 @@ video::SColor(255,30,30,30));d->endScene();}
 #include "irrlichttypes.h"
 
 #ifndef SERVER
-#include <SColor.h>
 #include <IMesh.h>
 #include <IImage.h>
 #include <IrrlichtDevice.h>
index 368e6c6114dacd235cf4c3b254385ef67741a52b..3950c83c3cfc0da20ef5c9a31c2d5a58db4361d6 100644 (file)
@@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "content_mapblock.h"
-#include "content_mapnode.h"
+
 #include "main.h" // For g_settings
 #include "mineral.h"
 #include "mapblock_mesh.h" // For MapBlock_LightColor()
@@ -125,7 +125,6 @@ void makeCuboid(video::SMaterial &material, MeshCollector *collector,
 void mapblock_mesh_generate_special(MeshMakeData *data,
                MeshCollector &collector, IGameDef *gamedef)
 {
-       ITextureSource *tsrc = gamedef->tsrc();
        INodeDefManager *nodedef = gamedef->ndef();
 
        // 0ms
@@ -135,9 +134,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                Some settings
        */
        bool new_style_water = g_settings->getBool("new_style_water");
-       bool new_style_leaves = g_settings->getBool("new_style_leaves");
-       //bool smooth_lighting = g_settings->getBool("smooth_lighting");
-       bool invisible_stone = g_settings->getBool("invisible_stone");
        
        float node_liquid_level = 1.0;
        if(new_style_water)
@@ -145,86 +141,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        
        v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE;
 
-       // New-style leaves material
-       video::SMaterial material_leaves1;
-       material_leaves1.setFlag(video::EMF_LIGHTING, false);
-       material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
-       material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
-       material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-       AtlasPointer pa_leaves1 = tsrc->getTexture(
-                       tsrc->getTextureId("leaves.png"));
-       material_leaves1.setTexture(0, pa_leaves1.atlas);
-
-       // Glass material
-       video::SMaterial material_glass;
-       material_glass.setFlag(video::EMF_LIGHTING, false);
-       material_glass.setFlag(video::EMF_BILINEAR_FILTER, false);
-       material_glass.setFlag(video::EMF_FOG_ENABLE, true);
-       material_glass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-       AtlasPointer pa_glass = tsrc->getTexture(
-                       tsrc->getTextureId("glass.png"));
-       material_glass.setTexture(0, pa_glass.atlas);
-
-       // Wood material
-       video::SMaterial material_wood;
-       material_wood.setFlag(video::EMF_LIGHTING, false);
-       material_wood.setFlag(video::EMF_BILINEAR_FILTER, false);
-       material_wood.setFlag(video::EMF_FOG_ENABLE, true);
-       material_wood.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-       AtlasPointer pa_wood = tsrc->getTexture(
-                       tsrc->getTextureId("wood.png"));
-       material_wood.setTexture(0, pa_wood.atlas);
-
-       // General ground material for special output
+       /*// General ground material for special output
        // Texture is modified just before usage
        video::SMaterial material_general;
        material_general.setFlag(video::EMF_LIGHTING, false);
        material_general.setFlag(video::EMF_BILINEAR_FILTER, false);
        material_general.setFlag(video::EMF_FOG_ENABLE, true);
-       material_general.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-
-
-       // Papyrus material
-       video::SMaterial material_papyrus;
-       material_papyrus.setFlag(video::EMF_LIGHTING, false);
-       material_papyrus.setFlag(video::EMF_BILINEAR_FILTER, false);
-       material_papyrus.setFlag(video::EMF_FOG_ENABLE, true);
-       material_papyrus.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-       AtlasPointer pa_papyrus = tsrc->getTexture(
-                       tsrc->getTextureId("papyrus.png"));
-       material_papyrus.setTexture(0, pa_papyrus.atlas);
-       
-       // Apple material
-       video::SMaterial material_apple;
-       material_apple.setFlag(video::EMF_LIGHTING, false);
-       material_apple.setFlag(video::EMF_BILINEAR_FILTER, false);
-       material_apple.setFlag(video::EMF_FOG_ENABLE, true);
-       material_apple.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-       AtlasPointer pa_apple = tsrc->getTexture(
-                       tsrc->getTextureId("apple.png"));
-       material_apple.setTexture(0, pa_apple.atlas);
-
-
-       // Sapling material
-       video::SMaterial material_sapling;
-       material_sapling.setFlag(video::EMF_LIGHTING, false);
-       material_sapling.setFlag(video::EMF_BILINEAR_FILTER, false);
-       material_sapling.setFlag(video::EMF_FOG_ENABLE, true);
-       material_sapling.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-       AtlasPointer pa_sapling = tsrc->getTexture(
-                       tsrc->getTextureId("sapling.png"));
-       material_sapling.setTexture(0, pa_sapling.atlas);
-
-
-       // junglegrass material
-       video::SMaterial material_junglegrass;
-       material_junglegrass.setFlag(video::EMF_LIGHTING, false);
-       material_junglegrass.setFlag(video::EMF_BILINEAR_FILTER, false);
-       material_junglegrass.setFlag(video::EMF_FOG_ENABLE, true);
-       material_junglegrass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-       AtlasPointer pa_junglegrass = tsrc->getTexture(
-                       tsrc->getTextureId("junglegrass.png"));
-       material_junglegrass.setTexture(0, pa_junglegrass.atlas);
+       material_general.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;*/
 
        for(s16 z=0; z<MAP_BLOCKSIZE; z++)
        for(s16 y=0; y<MAP_BLOCKSIZE; y++)
@@ -233,143 +156,74 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                v3s16 p(x,y,z);
 
                MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes+p);
+               const ContentFeatures &f = nodedef->get(n);
 
                // Only solidness=0 stuff is drawn here
-               if(nodedef->get(n).solidness != 0)
+               if(f.solidness != 0)
                        continue;
-
-               /*
-                       Add torches to mesh
-               */
-               if(n.getContent() == CONTENT_TORCH)
+               
+               switch(f.drawtype){
+               default:
+                       infostream<<"Got "<<f.drawtype<<std::endl;
+                       assert(0);
+                       break;
+               case NDT_AIRLIKE:
+                       break;
+               case NDT_LIQUID:
                {
-                       v3s16 dir = unpackDir(n.param2);
-                       
-                       const char *texturename = "torch.png";
-                       if(dir == v3s16(0,-1,0)){
-                               texturename = "torch_on_floor.png";
-                       } else if(dir == v3s16(0,1,0)){
-                               texturename = "torch_on_ceiling.png";
-                       // For backwards compatibility
-                       } else if(dir == v3s16(0,0,0)){
-                               texturename = "torch_on_floor.png";
-                       } else {
-                               texturename = "torch.png";
-                       }
-
-                       AtlasPointer ap = tsrc->getTexture(texturename);
-
-                       // Set material
-                       video::SMaterial material;
-                       material.setFlag(video::EMF_LIGHTING, false);
-                       material.setFlag(video::EMF_BACK_FACE_CULLING, false);
-                       material.setFlag(video::EMF_BILINEAR_FILTER, false);
-                       material.setFlag(video::EMF_FOG_ENABLE, true);
-                       //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
-                       material.MaterialType
-                                       = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-                       material.setTexture(0, ap.atlas);
-
-                       video::SColor c(255,255,255,255);
-
-                       // Wall at X+ of node
-                       video::S3DVertex vertices[4] =
-                       {
-                               video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
-                                               ap.x0(), ap.y1()),
-                               video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
-                                               ap.x1(), ap.y1()),
-                               video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
-                                               ap.x1(), ap.y0()),
-                               video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
-                                               ap.x0(), ap.y0()),
-                       };
-
-                       for(s32 i=0; i<4; i++)
-                       {
-                               if(dir == v3s16(1,0,0))
-                                       vertices[i].Pos.rotateXZBy(0);
-                               if(dir == v3s16(-1,0,0))
-                                       vertices[i].Pos.rotateXZBy(180);
-                               if(dir == v3s16(0,0,1))
-                                       vertices[i].Pos.rotateXZBy(90);
-                               if(dir == v3s16(0,0,-1))
-                                       vertices[i].Pos.rotateXZBy(-90);
-                               if(dir == v3s16(0,-1,0))
-                                       vertices[i].Pos.rotateXZBy(45);
-                               if(dir == v3s16(0,1,0))
-                                       vertices[i].Pos.rotateXZBy(-45);
-
-                               vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
-                       }
+                       /*
+                               Add water sources to mesh if using new style
+                       */
+                       assert(nodedef->get(n).special_materials[0]);
+                       //assert(nodedef->get(n).special_materials[1]);
+                       assert(nodedef->get(n).special_aps[0]);
 
-                       u16 indices[] = {0,1,2,2,3,0};
-                       // Add to mesh collector
-                       collector.append(material, vertices, 4, indices, 6);
-               }
-               /*
-                       Signs on walls
-               */
-               else if(n.getContent() == CONTENT_SIGN_WALL)
-               {
-                       AtlasPointer ap = tsrc->getTexture("sign_wall.png");
+                       video::SMaterial &liquid_material =
+                                       *nodedef->get(n).special_materials[0];
+                       /*video::SMaterial &liquid_material_bfculled =
+                                       *nodedef->get(n).special_materials[1];*/
+                       AtlasPointer &pa_liquid1 =
+                                       *nodedef->get(n).special_aps[0];
 
-                       // Set material
-                       video::SMaterial material;
-                       material.setFlag(video::EMF_LIGHTING, false);
-                       material.setFlag(video::EMF_BACK_FACE_CULLING, false);
-                       material.setFlag(video::EMF_BILINEAR_FILTER, false);
-                       material.setFlag(video::EMF_FOG_ENABLE, true);
-                       material.MaterialType
-                                       = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-                       material.setTexture(0, ap.atlas);
+                       bool top_is_air = false;
+                       MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
+                       if(n.getContent() == CONTENT_AIR)
+                               top_is_air = true;
+                       
+                       if(top_is_air == false)
+                               continue;
 
                        u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
-                       video::SColor c = MapBlock_LightColor(255, l);
-                               
-                       float d = (float)BS/16;
-                       // Wall at X+ of node
+                       video::SColor c = MapBlock_LightColor(
+                                       nodedef->get(n).alpha, l);
+                       
                        video::S3DVertex vertices[4] =
                        {
-                               video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
-                                               ap.x0(), ap.y1()),
-                               video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
-                                               ap.x1(), ap.y1()),
-                               video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
-                                               ap.x1(), ap.y0()),
-                               video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
-                                               ap.x0(), ap.y0()),
+                               video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
+                                               pa_liquid1.x0(), pa_liquid1.y1()),
+                               video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
+                                               pa_liquid1.x1(), pa_liquid1.y1()),
+                               video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
+                                               pa_liquid1.x1(), pa_liquid1.y0()),
+                               video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
+                                               pa_liquid1.x0(), pa_liquid1.y0()),
                        };
 
-                       v3s16 dir = unpackDir(n.param2);
-
                        for(s32 i=0; i<4; i++)
                        {
-                               if(dir == v3s16(1,0,0))
-                                       vertices[i].Pos.rotateXZBy(0);
-                               if(dir == v3s16(-1,0,0))
-                                       vertices[i].Pos.rotateXZBy(180);
-                               if(dir == v3s16(0,0,1))
-                                       vertices[i].Pos.rotateXZBy(90);
-                               if(dir == v3s16(0,0,-1))
-                                       vertices[i].Pos.rotateXZBy(-90);
-                               if(dir == v3s16(0,-1,0))
-                                       vertices[i].Pos.rotateXYBy(-90);
-                               if(dir == v3s16(0,1,0))
-                                       vertices[i].Pos.rotateXYBy(90);
-
+                               vertices[i].Pos.Y += (-0.5+node_liquid_level)*BS;
                                vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
                        }
 
                        u16 indices[] = {0,1,2,2,3,0};
                        // Add to mesh collector
-                       collector.append(material, vertices, 4, indices, 6);
-               }
-               /*
-                       Add flowing liquid to mesh
-               */
-               else if(nodedef->get(n).liquid_type == LIQUID_FLOWING)
+                       collector.append(liquid_material, vertices, 4, indices, 6);
+               break;}
+               case NDT_FLOWINGLIQUID:
                {
+                       /*
+                               Add flowing liquid to mesh
+                       */
                        assert(nodedef->get(n).special_materials[0]);
                        assert(nodedef->get(n).special_materials[1]);
                        assert(nodedef->get(n).special_aps[0]);
@@ -659,64 +513,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                // Add to mesh collector
                                collector.append(liquid_material, vertices, 4, indices, 6);
                        }
-               }
-               /*
-                       Add water sources to mesh if using new style
-               */
-               else if(nodedef->get(n).liquid_type == LIQUID_SOURCE
-                               && new_style_water)
+               break;}
+               case NDT_GLASSLIKE:
                {
-                       assert(nodedef->get(n).special_materials[0]);
-                       //assert(nodedef->get(n).special_materials[1]);
-                       assert(nodedef->get(n).special_aps[0]);
-
-                       video::SMaterial &liquid_material =
-                                       *nodedef->get(n).special_materials[0];
-                       /*video::SMaterial &liquid_material_bfculled =
-                                       *nodedef->get(n).special_materials[1];*/
-                       AtlasPointer &pa_liquid1 =
-                                       *nodedef->get(n).special_aps[0];
-
-                       bool top_is_air = false;
-                       MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
-                       if(n.getContent() == CONTENT_AIR)
-                               top_is_air = true;
-                       
-                       if(top_is_air == false)
-                               continue;
-
-                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
-                       video::SColor c = MapBlock_LightColor(
-                                       nodedef->get(n).alpha, l);
-                       
-                       video::S3DVertex vertices[4] =
-                       {
-                               video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c,
-                                               pa_liquid1.x0(), pa_liquid1.y1()),
-                               video::S3DVertex(BS/2,0,BS/2, 0,0,0, c,
-                                               pa_liquid1.x1(), pa_liquid1.y1()),
-                               video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c,
-                                               pa_liquid1.x1(), pa_liquid1.y0()),
-                               video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c,
-                                               pa_liquid1.x0(), pa_liquid1.y0()),
-                       };
-
-                       for(s32 i=0; i<4; i++)
-                       {
-                               vertices[i].Pos.Y += (-0.5+node_liquid_level)*BS;
-                               vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
-                       }
+                       video::SMaterial material_glass;
+                       material_glass.setFlag(video::EMF_LIGHTING, false);
+                       material_glass.setFlag(video::EMF_BILINEAR_FILTER, false);
+                       material_glass.setFlag(video::EMF_FOG_ENABLE, true);
+                       material_glass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+                       AtlasPointer pa_glass = f.tiles[0].texture;
+                       material_glass.setTexture(0, pa_glass.atlas);
 
-                       u16 indices[] = {0,1,2,2,3,0};
-                       // Add to mesh collector
-                       collector.append(liquid_material, vertices, 4, indices, 6);
-               }
-               /*
-                       Add leaves if using new style
-               */
-               else if(n.getContent() == CONTENT_LEAVES && new_style_leaves)
-               {
-                       /*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));*/
                        u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
                        video::SColor c = MapBlock_LightColor(255, l);
 
@@ -725,13 +532,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                video::S3DVertex vertices[4] =
                                {
                                        video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
-                                               pa_leaves1.x0(), pa_leaves1.y1()),
+                                               pa_glass.x0(), pa_glass.y1()),
                                        video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
-                                               pa_leaves1.x1(), pa_leaves1.y1()),
+                                               pa_glass.x1(), pa_glass.y1()),
                                        video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
-                                               pa_leaves1.x1(), pa_leaves1.y0()),
+                                               pa_glass.x1(), pa_glass.y0()),
                                        video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
-                                               pa_leaves1.x0(), pa_leaves1.y0()),
+                                               pa_glass.x0(), pa_glass.y0()),
                                };
 
                                if(j == 0)
@@ -772,14 +579,19 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 
                                u16 indices[] = {0,1,2,2,3,0};
                                // Add to mesh collector
-                               collector.append(material_leaves1, vertices, 4, indices, 6);
+                               collector.append(material_glass, vertices, 4, indices, 6);
                        }
-               }
-               /*
-                       Add glass
-               */
-               else if(n.getContent() == CONTENT_GLASS)
+               break;}
+               case NDT_ALLFACES:
                {
+                       video::SMaterial material_leaves1;
+                       material_leaves1.setFlag(video::EMF_LIGHTING, false);
+                       material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
+                       material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
+                       material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+                       AtlasPointer pa_leaves1 = f.tiles[0].texture;
+                       material_leaves1.setTexture(0, pa_leaves1.atlas);
+
                        u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
                        video::SColor c = MapBlock_LightColor(255, l);
 
@@ -788,13 +600,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                video::S3DVertex vertices[4] =
                                {
                                        video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
-                                               pa_glass.x0(), pa_glass.y1()),
+                                               pa_leaves1.x0(), pa_leaves1.y1()),
                                        video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
-                                               pa_glass.x1(), pa_glass.y1()),
+                                               pa_leaves1.x1(), pa_leaves1.y1()),
                                        video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
-                                               pa_glass.x1(), pa_glass.y0()),
+                                               pa_leaves1.x1(), pa_leaves1.y0()),
                                        video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
-                                               pa_glass.x0(), pa_glass.y0()),
+                                               pa_leaves1.x0(), pa_leaves1.y0()),
                                };
 
                                if(j == 0)
@@ -835,158 +647,141 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 
                                u16 indices[] = {0,1,2,2,3,0};
                                // Add to mesh collector
-                               collector.append(material_glass, vertices, 4, indices, 6);
+                               collector.append(material_leaves1, vertices, 4, indices, 6);
                        }
-               }
-               /*
-                       Add fence
-               */
-               else if(n.getContent() == CONTENT_FENCE)
+               break;}
+               case NDT_ALLFACES_OPTIONAL:
+                       // This is always pre-converted to something else
+                       assert(0);
+                       break;
+               case NDT_TORCHLIKE:
                {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
-                       video::SColor c = MapBlock_LightColor(255, l);
+                       v3s16 dir = unpackDir(n.param2);
+                       
+                       AtlasPointer ap(0);
+                       if(dir == v3s16(0,-1,0)){
+                               ap = f.tiles[0].texture; // floor
+                       } else if(dir == v3s16(0,1,0)){
+                               ap = f.tiles[1].texture; // ceiling
+                       // For backwards compatibility
+                       } else if(dir == v3s16(0,0,0)){
+                               ap = f.tiles[0].texture; // floor
+                       } else {
+                               ap = f.tiles[2].texture; // side
+                       }
 
-                       const f32 post_rad=(f32)BS/10;
-                       const f32 bar_rad=(f32)BS/20;
-                       const f32 bar_len=(f32)(BS/2)-post_rad;
+                       // Set material
+                       video::SMaterial material;
+                       material.setFlag(video::EMF_LIGHTING, false);
+                       material.setFlag(video::EMF_BACK_FACE_CULLING, false);
+                       material.setFlag(video::EMF_BILINEAR_FILTER, false);
+                       material.setFlag(video::EMF_FOG_ENABLE, true);
+                       //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+                       material.MaterialType
+                                       = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+                       material.setTexture(0, ap.atlas);
 
-                       // The post - always present
-                       v3f pos = intToFloat(p+blockpos_nodes, BS);
-                       f32 postuv[24]={
-                                       0.4,0.4,0.6,0.6,
-                                       0.35,0,0.65,1,
-                                       0.35,0,0.65,1,
-                                       0.35,0,0.65,1,
-                                       0.35,0,0.65,1,
-                                       0.4,0.4,0.6,0.6};
-                       makeCuboid(material_wood, &collector,
-                               &pa_wood, c, pos,
-                               post_rad,BS/2,post_rad, postuv);
+                       video::SColor c(255,255,255,255);
 
-                       // Now a section of fence, +X, if there's a post there
-                       v3s16 p2 = p;
-                       p2.X++;
-                       MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
-                       if(n2.getContent() == CONTENT_FENCE)
+                       // Wall at X+ of node
+                       video::S3DVertex vertices[4] =
                        {
-                               pos = intToFloat(p+blockpos_nodes, BS);
-                               pos.X += BS/2;
-                               pos.Y += BS/4;
-                               f32 xrailuv[24]={
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6};
-                               makeCuboid(material_wood, &collector,
-                                       &pa_wood, c, pos,
-                                       bar_len,bar_rad,bar_rad, xrailuv);
-
-                               pos.Y -= BS/2;
-                               makeCuboid(material_wood, &collector,
-                                       &pa_wood, c, pos,
-                                       bar_len,bar_rad,bar_rad, xrailuv);
-                       }
+                               video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
+                                               ap.x0(), ap.y1()),
+                               video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
+                                               ap.x1(), ap.y1()),
+                               video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
+                                               ap.x1(), ap.y0()),
+                               video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
+                                               ap.x0(), ap.y0()),
+                       };
 
-                       // Now a section of fence, +Z, if there's a post there
-                       p2 = p;
-                       p2.Z++;
-                       n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
-                       if(n2.getContent() == CONTENT_FENCE)
+                       for(s32 i=0; i<4; i++)
                        {
-                               pos = intToFloat(p+blockpos_nodes, BS);
-                               pos.Z += BS/2;
-                               pos.Y += BS/4;
-                               f32 zrailuv[24]={
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6,
-                                       0,0.4,1,0.6};
-                               makeCuboid(material_wood, &collector,
-                                       &pa_wood, c, pos,
-                                       bar_rad,bar_rad,bar_len, zrailuv);
-                               pos.Y -= BS/2;
-                               makeCuboid(material_wood, &collector,
-                                       &pa_wood, c, pos,
-                                       bar_rad,bar_rad,bar_len, zrailuv);
+                               if(dir == v3s16(1,0,0))
+                                       vertices[i].Pos.rotateXZBy(0);
+                               if(dir == v3s16(-1,0,0))
+                                       vertices[i].Pos.rotateXZBy(180);
+                               if(dir == v3s16(0,0,1))
+                                       vertices[i].Pos.rotateXZBy(90);
+                               if(dir == v3s16(0,0,-1))
+                                       vertices[i].Pos.rotateXZBy(-90);
+                               if(dir == v3s16(0,-1,0))
+                                       vertices[i].Pos.rotateXZBy(45);
+                               if(dir == v3s16(0,1,0))
+                                       vertices[i].Pos.rotateXZBy(-45);
 
+                               vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
                        }
 
-               }
-#if 1
-               /*
-                       Add stones with minerals if stone is invisible
-               */
-               else if(n.getContent() == CONTENT_STONE && invisible_stone && n.getMineral(nodedef) != MINERAL_NONE)
+                       u16 indices[] = {0,1,2,2,3,0};
+                       // Add to mesh collector
+                       collector.append(material, vertices, 4, indices, 6);
+               break;}
+               case NDT_SIGNLIKE:
                {
-                       for(u32 j=0; j<6; j++)
-                       {
-                               // NOTE: Hopefully g_6dirs[j] is the right direction...
-                               v3s16 dir = g_6dirs[j];
-                               /*u8 l = 0;
-                               MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir);
-                               if(nodedef->get(n2).param_type == CPT_LIGHT)
-                                       l = decode_light(n2.getLightBlend(data->m_daynight_ratio, nodedef));
-                               else
-                                       l = 255;*/
-                               u8 l = 255;
-                               video::SColor c = MapBlock_LightColor(255, l);
-                               
-                               // Get the right texture
-                               TileSpec ts = n.getTile(dir, tsrc, nodedef);
-                               AtlasPointer ap = ts.texture;
-                               material_general.setTexture(0, ap.atlas);
+                       // Set material
+                       video::SMaterial material;
+                       material.setFlag(video::EMF_LIGHTING, false);
+                       material.setFlag(video::EMF_BACK_FACE_CULLING, false);
+                       material.setFlag(video::EMF_BILINEAR_FILTER, false);
+                       material.setFlag(video::EMF_FOG_ENABLE, true);
+                       material.MaterialType
+                                       = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+                       AtlasPointer ap = f.tiles[0].texture;
+                       material.setTexture(0, ap.atlas);
 
-                               video::S3DVertex vertices[4] =
-                               {
-                                       video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
+                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
+                       video::SColor c = MapBlock_LightColor(255, l);
+                               
+                       float d = (float)BS/16;
+                       // Wall at X+ of node
+                       video::S3DVertex vertices[4] =
+                       {
+                               video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
                                                ap.x0(), ap.y1()),
-                                       video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
+                               video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
                                                ap.x1(), ap.y1()),
-                                       video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
+                               video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
                                                ap.x1(), ap.y0()),
-                                       video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
+                               video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
                                                ap.x0(), ap.y0()),
-                               };
+                       };
 
-                               if(j == 0)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(0);
-                               }
-                               else if(j == 1)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(180);
-                               }
-                               else if(j == 2)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(-90);
-                               }
-                               else if(j == 3)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(90);
-                               }
-                               else if(j == 4)
+                       v3s16 dir = unpackDir(n.param2);
 
-                               for(u16 i=0; i<4; i++)
-                               {
-                                       vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
-                               }
+                       for(s32 i=0; i<4; i++)
+                       {
+                               if(dir == v3s16(1,0,0))
+                                       vertices[i].Pos.rotateXZBy(0);
+                               if(dir == v3s16(-1,0,0))
+                                       vertices[i].Pos.rotateXZBy(180);
+                               if(dir == v3s16(0,0,1))
+                                       vertices[i].Pos.rotateXZBy(90);
+                               if(dir == v3s16(0,0,-1))
+                                       vertices[i].Pos.rotateXZBy(-90);
+                               if(dir == v3s16(0,-1,0))
+                                       vertices[i].Pos.rotateXYBy(-90);
+                               if(dir == v3s16(0,1,0))
+                                       vertices[i].Pos.rotateXYBy(90);
 
-                               u16 indices[] = {0,1,2,2,3,0};
-                               // Add to mesh collector
-                               collector.append(material_general, vertices, 4, indices, 6);
+                               vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
                        }
-               }
-#endif
-               else if(n.getContent() == CONTENT_PAPYRUS)
+
+                       u16 indices[] = {0,1,2,2,3,0};
+                       // Add to mesh collector
+                       collector.append(material, vertices, 4, indices, 6);
+               break;}
+               case NDT_PLANTLIKE:
                {
+                       video::SMaterial material_papyrus;
+                       material_papyrus.setFlag(video::EMF_LIGHTING, false);
+                       material_papyrus.setFlag(video::EMF_BILINEAR_FILTER, false);
+                       material_papyrus.setFlag(video::EMF_FOG_ENABLE, true);
+                       material_papyrus.MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+                       AtlasPointer pa_papyrus = f.tiles[0].texture;
+                       material_papyrus.setTexture(0, pa_papyrus.atlas);
+                       
                        u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
                        video::SColor c = MapBlock_LightColor(255, l);
 
@@ -1027,6 +822,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 
                                for(u16 i=0; i<4; i++)
                                {
+                                       vertices[i].Pos *= f.visual_scale;
                                        vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
                                }
 
@@ -1034,59 +830,92 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                // Add to mesh collector
                                collector.append(material_papyrus, vertices, 4, indices, 6);
                        }
-               }
-               else if(n.getContent() == CONTENT_JUNGLEGRASS)
+               break;}
+               case NDT_FENCELIKE:
                {
+                       video::SMaterial material_wood;
+                       material_wood.setFlag(video::EMF_LIGHTING, false);
+                       material_wood.setFlag(video::EMF_BILINEAR_FILTER, false);
+                       material_wood.setFlag(video::EMF_FOG_ENABLE, true);
+                       material_wood.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+                       AtlasPointer pa_wood = f.tiles[0].texture;
+                       material_wood.setTexture(0, pa_wood.atlas);
+
                        u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
                        video::SColor c = MapBlock_LightColor(255, l);
 
-                       for(u32 j=0; j<4; j++)
+                       const f32 post_rad=(f32)BS/10;
+                       const f32 bar_rad=(f32)BS/20;
+                       const f32 bar_len=(f32)(BS/2)-post_rad;
+
+                       // The post - always present
+                       v3f pos = intToFloat(p+blockpos_nodes, BS);
+                       f32 postuv[24]={
+                                       0.4,0.4,0.6,0.6,
+                                       0.35,0,0.65,1,
+                                       0.35,0,0.65,1,
+                                       0.35,0,0.65,1,
+                                       0.35,0,0.65,1,
+                                       0.4,0.4,0.6,0.6};
+                       makeCuboid(material_wood, &collector,
+                               &pa_wood, c, pos,
+                               post_rad,BS/2,post_rad, postuv);
+
+                       // Now a section of fence, +X, if there's a post there
+                       v3s16 p2 = p;
+                       p2.X++;
+                       MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
+                       const ContentFeatures *f2 = &nodedef->get(n2);
+                       if(f2->drawtype == NDT_FENCELIKE)
                        {
-                               video::S3DVertex vertices[4] =
-                               {
-                                       video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
-                                               pa_junglegrass.x0(), pa_junglegrass.y1()),
-                                       video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
-                                               pa_junglegrass.x1(), pa_junglegrass.y1()),
-                                       video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
-                                               pa_junglegrass.x1(), pa_junglegrass.y0()),
-                                       video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
-                                               pa_junglegrass.x0(), pa_junglegrass.y0()),
-                               };
+                               pos = intToFloat(p+blockpos_nodes, BS);
+                               pos.X += BS/2;
+                               pos.Y += BS/4;
+                               f32 xrailuv[24]={
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6};
+                               makeCuboid(material_wood, &collector,
+                                       &pa_wood, c, pos,
+                                       bar_len,bar_rad,bar_rad, xrailuv);
 
-                               if(j == 0)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(45);
-                               }
-                               else if(j == 1)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(-45);
-                               }
-                               else if(j == 2)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(135);
-                               }
-                               else if(j == 3)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(-135);
-                               }
+                               pos.Y -= BS/2;
+                               makeCuboid(material_wood, &collector,
+                                       &pa_wood, c, pos,
+                                       bar_len,bar_rad,bar_rad, xrailuv);
+                       }
 
-                               for(u16 i=0; i<4; i++)
-                               {
-                                       vertices[i].Pos *= 1.3;
-                                       vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
-                               }
+                       // Now a section of fence, +Z, if there's a post there
+                       p2 = p;
+                       p2.Z++;
+                       n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
+                       f2 = &nodedef->get(n2);
+                       if(f2->drawtype == NDT_FENCELIKE)
+                       {
+                               pos = intToFloat(p+blockpos_nodes, BS);
+                               pos.Z += BS/2;
+                               pos.Y += BS/4;
+                               f32 zrailuv[24]={
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6,
+                                       0,0.4,1,0.6};
+                               makeCuboid(material_wood, &collector,
+                                       &pa_wood, c, pos,
+                                       bar_rad,bar_rad,bar_len, zrailuv);
+                               pos.Y -= BS/2;
+                               makeCuboid(material_wood, &collector,
+                                       &pa_wood, c, pos,
+                                       bar_rad,bar_rad,bar_len, zrailuv);
 
-                               u16 indices[] = {0,1,2,2,3,0};
-                               // Add to mesh collector
-                               collector.append(material_junglegrass, vertices, 4, indices, 6);
                        }
-               }
-               else if(n.getContent() == CONTENT_RAIL)
+               break;}
+               case NDT_RAILLIKE:
                {
                        bool is_rail_x [] = { false, false };  /* x-1, x+1 */
                        bool is_rail_z [] = { false, false };  /* z-1, z+1 */
@@ -1095,36 +924,35 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        MapNode n_plus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1,y,z));
                        MapNode n_minus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z-1));
                        MapNode n_plus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z+1));
-
-                       if(n_minus_x.getContent() == CONTENT_RAIL)
+                       
+                       content_t thiscontent = n.getContent();
+                       if(n_minus_x.getContent() == thiscontent)
                                is_rail_x[0] = true;
-                       if(n_plus_x.getContent() == CONTENT_RAIL)
+                       if(n_plus_x.getContent() == thiscontent)
                                is_rail_x[1] = true;
-                       if(n_minus_z.getContent() == CONTENT_RAIL)
+                       if(n_minus_z.getContent() == thiscontent)
                                is_rail_z[0] = true;
-                       if(n_plus_z.getContent() == CONTENT_RAIL)
+                       if(n_plus_z.getContent() == thiscontent)
                                is_rail_z[1] = true;
 
                        int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1];
 
                        // Assign textures
-                       const char *texturename = "rail.png";
+                       AtlasPointer ap = f.tiles[0].texture; // straight
                        if(adjacencies < 2)
-                               texturename = "rail.png";
+                               ap = f.tiles[0].texture; // straight
                        else if(adjacencies == 2)
                        {
                                if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1]))
-                                       texturename = "rail.png";
+                                       ap = f.tiles[0].texture; // straight
                                else
-                                       texturename = "rail_curved.png";
+                                       ap = f.tiles[1].texture; // curved
                        }
                        else if(adjacencies == 3)
-                               texturename = "rail_t_junction.png";
+                               ap = f.tiles[2].texture; // t-junction
                        else if(adjacencies == 4)
-                               texturename = "rail_crossing.png";
+                               ap = f.tiles[3].texture; // crossing
                        
-                       AtlasPointer ap = tsrc->getTexture(texturename);
-
                        video::SMaterial material_rail;
                        material_rail.setFlag(video::EMF_LIGHTING, false);
                        material_rail.setFlag(video::EMF_BACK_FACE_CULLING, false);
@@ -1193,159 +1021,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 
                        u16 indices[] = {0,1,2,2,3,0};
                        collector.append(material_rail, vertices, 4, indices, 6);
-               }
-               else if (n.getContent() == CONTENT_LADDER) {
-                       AtlasPointer ap = tsrc->getTexture("ladder.png");
-                       
-                       // Set material
-                       video::SMaterial material_ladder;
-                       material_ladder.setFlag(video::EMF_LIGHTING, false);
-                       material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false);
-                       material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false);
-                       material_ladder.setFlag(video::EMF_FOG_ENABLE, true);
-                       material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-                       material_ladder.setTexture(0, ap.atlas);
-
-                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
-                       video::SColor c(255,l,l,l);
-
-                       float d = (float)BS/16;
-
-                       // Assume wall is at X+
-                       video::S3DVertex vertices[4] =
-                       {
-                               video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c,
-                                               ap.x0(), ap.y1()),
-                               video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c,
-                                               ap.x1(), ap.y1()),
-                               video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c,
-                                               ap.x1(), ap.y0()),
-                               video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c,
-                                               ap.x0(), ap.y0()),
-                       };
-
-                       v3s16 dir = unpackDir(n.param2);
-
-                       for(s32 i=0; i<4; i++)
-                       {
-                               if(dir == v3s16(1,0,0))
-                                       vertices[i].Pos.rotateXZBy(0);
-                               if(dir == v3s16(-1,0,0))
-                                       vertices[i].Pos.rotateXZBy(180);
-                               if(dir == v3s16(0,0,1))
-                                       vertices[i].Pos.rotateXZBy(90);
-                               if(dir == v3s16(0,0,-1))
-                                       vertices[i].Pos.rotateXZBy(-90);
-                               if(dir == v3s16(0,-1,0))
-                                       vertices[i].Pos.rotateXYBy(-90);
-                               if(dir == v3s16(0,1,0))
-                                       vertices[i].Pos.rotateXYBy(90);
-
-                               vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
-                       }
-
-                       u16 indices[] = {0,1,2,2,3,0};
-                       // Add to mesh collector
-                       collector.append(material_ladder, vertices, 4, indices, 6);
-               }
-               else if(n.getContent() == CONTENT_APPLE)
-               {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
-                       video::SColor c = MapBlock_LightColor(255, l);
-
-                       for(u32 j=0; j<4; j++)
-                       {
-                               video::S3DVertex vertices[4] =
-                               {
-                                       video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
-                                               pa_apple.x0(), pa_apple.y1()),
-                                       video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
-                                               pa_apple.x1(), pa_apple.y1()),
-                                       video::S3DVertex(BS/2,BS/2,0, 0,0,0, c,
-                                               pa_apple.x1(), pa_apple.y0()),
-                                       video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
-                                               pa_apple.x0(), pa_apple.y0()),
-                               };
-
-                               if(j == 0)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(45);
-                               }
-                               else if(j == 1)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(-45);
-                               }
-                               else if(j == 2)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(135);
-                               }
-                               else if(j == 3)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(-135);
-                               }
-
-                               for(u16 i=0; i<4; i++)
-                               {
-                                       vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
-                               }
-
-                               u16 indices[] = {0,1,2,2,3,0};
-                               // Add to mesh collector
-                               collector.append(material_apple, vertices, 4, indices, 6);
-                       }
-               }
-               else if(n.getContent() == CONTENT_SAPLING) {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
-                       video::SColor c = MapBlock_LightColor(255, l);
-
-                       for(u32 j=0; j<4; j++)
-                       {
-                               video::S3DVertex vertices[4] =
-                               {
-                                       video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
-                                               pa_sapling.x0(), pa_sapling.y1()),
-                                       video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
-                                               pa_sapling.x1(), pa_sapling.y1()),
-                                       video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
-                                               pa_sapling.x1(), pa_sapling.y0()),
-                                       video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
-                                               pa_sapling.x0(), pa_sapling.y0()),
-                               };
-
-                               if(j == 0)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(45);
-                               }
-                               else if(j == 1)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(-45);
-                               }
-                               else if(j == 2)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(135);
-                               }
-                               else if(j == 3)
-                               {
-                                       for(u16 i=0; i<4; i++)
-                                               vertices[i].Pos.rotateXZBy(-135);
-                               }
-
-                               for(u16 i=0; i<4; i++)
-                               {
-                                       vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
-                               }
-
-                               u16 indices[] = {0,1,2,2,3,0};
-                               // Add to mesh collector
-                               collector.append(material_sapling, vertices, 4, indices, 6);
-                       }
+               break;}
                }
        }
 }
index 0f1ae4a6ec2d7f2d84527c64e626733be0f39afd..58eaff108679e21bea491e51b910e558c131941a 100644 (file)
@@ -17,13 +17,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-// For g_settings
-#include "main.h"
-
 #include "content_mapnode.h"
+
+#include "irrlichttypes.h"
 #include "mapnode.h"
 #include "content_nodemeta.h"
-#include "settings.h"
 #include "nodedef.h"
 
 #define WATER_ALPHA 160
@@ -156,23 +154,8 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
 }
 
 // See header for description
-void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr)
+void content_mapnode_init(IWritableNodeDefManager *nodemgr)
 {
-       if(tsrc == NULL)
-               dstream<<"INFO: Initial run of content_mapnode_init with "
-                               "tsrc=NULL. If this segfaults, "
-                               "there is a bug with something not checking for "
-                               "the NULL value."<<std::endl;
-       else
-               dstream<<"INFO: Full run of content_mapnode_init with "
-                               "tsrc!=NULL"<<std::endl;
-
-       // Read some settings
-       bool new_style_water = g_settings->getBool("new_style_water");
-       bool new_style_leaves = g_settings->getBool("new_style_leaves");
-       bool invisible_stone = g_settings->getBool("invisible_stone");
-       bool opaque_water = g_settings->getBool("opaque_water");
-
        content_t i;
        ContentFeatures *f = NULL;
 
@@ -185,8 +168,6 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        f->often_contains_mineral = true;
        f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
        setStoneLikeMaterialProperties(f->material, 1.0);
-       if(invisible_stone)
-               f->solidness = 0; // For debugging, hides regular stone
        
        i = CONTENT_GRASS;
        f = nodemgr->getModifiable(i);
@@ -278,40 +259,29 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        f->setTexture(0, "jungletree_top.png");
        f->setTexture(1, "jungletree_top.png");
        f->param_type = CPT_MINERAL;
-       //f->is_ground_content = true;
        f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
        setWoodLikeMaterialProperties(f->material, 1.0);
        
        i = CONTENT_JUNGLEGRASS;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_PLANTLIKE;
+       f->visual_scale = 1.6;
+       f->setAllTextures("junglegrass.png");
        f->setInventoryTexture("junglegrass.png");
-       f->used_texturenames.insert("junglegrass.png"); // Add to atlas
        f->light_propagates = true;
        f->param_type = CPT_LIGHT;
-       //f->is_ground_content = true;
        f->air_equivalent = false; // grass grows underneath
        f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->solidness = 0; // drawn separately, makes no faces
        f->walkable = false;
        setLeavesLikeMaterialProperties(f->material, 1.0);
 
        i = CONTENT_LEAVES;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_ALLFACES_OPTIONAL;
+       f->setAllTextures("leaves.png");
+       //f->setAllTextures("[noalpha:leaves.png");
        f->light_propagates = true;
-       //f->param_type = CPT_MINERAL;
        f->param_type = CPT_LIGHT;
-       //f->is_ground_content = true;
-       if(new_style_leaves)
-       {
-               f->solidness = 0; // drawn separately, makes no faces
-               f->visual_solidness = 1;
-               f->setAllTextures("leaves.png");
-               f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
-       }
-       else
-       {
-               f->setAllTextures("[noalpha:leaves.png");
-       }
        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";
@@ -330,13 +300,13 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
 
        i = CONTENT_PAPYRUS;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_PLANTLIKE;
+       f->setAllTextures("papyrus.png");
        f->setInventoryTexture("papyrus.png");
-       f->used_texturenames.insert("papyrus.png"); // Add to atlas
        f->light_propagates = true;
        f->param_type = CPT_LIGHT;
        f->is_ground_content = true;
        f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
-       f->solidness = 0; // drawn separately, makes no faces
        f->walkable = false;
        setLeavesLikeMaterialProperties(f->material, 0.5);
 
@@ -354,27 +324,26 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
 
        i = CONTENT_GLASS;
        f = nodemgr->getModifiable(i);
+       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->solidness = 0; // drawn separately, makes no faces
-       f->visual_solidness = 1;
-       f->setAllTextures("glass.png");
        f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
        setGlassLikeMaterialProperties(f->material, 1.0);
 
        i = CONTENT_FENCE;
        f = nodemgr->getModifiable(i);
+       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->solidness = 0; // drawn separately, makes no faces
        f->air_equivalent = true; // grass grows underneath
-       f->setInventoryTexture("fence.png");
-       f->used_texturenames.insert("fence.png"); // Add to atlas
        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);
@@ -382,13 +351,16 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
 
        i = CONTENT_RAIL;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_RAILLIKE;
        f->setInventoryTexture("rail.png");
-       f->used_texturenames.insert("rail.png"); // Add to atlas
+       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->solidness = 0; // drawn separately, makes no faces
        f->air_equivalent = true; // grass grows underneath
        f->walkable = false;
        f->selection_box.type = NODEBOX_FIXED;
@@ -396,14 +368,14 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
 
        i = CONTENT_LADDER;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_SIGNLIKE;
+       f->setAllTextures("ladder.png");
        f->setInventoryTexture("ladder.png");
-       f->used_texturenames.insert("ladder.png"); // Add to atlas
        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->solidness = 0;
        f->air_equivalent = true;
        f->walkable = false;
        f->climbable = true;
@@ -445,7 +417,6 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        f->param_type = CPT_LIGHT;
        f->light_propagates = true;
        f->sunlight_propagates = true;
-       f->solidness = 0;
        f->walkable = false;
        f->pointable = false;
        f->diggable = false;
@@ -454,11 +425,11 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        
        i = CONTENT_WATER;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_FLOWINGLIQUID;
+       f->setAllTextures("water.png", WATER_ALPHA);
        f->setInventoryTextureCube("water.png", "water.png", "water.png");
        f->param_type = CPT_LIGHT;
        f->light_propagates = true;
-       f->solidness = 0; // Drawn separately, makes no faces
-       f->visual_solidness = 1;
        f->walkable = false;
        f->pointable = false;
        f->diggable = false;
@@ -467,8 +438,6 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        f->liquid_alternative_flowing = CONTENT_WATER;
        f->liquid_alternative_source = CONTENT_WATERSOURCE;
        f->liquid_viscosity = WATER_VISC;
-       if(!opaque_water)
-               f->alpha = WATER_ALPHA;
        f->post_effect_color = video::SColor(64, 100, 100, 200);
        // Flowing water material
        f->mspec_special[0].tname = "water.png";
@@ -478,16 +447,8 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
 
        i = CONTENT_WATERSOURCE;
        f = nodemgr->getModifiable(i);
-       if(new_style_water)
-       {
-               f->solidness = 0; // drawn separately, makes no faces
-       }
-       else // old style
-       {
-               f->solidness = 1;
-               f->setAllTextures("water.png", WATER_ALPHA);
-               f->backface_culling = false;
-       }
+       f->drawtype = NDT_LIQUID;
+       f->setAllTextures("water.png", WATER_ALPHA);
        //f->setInventoryTexture("water.png");
        f->setInventoryTextureCube("water.png", "water.png", "water.png");
        f->param_type = CPT_LIGHT;
@@ -501,8 +462,6 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        f->liquid_alternative_flowing = CONTENT_WATER;
        f->liquid_alternative_source = CONTENT_WATERSOURCE;
        f->liquid_viscosity = WATER_VISC;
-       if(!opaque_water)
-               f->alpha = WATER_ALPHA;
        f->post_effect_color = video::SColor(64, 100, 100, 200);
        // New-style water source material (mostly unused)
        f->mspec_special[0].tname = "water.png";
@@ -510,13 +469,12 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        
        i = CONTENT_LAVA;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_FLOWINGLIQUID;
+       f->setAllTextures("lava.png");
        f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
-       f->used_texturenames.insert("lava.png"); // Add to atlas
        f->param_type = CPT_LIGHT;
        f->light_propagates = false;
        f->light_source = LIGHT_MAX-1;
-       f->solidness = 0; // Drawn separately, makes no faces
-       f->visual_solidness = 1; // Does not completely cover block boundaries
        f->walkable = false;
        f->pointable = false;
        f->diggable = false;
@@ -535,16 +493,8 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        
        i = CONTENT_LAVASOURCE;
        f = nodemgr->getModifiable(i);
-       f->used_texturenames.insert("ladder.png"); // Add to atlas
-       if(new_style_water)
-       {
-               f->solidness = 0; // drawn separately, makes no faces
-       }
-       else // old style
-       {
-               f->solidness = 2;
-               f->setAllTextures("lava.png");
-       }
+       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;
@@ -566,14 +516,14 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        
        i = CONTENT_TORCH;
        f = nodemgr->getModifiable(i);
+       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->used_texturenames.insert("torch_on_floor.png"); // Add to atlas
-       f->used_texturenames.insert("torch_on_ceiling.png"); // Add to atlas
-       f->used_texturenames.insert("torch.png"); // Add to atlas
        f->param_type = CPT_LIGHT;
        f->light_propagates = true;
        f->sunlight_propagates = true;
-       f->solidness = 0; // drawn separately, makes no faces
        f->walkable = false;
        f->wall_mounted = true;
        f->air_equivalent = true;
@@ -590,12 +540,12 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
        
        i = CONTENT_SIGN_WALL;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_SIGNLIKE;
+       f->setAllTextures("sign_wall.png");
        f->setInventoryTexture("sign_wall.png");
-       f->used_texturenames.insert("sign_wall.png"); // Add to atlas
        f->param_type = CPT_LIGHT;
        f->light_propagates = true;
        f->sunlight_propagates = true;
-       f->solidness = 0; // drawn separately, makes no faces
        f->walkable = false;
        f->wall_mounted = true;
        f->air_equivalent = true;
@@ -692,25 +642,26 @@ void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr
 
        i = CONTENT_SAPLING;
        f = nodemgr->getModifiable(i);
-       f->param_type = CPT_LIGHT;
+       f->drawtype = NDT_PLANTLIKE;
+       f->visual_scale = 1.5;
        f->setAllTextures("sapling.png");
        f->setInventoryTexture("sapling.png");
-       f->used_texturenames.insert("sapling.png"); // Add to atlas
+       f->param_type = CPT_LIGHT;
        f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
        f->light_propagates = true;
        f->air_equivalent = false;
-       f->solidness = 0; // drawn separately, makes no faces
        f->walkable = false;
        setConstantMaterialProperties(f->material, 0.0);
        
        i = CONTENT_APPLE;
        f = nodemgr->getModifiable(i);
+       f->drawtype = NDT_PLANTLIKE;
+       f->visual_scale = 1.0;
+       f->setAllTextures("apple.png");
        f->setInventoryTexture("apple.png");
-       f->used_texturenames.insert("apple.png"); // Add to atlas
        f->param_type = CPT_LIGHT;
        f->light_propagates = true;
        f->sunlight_propagates = true;
-       f->solidness = 0; // drawn separately, makes no faces
        f->walkable = false;
        f->air_equivalent = true;
        f->dug_item = std::string("CraftItem apple 1");
index ace30be7b89ec81103226a6ba38056604a7b0f47..3140f2179936ee90b057d6ca2c00cb05b7d21d85 100644 (file)
@@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define CONTENT_MAPNODE_HEADER
 
 #include "mapnode.h"
-class ITextureSource;
 class IWritableNodeDefManager;
 
 /*
@@ -36,7 +35,7 @@ class IWritableNodeDefManager;
 
        Server only calls this once with tsrc=NULL.
 */
-void content_mapnode_init(ITextureSource *tsrc, IWritableNodeDefManager *nodemgr);
+void content_mapnode_init(IWritableNodeDefManager *nodemgr);
 
 // Backwards compatibility for non-extended content types in v19
 extern content_t trans_table_19[21][2];
index fbc22867d1505783c6858c29cdadc1eba7fd03af..2cb69b11620d128b23a6a2513231f41cc50e0e1e 100644 (file)
@@ -75,7 +75,6 @@ void set_default_settings(Settings *settings)
        settings->setDefault("invert_mouse", "false");
        settings->setDefault("enable_farmesh", "false");
        settings->setDefault("enable_clouds", "true");
-       settings->setDefault("invisible_stone", "false");
        settings->setDefault("screenshot_path", ".");
        settings->setDefault("view_bobbing_amount", "1.0");
        settings->setDefault("enable_3d_clouds", "false");
index 4fd6eebb0f5b40040bd61adae615394bd62b84b2..7efce23a4e83f0b4a2942d2b5de28cb507c6fad9 100644 (file)
@@ -645,7 +645,7 @@ void the_game(
        IWritableNodeDefManager *nodedef = createNodeDefManager();
 
        // Fill node feature table with default definitions
-       content_mapnode_init(tsrc, nodedef);
+       content_mapnode_init(nodedef);
 
        /*
                Create server.
index 7ab83bb7d4b14eea92ad5dc4a0dba072d08e688a..bc17694fc44903a2280e89fdd4d7cdb847e7b0cf 100644 (file)
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <irrList.h>
 #include <irrArray.h>
 #include <aabbox3d.h>
+#include <SColor.h>
 using namespace irr;
 typedef core::vector3df v3f;
 typedef core::vector3d<s16> v3s16;
index 9aceab17ea058cef6966316c1eb3374cf07e856c..1e8915b03035adb1d48904ec388ce5a49f83ab24 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nodedef.h"
 #include "content_mapnode.h" // For mapnode_translate_*_internal
 
+#ifndef SERVER
 /*
        Nodes make a face if contents differ and solidness differs.
        Return value:
@@ -81,6 +82,7 @@ u8 face_contents(content_t m1, content_t m2, bool *equivalent,
        else
                return 2;
 }
+#endif
 
 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
 {
index 70a7638d258b88ee37b8a1363ebb34bcdcc33f56..7fe2054631fb31d1b8b1cd5449386bb2399ad5e6 100644 (file)
@@ -62,6 +62,7 @@ typedef u16 content_t;
 */
 #define CONTENT_AIR 126
 
+#ifndef SERVER
 /*
        Nodes make a face if contents differ and solidness differs.
        Return value:
@@ -72,6 +73,7 @@ typedef u16 content_t;
 */
 u8 face_contents(content_t m1, content_t m2, bool *equivalent,
                INodeDefManager *nodemgr);
+#endif
 
 /*
        Packs directions like (1,0,0), (1,-1,0) in six bits.
index d89b1e07950aced430c3cff2730f15dfdac422dc..72547faceaf5e45ffa4f419578fe79b3ebf8766a 100644 (file)
@@ -1,7 +1,49 @@
+/*
+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 "materials.h"
 #include "mapnode.h"
 #include "nodedef.h"
 #include "tooldef.h"
+#include "utility.h"
+
+void MaterialProperties::serialize(std::ostream &os)
+{
+       writeU8(os, 0); // version
+       writeU8(os, diggability);
+       writeF1000(os, weight);
+       writeF1000(os, crackiness);
+       writeF1000(os, crumbliness);
+       writeF1000(os, cuttability);
+}
+
+void MaterialProperties::deSerialize(std::istream &is)
+{
+       int version = readU8(is);
+       if(version != 0)
+               throw SerializationError("unsupported MaterialProperties version");
+       diggability = (enum Diggability)readU8(is);
+       weight = readF1000(is);
+       crackiness = readF1000(is);
+       crumbliness = readF1000(is);
+       cuttability = readF1000(is);
+}
 
 DiggingProperties getDiggingProperties(u16 content, ToolDiggingProperties *tp,
                INodeDefManager *nodemgr)
index 62bce16694a677f672db290b0405a7fd9eda6eb5..4e067fd6674e513aacf4d7c7d768eef5ae9d7267 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2010-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
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "common_irrlicht.h"
 #include <string>
+#include <iostream>
 
 enum Diggability
 {
@@ -65,6 +66,9 @@ struct MaterialProperties
                crumbliness(1),
                cuttability(1)
        {}
+
+       void serialize(std::ostream &os);
+       void deSerialize(std::istream &is);
 };
 
 struct DiggingProperties
index 045615fbbf72f08eb5cd3c20964d1457cbcb7944..996b20781944a70fd7ba4fc34dc1a6bd3c0561d1 100644 (file)
@@ -25,6 +25,54 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "tile.h"
 #endif
 #include "log.h"
+#include "settings.h"
+
+void NodeBox::serialize(std::ostream &os)
+{
+       writeU8(os, 0); // version
+       writeU8(os, type);
+       writeV3F1000(os, fixed.MinEdge);
+       writeV3F1000(os, fixed.MaxEdge);
+       writeV3F1000(os, wall_top.MinEdge);
+       writeV3F1000(os, wall_top.MaxEdge);
+       writeV3F1000(os, wall_bottom.MinEdge);
+       writeV3F1000(os, wall_bottom.MaxEdge);
+       writeV3F1000(os, wall_side.MinEdge);
+       writeV3F1000(os, wall_side.MaxEdge);
+}
+
+void NodeBox::deSerialize(std::istream &is)
+{
+       int version = readU8(is);
+       if(version != 0)
+               throw SerializationError("unsupported NodeBox version");
+       type = (enum NodeBoxType)readU8(is);
+       fixed.MinEdge = readV3F1000(is);
+       fixed.MaxEdge = readV3F1000(is);
+       wall_top.MinEdge = readV3F1000(is);
+       wall_top.MaxEdge = readV3F1000(is);
+       wall_bottom.MinEdge = readV3F1000(is);
+       wall_bottom.MaxEdge = readV3F1000(is);
+       wall_side.MinEdge = readV3F1000(is);
+       wall_side.MaxEdge = readV3F1000(is);
+}
+
+void MaterialSpec::serialize(std::ostream &os)
+{
+       os<<serializeString(tname);
+       writeU8(os, backface_culling);
+}
+
+void MaterialSpec::deSerialize(std::istream &is)
+{
+       tname = deSerializeString(is);
+       backface_culling = readU8(is);
+}
+
+ContentFeatures::ContentFeatures()
+{
+       reset();
+}
 
 ContentFeatures::~ContentFeatures()
 {
@@ -37,6 +85,161 @@ ContentFeatures::~ContentFeatures()
 #endif
 }
 
+void ContentFeatures::reset()
+{
+       /*
+               Cached stuff
+       */
+#ifndef SERVER
+       inventory_texture = NULL;
+       
+       for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
+               special_materials[j] = NULL;
+               special_aps[j] = NULL;
+       }
+       solidness = 2;
+       visual_solidness = 0;
+       backface_culling = true;
+#endif
+       used_texturenames.clear();
+       modified = true; // NodeDefManager explicitly sets to false
+       /*
+               Actual data
+       */
+       drawtype = NDT_NORMAL;
+       visual_scale = 1.0;
+       for(u32 i=0; i<6; i++)
+               tname_tiles[i] = "";
+       for(u16 j=0; j<CF_SPECIAL_COUNT; j++)
+               mspec_special[j] = MaterialSpec();
+       tname_inventory = "";
+       alpha = 255;
+       post_effect_color = video::SColor(0, 0, 0, 0);
+       param_type = CPT_NONE;
+       is_ground_content = false;
+       light_propagates = false;
+       sunlight_propagates = false;
+       walkable = true;
+       pointable = true;
+       diggable = true;
+       climbable = false;
+       buildable_to = false;
+       wall_mounted = false;
+       air_equivalent = false;
+       often_contains_mineral = false;
+       dug_item = "";
+       initial_metadata = NULL;
+       liquid_type = LIQUID_NONE;
+       liquid_alternative_flowing = CONTENT_IGNORE;
+       liquid_alternative_source = CONTENT_IGNORE;
+       liquid_viscosity = 0;
+       light_source = 0;
+       damage_per_second = 0;
+       selection_box = NodeBox();
+       material = MaterialProperties();
+}
+
+void ContentFeatures::serialize(std::ostream &os)
+{
+       writeU8(os, 0); // version
+       writeU8(os, drawtype);
+       writeF1000(os, visual_scale);
+       writeU8(os, 6);
+       for(u32 i=0; i<6; i++)
+               os<<serializeString(tname_tiles[i]);
+       os<<serializeString(tname_inventory);
+       writeU8(os, CF_SPECIAL_COUNT);
+       for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
+               mspec_special[i].serialize(os);
+       }
+       writeU8(os, alpha);
+       writeU8(os, post_effect_color.getAlpha());
+       writeU8(os, post_effect_color.getRed());
+       writeU8(os, post_effect_color.getGreen());
+       writeU8(os, post_effect_color.getBlue());
+       writeU8(os, param_type);
+       writeU8(os, is_ground_content);
+       writeU8(os, light_propagates);
+       writeU8(os, sunlight_propagates);
+       writeU8(os, walkable);
+       writeU8(os, pointable);
+       writeU8(os, diggable);
+       writeU8(os, climbable);
+       writeU8(os, buildable_to);
+       writeU8(os, wall_mounted);
+       writeU8(os, air_equivalent);
+       writeU8(os, often_contains_mineral);
+       os<<serializeString(dug_item);
+       os<<serializeString(extra_dug_item);
+       writeS32(os, extra_dug_item_rarity);
+       if(initial_metadata){
+               writeU8(os, true);
+               initial_metadata->serialize(os);
+       } else {
+               writeU8(os, false);
+       }
+       writeU8(os, liquid_type);
+       writeU16(os, liquid_alternative_flowing);
+       writeU16(os, liquid_alternative_source);
+       writeU8(os, liquid_viscosity);
+       writeU8(os, light_source);
+       writeU32(os, damage_per_second);
+       selection_box.serialize(os);
+       material.serialize(os);
+}
+
+void ContentFeatures::deSerialize(std::istream &is, IGameDef *gamedef)
+{
+       int version = readU8(is);
+       if(version != 0)
+               throw SerializationError("unsupported ContentFeatures version");
+       drawtype = (enum NodeDrawType)readU8(is);
+       visual_scale = readF1000(is);
+       if(readU8(is) != 6)
+               throw SerializationError("unsupported tile count");
+       for(u32 i=0; i<6; i++)
+               tname_tiles[i] = deSerializeString(is);
+       tname_inventory = deSerializeString(is);
+       if(readU8(is) != CF_SPECIAL_COUNT)
+               throw SerializationError("unsupported CF_SPECIAL_COUNT");
+       for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
+               mspec_special[i].deSerialize(is);
+       }
+       alpha = readU8(is);
+       post_effect_color.setAlpha(readU8(is));
+       post_effect_color.setRed(readU8(is));
+       post_effect_color.setGreen(readU8(is));
+       post_effect_color.setBlue(readU8(is));
+       param_type = (enum ContentParamType)readU8(is);
+       is_ground_content = readU8(is);
+       light_propagates = readU8(is);
+       sunlight_propagates = readU8(is);
+       walkable = readU8(is);
+       pointable = readU8(is);
+       diggable = readU8(is);
+       climbable = readU8(is);
+       buildable_to = readU8(is);
+       wall_mounted = readU8(is);
+       air_equivalent = readU8(is);
+       often_contains_mineral = readU8(is);
+       dug_item = deSerializeString(is);
+       extra_dug_item = deSerializeString(is);
+       extra_dug_item_rarity = readS32(is);
+       if(readU8(is)){
+               initial_metadata = NodeMetadata::deSerialize(is, gamedef);
+       } else {
+               initial_metadata = NULL;
+       }
+       liquid_type = (enum LiquidType)readU8(is);
+       liquid_alternative_flowing = readU16(is);
+       liquid_alternative_source = readU16(is);
+       liquid_viscosity = readU8(is);
+       light_source = readU8(is);
+       damage_per_second = readU32(is);
+       selection_box.deSerialize(is);
+       material.deSerialize(is);
+}
+
 void ContentFeatures::setTexture(u16 i, std::string name)
 {
        used_texturenames.insert(name);
@@ -70,20 +273,28 @@ void ContentFeatures::setInventoryTextureCube(std::string top,
 class CNodeDefManager: public IWritableNodeDefManager
 {
 public:
-       CNodeDefManager()
+       void clear()
        {
                for(u16 i=0; i<=MAX_CONTENT; i++)
                {
                        ContentFeatures *f = &m_content_features[i];
-                       // Reset to defaults
-                       f->reset();
-                       if(i == CONTENT_IGNORE || i == CONTENT_AIR)
+                       f->reset(); // Reset to defaults
+                       f->modified = false; // Not changed from default
+                       if(i == CONTENT_IGNORE || i == CONTENT_AIR){
+                               f->drawtype = NDT_AIRLIKE;
                                continue;
+                       }
                        f->setAllTextures("unknown_block.png");
-                       f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+                       //f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
                }
+#ifndef SERVER
                // Make CONTENT_IGNORE to not block the view when occlusion culling
                m_content_features[CONTENT_IGNORE].solidness = 0;
+#endif
+       }
+       CNodeDefManager()
+       {
+               clear();
        }
        virtual ~CNodeDefManager()
        {
@@ -116,6 +327,7 @@ public:
        virtual ContentFeatures* getModifiable(content_t c)
        {
                assert(c <= MAX_CONTENT);
+               m_content_features[c].modified = true; // Assume it is modified
                return &m_content_features[c];
        }
        virtual void updateTextures(ITextureSource *tsrc)
@@ -123,10 +335,72 @@ public:
 #ifndef SERVER
                infostream<<"CNodeDefManager::updateTextures(): Updating "
                                <<"textures in node definitions"<<std::endl;
+
+               bool new_style_water = g_settings->getBool("new_style_water");
+               bool new_style_leaves = g_settings->getBool("new_style_leaves");
+               bool opaque_water = g_settings->getBool("opaque_water");
+               
                for(u16 i=0; i<=MAX_CONTENT; i++)
                {
-                       infostream<<"Updating content "<<i<<std::endl;
                        ContentFeatures *f = &m_content_features[i];
+
+                       switch(f->drawtype){
+                       default:
+                       case NDT_NORMAL:
+                               f->solidness = 2;
+                               break;
+                       case NDT_AIRLIKE:
+                               f->solidness = 0;
+                               break;
+                       case NDT_LIQUID:
+                               assert(f->liquid_type == LIQUID_SOURCE);
+                               if(opaque_water)
+                                       f->alpha = 255;
+                               if(new_style_water){
+                                       f->solidness = 0;
+                               } else {
+                                       f->solidness = 1;
+                                       if(f->alpha == 255)
+                                               f->solidness = 2;
+                               }
+                               break;
+                       case NDT_FLOWINGLIQUID:
+                               assert(f->liquid_type == LIQUID_FLOWING);
+                               f->solidness = 0;
+                               if(opaque_water)
+                                       f->alpha = 255;
+                               break;
+                       case NDT_GLASSLIKE:
+                               f->solidness = 0;
+                               f->visual_solidness = 1;
+                               break;
+                       case NDT_ALLFACES:
+                               f->solidness = 0;
+                               f->visual_solidness = 1;
+                               break;
+                       case NDT_ALLFACES_OPTIONAL:
+                               if(new_style_leaves){
+                                       f->drawtype = NDT_ALLFACES;
+                                       f->solidness = 0;
+                                       f->visual_solidness = 1;
+                               } else {
+                                       f->drawtype = NDT_NORMAL;
+                                       f->solidness = 1;
+                                       for(u32 i=0; i<6; i++){
+                                               f->tname_tiles[i] = std::string("[noalpha:")
+                                                               + f->tname_tiles[i];
+                                       }
+                               }
+                               break;
+                       case NDT_TORCHLIKE:
+                       case NDT_SIGNLIKE:
+                       case NDT_PLANTLIKE:
+                       case NDT_FENCELIKE:
+                       case NDT_RAILLIKE:
+                               f->solidness = 0;
+                               break;
+                       }
+
                        // Inventory texture
                        if(f->tname_inventory != "")
                                f->inventory_texture = tsrc->getTextureRaw(f->tname_inventory);
@@ -175,6 +449,35 @@ public:
                }
 #endif
        }
+       void serialize(std::ostream &os)
+       {
+               std::ostringstream tmp_os(std::ios::binary);
+               for(u16 i=0; i<=MAX_CONTENT; i++)
+               {
+                       ContentFeatures *f = &m_content_features[i];
+                       if(!f->modified)
+                               continue;
+                       writeU16(tmp_os, i);
+                       f->serialize(tmp_os);
+               }
+               os<<serializeLongString(tmp_os.str());
+       }
+       void deSerialize(std::istream &is, IGameDef *gamedef)
+       {
+               clear();
+               std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
+               while(!tmp_is.eof()){
+                       u16 i = readU16(tmp_is);
+                       if(i > MAX_CONTENT){
+                               errorstream<<"ContentFeatures::deSerialize(): "
+                                               <<"Too large content id: "<<i<<std::endl;
+                               continue;
+                       }
+                       ContentFeatures *f = &m_content_features[i];
+                       f->deSerialize(tmp_is, gamedef);
+                       f->modified = true;
+               }
+       }
 private:
        ContentFeatures m_content_features[MAX_CONTENT+1];
 };
index e70295616647abb93aa63250a0faee409406d3fb..43bd1966d9673a8dcb3699fc7aefe4ff880a8cca 100644 (file)
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "common_irrlicht.h"
 #include <string>
+#include <iostream>
 #include <set>
 #include "mapnode.h"
 #ifndef SERVER
@@ -29,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #endif
 #include "materials.h" // MaterialProperties
 class ITextureSource;
+class IGameDef;
 
 /*
        TODO: Rename to nodedef.h
@@ -95,6 +97,9 @@ struct NodeBox
                wall_bottom(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2),
                wall_side(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2)
        {}
+
+       void serialize(std::ostream &os);
+       void deSerialize(std::istream &is);
 };
 
 struct MapNode;
@@ -109,42 +114,70 @@ struct MaterialSpec
                tname(tname_),
                backface_culling(backface_culling_)
        {}
+
+       void serialize(std::ostream &os);
+       void deSerialize(std::istream &is);
+};
+
+enum NodeDrawType
+{
+       NDT_NORMAL, // A basic solid block
+       NDT_AIRLIKE, // Nothing is drawn
+       NDT_LIQUID, // Do not draw face towards same kind of flowing/source liquid
+       NDT_FLOWINGLIQUID, // A very special kind of thing
+       NDT_GLASSLIKE, // Glass-like, don't draw faces towards other glass
+       NDT_ALLFACES, // Leaves-like, draw all faces no matter what
+       NDT_ALLFACES_OPTIONAL, // Fancy -> allfaces, fast -> normal
+       NDT_TORCHLIKE,
+       NDT_SIGNLIKE,
+       NDT_PLANTLIKE,
+       NDT_FENCELIKE,
+       NDT_RAILLIKE,
 };
 
 #define CF_SPECIAL_COUNT 2
 
 struct ContentFeatures
 {
+       /*
+               Cached stuff
+       */
 #ifndef SERVER
        // 0     1     2     3     4     5
        // up    down  right left  back  front 
        TileSpec tiles[6];
-       
        video::ITexture *inventory_texture;
-
-       // Post effect color, drawn when the camera is inside the node.
-       video::SColor post_effect_color;
-
        // Special material/texture
        // - Currently used for flowing liquids
        video::SMaterial *special_materials[CF_SPECIAL_COUNT];
        AtlasPointer *special_aps[CF_SPECIAL_COUNT];
+       u8 solidness; // Used when choosing which face is drawn
+       u8 visual_solidness; // When solidness=0, this tells how it looks like
+       bool backface_culling;
 #endif
        
+       // List of all block textures that have been used (value is dummy)
+       // Used for texture atlas making.
+       // Exists on server too for cleaner code in content_mapnode.cpp.
+       std::set<std::string> used_texturenames;
+       
+       // True if this actually contains non-default data
+       bool modified;
+
+       /*
+               Actual data
+       */
+
        // Visual definition
+       enum NodeDrawType drawtype;
+       float visual_scale; // Misc. scale parameter
        std::string tname_tiles[6];
        std::string tname_inventory;
        MaterialSpec mspec_special[CF_SPECIAL_COUNT];
        u8 alpha;
-       bool backface_culling;
-       u8 solidness; // Used when choosing which face is drawn
-       u8 visual_solidness; // When solidness=0, this tells how it looks like
 
-       // List of all block textures that have been used (value is dummy)
-       // Used for texture atlas making.
-       // Exists on server too for cleaner code in content_mapnode.cpp.
-       std::set<std::string> used_texturenames;
-       
+       // Post effect color, drawn when the camera is inside the node.
+       video::SColor post_effect_color;
        // Type of MapNode::param1
        ContentParamType param_type;
        // True for all ground-like things like stone and mud, false for eg. trees
@@ -172,18 +205,14 @@ struct ContentFeatures
        // Used for texture atlas creation.
        // Currently only enabled for CONTENT_STONE.
        bool often_contains_mineral;
-       
        // Inventory item string as which the node appears in inventory when dug.
        // Mineral overrides this.
        std::string dug_item;
-
        // Extra dug item and its rarity
        std::string extra_dug_item;
        s32 extra_dug_item_rarity;
-
        // Initial metadata is cloned from this
        NodeMetadata *initial_metadata;
-       
        // Whether the node is non-liquid, source liquid or flowing liquid
        enum LiquidType liquid_type;
        // If the content is liquid, this is the flowing version of the liquid.
@@ -194,72 +223,22 @@ struct ContentFeatures
        // 1 giving almost instantaneous propagation and 7 being
        // the slowest possible
        u8 liquid_viscosity;
-       
        // Amount of light the node emits
        u8 light_source;
-       
        u32 damage_per_second;
-
        NodeBox selection_box;
-
        MaterialProperties material;
-       
-       // NOTE: Move relevant properties to here from elsewhere
 
-       void reset()
-       {
-               // This isn't exactly complete due to lazyness
-               // TODO: Make it completely reset everything
-#ifndef SERVER
-               inventory_texture = NULL;
-               
-               post_effect_color = video::SColor(0, 0, 0, 0);
-               for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
-                       special_materials[j] = NULL;
-                       special_aps[j] = NULL;
-               }
-#endif
-               for(u32 i=0; i<6; i++)
-                       tname_tiles[i] = "";
-               for(u16 j=0; j<CF_SPECIAL_COUNT; j++)
-                       mspec_special[j] = MaterialSpec();
-               tname_inventory = "";
-               alpha = 255;
-               backface_culling = true;
-               solidness = 2;
-               visual_solidness = 0;
-               used_texturenames.clear();
-               param_type = CPT_NONE;
-               is_ground_content = false;
-               light_propagates = false;
-               sunlight_propagates = false;
-               walkable = true;
-               pointable = true;
-               diggable = true;
-               climbable = false;
-               buildable_to = false;
-               wall_mounted = false;
-               air_equivalent = false;
-               often_contains_mineral = false;
-               dug_item = "";
-               initial_metadata = NULL;
-               liquid_type = LIQUID_NONE;
-               liquid_alternative_flowing = CONTENT_IGNORE;
-               liquid_alternative_source = CONTENT_IGNORE;
-               liquid_viscosity = 0;
-               light_source = 0;
-               damage_per_second = 0;
-               selection_box = NodeBox();
-               material = MaterialProperties();
-       }
-
-       ContentFeatures()
-       {
-               reset();
-       }
-
-       ~ContentFeatures();
+       /*
+               Methods
+       */
        
+       ContentFeatures();
+       ~ContentFeatures();
+       void reset();
+       void serialize(std::ostream &os);
+       void deSerialize(std::istream &is, IGameDef *gamedef);
+
        /*
                Quickhands for simple materials
        */
@@ -320,6 +299,9 @@ public:
                Call after updating the texture atlas of a TextureSource.
        */
        virtual void updateTextures(ITextureSource *tsrc)=0;
+
+       virtual void serialize(std::ostream &os)=0;
+       virtual void deSerialize(std::istream &is, IGameDef *gamedef)=0;
 };
 
 IWritableNodeDefManager* createNodeDefManager();
index 54c19be50535faa367cfe878e4984471d9a8adaf..698174e0a5db0159ddc469230875df8fd0d7bb0a 100644 (file)
@@ -1016,7 +1016,7 @@ Server::Server(
        infostream<<"m_nodemgr="<<m_nodemgr<<std::endl;
        
        // Initialize default node definitions
-       content_mapnode_init(NULL, m_nodemgr);
+       content_mapnode_init(m_nodemgr);
        
        // Add default global mod path
        m_modspaths.push_back(porting::path_data + DIR_DELIM + "mods");
index 7c9fa9408abf8f5c83857f9c81663c9532ea7113..c998a97ab4886444ef49c7f7447e87570b6c30c4 100644 (file)
@@ -1088,7 +1088,7 @@ void run_tests()
        
        // Create node definitions
        IWritableNodeDefManager *nodedef = createNodeDefManager();
-       content_mapnode_init(NULL, nodedef);
+       content_mapnode_init(nodedef);
 
        infostream<<"run_tests() started"<<std::endl;
        TEST(TestUtilities);
index b0e1fbf5af3b97ffbdadf02582f51628babfe1b8..f57abfbb8e9cc4a646351c105175e14d3f1edeba 100644 (file)
@@ -182,12 +182,15 @@ struct SourceAtlasPointer
 class SourceImageCache
 {
 public:
-       void insert(const std::string &name, video::IImage *img)
+       void insert(const std::string &name, video::IImage *img,
+                       bool do_overwrite)
        {
                assert(img);
                core::map<std::string, video::IImage*>::Node *n;
                n = m_images.find(name);
                if(n){
+                       if(!do_overwrite)
+                               return;
                        video::IImage *oldimg = n->getValue();
                        if(oldimg)
                                oldimg->drop();
@@ -720,7 +723,7 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im
        
        assert(get_current_thread_id() == m_main_thread);
        
-       m_sourcecache.insert(name, img);
+       m_sourcecache.insert(name, img, false);
 
 #if 0
        JMutexAutoLock lock(m_atlaspointer_cache_mutex);
index ed368b208d2237c53e5946cf76aac94a2f1fa5ec..7c1fde6f0798200d0149a80e0ea56a6dda7076ad 100644 (file)
@@ -235,6 +235,19 @@ inline u32 readU32(std::istream &is)
        return readU32((u8*)buf);
 }
 
+inline void writeS32(std::ostream &os, u32 p)
+{
+       char buf[4];
+       writeS32((u8*)buf, p);
+       os.write(buf, 4);
+}
+inline u32 readS32(std::istream &is)
+{
+       char buf[4];
+       is.read(buf, 4);
+       return readS32((u8*)buf);
+}
+
 inline void writeF1000(std::ostream &os, f32 p)
 {
        char buf[4];