before adding day/night lighting
[oweals/minetest.git] / src / mapnode.h
index 0d65f30a48cc209993010241446199a040f147e5..7314420115d1f54803b1fc9005369ad87f1c2869 100644 (file)
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "utility.h"
 #include "exceptions.h"
 #include "serialization.h"
+#include "tile.h"
 
 // Size of node in rendering units
 #define BS 10
@@ -41,66 +42,63 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        Doesn't create faces with anything and is considered being
        out-of-map in the game map.
 */
-#define MATERIAL_IGNORE 255
-#define MATERIAL_IGNORE_DEFAULT_PARAM 0
+#define CONTENT_IGNORE 255
+#define CONTENT_IGNORE_DEFAULT_PARAM 0
 
 /*
        The common material through which the player can walk and which
        is transparent to light
 */
-#define MATERIAL_AIR 254
+#define CONTENT_AIR 254
 
 /*
-       Materials-todo:
-
+       Suggested materials:
        GRAVEL
          - Dynamics of gravel: if there is a drop of more than two
            blocks on any side, it will drop in there. Is this doable?
        
-       TODO: These should be named to "content" or something like that
+       New naming scheme:
+       - Material = irrlicht's Material class
+       - Content = (u8) content of a node
+       - Tile = (u16) Material ID at some side of a node
 */
 
-enum Material
+enum Content
 {
-       MATERIAL_STONE=0,
-
-       MATERIAL_GRASS,
-
-       MATERIAL_WATER,
-
-       MATERIAL_LIGHT,
-
-       MATERIAL_TREE,
-       
-       MATERIAL_LEAVES,
-
-       MATERIAL_GRASS_FOOTSTEPS,
-       
-       MATERIAL_MESE,
-
-       MATERIAL_MUD,
-
-       MATERIAL_OCEAN,
+       CONTENT_STONE,
+       CONTENT_GRASS,
+       CONTENT_WATER,
+       CONTENT_TORCH,
+       CONTENT_TREE,
+       CONTENT_LEAVES,
+       CONTENT_GRASS_FOOTSTEPS,
+       CONTENT_MESE,
+       CONTENT_MUD,
+       CONTENT_OCEAN,
+       CONTENT_CLOUD,
        
        // This is set to the number of the actual values in this enum
-       USEFUL_MATERIAL_COUNT
+       USEFUL_CONTENT_COUNT
 };
 
+extern u16 g_content_tiles[USEFUL_CONTENT_COUNT][6];
+extern const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT];
+
 /*
        If true, the material allows light propagation and brightness is stored
        in param.
 */
-inline bool light_propagates_material(u8 m)
+inline bool light_propagates_content(u8 m)
 {
-       return (m == MATERIAL_AIR || m == MATERIAL_LIGHT || m == MATERIAL_WATER || m == MATERIAL_OCEAN);
+       return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_OCEAN);
 }
 
 /*
        If true, the material allows lossless sunlight propagation.
 */
-inline bool sunlight_propagates_material(u8 m)
+inline bool sunlight_propagates_content(u8 m)
 {
-       return (m == MATERIAL_AIR);
+       return (m == CONTENT_AIR || m == CONTENT_TORCH);
 }
 
 /*
@@ -110,98 +108,181 @@ inline bool sunlight_propagates_material(u8 m)
        1: Transparent
        2: Opaque
 */
-inline u8 material_solidness(u8 m)
+inline u8 content_solidness(u8 m)
 {
-       if(m == MATERIAL_AIR)
+       // As of now, every pseudo node like torches are added to this
+       if(m == CONTENT_AIR || m == CONTENT_TORCH)
                return 0;
-       if(m == MATERIAL_WATER || m == MATERIAL_OCEAN)
+       if(m == CONTENT_WATER || m == CONTENT_OCEAN)
                return 1;
        return 2;
 }
 
