ContentFeatures::~ContentFeatures()
{
- if(translate_to)
- delete translate_to;
- if(initial_metadata)
- delete initial_metadata;
+ delete initial_metadata;
+ delete special_material;
+ delete special_atlas;
}
void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
inventory_texture = g_texturesource->getTextureRaw(imgname_full);
}
-struct ContentFeatures g_content_features[256];
+struct ContentFeatures g_content_features[MAX_CONTENT+1];
-ContentFeatures & content_features(u8 i)
+ContentFeatures & content_features(content_t i)
{
return g_content_features[i];
}
+ContentFeatures & content_features(MapNode &n)
+{
+ return content_features(n.getContent());
+}
/*
See mapnode.h for description.
initial_material_type = MATERIAL_ALPHA_SIMPLE;
else
initial_material_type = MATERIAL_ALPHA_NONE;*/
- for(u16 i=0; i<256; i++)
+ for(u16 i=0; i<MAX_CONTENT+1; i++)
{
ContentFeatures *f = &g_content_features[i];
// Re-initialize
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; i<MAX_CONTENT+1; i++)
+ {
+ if(i == CONTENT_IGNORE || i == CONTENT_AIR)
+ continue;
+ ContentFeatures *f = &g_content_features[i];
+ f->setAllTextures("unknown_block.png");
+ f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
+ }
+
/*
Initialize mapnode content
*/
TileSpec MapNode::getTile(v3s16 dir)
{
- if(content_features(d).param_type == CPT_FACEDIR_SIMPLE)
+ if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
dir = facedir_rotate(param1, dir);
TileSpec spec;
if(dir_i == -1)
// Non-directional
- spec = content_features(d).tiles[0];
+ spec = content_features(*this).tiles[0];
else
- spec = content_features(d).tiles[dir_i];
+ spec = content_features(*this).tiles[dir_i];
/*
If it contains some mineral, change texture id
*/
- if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
+ if(content_features(*this).param_type == CPT_MINERAL && g_texturesource)
{
- u8 mineral = param & 0x1f;
+ u8 mineral = getMineral();
std::string mineral_texture_name = mineral_block_texture(mineral);
if(mineral_texture_name != "")
{
u8 MapNode::getMineral()
{
- if(content_features(d).param_type == CPT_MINERAL)
+ if(content_features(*this).param_type == CPT_MINERAL)
{
- return param & 0x1f;
+ return param1 & 0x0f;
}
return MINERAL_NONE;
}
+u32 MapNode::serializedLength(u8 version)
+{
+ 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)
+{
+ 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)
+{
+ try{
+ u8 light;
+ u8 l1 = n.getLightBlend(daynight_ratio);
+ u8 l2 = n2.getLightBlend(daynight_ratio);
+ if(l1 > 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)
+ {
+ return 0;
+ }
+}
+