954c85f2f7d9e75319ed9249a214525524f7bc9f
[oweals/minetest.git] / src / mapnode.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #include "common_irrlicht.h"
21 #include "mapnode.h"
22 #include "tile.h"
23 #include "porting.h"
24 #include <string>
25 #include "mineral.h"
26 // For g_settings
27 #include "main.h"
28 #include "nodemetadata.h"
29
30 ContentFeatures::~ContentFeatures()
31 {
32         if(translate_to)
33                 delete translate_to;
34         if(initial_metadata)
35                 delete initial_metadata;
36 }
37
38 void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
39 {
40         if(g_texturesource)
41         {
42                 tiles[i].texture = g_texturesource->getTexture(name);
43         }
44         
45         if(alpha != 255)
46         {
47                 tiles[i].alpha = alpha;
48                 tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
49         }
50
51         if(inventory_texture == NULL)
52                 setInventoryTexture(name);
53 }
54
55 void ContentFeatures::setInventoryTexture(std::string imgname)
56 {
57         if(g_texturesource == NULL)
58                 return;
59         
60         imgname += "^[forcesingle";
61         
62         inventory_texture = g_texturesource->getTextureRaw(imgname);
63 }
64
65 void ContentFeatures::setInventoryTextureCube(std::string top,
66                 std::string left, std::string right)
67 {
68         if(g_texturesource == NULL)
69                 return;
70         
71         str_replace_char(top, '^', '&');
72         str_replace_char(left, '^', '&');
73         str_replace_char(right, '^', '&');
74
75         std::string imgname_full;
76         imgname_full += "[inventorycube{";
77         imgname_full += top;
78         imgname_full += "{";
79         imgname_full += left;
80         imgname_full += "{";
81         imgname_full += right;
82         inventory_texture = g_texturesource->getTextureRaw(imgname_full);
83 }
84
85 struct ContentFeatures g_content_features[256];
86
87 ContentFeatures & content_features(u8 i)
88 {
89         return g_content_features[i];
90 }
91
92 /*
93         See mapnode.h for description.
94 */
95 void init_mapnode()
96 {
97         if(g_texturesource == NULL)
98         {
99                 dstream<<"INFO: Initial run of init_mapnode with "
100                                 "g_texturesource=NULL. If this segfaults, "
101                                 "there is a bug with something not checking for "
102                                 "the NULL value."<<std::endl;
103         }
104         else
105         {
106                 dstream<<"INFO: Full run of init_mapnode with "
107                                 "g_texturesource!=NULL"<<std::endl;
108         }
109
110         // Read some settings
111         bool new_style_water = g_settings.getBool("new_style_water");
112         bool new_style_leaves = g_settings.getBool("new_style_leaves");
113
114         /*
115                 Initialize content feature table
116         */
117         
118         /*
119                 Set initial material type to same in all tiles, so that the
120                 same material can be used in more stuff.
121                 This is set according to the leaves because they are the only
122                 differing material to which all materials can be changed to
123                 get this optimization.
124         */
125         u8 initial_material_type = MATERIAL_ALPHA_SIMPLE;
126         /*if(new_style_leaves)
127                 initial_material_type = MATERIAL_ALPHA_SIMPLE;
128         else
129                 initial_material_type = MATERIAL_ALPHA_NONE;*/
130         for(u16 i=0; i<256; i++)
131         {
132                 ContentFeatures *f = &g_content_features[i];
133                 // Re-initialize
134                 *f = ContentFeatures();
135
136                 for(u16 j=0; j<6; j++)
137                         f->tiles[j].material_type = initial_material_type;
138         }
139         
140         u8 i;
141         ContentFeatures *f = NULL;
142
143         i = CONTENT_STONE;
144         f = &g_content_features[i];
145         f->setAllTextures("stone.png");
146         f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
147         f->param_type = CPT_MINERAL;
148         f->is_ground_content = true;
149         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 1";
150         
151         i = CONTENT_GRASS;
152         f = &g_content_features[i];
153         f->setAllTextures("mud.png^grass_side.png");
154         f->setTexture(0, "grass.png");
155         f->setTexture(1, "mud.png");
156         f->param_type = CPT_MINERAL;
157         f->is_ground_content = true;
158         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
159         
160         i = CONTENT_GRASS_FOOTSTEPS;
161         f = &g_content_features[i];
162         f->setAllTextures("mud.png^grass_side.png");
163         f->setTexture(0, "grass_footsteps.png");
164         f->setTexture(1, "mud.png");
165         f->param_type = CPT_MINERAL;
166         f->is_ground_content = true;
167         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
168         
169         i = CONTENT_MUD;
170         f = &g_content_features[i];
171         f->setAllTextures("mud.png");
172         f->setInventoryTextureCube("mud.png", "mud.png", "mud.png");
173         f->param_type = CPT_MINERAL;
174         f->is_ground_content = true;
175         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
176         
177         i = CONTENT_SAND;
178         f = &g_content_features[i];
179         f->setAllTextures("sand.png");
180         f->param_type = CPT_MINERAL;
181         f->is_ground_content = true;
182         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
183         
184         i = CONTENT_SANDSTONE;
185         f = &g_content_features[i];
186         f->setAllTextures("sandstone.png");
187         f->setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png");
188         f->param_type = CPT_MINERAL;
189         f->is_ground_content = true;
190         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_SAND)+" 1";
191         
192         i = CONTENT_CLAY;
193         f = &g_content_features[i];
194         f->setAllTextures("clay.png");
195         f->setInventoryTextureCube("clay.png", "clay.png", "clay.png");
196         f->param_type = CPT_MINERAL;
197         f->is_ground_content = true;
198         f->dug_item = std::string("CraftItem lump_of_clay 4");
199         
200         i = CONTENT_BRICK;
201         f = &g_content_features[i];
202         f->setAllTextures("brick.png");
203         f->setInventoryTextureCube("brick.png", "brick.png", "brick.png");
204         f->param_type = CPT_MINERAL;
205         f->is_ground_content = true;
206         f->dug_item = std::string("CraftItem clay_brick 4");
207         
208         i = CONTENT_TREE;
209         f = &g_content_features[i];
210         f->setAllTextures("tree.png");
211         f->setTexture(0, "tree_top.png");
212         f->setTexture(1, "tree_top.png");
213         f->param_type = CPT_MINERAL;
214         f->is_ground_content = true;
215         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
216         
217         i = CONTENT_LEAVES;
218         f = &g_content_features[i];
219         f->light_propagates = true;
220         //f->param_type = CPT_MINERAL;
221         f->param_type = CPT_LIGHT;
222         f->is_ground_content = true;
223         if(new_style_leaves)
224         {
225                 f->solidness = 0; // drawn separately, makes no faces
226                 f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
227         }
228         else
229         {
230                 f->setAllTextures("[noalpha:leaves.png");
231         }
232         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
233
234         i = CONTENT_CACTUS;
235         f = &g_content_features[i];
236         f->setAllTextures("cactus_side.png");
237         f->setTexture(0, "cactus_top.png");
238         f->setTexture(1, "cactus_top.png");
239         f->setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png");
240         f->param_type = CPT_MINERAL;
241         f->is_ground_content = true;
242         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
243
244         i = CONTENT_PAPYRUS;
245         f = &g_content_features[i];
246         f->setInventoryTexture("papyrus.png");
247         f->light_propagates = true;
248         f->param_type = CPT_LIGHT;
249         f->is_ground_content = true;
250         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
251         f->solidness = 0; // drawn separately, makes no faces
252         f->walkable = false;
253
254         i = CONTENT_GLASS;
255         f = &g_content_features[i];
256         f->light_propagates = true;
257         f->param_type = CPT_LIGHT;
258         f->is_ground_content = true;
259         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
260         f->solidness = 0; // drawn separately, makes no faces
261         f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
262
263         i = CONTENT_FENCE;
264         f = &g_content_features[i];
265         f->setInventoryTexture("fence.png");
266         f->light_propagates = true;
267         f->param_type = CPT_LIGHT;
268         f->is_ground_content = true;
269         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
270         f->solidness = 0; // drawn separately, makes no faces
271         f->air_equivalent = true; // grass grows underneath
272
273         // Deprecated
274         i = CONTENT_COALSTONE;
275         f = &g_content_features[i];
276         //f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
277         f->setAllTextures("stone.png^mineral_coal.png");
278         f->is_ground_content = true;
279         
280         i = CONTENT_WOOD;
281         f = &g_content_features[i];
282         f->setAllTextures("wood.png");
283         f->is_ground_content = true;
284         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
285         
286         i = CONTENT_MESE;
287         f = &g_content_features[i];
288         f->setAllTextures("mese.png");
289         f->is_ground_content = true;
290         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
291         
292         i = CONTENT_CLOUD;
293         f = &g_content_features[i];
294         f->setAllTextures("cloud.png");
295         f->is_ground_content = true;
296         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
297         
298         i = CONTENT_AIR;
299         f = &g_content_features[i];
300         f->param_type = CPT_LIGHT;
301         f->light_propagates = true;
302         f->sunlight_propagates = true;
303         f->solidness = 0;
304         f->walkable = false;
305         f->pointable = false;
306         f->diggable = false;
307         f->buildable_to = true;
308         f->air_equivalent = true;
309         
310         i = CONTENT_WATER;
311         f = &g_content_features[i];
312         f->setInventoryTextureCube("water.png", "water.png", "water.png");
313         f->param_type = CPT_LIGHT;
314         f->light_propagates = true;
315         f->solidness = 0; // Drawn separately, makes no faces
316         f->walkable = false;
317         f->pointable = false;
318         f->diggable = false;
319         f->buildable_to = true;
320         f->liquid_type = LIQUID_FLOWING;
321         
322         i = CONTENT_WATERSOURCE;
323         f = &g_content_features[i];
324         f->setInventoryTexture("water.png");
325         if(new_style_water)
326         {
327                 f->solidness = 0; // drawn separately, makes no faces
328         }
329         else // old style
330         {
331                 f->solidness = 1;
332
333                 TileSpec t;
334                 if(g_texturesource)
335                         t.texture = g_texturesource->getTexture("water.png");
336                 
337                 t.alpha = WATER_ALPHA;
338                 t.material_type = MATERIAL_ALPHA_VERTEX;
339                 t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
340                 f->setAllTiles(t);
341         }
342         f->param_type = CPT_LIGHT;
343         f->light_propagates = true;
344         f->walkable = false;
345         f->pointable = false;
346         f->diggable = false;
347         f->buildable_to = true;
348         f->liquid_type = LIQUID_SOURCE;
349         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
350         
351         i = CONTENT_TORCH;
352         f = &g_content_features[i];
353         f->setInventoryTexture("torch_on_floor.png");
354         f->param_type = CPT_LIGHT;
355         f->light_propagates = true;
356         f->sunlight_propagates = true;
357         f->solidness = 0; // drawn separately, makes no faces
358         f->walkable = false;
359         f->wall_mounted = true;
360         f->air_equivalent = true;
361         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
362         
363         i = CONTENT_SIGN_WALL;
364         f = &g_content_features[i];
365         f->setInventoryTexture("sign_wall.png");
366         f->param_type = CPT_LIGHT;
367         f->light_propagates = true;
368         f->sunlight_propagates = true;
369         f->solidness = 0; // drawn separately, makes no faces
370         f->walkable = false;
371         f->wall_mounted = true;
372         f->air_equivalent = true;
373         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
374         if(f->initial_metadata == NULL)
375                 f->initial_metadata = new SignNodeMetadata("Some sign");
376         
377         i = CONTENT_CHEST;
378         f = &g_content_features[i];
379         f->param_type = CPT_FACEDIR_SIMPLE;
380         f->setAllTextures("chest_side.png");
381         f->setTexture(0, "chest_top.png");
382         f->setTexture(1, "chest_top.png");
383         f->setTexture(5, "chest_front.png"); // Z-
384         f->setInventoryTexture("chest_top.png");
385         //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
386         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
387         if(f->initial_metadata == NULL)
388                 f->initial_metadata = new ChestNodeMetadata();
389         
390         i = CONTENT_FURNACE;
391         f = &g_content_features[i];
392         f->param_type = CPT_FACEDIR_SIMPLE;
393         f->setAllTextures("furnace_side.png");
394         f->setTexture(5, "furnace_front.png"); // Z-
395         f->setInventoryTexture("furnace_front.png");
396         //f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
397         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 6";
398         if(f->initial_metadata == NULL)
399                 f->initial_metadata = new FurnaceNodeMetadata();
400         
401         i = CONTENT_COBBLE;
402         f = &g_content_features[i];
403         f->setAllTextures("cobble.png");
404         f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
405         f->param_type = CPT_NONE;
406         f->is_ground_content = true;
407         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
408         
409         i = CONTENT_STEEL;
410         f = &g_content_features[i];
411         f->setAllTextures("steel_block.png");
412         f->setInventoryTextureCube("steel_block.png", "steel_block.png",
413                         "steel_block.png");
414         f->param_type = CPT_NONE;
415         f->is_ground_content = true;
416         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
417         
418         // NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
419 }
420
421 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
422 {
423         /*
424                 Face 2 (normally Z-) direction:
425                 facedir=0: Z-
426                 facedir=1: X-
427                 facedir=2: Z+
428                 facedir=3: X+
429         */
430         v3s16 newdir;
431         if(facedir==0) // Same
432                 newdir = v3s16(dir.X, dir.Y, dir.Z);
433         else if(facedir == 1) // Face is taken from rotXZccv(-90)
434                 newdir = v3s16(-dir.Z, dir.Y, dir.X);
435         else if(facedir == 2) // Face is taken from rotXZccv(180)
436                 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
437         else if(facedir == 3) // Face is taken from rotXZccv(90)
438                 newdir = v3s16(dir.Z, dir.Y, -dir.X);
439         else
440                 newdir = dir;
441         return newdir;
442 }
443
444 TileSpec MapNode::getTile(v3s16 dir)
445 {
446         if(content_features(d).param_type == CPT_FACEDIR_SIMPLE)
447                 dir = facedir_rotate(param1, dir);
448         
449         TileSpec spec;
450         
451         s32 dir_i = -1;
452         
453         if(dir == v3s16(0,0,0))
454                 dir_i = -1;
455         else if(dir == v3s16(0,1,0))
456                 dir_i = 0;
457         else if(dir == v3s16(0,-1,0))
458                 dir_i = 1;
459         else if(dir == v3s16(1,0,0))
460                 dir_i = 2;
461         else if(dir == v3s16(-1,0,0))
462                 dir_i = 3;
463         else if(dir == v3s16(0,0,1))
464                 dir_i = 4;
465         else if(dir == v3s16(0,0,-1))
466                 dir_i = 5;
467         
468         if(dir_i == -1)
469                 // Non-directional
470                 spec = content_features(d).tiles[0];
471         else 
472                 spec = content_features(d).tiles[dir_i];
473         
474         /*
475                 If it contains some mineral, change texture id
476         */
477         if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
478         {
479                 u8 mineral = param & 0x1f;
480                 std::string mineral_texture_name = mineral_block_texture(mineral);
481                 if(mineral_texture_name != "")
482                 {
483                         u32 orig_id = spec.texture.id;
484                         std::string texture_name = g_texturesource->getTextureName(orig_id);
485                         //texture_name += "^blit:";
486                         texture_name += "^";
487                         texture_name += mineral_texture_name;
488                         u32 new_id = g_texturesource->getTextureId(texture_name);
489                         spec.texture = g_texturesource->getTexture(new_id);
490                 }
491         }
492
493         return spec;
494 }
495
496 u8 MapNode::getMineral()
497 {
498         if(content_features(d).param_type == CPT_MINERAL)
499         {
500                 return param & 0x1f;
501         }
502
503         return MINERAL_NONE;
504 }
505
506 // Pointers to c_str()s g_content_features[i].inventory_image_path
507 //const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
508
509 void init_content_inventory_texture_paths()
510 {
511         dstream<<"DEPRECATED "<<__FUNCTION_NAME<<std::endl;
512         /*for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
513         {
514                 g_content_inventory_texture_paths[i] =
515                                 g_content_features[i].inventory_image_path.c_str();
516         }*/
517 }
518