-// Objects collide with walkable materials
-inline bool material_walkable(u8 m)
+// Objects collide with walkable contents
+inline bool content_walkable(u8 m)
 {
-       return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN && m != MATERIAL_LIGHT);
+       return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN && m != CONTENT_TORCH);
 }
 
 // A liquid resists fast movement
-inline bool material_liquid(u8 m)
-{
-       return (m == MATERIAL_WATER || m == MATERIAL_OCEAN);
-}
-
-// Pointable materials can be pointed to in the map
-inline bool material_pointable(u8 m)
+inline bool content_liquid(u8 m)
 {
-       return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN);
+       return (m == CONTENT_WATER || m == CONTENT_OCEAN);
 }
 
-inline bool material_diggable(u8 m)
+// Pointable contents can be pointed to in the map
+inline bool content_pointable(u8 m)
 {
-       return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN);
+       return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN);
 }
 
-inline bool material_buildable_to(u8 m)
+inline bool content_diggable(u8 m)
 {
-       return (m == MATERIAL_AIR || m == MATERIAL_WATER || m == MATERIAL_OCEAN);
+       return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN);
 }
 
-/*
-       As of now, input is a "material" and the output is a "material"
-*/
-inline u8 content_cube_material(u8 c)
+inline bool content_buildable_to(u8 m)
 {
-       if(c == MATERIAL_IGNORE || c == MATERIAL_LIGHT)
-               return MATERIAL_AIR;
-       return c;
+       return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_OCEAN);
 }
 
 /*
-       Returns true for materials that form the base ground that
+       Returns true for contents that form the base ground that
        follows the main heightmap
 */
-inline bool is_ground_material(u8 m)
+inline bool is_ground_content(u8 m)
 {
        return(
-               m == MATERIAL_STONE ||
-               m == MATERIAL_GRASS ||
-               m == MATERIAL_GRASS_FOOTSTEPS ||
-               m == MATERIAL_MESE ||
-               m == MATERIAL_MUD
+               m == CONTENT_STONE ||
+               m == CONTENT_GRASS ||
+               m == CONTENT_GRASS_FOOTSTEPS ||
+               m == CONTENT_MESE ||
+               m == CONTENT_MUD
        );
 }
 
+/*inline bool content_has_faces(u8 c)
+{
+       return (m != CONTENT_IGNORE
+            && m != CONTENT_AIR
+                && m != CONTENT_TORCH);
+}*/
+
 /*
-       Nodes make a face if materials differ and solidness differs.
+       Nodes make a face if contents differ and solidness differs.
        Return value:
                0: No face
-               1: Face uses m1's material
-               2: Face uses m2's material
+               1: Face uses m1's content
+               2: Face uses m2's content
 */
-inline u8 face_materials(u8 m1, u8 m2)
+inline u8 face_contents(u8 m1, u8 m2)
 {
-       if(m1 == MATERIAL_IGNORE || m2 == MATERIAL_IGNORE)
+       if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
                return 0;
        
-       bool materials_differ = (m1 != m2);
-       bool solidness_differs = (material_solidness(m1) != material_solidness(m2));
-       bool makes_face = materials_differ && solidness_differs;
+       bool contents_differ = (m1 != m2);
+       bool solidness_differs = (content_solidness(m1) != content_solidness(m2));
+       bool makes_face = contents_differ && solidness_differs;
 
        if(makes_face == false)
                return 0;
 
-       if(material_solidness(m1) > material_solidness(m2))
+       if(content_solidness(m1) > content_solidness(m2))
                return 1;
        else
                return 2;
 }
 
