ServerRemotePlayer implements ServerActiveObject
[oweals/minetest.git] / src / mapnode.cpp
index 391e593f9548b9715de7f733169e88a50eb44f78..f816319999e1c30196c0b066f5aa83a45f55800a 100644 (file)
@@ -19,7 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "common_irrlicht.h"
 #include "mapnode.h"
+#ifndef SERVER
 #include "tile.h"
+#endif
 #include "porting.h"
 #include <string>
 #include "mineral.h"
@@ -30,14 +32,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 ContentFeatures::~ContentFeatures()
 {
-       /*if(translate_to)
-               delete translate_to;*/
-       if(initial_metadata)
-               delete initial_metadata;
+       delete initial_metadata;
+#ifndef SERVER
+       delete special_material;
+       delete special_atlas;
+#endif
 }
 
+#ifndef SERVER
 void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
 {
+       used_texturenames[name] = true;
+       
        if(g_texturesource)
        {
                tiles[i].texture = g_texturesource->getTexture(name);
@@ -82,13 +88,18 @@ void ContentFeatures::setInventoryTextureCube(std::string top,
        imgname_full += right;
        inventory_texture = g_texturesource->getTextureRaw(imgname_full);
 }
+#endif
 
-struct ContentFeatures g_content_features[256];
+struct ContentFeatures g_content_features[MAX_CONTENT+1];
 
-ContentFeatures & content_features(u8 i)
+ContentFeatures & content_features(content_t i)
 {
        return g_content_features[i];
 }
+ContentFeatures & content_features(MapNode &n)
+{
+       return content_features(n.getContent());
+}
 
 /*
        See mapnode.h for description.
@@ -115,7 +126,8 @@ void init_mapnode()
        /*
                Initialize content feature table
        */
-       
+
+#ifndef SERVER
        /*
                Set initial material type to same in all tiles, so that the
                same material can be used in more stuff.
@@ -128,7 +140,7 @@ void init_mapnode()
                initial_material_type = MATERIAL_ALPHA_SIMPLE;
        else
                initial_material_type = MATERIAL_ALPHA_NONE;*/
-       for(u16 i=0; i<256; i++)
+       for(u16 i=0; i<MAX_CONTENT+1; i++)
        {
                ContentFeatures *f = &g_content_features[i];
                // Re-initialize
@@ -137,18 +149,24 @@ void init_mapnode()
                for(u16 j=0; j<6; j++)
                        f->tiles[j].material_type = initial_material_type;
        }
+#endif
 
        /*
                Initially set every block to be shown as an unknown block.
                Don't touch CONTENT_IGNORE or CONTENT_AIR.
        */
-       for(u16 i=0; i<=253; i++)
+       for(u16 i=0; i<MAX_CONTENT+1; i++)
        {
+               if(i == CONTENT_IGNORE || i == CONTENT_AIR)
+                       continue;
                ContentFeatures *f = &g_content_features[i];
                f->setAllTextures("unknown_block.png");
-               f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+               f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
        }
 
+       // Make CONTENT_IGNORE to not block the view when occlusion culling
+       content_features(CONTENT_IGNORE).solidness = 0;
+
        /*
                Initialize mapnode content
        */
@@ -156,6 +174,57 @@ void init_mapnode()
        
 }
 
+/*
+       Nodes make a face if contents differ and solidness differs.
+       Return value:
+               0: No face
+               1: Face uses m1's content
+               2: Face uses m2's content
+       equivalent: Whether the blocks share the same face (eg. water and glass)
+*/
+u8 face_contents(content_t m1, content_t m2, bool *equivalent)
+{
+       *equivalent = false;
+
+       if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
+               return 0;
+       
+       bool contents_differ = (m1 != m2);
+       
+       // Contents don't differ for different forms of same liquid
+       if(content_liquid(m1) && content_liquid(m2)
+                       && make_liquid_flowing(m1) == make_liquid_flowing(m2))
+               contents_differ = false;
+       
+       u8 c1 = content_solidness(m1);
+       u8 c2 = content_solidness(m2);
+
+       bool solidness_differs = (c1 != c2);
+       bool makes_face = contents_differ && solidness_differs;
+
+       if(makes_face == false)
+               return 0;
+       
+       if(c1 == 0)
+               c1 = content_features(m1).visual_solidness;
+       if(c2 == 0)
+               c2 = content_features(m2).visual_solidness;
+       
+       if(c1 == c2){
+               *equivalent = true;
+               // If same solidness, liquid takes precense
+               if(content_features(m1).liquid_type != LIQUID_NONE)
+                       return 1;
+               if(content_features(m2).liquid_type != LIQUID_NONE)
+                       return 2;
+       }
+       
+       if(c1 > c2)
+               return 1;
+       else
+               return 2;
+}
+
 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
 {
        /*
@@ -179,9 +248,10 @@ v3s16 facedir_rotate(u8 facedir, v3s16 dir)
        return newdir;
 }
 
+#ifndef SERVER
 TileSpec MapNode::getTile(v3s16 dir)
 {
-       if(content_features(d).param_type == CPT_FACEDIR_SIMPLE)
+       if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
                dir = facedir_rotate(param1, dir);
        
        TileSpec spec;
@@ -205,16 +275,16 @@ TileSpec MapNode::getTile(v3s16 dir)
        
        if(dir_i == -1)
                // Non-directional
-               spec = content_features(d).tiles[0];
+               spec = content_features(*this).tiles[0];
        else 
-               spec = content_features(d).tiles[dir_i];
+               spec = content_features(*this).tiles[dir_i];
        
        /*
                If it contains some mineral, change texture id
        */
-       if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
+       if(content_features(*this).param_type == CPT_MINERAL && g_texturesource)
        {
-               u8 mineral = param & 0x1f;
+               u8 mineral = getMineral();
                std::string mineral_texture_name = mineral_block_texture(mineral);
                if(mineral_texture_name != "")
                {
@@ -230,12 +300,13 @@ TileSpec MapNode::getTile(v3s16 dir)
 
        return spec;
 }
+#endif
 
 u8 MapNode::getMineral()
 {
-       if(content_features(d).param_type == CPT_MINERAL)
+       if(content_features(*this).param_type == CPT_MINERAL)
        {
-               return param & 0x1f;
+               return param1 & 0x0f;
        }
 
        return MINERAL_NONE;
@@ -258,33 +329,36 @@ void MapNode::serialize(u8 *dest, u8 version)
        if(!ser_ver_supported(version))
                throw VersionMismatchException("ERROR: MapNode format not supported");
                
-       u8 actual_d = d;
+       // Translate to wanted version
+       MapNode n_foreign = mapnode_translate_from_internal(*this, version);
+
+       u8 actual_param0 = n_foreign.param0;
 
-       // Convert from new version to old
+       // Convert special values from new version to old
        if(version <= 18)
        {
                // In these versions, CONTENT_IGNORE and CONTENT_AIR
                // are 255 and 254
-               if(d == CONTENT_IGNORE)
-                       d = 255;
-               else if(d == CONTENT_AIR)
-                       d = 254;
+               if(actual_param0 == CONTENT_IGNORE)
+                       actual_param0 = 255;
+               else if(actual_param0 == CONTENT_AIR)
+                       actual_param0 = 254;
        }
 
        if(version == 0)
        {
-               dest[0] = actual_d;
+               dest[0] = actual_param0;
        }
        else if(version <= 9)
        {
-               dest[0] = actual_d;
-               dest[1] = param;
+               dest[0] = actual_param0;
+               dest[1] = n_foreign.param1;
        }
        else
        {
-               dest[0] = actual_d;
-               dest[1] = param;
-               dest[2] = param2;
+               dest[0] = actual_param0;
+               dest[1] = n_foreign.param1;
+               dest[2] = n_foreign.param2;
        }
 }
 void MapNode::deSerialize(u8 *source, u8 version)
@@ -294,39 +368,50 @@ void MapNode::deSerialize(u8 *source, u8 version)
                
        if(version == 0)
        {
-               d = source[0];
+               param0 = source[0];
        }
        else if(version == 1)
        {
-               d = source[0];
+               param0 = source[0];
                // This version doesn't support saved lighting
                if(light_propagates() || light_source() > 0)
-                       param = 0;
+                       param1 = 0;
                else
-                       param = source[1];
+                       param1 = source[1];
        }
        else if(version <= 9)
        {
-               d = source[0];
-               param = source[1];
+               param0 = source[0];
+               param1 = source[1];
        }
        else
        {
-               d = source[0];
-               param = source[1];
+               param0 = source[0];
+               param1 = source[1];
                param2 = source[2];
-               
-               // Convert from old version to new
-               if(version <= 18)
-               {
-                       // In these versions, CONTENT_IGNORE and CONTENT_AIR
-                       // are 255 and 254
-                       if(d == 255)
-                               d = CONTENT_IGNORE;
-                       else if(d == 254)
-                               d = CONTENT_AIR;
-               }
        }
+       
+       // Convert special values from old version to new
+       if(version <= 18)
+       {
+               // In these versions, CONTENT_IGNORE and CONTENT_AIR
+               // are 255 and 254
+               if(param0 == 255)
+                       param0 = CONTENT_IGNORE;
+               else if(param0 == 254)
+                       param0 = CONTENT_AIR;
+       }
+       // version 19 is fucked up with sometimes the old values and sometimes not
+       if(version == 19)
+       {
+               if(param0 == 255)
+                       param0 = CONTENT_IGNORE;
+               else if(param0 == 254)
+                       param0 = CONTENT_AIR;
+       }
+
+       // Translate to our known version
+       *this = mapnode_translate_to_internal(*this, version);
 }
 
 /*