]> git.lizzy.rs Git - minetest.git/blob - src/mapnode.cpp
+ rail
[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_BOOKSHELF;
255         f = &g_content_features[i];
256         f->setAllTextures("bookshelf.png");
257         f->setTexture(0, "wood.png");
258         f->setTexture(1, "wood.png");
259         // FIXME: setInventoryTextureCube() only cares for the first texture
260         f->setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png");
261         //f->setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png");
262         f->param_type = CPT_MINERAL;
263         f->is_ground_content = true;
264
265         i = CONTENT_GLASS;
266         f = &g_content_features[i];
267         f->light_propagates = true;
268         f->param_type = CPT_LIGHT;
269         f->is_ground_content = true;
270         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
271         f->solidness = 0; // drawn separately, makes no faces
272         f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
273
274         i = CONTENT_FENCE;
275         f = &g_content_features[i];
276         f->setInventoryTexture("fence.png");
277         f->light_propagates = true;
278         f->param_type = CPT_LIGHT;
279         f->is_ground_content = true;
280         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
281         f->solidness = 0; // drawn separately, makes no faces
282         f->air_equivalent = true; // grass grows underneath
283
284         i = CONTENT_RAIL;
285         f = &g_content_features[i];
286         f->setInventoryTexture("rail.png");
287         f->light_propagates = true;
288         f->param_type = CPT_LIGHT;
289         f->is_ground_content = true;
290         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
291         f->solidness = 0; // drawn separately, makes no faces
292         f->air_equivalent = true; // grass grows underneath
293         f->walkable = false;
294
295         // Deprecated
296         i = CONTENT_COALSTONE;
297         f = &g_content_features[i];
298         //f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
299         f->setAllTextures("stone.png^mineral_coal.png");
300         f->is_ground_content = true;
301         
302         i = CONTENT_WOOD;
303         f = &g_content_features[i];
304         f->setAllTextures("wood.png");
305         f->is_ground_content = true;
306         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
307         
308         i = CONTENT_MESE;
309         f = &g_content_features[i];
310         f->setAllTextures("mese.png");
311         f->is_ground_content = true;
312         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
313         
314         i = CONTENT_CLOUD;
315         f = &g_content_features[i];
316         f->setAllTextures("cloud.png");
317         f->is_ground_content = true;
318         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
319         
320         i = CONTENT_AIR;
321         f = &g_content_features[i];
322         f->param_type = CPT_LIGHT;
323         f->light_propagates = true;
324         f->sunlight_propagates = true;
325         f->solidness = 0;
326         f->walkable = false;
327         f->pointable = false;
328         f->diggable = false;
329         f->buildable_to = true;
330         f->air_equivalent = true;
331         
332         i = CONTENT_WATER;
333         f = &g_content_features[i];
334         f->setInventoryTextureCube("water.png", "water.png", "water.png");
335         f->param_type = CPT_LIGHT;
336         f->light_propagates = true;
337         f->solidness = 0; // Drawn separately, makes no faces
338         f->walkable = false;
339         f->pointable = false;
340         f->diggable = false;
341         f->buildable_to = true;
342         f->liquid_type = LIQUID_FLOWING;
343         
344         i = CONTENT_WATERSOURCE;
345         f = &g_content_features[i];
346         f->setInventoryTexture("water.png");
347         if(new_style_water)
348         {
349                 f->solidness = 0; // drawn separately, makes no faces
350         }
351         else // old style
352         {
353                 f->solidness = 1;
354
355                 TileSpec t;
356                 if(g_texturesource)
357                         t.texture = g_texturesource->getTexture("water.png");
358                 
359                 t.alpha = WATER_ALPHA;
360                 t.material_type = MATERIAL_ALPHA_VERTEX;
361                 t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
362                 f->setAllTiles(t);
363         }
364         f->param_type = CPT_LIGHT;
365         f->light_propagates = true;
366         f->walkable = false;
367         f->pointable = false;
368         f->diggable = false;
369         f->buildable_to = true;
370         f->liquid_type = LIQUID_SOURCE;
371         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
372         
373         i = CONTENT_TORCH;
374         f = &g_content_features[i];
375         f->setInventoryTexture("torch_on_floor.png");
376         f->param_type = CPT_LIGHT;
377         f->light_propagates = true;
378         f->sunlight_propagates = true;
379         f->solidness = 0; // drawn separately, makes no faces
380         f->walkable = false;
381         f->wall_mounted = true;
382         f->air_equivalent = true;
383         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
384         
385         i = CONTENT_SIGN_WALL;
386         f = &g_content_features[i];
387         f->setInventoryTexture("sign_wall.png");
388         f->param_type = CPT_LIGHT;
389         f->light_propagates = true;
390         f->sunlight_propagates = true;
391         f->solidness = 0; // drawn separately, makes no faces
392         f->walkable = false;
393         f->wall_mounted = true;
394         f->air_equivalent = true;
395         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
396         if(f->initial_metadata == NULL)
397                 f->initial_metadata = new SignNodeMetadata("Some sign");
398         
399         i = CONTENT_CHEST;
400         f = &g_content_features[i];
401         f->param_type = CPT_FACEDIR_SIMPLE;
402         f->setAllTextures("chest_side.png");
403         f->setTexture(0, "chest_top.png");
404         f->setTexture(1, "chest_top.png");
405         f->setTexture(5, "chest_front.png"); // Z-
406         f->setInventoryTexture("chest_top.png");
407         //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
408         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
409         if(f->initial_metadata == NULL)
410                 f->initial_metadata = new ChestNodeMetadata();
411         
412         i = CONTENT_FURNACE;
413         f = &g_content_features[i];
414         f->param_type = CPT_FACEDIR_SIMPLE;
415         f->setAllTextures("furnace_side.png");
416         f->setTexture(5, "furnace_front.png"); // Z-
417         f->setInventoryTexture("furnace_front.png");
418         //f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
419         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 6";
420         if(f->initial_metadata == NULL)
421                 f->initial_metadata = new FurnaceNodeMetadata();
422         
423         i = CONTENT_COBBLE;
424         f = &g_content_features[i];
425         f->setAllTextures("cobble.png");
426         f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
427         f->param_type = CPT_NONE;
428         f->is_ground_content = true;
429         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
430         
431         i = CONTENT_STEEL;
432         f = &g_content_features[i];
433         f->setAllTextures("steel_block.png");
434         f->setInventoryTextureCube("steel_block.png", "steel_block.png",
435                         "steel_block.png");
436         f->param_type = CPT_NONE;
437         f->is_ground_content = true;
438         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
439         
440         // NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
441 }
442
443 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
444 {
445         /*
446                 Face 2 (normally Z-) direction:
447                 facedir=0: Z-
448                 facedir=1: X-
449                 facedir=2: Z+
450                 facedir=3: X+
451         */
452         v3s16 newdir;
453         if(facedir==0) // Same
454                 newdir = v3s16(dir.X, dir.Y, dir.Z);
455         else if(facedir == 1) // Face is taken from rotXZccv(-90)
456                 newdir = v3s16(-dir.Z, dir.Y, dir.X);
457         else if(facedir == 2) // Face is taken from rotXZccv(180)
458                 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
459         else if(facedir == 3) // Face is taken from rotXZccv(90)
460                 newdir = v3s16(dir.Z, dir.Y, -dir.X);
461         else
462                 newdir = dir;
463         return newdir;
464 }
465
466 TileSpec MapNode::getTile(v3s16 dir)
467 {
468         if(content_features(d).param_type == CPT_FACEDIR_SIMPLE)
469                 dir = facedir_rotate(param1, dir);
470         
471         TileSpec spec;
472         
473         s32 dir_i = -1;
474         
475         if(dir == v3s16(0,0,0))
476                 dir_i = -1;
477         else if(dir == v3s16(0,1,0))
478                 dir_i = 0;
479         else if(dir == v3s16(0,-1,0))
480                 dir_i = 1;
481         else if(dir == v3s16(1,0,0))
482                 dir_i = 2;
483         else if(dir == v3s16(-1,0,0))
484                 dir_i = 3;
485         else if(dir == v3s16(0,0,1))
486                 dir_i = 4;
487         else if(dir == v3s16(0,0,-1))
488                 dir_i = 5;
489         
490         if(dir_i == -1)
491                 // Non-directional
492                 spec = content_features(d).tiles[0];
493         else 
494                 spec = content_features(d).tiles[dir_i];
495         
496         /*
497                 If it contains some mineral, change texture id
498         */
499         if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
500         {
501                 u8 mineral = param & 0x1f;
502                 std::string mineral_texture_name = mineral_block_texture(mineral);
503                 if(mineral_texture_name != "")
504                 {
505                         u32 orig_id = spec.texture.id;
506                         std::string texture_name = g_texturesource->getTextureName(orig_id);
507                         //texture_name += "^blit:";
508                         texture_name += "^";
509                         texture_name += mineral_texture_name;
510                         u32 new_id = g_texturesource->getTextureId(texture_name);
511                         spec.texture = g_texturesource->getTexture(new_id);
512                 }
513         }
514
515         return spec;
516 }
517
518 u8 MapNode::getMineral()
519 {
520         if(content_features(d).param_type == CPT_MINERAL)
521         {
522                 return param & 0x1f;
523         }
524
525         return MINERAL_NONE;
526 }
527
528 // Pointers to c_str()s g_content_features[i].inventory_image_path
529 //const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
530
531 void init_content_inventory_texture_paths()
532 {
533         dstream<<"DEPRECATED "<<__FUNCTION_NAME<<std::endl;
534         /*for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
535         {
536                 g_content_inventory_texture_paths[i] =
537                                 g_content_features[i].inventory_image_path.c_str();
538         }*/
539 }
540