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