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