ToolDefManager serialization
[oweals/minetest.git] / src / content_mapblock.cpp
index 5e1bac2e997d254238693763e49c899b38526e6a..ff6215a540abd08653fd3499ce7d4955619c34be 100644 (file)
@@ -19,10 +19,12 @@ 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 and g_texturesource
+#include "main.h" // For g_settings
 #include "mineral.h"
 #include "mapblock_mesh.h" // For MapBlock_LightColor()
 #include "settings.h"
+#include "nodedef.h"
+#include "gamedef.h"
 
 #ifndef SERVER
 // Create a cuboid.
@@ -121,8 +123,11 @@ void makeCuboid(video::SMaterial &material, MeshCollector *collector,
 
 #ifndef SERVER
 void mapblock_mesh_generate_special(MeshMakeData *data,
-               MeshCollector &collector)
+               MeshCollector &collector, IGameDef *gamedef)
 {
+       ITextureSource *tsrc = gamedef->tsrc();
+       INodeDefManager *nodedef = gamedef->ndef();
+
        // 0ms
        //TimeTaker timer("mapblock_mesh_generate_special()");
 
@@ -146,8 +151,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        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 = g_texturesource->getTexture(
-                       g_texturesource->getTextureId("leaves.png"));
+       AtlasPointer pa_leaves1 = tsrc->getTexture(
+                       tsrc->getTextureId("leaves.png"));
        material_leaves1.setTexture(0, pa_leaves1.atlas);
 
        // Glass material
@@ -156,8 +161,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        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 = g_texturesource->getTexture(
-                       g_texturesource->getTextureId("glass.png"));
+       AtlasPointer pa_glass = tsrc->getTexture(
+                       tsrc->getTextureId("glass.png"));
        material_glass.setTexture(0, pa_glass.atlas);
 
        // Wood material
@@ -166,8 +171,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        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 = g_texturesource->getTexture(
-                       g_texturesource->getTextureId("wood.png"));
+       AtlasPointer pa_wood = tsrc->getTexture(
+                       tsrc->getTextureId("wood.png"));
        material_wood.setTexture(0, pa_wood.atlas);
 
        // General ground material for special output
@@ -185,8 +190,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        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 = g_texturesource->getTexture(
-                       g_texturesource->getTextureId("papyrus.png"));
+       AtlasPointer pa_papyrus = tsrc->getTexture(
+                       tsrc->getTextureId("papyrus.png"));
        material_papyrus.setTexture(0, pa_papyrus.atlas);
        
        // Apple material
@@ -195,8 +200,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        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 = g_texturesource->getTexture(
-                       g_texturesource->getTextureId("apple.png"));
+       AtlasPointer pa_apple = tsrc->getTexture(
+                       tsrc->getTextureId("apple.png"));
        material_apple.setTexture(0, pa_apple.atlas);
 
 
@@ -206,8 +211,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        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 = g_texturesource->getTexture(
-                       g_texturesource->getTextureId("sapling.png"));
+       AtlasPointer pa_sapling = tsrc->getTexture(
+                       tsrc->getTextureId("sapling.png"));
        material_sapling.setTexture(0, pa_sapling.atlas);
 
 
@@ -217,8 +222,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
        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 = g_texturesource->getTexture(
-                       g_texturesource->getTextureId("junglegrass.png"));
+       AtlasPointer pa_junglegrass = tsrc->getTexture(
+                       tsrc->getTextureId("junglegrass.png"));
        material_junglegrass.setTexture(0, pa_junglegrass.atlas);
 
        for(s16 z=0; z<MAP_BLOCKSIZE; z++)
@@ -248,7 +253,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                texturename = "torch.png";
                        }
 
-                       AtlasPointer ap = g_texturesource->getTexture(texturename);
+                       AtlasPointer ap = tsrc->getTexture(texturename);
 
                        // Set material
                        video::SMaterial material;
