X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmapnode.cpp;h=956abe5c714b86d36f828f31beb20ae030f42c7e;hb=785a2fd23a47af3629db824adc5e4e1376880d4d;hp=59e40935c0e85eda949978170b5cc8a3c900224d;hpb=d44abdab17f6ad7a05ddc08d418af35e9cabddef;p=oweals%2Fminetest.git diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 59e40935c..956abe5c7 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -17,65 +17,385 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "common_irrlicht.h" #include "mapnode.h" #include "tile.h" #include "porting.h" #include +#include "mineral.h" +// For g_settings +#include "main.h" +#include "content_mapnode.h" +#include "nodemetadata.h" + +ContentFeatures::~ContentFeatures() +{ + delete initial_metadata; + delete special_material; + delete special_atlas; +} + +void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha) +{ + if(g_texturesource) + { + tiles[i].texture = g_texturesource->getTexture(name); + } + + if(alpha != 255) + { + tiles[i].alpha = alpha; + tiles[i].material_type = MATERIAL_ALPHA_VERTEX; + } + + if(inventory_texture == NULL) + setInventoryTexture(name); +} + +void ContentFeatures::setInventoryTexture(std::string imgname) +{ + if(g_texturesource == NULL) + return; + + imgname += "^[forcesingle"; + + inventory_texture = g_texturesource->getTextureRaw(imgname); +} + +void ContentFeatures::setInventoryTextureCube(std::string top, + std::string left, std::string right) +{ + if(g_texturesource == NULL) + return; + + str_replace_char(top, '^', '&'); + str_replace_char(left, '^', '&'); + str_replace_char(right, '^', '&'); + + std::string imgname_full; + imgname_full += "[inventorycube{"; + imgname_full += top; + imgname_full += "{"; + imgname_full += left; + imgname_full += "{"; + imgname_full += right; + inventory_texture = g_texturesource->getTextureRaw(imgname_full); +} + +struct ContentFeatures g_content_features[MAX_CONTENT+1]; + +ContentFeatures & content_features(content_t i) +{ + return g_content_features[i]; +} +ContentFeatures & content_features(MapNode &n) +{ + return content_features(n.getContent()); +} /* - Face directions: - 0: up - 1: down - 2: right - 3: left - 4: back - 5: front + See mapnode.h for description. */ -u16 g_content_tiles[USEFUL_CONTENT_COUNT][6] = +void init_mapnode() +{ + if(g_texturesource == NULL) + { + dstream<<"INFO: Initial run of init_mapnode with " + "g_texturesource=NULL. If this segfaults, " + "there is a bug with something not checking for " + "the NULL value."<reset(); + + for(u16 j=0; j<6; j++) + f->tiles[j].material_type = initial_material_type; + } + + /* + Initially set every block to be shown as an unknown block. + Don't touch CONTENT_IGNORE or CONTENT_AIR. + */ + for(u16 i=0; isetAllTextures("unknown_block.png"); + f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1"; + } + + /* + Initialize mapnode content + */ + content_mapnode_init(); + +} + +v3s16 facedir_rotate(u8 facedir, v3s16 dir) +{ + /* + Face 2 (normally Z-) direction: + facedir=0: Z- + facedir=1: X- + facedir=2: Z+ + facedir=3: X+ + */ + v3s16 newdir; + if(facedir==0) // Same + newdir = v3s16(dir.X, dir.Y, dir.Z); + else if(facedir == 1) // Face is taken from rotXZccv(-90) + newdir = v3s16(-dir.Z, dir.Y, dir.X); + else if(facedir == 2) // Face is taken from rotXZccv(180) + newdir = v3s16(-dir.X, dir.Y, -dir.Z); + else if(facedir == 3) // Face is taken from rotXZccv(90) + newdir = v3s16(dir.Z, dir.Y, -dir.X); + else + newdir = dir; + return newdir; +} + +TileSpec MapNode::getTile(v3s16 dir) +{ + if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE) + dir = facedir_rotate(param1, dir); + + TileSpec spec; + + s32 dir_i = -1; + + if(dir == v3s16(0,0,0)) + dir_i = -1; + else 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) + // Non-directional + spec = content_features(*this).tiles[0]; + else + spec = content_features(*this).tiles[dir_i]; + + /* + If it contains some mineral, change texture id + */ + if(content_features(*this).param_type == CPT_MINERAL && g_texturesource) + { + u8 mineral = getMineral(); + std::string mineral_texture_name = mineral_block_texture(mineral); + if(mineral_texture_name != "") + { + u32 orig_id = spec.texture.id; + std::string texture_name = g_texturesource->getTextureName(orig_id); + //texture_name += "^blit:"; + texture_name += "^"; + texture_name += mineral_texture_name; + u32 new_id = g_texturesource->getTextureId(texture_name); + spec.texture = g_texturesource->getTexture(new_id); + } + } + + return spec; +} + +u8 MapNode::getMineral() +{ + if(content_features(*this).param_type == CPT_MINERAL) + { + return param1 & 0x0f; + } + + return MINERAL_NONE; +} + +u32 MapNode::serializedLength(u8 version) { - {TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE}, - {TILE_GRASS,TILE_MUD,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS}, - //{TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER}, - {TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE}, - {TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE}, - {TILE_TREE_TOP,TILE_TREE_TOP,TILE_TREE,TILE_TREE,TILE_TREE,TILE_TREE}, - {TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES}, - {TILE_GRASS_FOOTSTEPS,TILE_MUD,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS}, - {TILE_MESE,TILE_MESE,TILE_MESE,TILE_MESE,TILE_MESE,TILE_MESE}, - {TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD}, - {TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER}, // ocean - {TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD}, - {TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE}, - {TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD}, -}; - -std::string g_content_inventory_texture_strings[USEFUL_CONTENT_COUNT]; -// Pointers to c_str()s of the above -const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0}; - -const char * g_content_inventory_texture_paths_base[USEFUL_CONTENT_COUNT] = + if(!ser_ver_supported(version)) + throw VersionMismatchException("ERROR: MapNode format not supported"); + + if(version == 0) + return 1; + else if(version <= 9) + return 2; + else + return 3; +} +void MapNode::serialize(u8 *dest, u8 version) +{ + if(!ser_ver_supported(version)) + throw VersionMismatchException("ERROR: MapNode format not supported"); + + // Translate to wanted version + MapNode n_foreign = mapnode_translate_from_internal(*this, version); + + u8 actual_param0 = n_foreign.param0; + + // Convert special values from new version to old + if(version <= 18) + { + // In these versions, CONTENT_IGNORE and CONTENT_AIR + // are 255 and 254 + if(actual_param0 == CONTENT_IGNORE) + actual_param0 = 255; + else if(actual_param0 == CONTENT_AIR) + actual_param0 = 254; + } + + if(version == 0) + { + dest[0] = actual_param0; + } + else if(version <= 9) + { + dest[0] = actual_param0; + dest[1] = n_foreign.param1; + } + else + { + dest[0] = actual_param0; + dest[1] = n_foreign.param1; + dest[2] = n_foreign.param2; + } +} +void MapNode::deSerialize(u8 *source, u8 version) { - "stone.png", - "grass.png", - "water.png", - "torch_on_floor.png", - "tree_top.png", - "leaves.png", - "grass_footsteps.png", - "mese.png", - "mud.png", - "water.png", //ocean - "cloud.png", - "coalstone.png", - "wood.png", -}; - -void init_content_inventory_texture_paths() + if(!ser_ver_supported(version)) + throw VersionMismatchException("ERROR: MapNode format not supported"); + + if(version == 0) + { + param0 = source[0]; + } + else if(version == 1) + { + param0 = source[0]; + // This version doesn't support saved lighting + if(light_propagates() || light_source() > 0) + param1 = 0; + else + param1 = source[1]; + } + else if(version <= 9) + { + param0 = source[0]; + param1 = source[1]; + } + else + { + param0 = source[0]; + param1 = source[1]; + param2 = source[2]; + } + + // 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); +} + +/* + 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) { - for(u16 i=0; i l2) + light = l1; + else + light = l2; + + // Make some nice difference to different sides + + // This makes light come from a corner + /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1) + light = diminish_light(diminish_light(light)); + else if(face_dir.X == -1 || face_dir.Z == -1) + light = diminish_light(light);*/ + + // All neighboring faces have different shade (like in minecraft) + if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1) + light = diminish_light(diminish_light(light)); + else if(face_dir.Z == 1 || face_dir.Z == -1) + light = diminish_light(light); + + return light; + } + catch(InvalidPositionException &e) { - g_content_inventory_texture_strings[i] = porting::getDataPath(g_content_inventory_texture_paths_base[i]); - g_content_inventory_texture_paths[i] = g_content_inventory_texture_strings[i].c_str(); + return 0; } } +