+ sandstone
[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_TREE;
193         f = &g_content_features[i];
194         f->setAllTextures("tree.png");
195         f->setTexture(0, "tree_top.png");
196         f->setTexture(1, "tree_top.png");
197         f->param_type = CPT_MINERAL;
198         f->is_ground_content = true;
199         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
200         
201         i = CONTENT_LEAVES;
202         f = &g_content_features[i];
203         f->light_propagates = true;
204         //f->param_type = CPT_MINERAL;
205         f->param_type = CPT_LIGHT;
206         f->is_ground_content = true;
207         if(new_style_leaves)
208         {
209                 f->solidness = 0; // drawn separately, makes no faces
210                 f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
211         }
212         else
213         {
214                 f->setAllTextures("[noalpha:leaves.png");
215         }
216         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
217
218         i = CONTENT_GLASS;
219         f = &g_content_features[i];
220         f->light_propagates = true;
221         f->param_type = CPT_LIGHT;
222         f->is_ground_content = true;
223         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
224         f->solidness = 0; // drawn separately, makes no faces
225         f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
226
227         i = CONTENT_FENCE;
228         f = &g_content_features[i];
229         f->light_propagates = true;
230         f->param_type = CPT_LIGHT;
231         f->is_ground_content = true;
232         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
233         f->solidness = 0; // drawn separately, makes no faces
234         f->air_equivalent = true; // grass grows underneath
235
236         // Deprecated
237         i = CONTENT_COALSTONE;
238         f = &g_content_features[i];
239         //f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
240         f->setAllTextures("stone.png^mineral_coal.png");
241         f->is_ground_content = true;
242         
243         i = CONTENT_WOOD;
244         f = &g_content_features[i];
245         f->setAllTextures("wood.png");
246         f->is_ground_content = true;
247         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
248         
249         i = CONTENT_MESE;
250         f = &g_content_features[i];
251         f->setAllTextures("mese.png");
252         f->is_ground_content = true;
253         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
254         
255         i = CONTENT_CLOUD;
256         f = &g_content_features[i];
257         f->setAllTextures("cloud.png");
258         f->is_ground_content = true;
259         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
260         
261         i = CONTENT_AIR;
262         f = &g_content_features[i];
263         f->param_type = CPT_LIGHT;
264         f->light_propagates = true;
265         f->sunlight_propagates = true;
266         f->solidness = 0;
267         f->walkable = false;
268         f->pointable = false;
269         f->diggable = false;
270         f->buildable_to = true;
271         f->air_equivalent = true;
272         
273         i = CONTENT_WATER;
274         f = &g_content_features[i];
275         f->setInventoryTextureCube("water.png", "water.png", "water.png");
276         f->param_type = CPT_LIGHT;
277         f->light_propagates = true;
278         f->solidness = 0; // Drawn separately, makes no faces
279         f->walkable = false;
280         f->pointable = false;
281         f->diggable = false;
282         f->buildable_to = true;
283         f->liquid_type = LIQUID_FLOWING;
284         
285         i = CONTENT_WATERSOURCE;
286         f = &g_content_features[i];
287         f->setInventoryTexture("water.png");
288         if(new_style_water)
289         {
290                 f->solidness = 0; // drawn separately, makes no faces
291         }
292         else // old style
293         {
294                 f->solidness = 1;
295
296                 TileSpec t;
297                 if(g_texturesource)
298                         t.texture = g_texturesource->getTexture("water.png");
299                 
300                 t.alpha = WATER_ALPHA;
301                 t.material_type = MATERIAL_ALPHA_VERTEX;
302                 t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
303                 f->setAllTiles(t);
304         }
305         f->param_type = CPT_LIGHT;
306         f->light_propagates = true;
307         f->walkable = false;
308         f->pointable = false;
309         f->diggable = false;
310         f->buildable_to = true;
311         f->liquid_type = LIQUID_SOURCE;
312         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
313         
314         i = CONTENT_TORCH;
315         f = &g_content_features[i];
316         f->setInventoryTexture("torch_on_floor.png");
317         f->param_type = CPT_LIGHT;
318         f->light_propagates = true;
319         f->sunlight_propagates = true;
320         f->solidness = 0; // drawn separately, makes no faces
321         f->walkable = false;
322         f->wall_mounted = true;
323         f->air_equivalent = true;
324         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
325         
326         i = CONTENT_SIGN_WALL;
327         f = &g_content_features[i];
328         f->setInventoryTexture("sign_wall.png");
329         f->param_type = CPT_LIGHT;
330         f->light_propagates = true;
331         f->sunlight_propagates = true;
332         f->solidness = 0; // drawn separately, makes no faces
333         f->walkable = false;
334         f->wall_mounted = true;
335         f->air_equivalent = true;
336         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
337         if(f->initial_metadata == NULL)
338                 f->initial_metadata = new SignNodeMetadata("Some sign");
339         
340         i = CONTENT_CHEST;
341         f = &g_content_features[i];
342         f->param_type = CPT_FACEDIR_SIMPLE;
343         f->setAllTextures("chest_side.png");
344         f->setTexture(0, "chest_top.png");
345         f->setTexture(1, "chest_top.png");
346         f->setTexture(5, "chest_front.png"); // Z-
347         f->setInventoryTexture("chest_top.png");
348         //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
349         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
350         if(f->initial_metadata == NULL)
351                 f->initial_metadata = new ChestNodeMetadata();
352         
353         i = CONTENT_FURNACE;
354         f = &g_content_features[i];
355         f->param_type = CPT_FACEDIR_SIMPLE;
356         f->setAllTextures("furnace_side.png");
357         f->setTexture(5, "furnace_front.png"); // Z-
358         f->setInventoryTexture("furnace_front.png");
359         //f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
360         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 6";
361         if(f->initial_metadata == NULL)
362                 f->initial_metadata = new FurnaceNodeMetadata();
363         
364         i = CONTENT_COBBLE;
365         f = &g_content_features[i];
366         f->setAllTextures("cobble.png");
367         f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
368         f->param_type = CPT_NONE;
369         f->is_ground_content = true;
370         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
371         
372         i = CONTENT_STEEL;
373         f = &g_content_features[i];
374         f->setAllTextures("steel_block.png");
375         f->setInventoryTextureCube("steel_block.png", "steel_block.png",
376                         "steel_block.png");
377         f->param_type = CPT_NONE;
378         f->is_ground_content = true;
379         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
380         
381         // NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
382 }
383
384 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
385 {
386         /*
387                 Face 2 (normally Z-) direction:
388                 facedir=0: Z-
389                 facedir=1: X-
390                 facedir=2: Z+
391                 facedir=3: X+
392         */
393         v3s16 newdir;
394         if(facedir==0) // Same
395                 newdir = v3s16(dir.X, dir.Y, dir.Z);
396         else if(facedir == 1) // Face is taken from rotXZccv(-90)
397                 newdir = v3s16(-dir.Z, dir.Y, dir.X);
398         else if(facedir == 2) // Face is taken from rotXZccv(180)
399                 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
400         else if(facedir == 3) // Face is taken from rotXZccv(90)
401                 newdir = v3s16(dir.Z, dir.Y, -dir.X);
402         else
403                 newdir = dir;
404         return newdir;
405 }
406
407 TileSpec MapNode::getTile(v3s16 dir)
408 {
409         if(content_features(d).param_type == CPT_FACEDIR_SIMPLE)
410                 dir = facedir_rotate(param1, dir);
411         
412         TileSpec spec;
413         
414         s32 dir_i = -1;
415         
416         if(dir == v3s16(0,0,0))
417                 dir_i = -1;
418         else if(dir == v3s16(0,1,0))
419                 dir_i = 0;
420         else if(dir == v3s16(0,-1,0))
421                 dir_i = 1;
422         else if(dir == v3s16(1,0,0))
423                 dir_i = 2;
424         else if(dir == v3s16(-1,0,0))
425                 dir_i = 3;
426         else if(dir == v3s16(0,0,1))
427                 dir_i = 4;
428         else if(dir == v3s16(0,0,-1))
429                 dir_i = 5;
430         
431         if(dir_i == -1)
432                 // Non-directional
433                 spec = content_features(d).tiles[0];
434         else 
435                 spec = content_features(d).tiles[dir_i];
436         
437         /*
438                 If it contains some mineral, change texture id
439         */
440         if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
441         {
442                 u8 mineral = param & 0x1f;
443                 std::string mineral_texture_name = mineral_block_texture(mineral);
444                 if(mineral_texture_name != "")
445                 {
446                         u32 orig_id = spec.texture.id;
447                         std::string texture_name = g_texturesource->getTextureName(orig_id);
448                         //texture_name += "^blit:";
449                         texture_name += "^";
450                         texture_name += mineral_texture_name;
451                         u32 new_id = g_texturesource->getTextureId(texture_name);
452                         spec.texture = g_texturesource->getTexture(new_id);
453                 }
454         }
455
456         return spec;
457 }
458
459 u8 MapNode::getMineral()
460 {
461         if(content_features(d).param_type == CPT_MINERAL)
462         {
463                 return param & 0x1f;
464         }
465
466         return MINERAL_NONE;
467 }
468
469 // Pointers to c_str()s g_content_features[i].inventory_image_path
470 //const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
471
472 void init_content_inventory_texture_paths()
473 {
474         dstream<<"DEPRECATED "<<__FUNCTION_NAME<<std::endl;
475         /*for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
476         {
477                 g_content_inventory_texture_paths[i] =
478                                 g_content_features[i].inventory_image_path.c_str();
479         }*/
480 }
481