@@ -303,7 +308,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                */
                else if(n.getContent() == CONTENT_SIGN_WALL)
                {
-                       AtlasPointer ap = g_texturesource->getTexture("sign_wall.png");
+                       AtlasPointer ap = tsrc->getTexture("sign_wall.png");
 
                        // Set material
                        video::SMaterial material;
@@ -315,7 +320,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                        = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
                        material.setTexture(0, ap.atlas);
 
-                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
+                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
                        video::SColor c = MapBlock_LightColor(255, l);
                                
                        float d = (float)BS/16;
@@ -359,31 +364,34 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                /*
                        Add flowing liquid to mesh
                */
-               else if(content_features(n).liquid_type == LIQUID_FLOWING)
+               else if(nodedef->get(n).liquid_type == LIQUID_FLOWING)
                {
-                       assert(content_features(n).special_material);
+                       assert(nodedef->get(n).special_material);
                        video::SMaterial &liquid_material =
-                                       *content_features(n).special_material;
-                       assert(content_features(n).special_atlas);
+                                       *nodedef->get(n).special_material;
+                       video::SMaterial &liquid_material_bfculled =
+                                       *nodedef->get(n).special_material2;
+
+                       assert(nodedef->get(n).special_atlas);
                        AtlasPointer &pa_liquid1 =
-                                       *content_features(n).special_atlas;
+                                       *nodedef->get(n).special_atlas;
 
                        bool top_is_same_liquid = false;
                        MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
-                       content_t c_flowing = content_features(n).liquid_alternative_flowing;
-                       content_t c_source = content_features(n).liquid_alternative_source;
+                       content_t c_flowing = nodedef->get(n).liquid_alternative_flowing;
+                       content_t c_source = nodedef->get(n).liquid_alternative_source;
                        if(ntop.getContent() == c_flowing || ntop.getContent() == c_source)
                                top_is_same_liquid = true;
                        
                        u8 l = 0;
                        // Use the light of the node on top if possible
-                       if(content_features(ntop).param_type == CPT_LIGHT)
-                               l = decode_light(ntop.getLightBlend(data->m_daynight_ratio));
+                       if(nodedef->get(ntop).param_type == CPT_LIGHT)
+                               l = decode_light(ntop.getLightBlend(data->m_daynight_ratio, nodedef));
                        // Otherwise use the light of this node (the liquid)
                        else
-                               l = decode_light(n.getLightBlend(data->m_daynight_ratio));
+                               l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
                        video::SColor c = MapBlock_LightColor(
-                                       content_features(n).vertex_alpha, l);
+                                       nodedef->get(n).vertex_alpha, l);
                        
                        // Neighbor liquid levels (key = relative position)
                        // Includes current node
@@ -516,10 +524,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                        continue;
 
                                content_t neighbor_content = neighbor_contents[dir];
+                               const ContentFeatures &n_feat = nodedef->get(neighbor_content);
                                
-                               // Don't draw face if neighbor is not air or liquid
-                               if(neighbor_content != CONTENT_AIR
-                                               && content_liquid(neighbor_content) == false)
+                               // Don't draw face if neighbor is blocking the view
+                               if(n_feat.solidness == 2)
                                        continue;
                                
                                bool neighbor_is_same_liquid = (neighbor_content == c_source
@@ -530,6 +538,12 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                if(neighbor_is_same_liquid == true
                                                && top_is_same_liquid == false)
                                        continue;
+
+                               // Use backface culled material if neighbor doesn't have a
+                               // solidness of 0
+                               video::SMaterial *current_material = &liquid_material;
+                               if(n_feat.solidness != 0 || n_feat.visual_solidness != 0)
+                                       current_material = &liquid_material_bfculled;
                                
                                video::S3DVertex vertices[4] =
                                {
@@ -593,17 +607,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                                
                                        // Do this to not cause glitches when two liquids are
                                        // side-by-side
-                                       if(neighbor_is_same_liquid == false){
+                                       /*if(neighbor_is_same_liquid == false){
                                                vertices[j].Pos.X *= 0.98;
                                                vertices[j].Pos.Z *= 0.98;
-                                       }
+                                       }*/
 
                                        vertices[j].Pos += intToFloat(p + blockpos_nodes, BS);
                                }
 
                                u16 indices[] = {0,1,2,2,3,0};
                                // Add to mesh collector
-                               collector.append(liquid_material, vertices, 4, indices, 6);
+                               collector.append(*current_material, vertices, 4, indices, 6);
                        }
                        
                        /*
@@ -644,15 +658,15 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                /*
                        Add water sources to mesh if using new style
                */
-               else if(content_features(n).liquid_type == LIQUID_SOURCE
+               else if(nodedef->get(n).liquid_type == LIQUID_SOURCE
                                && new_style_water)
                {
-                       assert(content_features(n).special_material);
+                       assert(nodedef->get(n).special_material);
                        video::SMaterial &liquid_material =
-                                       *content_features(n).special_material;
-                       assert(content_features(n).special_atlas);
+                                       *nodedef->get(n).special_material;
+                       assert(nodedef->get(n).special_atlas);
                        AtlasPointer &pa_liquid1 =
-                                       *content_features(n).special_atlas;
+                                       *nodedef->get(n).special_atlas;
 
                        bool top_is_air = false;
                        MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
@@ -662,9 +676,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        if(top_is_air == false)
                                continue;
 
-                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
+                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
                        video::SColor c = MapBlock_LightColor(
-                                       content_features(n).vertex_alpha, l);
+                                       nodedef->get(n).vertex_alpha, l);
                        
                        video::S3DVertex vertices[4] =
                        {
@@ -693,8 +707,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                */
                else if(n.getContent() == CONTENT_LEAVES && new_style_leaves)
                {
-                       /*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));*/
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       /*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);
 
                        for(u32 j=0; j<6; j++)
@@ -757,7 +771,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                */
                else if(n.getContent() == CONTENT_GLASS)
                {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       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<6; j++)
@@ -820,7 +834,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                */
                else if(n.getContent() == CONTENT_FENCE)
                {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
                        video::SColor c = MapBlock_LightColor(255, l);
 
                        const f32 post_rad=(f32)BS/10;
@@ -897,7 +911,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                /*
                        Add stones with minerals if stone is invisible
                */
-               else if(n.getContent() == CONTENT_STONE && invisible_stone && n.getMineral() != MINERAL_NONE)
+               else if(n.getContent() == CONTENT_STONE && invisible_stone && n.getMineral(nodedef) != MINERAL_NONE)
                {
                        for(u32 j=0; j<6; j++)
                        {
@@ -905,15 +919,15 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                v3s16 dir = g_6dirs[j];
                                /*u8 l = 0;
                                MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir);
-                               if(content_features(n2).param_type == CPT_LIGHT)
-                                       l = decode_light(n2.getLightBlend(data->m_daynight_ratio));
+                               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);
+                               TileSpec ts = n.getTile(dir, tsrc, nodedef);
                                AtlasPointer ap = ts.texture;
                                material_general.setTexture(0, ap.atlas);
 
@@ -964,7 +978,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 #endif
                else if(n.getContent() == CONTENT_PAPYRUS)
                {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       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++)
@@ -1014,7 +1028,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                }
                else if(n.getContent() == CONTENT_JUNGLEGRASS)
                {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       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++)
@@ -1100,7 +1114,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        else if(adjacencies == 4)
                                texturename = "rail_crossing.png";
                        
-                       AtlasPointer ap = g_texturesource->getTexture(texturename);
+                       AtlasPointer ap = tsrc->getTexture(texturename);
 
                        video::SMaterial material_rail;
                        material_rail.setFlag(video::EMF_LIGHTING, false);
@@ -1111,7 +1125,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                                        = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
                        material_rail.setTexture(0, ap.atlas);
 
-                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
+                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
                        video::SColor c = MapBlock_LightColor(255, l);
 
                        float d = (float)BS/16;
@@ -1172,7 +1186,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        collector.append(material_rail, vertices, 4, indices, 6);
                }
                else if (n.getContent() == CONTENT_LADDER) {
-                       AtlasPointer ap = g_texturesource->getTexture("ladder.png");
+                       AtlasPointer ap = tsrc->getTexture("ladder.png");
                        
                        // Set material
                        video::SMaterial material_ladder;
@@ -1183,7 +1197,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        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));
+                       u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio, nodedef));
                        video::SColor c(255,l,l,l);
 
                        float d = (float)BS/16;
@@ -1227,7 +1241,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                }
                else if(n.getContent() == CONTENT_APPLE)
                {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       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++)
@@ -1276,7 +1290,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
                        }
                }
                else if(n.getContent() == CONTENT_SAPLING) {
-                       u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+                       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++)