X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmapnode.h;h=03a294ad27bddc2b4fc6575540ab3c47439031df;hb=9a22d02903549c09f059b12f0ec06ea12a19abbb;hp=680884bcd96ec83e494d463585edba524684945b;hpb=6129e31b96f31521a79f5dfd7968f0cf0decb200;p=dragonfireclient.git diff --git a/src/mapnode.h b/src/mapnode.h index 680884bcd..03a294ad2 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,10 +27,27 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "exceptions.h" #include "serialization.h" #include "tile.h" +#include "iirrlichtwrapper.h" -// Size of node in rendering units -#define BS 10 +/* + 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(); + +// NOTE: This is not used appropriately everywhere. #define MATERIALS_COUNT 256 /* @@ -53,9 +70,8 @@ with this program; if not, write to the Free Software Foundation, Inc., /* 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 @@ -63,41 +79,168 @@ with this program; if not, write to the Free Software Foundation, Inc., - 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, + 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 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); } /* @@ -106,65 +249,86 @@ inline bool sunlight_propagates_content(u8 m) 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) -{ - return( - m == CONTENT_STONE || - m == CONTENT_GRASS || - m == CONTENT_GRASS_FOOTSTEPS || - m == CONTENT_MESE || - m == CONTENT_MUD - ); -} - -/*inline bool content_has_faces(u8 c) +/*inline bool is_ground_content(u8 m) { - return (m != CONTENT_IGNORE - && m != CONTENT_AIR - && m != CONTENT_TORCH); + return content_features(m).is_ground_content; }*/ /* @@ -180,6 +344,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; @@ -192,19 +362,6 @@ inline u8 face_contents(u8 m1, u8 m2) 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) */ @@ -251,33 +408,15 @@ inline v3s16 unpackDir(u8 b) return d; } -inline u16 content_tile(u8 c, v3s16 dir) +enum LightBank { - 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); + LIGHTBANK_DAY, + LIGHTBANK_NIGHT +}; - return g_content_tiles[c][dir_i]; -} +/* + This is the stuff what the whole world consists of. +*/ struct MapNode { @@ -289,20 +428,17 @@ struct MapNode - 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; }; @@ -311,18 +447,26 @@ 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); } bool light_propagates() @@ -351,29 +495,95 @@ struct MapNode return 0; } - u8 getLight() + u8 getLightBanksWithSource() + { + // Select the brightest of [light source, propagated light] + u8 lightday = 0; + u8 lightnight = 0; + if(light_propagates()) + { + lightday = param & 0x0f; + lightnight = (param>>4)&0x0f; + } + if(light_source() > lightday) + lightday = light_source(); + if(light_source() > lightnight) + lightnight = light_source(); + 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()) - light = param & 0x0f; + { + if(bank == LIGHTBANK_DAY) + light = param & 0x0f; + else if(bank == LIGHTBANK_NIGHT) + light = (param>>4)&0x0f; + else + assert(0); + } if(light_source() > light) light = light_source(); return light; } - - void setLight(u8 a_light) + + // 0 <= daylight_factor <= 1000 + // 0 <= return value <= LIGHT_SUN + u8 getLightBlend(u32 daylight_factor) + { + u8 l = ((daylight_factor * getLight(LIGHTBANK_DAY) + + (1000-daylight_factor) * getLight(LIGHTBANK_NIGHT)) + )/1000; + u8 max = LIGHT_MAX; + if(getLight(LIGHTBANK_DAY) == LIGHT_SUN) + max = LIGHT_SUN; + if(l > max) + l = max; + return l; + } + /*// 0 <= daylight_factor <= 1000 + // 0 <= return value <= 255 + u8 getLightBlend(u32 daylight_factor) + { + u8 daylight = decode_light(getLight(LIGHTBANK_DAY)); + u8 nightlight = decode_light(getLight(LIGHTBANK_NIGHT)); + u8 mix = ((daylight_factor * daylight + + (1000-daylight_factor) * nightlight) + )/1000; + return mix; + }*/ + + void setLight(enum LightBank bank, u8 a_light) { // If not transparent, can't set light if(light_propagates() == false) return; - param = a_light; + if(bank == LIGHTBANK_DAY) + { + param &= 0xf0; + param |= a_light & 0x0f; + } + else if(bank == LIGHTBANK_NIGHT) + { + param &= 0x0f; + param |= (a_light & 0x0f)<<4; + } + 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 @@ -410,7 +620,7 @@ struct MapNode { dest[0] = d; dest[1] = param; - dest[2] = pressure; + dest[2] = param2; } } void deSerialize(u8 *source, u8 version) @@ -440,34 +650,22 @@ 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; -} - #endif