/*
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
#include "exceptions.h"
#include "serialization.h"
#include "tile.h"
+#include "iirrlichtwrapper.h"
+
+/*
+ Initializes all kind of stuff in here.
+ Many things depend on this.
+
+ This accesses g_texturesource; if it is non-NULL, textures are set.
+
+ Client first calls this with g_texturesource=NULL to run some
+ unit tests and stuff, then it runs this again with g_texturesource
+ defined to get the textures.
+
+ Server only calls this once with g_texturesource=NULL.
+*/
+void init_mapnode();
+
+// Initializes g_content_inventory_texture_paths
+void init_content_inventory_texture_paths();
-// Size of node in rendering units
-#define BS 10
+// NOTE: This is not used appropriately everywhere.
#define MATERIALS_COUNT 256
/*
/*
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?
+ - Gravel
+ - Sand
New naming scheme:
- Material = irrlicht's Material class
- Tile = (u16) Material ID at some side of a node
*/
-enum Content
+#define CONTENT_STONE 0
+#define CONTENT_GRASS 1
+#define CONTENT_WATER 2
+#define CONTENT_TORCH 3
+#define CONTENT_TREE 4
+#define CONTENT_LEAVES 5
+#define CONTENT_GRASS_FOOTSTEPS 6
+#define CONTENT_MESE 7
+#define CONTENT_MUD 8
+#define CONTENT_WATERSOURCE 9
+// Pretty much useless, clouds won't be drawn this way
+#define CONTENT_CLOUD 10
+#define CONTENT_COALSTONE 11
+#define CONTENT_WOOD 12
+#define CONTENT_SAND 13
+
+/*
+ This is used by all kinds of things to allocate memory for all
+ contents except CONTENT_AIR and CONTENT_IGNORE
+*/
+#define USEFUL_CONTENT_COUNT 14
+
+/*
+ Content feature list
+*/
+
+enum ContentParamType
{
- CONTENT_STONE,
- CONTENT_GRASS,
- CONTENT_WATER,
- CONTENT_TORCH,
- CONTENT_TREE,
- CONTENT_LEAVES,
- CONTENT_GRASS_FOOTSTEPS,
- CONTENT_MESE,
- CONTENT_MUD,
- CONTENT_OCEAN,
- CONTENT_CLOUD,
- CONTENT_COALSTONE,
+ CPT_NONE,
+ CPT_LIGHT,
+ CPT_MINERAL
+};
+
+enum LiquidType
+{
+ LIQUID_NONE,
+ LIQUID_FLOWING,
+ LIQUID_SOURCE
+};
+
+class MapNode;
+
+struct ContentFeatures
+{
+ // If non-NULL, content is translated to this when deserialized
+ MapNode *translate_to;
+
+ // Type of MapNode::param
+ ContentParamType param_type;
+
+ /*
+ 0: up
+ 1: down
+ 2: right
+ 3: left
+ 4: back
+ 5: front
+ */
+ TileSpec tiles[6];
+
+ // TODO: Somehow specify inventory image
+ //std::string inventory_image_path;
+ //TextureSpec inventory_texture;
+ //u32 inventory_texture_id;
+ video::ITexture *inventory_texture;
+
+ bool is_ground_content; //TODO: Remove, use walkable instead
+ bool light_propagates;
+ bool sunlight_propagates;
+ u8 solidness; // Used when choosing which face is drawn
+ bool walkable;
+ bool pointable;
+ bool diggable;
+ bool buildable_to;
+ enum LiquidType liquid_type;
+ // If true, param2 is set to direction when placed
+ // NOTE: the direction format is quite inefficient and should be changed
+ bool wall_mounted;
+
+ // Inventory item string as which the node appears in inventory when dug.
+ // Mineral overrides this.
+ std::string dug_item;
+
+ //TODO: Move more properties here
+
+ ContentFeatures()
+ {
+ translate_to = NULL;
+ param_type = CPT_NONE;
+ inventory_texture = NULL;
+ is_ground_content = false;
+ light_propagates = false;
+ sunlight_propagates = false;
+ solidness = 2;
+ walkable = true;
+ pointable = true;
+ diggable = true;
+ buildable_to = false;
+ liquid_type = LIQUID_NONE;
+ wall_mounted = false;
+ dug_item = "";
+ }
+
+ ~ContentFeatures();
+
+ /*
+ Quickhands for simple materials
+ */
- // This is set to the number of the actual values in this enum
- USEFUL_CONTENT_COUNT
+ void setTexture(u16 i, std::string name, u8 alpha=255);
+
+ void setAllTextures(std::string name, u8 alpha=255)
+ {
+ for(u16 i=0; i<6; i++)
+ {
+ setTexture(i, name, alpha);
+ }
+ }
+
+ /*void setTexture(u16 i, AtlasPointer p, u8 alpha=255)
+ {
+ tiles[i].texture = p;
+ if(alpha != 255)
+ {
+ tiles[i].alpha = alpha;
+ tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
+ }
+ }
+ void setAllTextures(AtlasPointer p, u8 alpha=255)
+ {
+ for(u16 i=0; i<6; i++)
+ {
+ setTexture(i, p, alpha);
+ }
+ }*/
+
+ void setTile(u16 i, const TileSpec &tile)
+ {
+ tiles[i] = tile;
+ }
+ void setAllTiles(const TileSpec &tile)
+ {
+ for(u16 i=0; i<6; i++)
+ {
+ setTile(i, tile);
+ }
+ }
+
+ void setInventoryTexture(std::string imgname);
+
+ void setInventoryTextureCube(std::string top,
+ std::string left, std::string right);
};
-extern u16 g_content_tiles[USEFUL_CONTENT_COUNT][6];
-extern const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT];
+/*
+ Call this to access the ContentFeature list
+*/
+ContentFeatures & content_features(u8 i);
/*
If true, the material allows light propagation and brightness is stored
in param.
+ NOTE: Don't use, use "content_features(m).whatever" instead
*/
inline bool light_propagates_content(u8 m)
{
- return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_OCEAN);
+ return content_features(m).light_propagates;
+ //return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
}
/*
If true, the material allows lossless sunlight propagation.
+ NOTE: It doesn't seem to go through torches regardlessly of this
+ NOTE: Don't use, use "content_features(m).whatever" instead
*/
inline bool sunlight_propagates_content(u8 m)
{
- return (m == CONTENT_AIR || m == CONTENT_TORCH);
+ return content_features(m).sunlight_propagates;
+ //return (m == CONTENT_AIR || m == CONTENT_TORCH);
}
/*
0: Invisible
1: Transparent
2: Opaque
+ NOTE: Don't use, use "content_features(m).whatever" instead
*/
inline u8 content_solidness(u8 m)
{
- // As of now, every pseudo node like torches are added to this
- if(m == CONTENT_AIR || m == CONTENT_TORCH)
+ return content_features(m).solidness;
+ /*// As of now, every pseudo node like torches are added to this
+ if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER)
return 0;
- if(m == CONTENT_WATER || m == CONTENT_OCEAN)
+ if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
return 1;
- return 2;
+ return 2;*/
}
// Objects collide with walkable contents
+// NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_walkable(u8 m)
{
- return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN && m != CONTENT_TORCH);
+ return content_features(m).walkable;
+ //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH);
}
-// A liquid resists fast movement
+// NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_liquid(u8 m)
{
- return (m == CONTENT_WATER || m == CONTENT_OCEAN);
+ return content_features(m).liquid_type != LIQUID_NONE;
+ //return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
+}
+
+// NOTE: Don't use, use "content_features(m).whatever" instead
+inline bool content_flowing_liquid(u8 m)
+{
+ return content_features(m).liquid_type == LIQUID_FLOWING;
+ //return (m == CONTENT_WATER);
+}
+
+// NOTE: Don't use, use "content_features(m).whatever" instead
+inline bool content_liquid_source(u8 m)
+{
+ return content_features(m).liquid_type == LIQUID_SOURCE;
+ //return (m == CONTENT_WATERSOURCE);
+}
+
+// CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
+// CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
+inline u8 make_liquid_flowing(u8 m)
+{
+ if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
+ return CONTENT_WATER;
+ assert(0);
}
// Pointable contents can be pointed to in the map
+// NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_pointable(u8 m)
{
- return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN);
+ return content_features(m).pointable;
+ //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
}
+// NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_diggable(u8 m)
{
- return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN);
+ return content_features(m).diggable;
+ //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
}
+// NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_buildable_to(u8 m)
{
- return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_OCEAN);
+ return content_features(m).buildable_to;
+ //return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
}
/*
Returns true for contents that form the base ground that
follows the main heightmap
*/
-inline bool is_ground_content(u8 m)
+/*inline bool is_ground_content(u8 m)
{
- return(
- 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);
+ return content_features(m).is_ground_content;
}*/
/*
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;
+
bool solidness_differs = (content_solidness(m1) != content_solidness(m2));
bool makes_face = contents_differ && solidness_differs;
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)
*/
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];
-}
-
enum LightBank
{
LIGHTBANK_DAY,
LIGHTBANK_NIGHT
};
+/*
+ This is the stuff what the whole world consists of.
+*/
+
struct MapNode
{
// Content
- For light_propagates() blocks, this is light intensity,
stored logarithmically from 0 to LIGHT_MAX.
Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
+ - Contains 2 values, day- and night lighting. Each takes 4 bits.
*/
s8 param;
union
{
/*
- Pressure for liquids
- */
- u8 pressure;
-
- /*
- Direction for torches and other stuff.
- If possible, packed with packDir.
+ The second parameter. Initialized to 0.
+ Direction for torches and flowing water.
*/
+ u8 param2;
u8 dir;
};
*this = n;
}
- MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_pressure=0)
+ MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_param2=0)
{
d = data;
param = a_param;
- pressure = a_pressure;
+ param2 = a_param2;
}
+ /*MapNode & operator=(const MapNode &other)
+ {
+ d = other.d;
+ param = other.param;
+ param2 = other.param2;
+ return *this;
+ }*/
+
bool operator==(const MapNode &other)
{
return (d == other.d
&& param == other.param
- && pressure == other.pressure);
+ && param2 == other.param2);
}
bool light_propagates()
else
assert(0);
}
+
+ // In mapnode.cpp
+ TileSpec getTile(v3s16 dir);
- u16 getTile(v3s16 dir)
- {
- return content_tile(d, dir);
- }
+ u8 getMineral();
/*
These serialization functions are used when informing client
{
dest[0] = d;
dest[1] = param;
- dest[2] = pressure;
+ dest[2] = param2;
}
}
void deSerialize(u8 *source, u8 version)
{
d = source[0];
param = source[1];
- pressure = source[2];
+ param2 = source[2];
+ }
+
+ // Translate deprecated stuff
+ // NOTE: This doesn't get used because MapBlock handles node
+ // parameters directly
+ MapNode *translate_to = content_features(d).translate_to;
+ if(translate_to)
+ {
+ dstream<<"MapNode: WARNING: Translating "<<d<<" to "
+ <<translate_to->d<<std::endl;
+ *this = *translate_to;
}
}
};
return p2;
}
+/*
+ The same thing backwards
+*/
inline v3f intToFloat(v3s16 p)
{
v3f p2(