X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapnode.h;h=d975a50c46fb0bf83740b6075c652e56ff8adc39;hb=30c34cc23e9a060ef964854038a314a94ad5cbae;hp=e3b921a66604405c5bc44f4f6a89330f7774bdcc;hpb=d44abdab17f6ad7a05ddc08d418af35e9cabddef;p=dragonfireclient.git diff --git a/src/mapnode.h b/src/mapnode.h index e3b921a66..d975a50c4 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -1,6 +1,6 @@ /* Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola +Copyright (C) 2010-2011 celeron55, Perttu Ahola 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 @@ -27,8 +27,28 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "exceptions.h" #include "serialization.h" #include "tile.h" +#include "materials.h" -#define MATERIALS_COUNT 256 +/* + Naming scheme: + - Material = irrlicht's Material class + - Content = (u8) content of a node + - Tile = TileSpec at some side of a node of some content type +*/ + +/* + 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(); /* Ignored node. @@ -49,153 +69,236 @@ with this program; if not, write to the Free Software Foundation, Inc., #define CONTENT_AIR 254 /* - Suggested materials: - - Gravel - - Sand - - New naming scheme: - - Material = irrlicht's Material class - - Content = (u8) content of a node - - Tile = (u16) Material ID at some side of a node + Content feature list */ -#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 -#define CONTENT_CLOUD 10 -#define CONTENT_COALSTONE 11 -#define CONTENT_WOOD 12 +enum ContentParamType +{ + CPT_NONE, + CPT_LIGHT, + CPT_MINERAL, + // Direction for chests and furnaces and such + CPT_FACEDIR_SIMPLE +}; + +enum LiquidType +{ + LIQUID_NONE, + LIQUID_FLOWING, + LIQUID_SOURCE +}; + +class MapNode; +class NodeMetadata; + +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]; + + video::ITexture *inventory_texture; + + bool is_ground_content; + bool light_propagates; + bool sunlight_propagates; + u8 solidness; // Used when choosing which face is drawn + // This is used for collision detection. + // Also for general solidness queries. + bool walkable; + // Player can point to these + bool pointable; + // Player can dig these + bool diggable; + // Player can build on these + bool buildable_to; + // Whether the node has no liquid, source liquid or flowing liquid + enum LiquidType liquid_type; + // If true, param2 is set to direction when placed. Used for torches. + // NOTE: the direction format is quite inefficient and should be changed + bool wall_mounted; + // If true, node is equivalent to air. Torches are, air is. Water is not. + // Is used for example to check whether a mud block can have grass on. + bool air_equivalent; + + // Inventory item string as which the node appears in inventory when dug. + // Mineral overrides this. + std::string dug_item; + + // Initial metadata is cloned from this + NodeMetadata *initial_metadata; + + // If the content is liquid, this is the flowing version of the liquid. + // If content is liquid, this is the same content. + u8 liquid_alternative_flowing; + + // Amount of light the node emits + u8 light_source; -#define USEFUL_CONTENT_COUNT 13 + // Digging properties for different tools + DiggingPropertiesList digging_properties; + + // NOTE: Move relevant properties to here from elsewhere + + void reset() + { + 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; + air_equivalent = false; + dug_item = ""; + initial_metadata = NULL; + liquid_alternative_flowing = CONTENT_IGNORE; + light_source = 0; + digging_properties.clear(); + } + + ContentFeatures() + { + reset(); + } + + ~ContentFeatures(); + + /* + Quickhands for simple materials + */ + + 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 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); +}; + +/* + Call this to access the ContentFeature list +*/ +ContentFeatures & content_features(u8 i); -extern u16 g_content_tiles[USEFUL_CONTENT_COUNT][6]; -extern const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT]; -// Initializes g_content_inventory_texture_paths -void init_content_inventory_texture_paths(); + +/* + Here is a bunch of DEPRECATED functions. +*/ /* 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_WATERSOURCE); + return content_features(m).light_propagates; } - /* 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; } - /* On a node-node surface, the material of the node with higher solidness is used for drawing. 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 || m == CONTENT_WATER) - return 0; - if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE) - return 1; - return 2; + return content_features(m).solidness; } - // 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_WATERSOURCE && m != CONTENT_TORCH); + return content_features(m).walkable; } - +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_liquid(u8 m) { - return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE); + return content_features(m).liquid_type != LIQUID_NONE; } - +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_flowing_liquid(u8 m) { - return (m == CONTENT_WATER); + return content_features(m).liquid_type == LIQUID_FLOWING; } - +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_liquid_source(u8 m) { - return (m == CONTENT_WATERSOURCE); + return content_features(m).liquid_type == LIQUID_SOURCE; } - // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER // CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA +// NOTE: Don't use, use "content_features(m).whatever" instead inline u8 make_liquid_flowing(u8 m) { - if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE) - return CONTENT_WATER; - assert(0); + u8 c = content_features(m).liquid_alternative_flowing; + assert(c != CONTENT_IGNORE); + return c; } - // 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_WATERSOURCE); + return content_features(m).pointable; } - +// 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_WATERSOURCE); + return content_features(m).diggable; } - +// 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_WATERSOURCE); -} - -/* - Returns true for contents that form the base ground that - follows the main heightmap -*/ -inline bool is_ground_content(u8 m) -{ - return ( - m != CONTENT_IGNORE - && m != CONTENT_AIR - && m != CONTENT_WATER - && m != CONTENT_TORCH - && m != CONTENT_TREE - && m != CONTENT_LEAVES - && m != CONTENT_WATERSOURCE - && m != CONTENT_CLOUD - ); -} - -inline bool is_mineral(u8 c) -{ - return(c == CONTENT_MESE - || c == CONTENT_COALSTONE); -} - -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); + return content_features(m).buildable_to; } /* @@ -211,6 +314,12 @@ inline u8 face_contents(u8 m1, u8 m2) 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; @@ -269,33 +378,12 @@ inline v3s16 unpackDir(u8 b) 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]; -} +/* + facedir: CPT_FACEDIR_SIMPLE param1 value + dir: The face for which stuff is wanted + return value: The face from which the stuff is actually found +*/ +v3s16 facedir_rotate(u8 facedir, v3s16 dir); enum LightBank { @@ -303,53 +391,9 @@ enum LightBank LIGHTBANK_NIGHT }; -#if 0 -#define DIR_PX 1 //X+ -#define DIR_NX 2 //X- -#define DIR_PZ 4 //Z+ -#define DIR_NZ 8 //Z- -#define DIR_PY 16 //Y+ -#define DIR_NY 32 //Y- - -inline void decode_dirs(u8 b, core::list &dirs) -{ - if(b & DIR_PX) - dirs.push_back(v3s16(1,0,0)); - if(b & DIR_NX) - dirs.push_back(v3s16(-1,0,0)); - if(b & DIR_PZ) - dirs.push_back(v3s16(0,0,1)); - if(b & DIR_NZ) - dirs.push_back(v3s16(0,0,-1)); - if(b & DIR_PY) - dirs.push_back(v3s16(0,1,0)); - if(b & DIR_NY) - dirs.push_back(v3s16(0,-1,0)); -} - -inline u8 encode_dirs(core::list &dirs) -{ - u8 b = 0; - for(core::list::Iterator - i = dirs.begin(); - i != dirs.end(); i++) - { - if(*i == v3s16(1,0,0)) - b += DIR_PX; - else if(*i == v3s16(-1,0,0)) - b += DIR_NX; - else if(*i == v3s16(0,0,1)) - b += DIR_PZ; - else if(*i == v3s16(0,0,-1)) - b += DIR_NZ; - else if(*i == v3s16(0,1,0)) - b += DIR_PY; - else if(*i == v3s16(0,-1,0)) - b += DIR_NY; - } - return b; -} -#endif +/* + This is the stuff what the whole world consists of. +*/ struct MapNode { @@ -363,21 +407,19 @@ struct MapNode Sunlight is LIGHT_SUN, which is LIGHT_MAX+1. - Contains 2 values, day- and night lighting. Each takes 4 bits. */ - s8 param; + union + { + s8 param; + u8 param1; + }; + /* + The second parameter. Initialized to 0. + E.g. direction for torches and flowing water. + */ union { u8 param2; - - /* - Pressure for liquids - */ - u8 pressure; - - /* - Direction for torches and other stuff. - Format is freeform. e.g. packDir or encode_dirs can be used. - */ u8 dir; }; @@ -386,44 +428,46 @@ struct MapNode *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); } - + + /* + These four are DEPRECATED I guess. -c55 + */ bool light_propagates() { return light_propagates_content(d); } - bool sunlight_propagates() { return sunlight_propagates_content(d); } - u8 solidness() { return content_solidness(d); } - u8 light_source() { - /* - Note that a block that isn't light_propagates() can be a light source. - */ - if(d == CONTENT_TORCH) - return LIGHT_MAX; - - return 0; + return content_features(d).light_source; } u8 getLightBanksWithSource() @@ -431,7 +475,7 @@ struct MapNode // Select the brightest of [light source, propagated light] u8 lightday = 0; u8 lightnight = 0; - if(light_propagates()) + if(content_features(d).param_type == CPT_LIGHT) { lightday = param & 0x0f; lightnight = (param>>4)&0x0f; @@ -443,16 +487,11 @@ struct MapNode return (lightday&0x0f) | ((lightnight<<4)&0xf0); } - void setLightBanks(u8 a_light) - { - param = a_light; - } - u8 getLight(enum LightBank bank) { // Select the brightest of [light source, propagated light] u8 light = 0; - if(light_propagates()) + if(content_features(d).param_type == CPT_LIGHT) { if(bank == LIGHTBANK_DAY) light = param & 0x0f; @@ -494,8 +533,8 @@ struct MapNode void setLight(enum LightBank bank, u8 a_light) { - // If not transparent, can't set light - if(light_propagates() == false) + // If node doesn't contain light data, ignore this + if(content_features(d).param_type != CPT_LIGHT) return; if(bank == LIGHTBANK_DAY) { @@ -510,15 +549,27 @@ struct MapNode else assert(0); } - - u16 getTile(v3s16 dir) - { - return content_tile(d, dir); - } + + // In mapnode.cpp + /* + Get tile of a face of the node. + dir: direction of face + Returns: TileSpec. Can contain miscellaneous texture coordinates, + which must be obeyed so that the texture atlas can be used. + */ + TileSpec getTile(v3s16 dir); + + /* + Gets mineral content of node, if there is any. + MINERAL_NONE if doesn't contain or isn't able to contain mineral. + */ + u8 getMineral(); /* These serialization functions are used when informing client - of a single node add + of a single node add. + + NOTE: When loading a MapBlock, these are not used. Should they? */ static u32 serializedLength(u8 version) @@ -551,7 +602,7 @@ struct MapNode { dest[0] = d; dest[1] = param; - dest[2] = pressure; + dest[2] = param2; } } void deSerialize(u8 *source, u8 version) @@ -581,35 +632,40 @@ struct MapNode { 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<0 ? BS/2 : -BS/2))/BS, - (p.Y + (p.Y>0 ? BS/2 : -BS/2))/BS, - (p.Z + (p.Z>0 ? BS/2 : -BS/2))/BS); - return p2; -} - -inline v3f intToFloat(v3s16 p) -{ - v3f p2( - p.X * BS, - p.Y * BS, - p.Z * BS - ); - return p2; -} - + Gets lighting value at face of node + + Parameters must consist of air and !air. + Order doesn't matter. + If either of the nodes doesn't exist, light is 0. + + parameters: + daynight_ratio: 0...1000 + n: getNodeParent(p) + n2: getNodeParent(p + face_dir) + face_dir: axis oriented unit vector from p to p2 + + returns encoded light value. +*/ +u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2, + v3s16 face_dir); #endif