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"
30 #include "content_mapnode.h"
31 #include "nodemetadata.h"
33 ContentFeatures::~ContentFeatures()
35 delete initial_metadata;
37 delete special_material;
43 void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
45 used_texturenames[name] = true;
49 tiles[i].texture = g_texturesource->getTexture(name);
54 tiles[i].alpha = alpha;
55 tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
58 if(inventory_texture == NULL)
59 setInventoryTexture(name);
62 void ContentFeatures::setInventoryTexture(std::string imgname)
64 if(g_texturesource == NULL)
67 imgname += "^[forcesingle";
69 inventory_texture = g_texturesource->getTextureRaw(imgname);
72 void ContentFeatures::setInventoryTextureCube(std::string top,
73 std::string left, std::string right)
75 if(g_texturesource == NULL)
78 str_replace_char(top, '^', '&');
79 str_replace_char(left, '^', '&');
80 str_replace_char(right, '^', '&');
82 std::string imgname_full;
83 imgname_full += "[inventorycube{";
88 imgname_full += right;
89 inventory_texture = g_texturesource->getTextureRaw(imgname_full);
93 struct ContentFeatures g_content_features[MAX_CONTENT+1];
95 ContentFeatures & content_features(content_t i)
97 return g_content_features[i];
99 ContentFeatures & content_features(MapNode &n)
101 return content_features(n.getContent());
105 See mapnode.h for description.
109 if(g_texturesource == NULL)
111 dstream<<"INFO: Initial run of init_mapnode with "
112 "g_texturesource=NULL. If this segfaults, "
113 "there is a bug with something not checking for "
114 "the NULL value."<<std::endl;
118 dstream<<"INFO: Full run of init_mapnode with "
119 "g_texturesource!=NULL"<<std::endl;
122 /*// Read some settings
123 bool new_style_water = g_settings.getBool("new_style_water");
124 bool new_style_leaves = g_settings.getBool("new_style_leaves");*/
127 Initialize content feature table
132 Set initial material type to same in all tiles, so that the
133 same material can be used in more stuff.
134 This is set according to the leaves because they are the only
135 differing material to which all materials can be changed to
136 get this optimization.
138 u8 initial_material_type = MATERIAL_ALPHA_SIMPLE;
139 /*if(new_style_leaves)
140 initial_material_type = MATERIAL_ALPHA_SIMPLE;
142 initial_material_type = MATERIAL_ALPHA_NONE;*/
143 for(u16 i=0; i<MAX_CONTENT+1; i++)
145 ContentFeatures *f = &g_content_features[i];
149 for(u16 j=0; j<6; j++)
150 f->tiles[j].material_type = initial_material_type;
155 Initially set every block to be shown as an unknown block.
156 Don't touch CONTENT_IGNORE or CONTENT_AIR.
158 for(u16 i=0; i<MAX_CONTENT+1; i++)
160 if(i == CONTENT_IGNORE || i == CONTENT_AIR)
162 ContentFeatures *f = &g_content_features[i];
163 f->setAllTextures("unknown_block.png");
164 f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
168 Initialize mapnode content
170 content_mapnode_init();
174 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
177 Face 2 (normally Z-) direction:
184 if(facedir==0) // Same
185 newdir = v3s16(dir.X, dir.Y, dir.Z);
186 else if(facedir == 1) // Face is taken from rotXZccv(-90)
187 newdir = v3s16(-dir.Z, dir.Y, dir.X);
188 else if(facedir == 2) // Face is taken from rotXZccv(180)
189 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
190 else if(facedir == 3) // Face is taken from rotXZccv(90)
191 newdir = v3s16(dir.Z, dir.Y, -dir.X);
198 TileSpec MapNode::getTile(v3s16 dir)
200 if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
201 dir = facedir_rotate(param1, dir);
207 if(dir == v3s16(0,0,0))
209 else if(dir == v3s16(0,1,0))
211 else if(dir == v3s16(0,-1,0))
213 else if(dir == v3s16(1,0,0))
215 else if(dir == v3s16(-1,0,0))
217 else if(dir == v3s16(0,0,1))
219 else if(dir == v3s16(0,0,-1))
224 spec = content_features(*this).tiles[0];
226 spec = content_features(*this).tiles[dir_i];
229 If it contains some mineral, change texture id
231 if(content_features(*this).param_type == CPT_MINERAL && g_texturesource)
233 u8 mineral = getMineral();
234 std::string mineral_texture_name = mineral_block_texture(mineral);
235 if(mineral_texture_name != "")
237 u32 orig_id = spec.texture.id;
238 std::string texture_name = g_texturesource->getTextureName(orig_id);
239 //texture_name += "^blit:";
241 texture_name += mineral_texture_name;
242 u32 new_id = g_texturesource->getTextureId(texture_name);
243 spec.texture = g_texturesource->getTexture(new_id);
251 u8 MapNode::getMineral()
253 if(content_features(*this).param_type == CPT_MINERAL)
255 return param1 & 0x0f;
261 u32 MapNode::serializedLength(u8 version)
263 if(!ser_ver_supported(version))
264 throw VersionMismatchException("ERROR: MapNode format not supported");
268 else if(version <= 9)
273 void MapNode::serialize(u8 *dest, u8 version)
275 if(!ser_ver_supported(version))
276 throw VersionMismatchException("ERROR: MapNode format not supported");
278 // Translate to wanted version
279 MapNode n_foreign = mapnode_translate_from_internal(*this, version);
281 u8 actual_param0 = n_foreign.param0;
283 // Convert special values from new version to old
286 // In these versions, CONTENT_IGNORE and CONTENT_AIR
288 if(actual_param0 == CONTENT_IGNORE)
290 else if(actual_param0 == CONTENT_AIR)
296 dest[0] = actual_param0;
298 else if(version <= 9)
300 dest[0] = actual_param0;
301 dest[1] = n_foreign.param1;
305 dest[0] = actual_param0;
306 dest[1] = n_foreign.param1;
307 dest[2] = n_foreign.param2;
310 void MapNode::deSerialize(u8 *source, u8 version)
312 if(!ser_ver_supported(version))
313 throw VersionMismatchException("ERROR: MapNode format not supported");
319 else if(version == 1)
322 // This version doesn't support saved lighting
323 if(light_propagates() || light_source() > 0)
328 else if(version <= 9)
340 // Convert special values from old version to new
343 // In these versions, CONTENT_IGNORE and CONTENT_AIR
346 param0 = CONTENT_IGNORE;
347 else if(param0 == 254)
348 param0 = CONTENT_AIR;
350 // version 19 is fucked up with sometimes the old values and sometimes not
354 param0 = CONTENT_IGNORE;
355 else if(param0 == 254)
356 param0 = CONTENT_AIR;
359 // Translate to our known version
360 *this = mapnode_translate_to_internal(*this, version);
364 Gets lighting value at face of node
366 Parameters must consist of air and !air.
367 Order doesn't matter.
369 If either of the nodes doesn't exist, light is 0.
372 daynight_ratio: 0...1000
374 n2: getNodeParent(p + face_dir)
375 face_dir: axis oriented unit vector from p to p2
377 returns encoded light value.
379 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
384 u8 l1 = n.getLightBlend(daynight_ratio);
385 u8 l2 = n2.getLightBlend(daynight_ratio);
391 // Make some nice difference to different sides
393 // This makes light come from a corner
394 /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
395 light = diminish_light(diminish_light(light));
396 else if(face_dir.X == -1 || face_dir.Z == -1)
397 light = diminish_light(light);*/
399 // All neighboring faces have different shade (like in minecraft)
400 if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
401 light = diminish_light(diminish_light(light));
402 else if(face_dir.Z == 1 || face_dir.Z == -1)
403 light = diminish_light(light);
407 catch(InvalidPositionException &e)