+inline bool liquid_replaces_content(u8 c)
+{
+       return (c == CONTENT_AIR || c == CONTENT_TORCH);
+}
+
+/*
+       When placing a node, drection info is added to it if this is true
+*/
+inline bool content_directional(u8 c)
+{
+       return (c == CONTENT_TORCH);
+}
+
+/*
+       Packs directions like (1,0,0), (1,-1,0)
+*/
+inline u8 packDir(v3s16 dir)
+{
+       u8 b = 0;
+
+       if(dir.X > 0)
+               b |= (1<<0);
+       else if(dir.X < 0)
+               b |= (1<<1);
+
+       if(dir.Y > 0)
+               b |= (1<<2);
+       else if(dir.Y < 0)
+               b |= (1<<3);
+
+       if(dir.Z > 0)
+               b |= (1<<4);
+       else if(dir.Z < 0)
+               b |= (1<<5);
+       
+       return b;
+}
+inline v3s16 unpackDir(u8 b)
+{
+       v3s16 d(0,0,0);
+
+       if(b & (1<<0))
+               d.X = 1;
+       else if(b & (1<<1))
+               d.X = -1;
+
+       if(b & (1<<2))
+               d.Y = 1;
+       else if(b & (1<<3))
+               d.Y = -1;
+
+       if(b & (1<<4))
+               d.Z = 1;
+       else if(b & (1<<5))
+               d.Z = -1;
+       
+       return d;
+}
+
+inline u16 content_tile(u8 c, v3s16 dir)
+{
+       if(c == CONTENT_IGNORE || c == CONTENT_AIR
+                       || c >= USEFUL_CONTENT_COUNT)
+               return TILE_NONE;
+
+       s32 dir_i = -1;
+       
+       if(dir == v3s16(0,1,0))
+               dir_i = 0;
+       else if(dir == v3s16(0,-1,0))
+               dir_i = 1;
+       else if(dir == v3s16(1,0,0))
+               dir_i = 2;
+       else if(dir == v3s16(-1,0,0))
+               dir_i = 3;
+       else if(dir == v3s16(0,0,1))
+               dir_i = 4;
+       else if(dir == v3s16(0,0,-1))
+               dir_i = 5;
+       
+       /*if(dir_i == -1)
+               return TILE_NONE;*/
+       assert(dir_i != -1);
+
+       return g_content_tiles[c][dir_i];
+}
+
 struct MapNode
 {
-       //TODO: block type to differ from material
-       //      (e.g. grass edges or something)
-       // block type
+       // Content
        u8 d;
 
        /*
@@ -211,15 +292,27 @@ struct MapNode
                  Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
        */
        s8 param;
+       
+       union
+       {
+               /*
+                       Pressure for liquids
+               */
+               u8 pressure;
 
-       u8 pressure;
+               /*
+                       Direction for torches and other stuff.
+                       If possible, packed with packDir.
+               */
+               u8 dir;
+       };
 
        MapNode(const MapNode & n)
        {
                *this = n;
        }
        
-       MapNode(u8 data=MATERIAL_AIR, u8 a_param=0, u8 a_pressure=0)
+       MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_pressure=0)
        {
                d = data;
                param = a_param;
@@ -235,17 +328,17 @@ struct MapNode
 
        bool light_propagates()
        {
-               return light_propagates_material(d);
+               return light_propagates_content(d);
        }
        
        bool sunlight_propagates()
        {
-               return sunlight_propagates_material(d);
+               return sunlight_propagates_content(d);
        }
        
        u8 solidness()
        {
-               return material_solidness(d);
+               return content_solidness(d);
        }
 
        u8 light_source()
@@ -253,7 +346,7 @@ struct MapNode
                /*
                        Note that a block that isn't light_propagates() can be a light source.
                */
-               if(d == MATERIAL_LIGHT)
+               if(d == CONTENT_TORCH)
                        return LIGHT_MAX;
                
                return 0;
@@ -261,7 +354,7 @@ struct MapNode
 
        u8 getLight()
        {
-               // Select the brightest of [light_source, transparent_light]
+               // Select the brightest of [light source, propagated light]
                u8 light = 0;
                if(light_propagates())
                        light = param & 0x0f;
@@ -275,7 +368,13 @@ struct MapNode
                // If not transparent, can't set light
                if(light_propagates() == false)
                        return;
-               param = a_light;
+               param &= 0xf0;
+               param |= a_light;
+       }
+
+       u16 getTile(v3s16 dir)
+       {
+               return content_tile(d, dir);
        }
 
        /*