3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "common_irrlicht.h"
28 #include "content_mapnode.h"
29 #include "nodemetadata.h"
31 ContentFeatures::~ContentFeatures()
33 delete initial_metadata;
34 delete special_material;
38 void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
42 tiles[i].texture = g_texturesource->getTexture(name);
47 tiles[i].alpha = alpha;
48 tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
51 if(inventory_texture == NULL)
52 setInventoryTexture(name);
55 void ContentFeatures::setInventoryTexture(std::string imgname)
57 if(g_texturesource == NULL)
60 imgname += "^[forcesingle";
62 inventory_texture = g_texturesource->getTextureRaw(imgname);
65 void ContentFeatures::setInventoryTextureCube(std::string top,
66 std::string left, std::string right)
68 if(g_texturesource == NULL)
71 str_replace_char(top, '^', '&');
72 str_replace_char(left, '^', '&');
73 str_replace_char(right, '^', '&');
75 std::string imgname_full;
76 imgname_full += "[inventorycube{";
81 imgname_full += right;
82 inventory_texture = g_texturesource->getTextureRaw(imgname_full);
85 struct ContentFeatures g_content_features[MAX_CONTENT+1];
87 ContentFeatures & content_features(content_t i)
89 return g_content_features[i];
91 ContentFeatures & content_features(MapNode &n)
93 return content_features(n.getContent());
97 See mapnode.h for description.
101 if(g_texturesource == NULL)
103 dstream<<"INFO: Initial run of init_mapnode with "
104 "g_texturesource=NULL. If this segfaults, "
105 "there is a bug with something not checking for "
106 "the NULL value."<<std::endl;
110 dstream<<"INFO: Full run of init_mapnode with "
111 "g_texturesource!=NULL"<<std::endl;
114 /*// Read some settings
115 bool new_style_water = g_settings.getBool("new_style_water");
116 bool new_style_leaves = g_settings.getBool("new_style_leaves");*/
119 Initialize content feature table
123 Set initial material type to same in all tiles, so that the
124 same material can be used in more stuff.
125 This is set according to the leaves because they are the only
126 differing material to which all materials can be changed to
127 get this optimization.
129 u8 initial_material_type = MATERIAL_ALPHA_SIMPLE;
130 /*if(new_style_leaves)
131 initial_material_type = MATERIAL_ALPHA_SIMPLE;
133 initial_material_type = MATERIAL_ALPHA_NONE;*/
134 for(u16 i=0; i<MAX_CONTENT+1; i++)
136 ContentFeatures *f = &g_content_features[i];
140 for(u16 j=0; j<6; j++)
141 f->tiles[j].material_type = initial_material_type;
145 Initially set every block to be shown as an unknown block.
146 Don't touch CONTENT_IGNORE or CONTENT_AIR.
148 for(u16 i=0; i<MAX_CONTENT+1; i++)
150 if(i == CONTENT_IGNORE || i == CONTENT_AIR)
152 ContentFeatures *f = &g_content_features[i];
153 f->setAllTextures("unknown_block.png");
154 f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
158 Initialize mapnode content
160 content_mapnode_init();
164 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
167 Face 2 (normally Z-) direction:
174 if(facedir==0) // Same
175 newdir = v3s16(dir.X, dir.Y, dir.Z);
176 else if(facedir == 1) // Face is taken from rotXZccv(-90)
177 newdir = v3s16(-dir.Z, dir.Y, dir.X);
178 else if(facedir == 2) // Face is taken from rotXZccv(180)
179 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
180 else if(facedir == 3) // Face is taken from rotXZccv(90)
181 newdir = v3s16(dir.Z, dir.Y, -dir.X);
187 TileSpec MapNode::getTile(v3s16 dir)
189 if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
190 dir = facedir_rotate(param1, dir);
196 if(dir == v3s16(0,0,0))
198 else if(dir == v3s16(0,1,0))
200 else if(dir == v3s16(0,-1,0))
202 else if(dir == v3s16(1,0,0))
204 else if(dir == v3s16(-1,0,0))
206 else if(dir == v3s16(0,0,1))
208 else if(dir == v3s16(0,0,-1))
213 spec = content_features(*this).tiles[0];
215 spec = content_features(*this).tiles[dir_i];
218 If it contains some mineral, change texture id
220 if(content_features(*this).param_type == CPT_MINERAL && g_texturesource)
222 u8 mineral = getMineral();
223 std::string mineral_texture_name = mineral_block_texture(mineral);
224 if(mineral_texture_name != "")
226 u32 orig_id = spec.texture.id;
227 std::string texture_name = g_texturesource->getTextureName(orig_id);
228 //texture_name += "^blit:";
230 texture_name += mineral_texture_name;
231 u32 new_id = g_texturesource->getTextureId(texture_name);
232 spec.texture = g_texturesource->getTexture(new_id);
239 u8 MapNode::getMineral()
241 if(content_features(*this).param_type == CPT_MINERAL)
243 return param1 & 0x0f;
249 u32 MapNode::serializedLength(u8 version)
251 if(!ser_ver_supported(version))
252 throw VersionMismatchException("ERROR: MapNode format not supported");
256 else if(version <= 9)
261 void MapNode::serialize(u8 *dest, u8 version)
263 if(!ser_ver_supported(version))
264 throw VersionMismatchException("ERROR: MapNode format not supported");
266 // Translate to wanted version
267 MapNode n_foreign = mapnode_translate_from_internal(*this, version);
269 u8 actual_param0 = n_foreign.param0;
271 // Convert special values from new version to old
274 // In these versions, CONTENT_IGNORE and CONTENT_AIR
276 if(actual_param0 == CONTENT_IGNORE)
278 else if(actual_param0 == CONTENT_AIR)
284 dest[0] = actual_param0;
286 else if(version <= 9)
288 dest[0] = actual_param0;
289 dest[1] = n_foreign.param1;
293 dest[0] = actual_param0;
294 dest[1] = n_foreign.param1;
295 dest[2] = n_foreign.param2;
298 void MapNode::deSerialize(u8 *source, u8 version)
300 if(!ser_ver_supported(version))
301 throw VersionMismatchException("ERROR: MapNode format not supported");
307 else if(version == 1)
310 // This version doesn't support saved lighting
311 if(light_propagates() || light_source() > 0)
316 else if(version <= 9)
328 // Convert special values from old version to new
331 // In these versions, CONTENT_IGNORE and CONTENT_AIR
334 param0 = CONTENT_IGNORE;
335 else if(param0 == 254)
336 param0 = CONTENT_AIR;
338 // version 19 is fucked up with sometimes the old values and sometimes not
342 param0 = CONTENT_IGNORE;
343 else if(param0 == 254)
344 param0 = CONTENT_AIR;
347 // Translate to our known version
348 *this = mapnode_translate_to_internal(*this, version);
352 Gets lighting value at face of node
354 Parameters must consist of air and !air.
355 Order doesn't matter.
357 If either of the nodes doesn't exist, light is 0.
360 daynight_ratio: 0...1000
362 n2: getNodeParent(p + face_dir)
363 face_dir: axis oriented unit vector from p to p2
365 returns encoded light value.
367 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
372 u8 l1 = n.getLightBlend(daynight_ratio);
373 u8 l2 = n2.getLightBlend(daynight_ratio);
379 // Make some nice difference to different sides
381 // This makes light come from a corner
382 /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
383 light = diminish_light(diminish_light(light));
384 else if(face_dir.X == -1 || face_dir.Z == -1)
385 light = diminish_light(light);*/
387 // All neighboring faces have different shade (like in minecraft)
388 if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
389 light = diminish_light(diminish_light(light));
390 else if(face_dir.Z == 1 || face_dir.Z == -1)
391 light = diminish_light(light);
395 catch(InvalidPositionException &e)