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()
34 delete initial_metadata;
37 void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
41 tiles[i].texture = g_texturesource->getTexture(name);
46 tiles[i].alpha = alpha;
47 tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
50 if(inventory_texture == NULL)
51 setInventoryTexture(name);
54 void ContentFeatures::setInventoryTexture(std::string imgname)
56 if(g_texturesource == NULL)
59 imgname += "^[forcesingle";
61 inventory_texture = g_texturesource->getTextureRaw(imgname);
64 void ContentFeatures::setInventoryTextureCube(std::string top,
65 std::string left, std::string right)
67 if(g_texturesource == NULL)
70 str_replace_char(top, '^', '&');
71 str_replace_char(left, '^', '&');
72 str_replace_char(right, '^', '&');
74 std::string imgname_full;
75 imgname_full += "[inventorycube{";
80 imgname_full += right;
81 inventory_texture = g_texturesource->getTextureRaw(imgname_full);
84 struct ContentFeatures g_content_features[MAX_CONTENT+1];
86 ContentFeatures & content_features(content_t i)
88 return g_content_features[i];
90 ContentFeatures & content_features(MapNode &n)
92 return content_features(n.getContent());
96 See mapnode.h for description.
100 if(g_texturesource == NULL)
102 dstream<<"INFO: Initial run of init_mapnode with "
103 "g_texturesource=NULL. If this segfaults, "
104 "there is a bug with something not checking for "
105 "the NULL value."<<std::endl;
109 dstream<<"INFO: Full run of init_mapnode with "
110 "g_texturesource!=NULL"<<std::endl;
113 /*// Read some settings
114 bool new_style_water = g_settings.getBool("new_style_water");
115 bool new_style_leaves = g_settings.getBool("new_style_leaves");*/
118 Initialize content feature table
122 Set initial material type to same in all tiles, so that the
123 same material can be used in more stuff.
124 This is set according to the leaves because they are the only
125 differing material to which all materials can be changed to
126 get this optimization.
128 u8 initial_material_type = MATERIAL_ALPHA_SIMPLE;
129 /*if(new_style_leaves)
130 initial_material_type = MATERIAL_ALPHA_SIMPLE;
132 initial_material_type = MATERIAL_ALPHA_NONE;*/
133 for(u16 i=0; i<MAX_CONTENT+1; i++)
135 ContentFeatures *f = &g_content_features[i];
139 for(u16 j=0; j<6; j++)
140 f->tiles[j].material_type = initial_material_type;
144 Initially set every block to be shown as an unknown block.
145 Don't touch CONTENT_IGNORE or CONTENT_AIR.
147 for(u16 i=0; i<MAX_CONTENT+1; i++)
149 if(i == CONTENT_IGNORE || i == CONTENT_AIR)
151 ContentFeatures *f = &g_content_features[i];
152 f->setAllTextures("unknown_block.png");
153 f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
157 Initialize mapnode content
159 content_mapnode_init();
163 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
166 Face 2 (normally Z-) direction:
173 if(facedir==0) // Same
174 newdir = v3s16(dir.X, dir.Y, dir.Z);
175 else if(facedir == 1) // Face is taken from rotXZccv(-90)
176 newdir = v3s16(-dir.Z, dir.Y, dir.X);
177 else if(facedir == 2) // Face is taken from rotXZccv(180)
178 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
179 else if(facedir == 3) // Face is taken from rotXZccv(90)
180 newdir = v3s16(dir.Z, dir.Y, -dir.X);
186 TileSpec MapNode::getTile(v3s16 dir)
188 if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
189 dir = facedir_rotate(param1, dir);
195 if(dir == v3s16(0,0,0))
197 else if(dir == v3s16(0,1,0))
199 else if(dir == v3s16(0,-1,0))
201 else if(dir == v3s16(1,0,0))
203 else if(dir == v3s16(-1,0,0))
205 else if(dir == v3s16(0,0,1))
207 else if(dir == v3s16(0,0,-1))
212 spec = content_features(*this).tiles[0];
214 spec = content_features(*this).tiles[dir_i];
217 If it contains some mineral, change texture id
219 if(content_features(*this).param_type == CPT_MINERAL && g_texturesource)
221 u8 mineral = getMineral();
222 std::string mineral_texture_name = mineral_block_texture(mineral);
223 if(mineral_texture_name != "")
225 u32 orig_id = spec.texture.id;
226 std::string texture_name = g_texturesource->getTextureName(orig_id);
227 //texture_name += "^blit:";
229 texture_name += mineral_texture_name;
230 u32 new_id = g_texturesource->getTextureId(texture_name);
231 spec.texture = g_texturesource->getTexture(new_id);
238 u8 MapNode::getMineral()
240 if(content_features(*this).param_type == CPT_MINERAL)
242 return param1 & 0x0f;
248 u32 MapNode::serializedLength(u8 version)
250 if(!ser_ver_supported(version))
251 throw VersionMismatchException("ERROR: MapNode format not supported");
255 else if(version <= 9)
260 void MapNode::serialize(u8 *dest, u8 version)
262 if(!ser_ver_supported(version))
263 throw VersionMismatchException("ERROR: MapNode format not supported");
265 // Translate to wanted version
266 MapNode n_foreign = mapnode_translate_from_internal(*this, version);
268 u8 actual_param0 = n_foreign.param0;
270 // Convert special values from new version to old
273 // In these versions, CONTENT_IGNORE and CONTENT_AIR
275 if(actual_param0 == CONTENT_IGNORE)
277 else if(actual_param0 == CONTENT_AIR)
283 dest[0] = actual_param0;
285 else if(version <= 9)
287 dest[0] = actual_param0;
288 dest[1] = n_foreign.param1;
292 dest[0] = actual_param0;
293 dest[1] = n_foreign.param1;
294 dest[2] = n_foreign.param2;
297 void MapNode::deSerialize(u8 *source, u8 version)
299 if(!ser_ver_supported(version))
300 throw VersionMismatchException("ERROR: MapNode format not supported");
306 else if(version == 1)
309 // This version doesn't support saved lighting
310 if(light_propagates() || light_source() > 0)
315 else if(version <= 9)
327 // Convert special values from old version to new
330 // In these versions, CONTENT_IGNORE and CONTENT_AIR
333 param0 = CONTENT_IGNORE;
334 else if(param0 == 254)
335 param0 = CONTENT_AIR;
337 // version 19 is fucked up with sometimes the old values and sometimes not
341 param0 = CONTENT_IGNORE;
342 else if(param0 == 254)
343 param0 = CONTENT_AIR;
346 // Translate to our known version
347 *this = mapnode_translate_to_internal(*this, version);
351 Gets lighting value at face of node
353 Parameters must consist of air and !air.
354 Order doesn't matter.
356 If either of the nodes doesn't exist, light is 0.
359 daynight_ratio: 0...1000
361 n2: getNodeParent(p + face_dir)
362 face_dir: axis oriented unit vector from p to p2
364 returns encoded light value.
366 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
371 u8 l1 = n.getLightBlend(daynight_ratio);
372 u8 l2 = n2.getLightBlend(daynight_ratio);
378 // Make some nice difference to different sides
380 // This makes light come from a corner
381 /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
382 light = diminish_light(diminish_light(light));
383 else if(face_dir.X == -1 || face_dir.Z == -1)
384 light = diminish_light(light);*/
386 // All neighboring faces have different shade (like in minecraft)
387 if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
388 light = diminish_light(diminish_light(light));
389 else if(face_dir.Z == 1 || face_dir.Z == -1)
390 light = diminish_light(light);
394 catch(InvalidPositionException &e)