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)
47 tiles[i].texture = g_texturesource->getTexture(name);
52 tiles[i].alpha = alpha;
53 tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
56 if(inventory_texture == NULL)
57 setInventoryTexture(name);
60 void ContentFeatures::setInventoryTexture(std::string imgname)
62 if(g_texturesource == NULL)
65 imgname += "^[forcesingle";
67 inventory_texture = g_texturesource->getTextureRaw(imgname);
70 void ContentFeatures::setInventoryTextureCube(std::string top,
71 std::string left, std::string right)
73 if(g_texturesource == NULL)
76 str_replace_char(top, '^', '&');
77 str_replace_char(left, '^', '&');
78 str_replace_char(right, '^', '&');
80 std::string imgname_full;
81 imgname_full += "[inventorycube{";
86 imgname_full += right;
87 inventory_texture = g_texturesource->getTextureRaw(imgname_full);
91 struct ContentFeatures g_content_features[MAX_CONTENT+1];
93 ContentFeatures & content_features(content_t i)
95 return g_content_features[i];
97 ContentFeatures & content_features(MapNode &n)
99 return content_features(n.getContent());
103 See mapnode.h for description.
107 if(g_texturesource == NULL)
109 dstream<<"INFO: Initial run of init_mapnode with "
110 "g_texturesource=NULL. If this segfaults, "
111 "there is a bug with something not checking for "
112 "the NULL value."<<std::endl;
116 dstream<<"INFO: Full run of init_mapnode with "
117 "g_texturesource!=NULL"<<std::endl;
120 /*// Read some settings
121 bool new_style_water = g_settings.getBool("new_style_water");
122 bool new_style_leaves = g_settings.getBool("new_style_leaves");*/
125 Initialize content feature table
130 Set initial material type to same in all tiles, so that the
131 same material can be used in more stuff.
132 This is set according to the leaves because they are the only
133 differing material to which all materials can be changed to
134 get this optimization.
136 u8 initial_material_type = MATERIAL_ALPHA_SIMPLE;
137 /*if(new_style_leaves)
138 initial_material_type = MATERIAL_ALPHA_SIMPLE;
140 initial_material_type = MATERIAL_ALPHA_NONE;*/
141 for(u16 i=0; i<MAX_CONTENT+1; i++)
143 ContentFeatures *f = &g_content_features[i];
147 for(u16 j=0; j<6; j++)
148 f->tiles[j].material_type = initial_material_type;
153 Initially set every block to be shown as an unknown block.
154 Don't touch CONTENT_IGNORE or CONTENT_AIR.
156 for(u16 i=0; i<MAX_CONTENT+1; i++)
158 if(i == CONTENT_IGNORE || i == CONTENT_AIR)
160 ContentFeatures *f = &g_content_features[i];
161 f->setAllTextures("unknown_block.png");
162 f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
166 Initialize mapnode content
168 content_mapnode_init();
172 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
175 Face 2 (normally Z-) direction:
182 if(facedir==0) // Same
183 newdir = v3s16(dir.X, dir.Y, dir.Z);
184 else if(facedir == 1) // Face is taken from rotXZccv(-90)
185 newdir = v3s16(-dir.Z, dir.Y, dir.X);
186 else if(facedir == 2) // Face is taken from rotXZccv(180)
187 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
188 else if(facedir == 3) // Face is taken from rotXZccv(90)
189 newdir = v3s16(dir.Z, dir.Y, -dir.X);
196 TileSpec MapNode::getTile(v3s16 dir)
198 if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
199 dir = facedir_rotate(param1, dir);
205 if(dir == v3s16(0,0,0))
207 else if(dir == v3s16(0,1,0))
209 else if(dir == v3s16(0,-1,0))
211 else if(dir == v3s16(1,0,0))
213 else if(dir == v3s16(-1,0,0))
215 else if(dir == v3s16(0,0,1))
217 else if(dir == v3s16(0,0,-1))
222 spec = content_features(*this).tiles[0];
224 spec = content_features(*this).tiles[dir_i];
227 If it contains some mineral, change texture id
229 if(content_features(*this).param_type == CPT_MINERAL && g_texturesource)
231 u8 mineral = getMineral();
232 std::string mineral_texture_name = mineral_block_texture(mineral);
233 if(mineral_texture_name != "")
235 u32 orig_id = spec.texture.id;
236 std::string texture_name = g_texturesource->getTextureName(orig_id);
237 //texture_name += "^blit:";
239 texture_name += mineral_texture_name;
240 u32 new_id = g_texturesource->getTextureId(texture_name);
241 spec.texture = g_texturesource->getTexture(new_id);
249 u8 MapNode::getMineral()
251 if(content_features(*this).param_type == CPT_MINERAL)
253 return param1 & 0x0f;
259 u32 MapNode::serializedLength(u8 version)
261 if(!ser_ver_supported(version))
262 throw VersionMismatchException("ERROR: MapNode format not supported");
266 else if(version <= 9)
271 void MapNode::serialize(u8 *dest, u8 version)
273 if(!ser_ver_supported(version))
274 throw VersionMismatchException("ERROR: MapNode format not supported");
276 // Translate to wanted version
277 MapNode n_foreign = mapnode_translate_from_internal(*this, version);
279 u8 actual_param0 = n_foreign.param0;
281 // Convert special values from new version to old
284 // In these versions, CONTENT_IGNORE and CONTENT_AIR
286 if(actual_param0 == CONTENT_IGNORE)
288 else if(actual_param0 == CONTENT_AIR)
294 dest[0] = actual_param0;
296 else if(version <= 9)
298 dest[0] = actual_param0;
299 dest[1] = n_foreign.param1;
303 dest[0] = actual_param0;
304 dest[1] = n_foreign.param1;
305 dest[2] = n_foreign.param2;
308 void MapNode::deSerialize(u8 *source, u8 version)
310 if(!ser_ver_supported(version))
311 throw VersionMismatchException("ERROR: MapNode format not supported");
317 else if(version == 1)
320 // This version doesn't support saved lighting
321 if(light_propagates() || light_source() > 0)
326 else if(version <= 9)
338 // Convert special values from old version to new
341 // In these versions, CONTENT_IGNORE and CONTENT_AIR
344 param0 = CONTENT_IGNORE;
345 else if(param0 == 254)
346 param0 = CONTENT_AIR;
348 // version 19 is fucked up with sometimes the old values and sometimes not
352 param0 = CONTENT_IGNORE;
353 else if(param0 == 254)
354 param0 = CONTENT_AIR;
357 // Translate to our known version
358 *this = mapnode_translate_to_internal(*this, version);
362 Gets lighting value at face of node
364 Parameters must consist of air and !air.
365 Order doesn't matter.
367 If either of the nodes doesn't exist, light is 0.
370 daynight_ratio: 0...1000
372 n2: getNodeParent(p + face_dir)
373 face_dir: axis oriented unit vector from p to p2
375 returns encoded light value.
377 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
382 u8 l1 = n.getLightBlend(daynight_ratio);
383 u8 l2 = n2.getLightBlend(daynight_ratio);
389 // Make some nice difference to different sides
391 // This makes light come from a corner
392 /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
393 light = diminish_light(diminish_light(light));
394 else if(face_dir.X == -1 || face_dir.Z == -1)
395 light = diminish_light(light);*/
397 // All neighboring faces have different shade (like in minecraft)
398 if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
399 light = diminish_light(diminish_light(light));
400 else if(face_dir.Z == 1 || face_dir.Z == -1)
401 light = diminish_light(light);
405 catch(InvalidPositionException &e)