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