Fix water-glass and water-lava surfaces
[oweals/minetest.git] / src / content_mapnode.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 // For g_settings
21 #include "main.h"
22
23 #include "content_mapnode.h"
24 #include "mapnode.h"
25 #include "content_nodemeta.h"
26 #include "settings.h"
27
28 #define WATER_ALPHA 160
29
30 #define WATER_VISC 1
31 #define LAVA_VISC 7
32
33 // TODO: Get rid of these and set up some attributes like toughness,
34 //       fluffyness, and a funciton to calculate time and durability loss
35 //       (and sound? and whatever else) from them
36 void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
37 void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
38 void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
39
40 /*
41         A conversion table for backwards compatibility.
42         Maps <=v19 content types to current ones.
43         Should never be touched.
44 */
45 content_t trans_table_19[21][2] = {
46         {CONTENT_GRASS, 1},
47         {CONTENT_TREE, 4},
48         {CONTENT_LEAVES, 5},
49         {CONTENT_GRASS_FOOTSTEPS, 6},
50         {CONTENT_MESE, 7},
51         {CONTENT_MUD, 8},
52         {CONTENT_CLOUD, 10},
53         {CONTENT_COALSTONE, 11},
54         {CONTENT_WOOD, 12},
55         {CONTENT_SAND, 13},
56         {CONTENT_COBBLE, 18},
57         {CONTENT_STEEL, 19},
58         {CONTENT_GLASS, 20},
59         {CONTENT_MOSSYCOBBLE, 22},
60         {CONTENT_GRAVEL, 23},
61         {CONTENT_SANDSTONE, 24},
62         {CONTENT_CACTUS, 25},
63         {CONTENT_BRICK, 26},
64         {CONTENT_CLAY, 27},
65         {CONTENT_PAPYRUS, 28},
66         {CONTENT_BOOKSHELF, 29},
67 };
68
69 MapNode mapnode_translate_from_internal(MapNode n_from, u8 version)
70 {
71         MapNode result = n_from;
72         if(version <= 19)
73         {
74                 content_t c_from = n_from.getContent();
75                 for(u32 i=0; i<sizeof(trans_table_19)/sizeof(trans_table_19[0]); i++)
76                 {
77                         if(trans_table_19[i][0] == c_from)
78                         {
79                                 result.setContent(trans_table_19[i][1]);
80                                 break;
81                         }
82                 }
83         }
84         return result;
85 }
86 MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
87 {
88         MapNode result = n_from;
89         if(version <= 19)
90         {
91                 content_t c_from = n_from.getContent();
92                 for(u32 i=0; i<sizeof(trans_table_19)/sizeof(trans_table_19[0]); i++)
93                 {
94                         if(trans_table_19[i][1] == c_from)
95                         {
96                                 result.setContent(trans_table_19[i][0]);
97                                 break;
98                         }
99                 }
100         }
101         return result;
102 }
103
104 void content_mapnode_init()
105 {
106         // Read some settings
107         bool new_style_water = g_settings->getBool("new_style_water");
108         bool new_style_leaves = g_settings->getBool("new_style_leaves");
109         bool invisible_stone = g_settings->getBool("invisible_stone");
110         bool opaque_water = g_settings->getBool("opaque_water");
111
112         content_t i;
113         ContentFeatures *f = NULL;
114
115         i = CONTENT_STONE;
116         f = &content_features(i);
117         f->setAllTextures("stone.png");
118         f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
119         f->param_type = CPT_MINERAL;
120         f->is_ground_content = true;
121         f->often_contains_mineral = true;
122         f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 1";
123         setStoneLikeDiggingProperties(f->digging_properties, 1.0);
124         if(invisible_stone)
125                 f->solidness = 0; // For debugging, hides regular stone
126         
127         i = CONTENT_GRASS;
128         f = &content_features(i);
129         f->setAllTextures("mud.png^grass_side.png");
130         f->setTexture(0, "grass.png");
131         f->setTexture(1, "mud.png");
132         f->param_type = CPT_MINERAL;
133         f->is_ground_content = true;
134         f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
135         setDirtLikeDiggingProperties(f->digging_properties, 1.0);
136         
137         i = CONTENT_GRASS_FOOTSTEPS;
138         f = &content_features(i);
139         f->setAllTextures("mud.png^grass_side.png");
140         f->setTexture(0, "grass_footsteps.png");
141         f->setTexture(1, "mud.png");
142         f->param_type = CPT_MINERAL;
143         f->is_ground_content = true;
144         f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_MUD)+" 1";
145         setDirtLikeDiggingProperties(f->digging_properties, 1.0);
146         
147         i = CONTENT_MUD;
148         f = &content_features(i);
149         f->setAllTextures("mud.png");
150         f->setInventoryTextureCube("mud.png", "mud.png", "mud.png");
151         f->param_type = CPT_MINERAL;
152         f->is_ground_content = true;
153         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
154         setDirtLikeDiggingProperties(f->digging_properties, 1.0);
155         
156         i = CONTENT_SAND;
157         f = &content_features(i);
158         f->setAllTextures("sand.png");
159         f->setInventoryTextureCube("sand.png", "sand.png", "sand.png");
160         f->param_type = CPT_MINERAL;
161         f->is_ground_content = true;
162         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
163         setDirtLikeDiggingProperties(f->digging_properties, 1.0);
164         
165         i = CONTENT_GRAVEL;
166         f = &content_features(i);
167         f->setAllTextures("gravel.png");
168         f->setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png");
169         f->param_type = CPT_MINERAL;
170         f->is_ground_content = true;
171         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
172         setDirtLikeDiggingProperties(f->digging_properties, 1.75);
173         
174         i = CONTENT_SANDSTONE;
175         f = &content_features(i);
176         f->setAllTextures("sandstone.png");
177         f->setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png");
178         f->param_type = CPT_MINERAL;
179         f->is_ground_content = true;
180         f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAND)+" 1";
181         setDirtLikeDiggingProperties(f->digging_properties, 1.0);
182
183         i = CONTENT_CLAY;
184         f = &content_features(i);
185         f->setAllTextures("clay.png");
186         f->setInventoryTextureCube("clay.png", "clay.png", "clay.png");
187         f->param_type = CPT_MINERAL;
188         f->is_ground_content = true;
189         f->dug_item = std::string("CraftItem lump_of_clay 4");
190         setDirtLikeDiggingProperties(f->digging_properties, 1.0);
191
192         i = CONTENT_BRICK;
193         f = &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("CraftItem clay_brick 4");
199         setStoneLikeDiggingProperties(f->digging_properties, 1.0);
200
201         i = CONTENT_TREE;
202         f = &content_features(i);
203         f->setAllTextures("tree.png");
204         f->setTexture(0, "tree_top.png");
205         f->setTexture(1, "tree_top.png");
206         f->param_type = CPT_MINERAL;
207         f->is_ground_content = true;
208         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
209         setWoodLikeDiggingProperties(f->digging_properties, 1.0);
210         
211         i = CONTENT_JUNGLETREE;
212         f = &content_features(i);
213         f->setAllTextures("jungletree.png");
214         f->setTexture(0, "jungletree_top.png");
215         f->setTexture(1, "jungletree_top.png");
216         f->param_type = CPT_MINERAL;
217         //f->is_ground_content = true;
218         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
219         setWoodLikeDiggingProperties(f->digging_properties, 1.0);
220         
221         i = CONTENT_JUNGLEGRASS;
222         f = &content_features(i);
223         f->setInventoryTexture("junglegrass.png");
224         f->used_texturenames["junglegrass.png"] = true;
225         f->light_propagates = true;
226         f->param_type = CPT_LIGHT;
227         //f->is_ground_content = true;
228         f->air_equivalent = false; // grass grows underneath
229         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
230         f->solidness = 0; // drawn separately, makes no faces
231         f->walkable = false;
232         setWoodLikeDiggingProperties(f->digging_properties, 0.10);
233
234         i = CONTENT_LEAVES;
235         f = &content_features(i);
236         f->light_propagates = true;
237         //f->param_type = CPT_MINERAL;
238         f->param_type = CPT_LIGHT;
239         //f->is_ground_content = true;
240         if(new_style_leaves)
241         {
242                 f->solidness = 0; // drawn separately, makes no faces
243                 f->visual_solidness = 1;
244                 f->setAllTextures("leaves.png");
245                 f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
246         }
247         else
248         {
249                 f->setAllTextures("[noalpha:leaves.png");
250         }
251         f->extra_dug_item = std::string("MaterialItem2 ")+itos(CONTENT_SAPLING)+" 1";
252         f->extra_dug_item_rarity = 20;
253         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
254         setWoodLikeDiggingProperties(f->digging_properties, 0.15);
255
256         i = CONTENT_CACTUS;
257         f = &content_features(i);
258         f->setAllTextures("cactus_side.png");
259         f->setTexture(0, "cactus_top.png");
260         f->setTexture(1, "cactus_top.png");
261         f->setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png");
262         f->param_type = CPT_MINERAL;
263         f->is_ground_content = true;
264         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
265         setWoodLikeDiggingProperties(f->digging_properties, 0.75);
266
267         i = CONTENT_PAPYRUS;
268         f = &content_features(i);
269         f->setInventoryTexture("papyrus.png");
270         f->used_texturenames["papyrus.png"] = true;
271         f->light_propagates = true;
272         f->param_type = CPT_LIGHT;
273         f->is_ground_content = true;
274         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
275         f->solidness = 0; // drawn separately, makes no faces
276         f->walkable = false;
277         setWoodLikeDiggingProperties(f->digging_properties, 0.25);
278
279         i = CONTENT_BOOKSHELF;
280         f = &content_features(i);
281         f->setAllTextures("bookshelf.png");
282         f->setTexture(0, "wood.png");
283         f->setTexture(1, "wood.png");
284         // FIXME: setInventoryTextureCube() only cares for the first texture
285         f->setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png");
286         //f->setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png");
287         f->param_type = CPT_MINERAL;
288         f->is_ground_content = true;
289         setWoodLikeDiggingProperties(f->digging_properties, 0.75);
290
291         i = CONTENT_GLASS;
292         f = &content_features(i);
293         f->light_propagates = true;
294         f->sunlight_propagates = true;
295         f->param_type = CPT_LIGHT;
296         f->is_ground_content = true;
297         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
298         f->solidness = 0; // drawn separately, makes no faces
299         f->visual_solidness = 1;
300         f->setAllTextures("glass.png");
301         f->setInventoryTextureCube("glass.png", "glass.png", "glass.png");
302         setWoodLikeDiggingProperties(f->digging_properties, 0.15);
303
304         i = CONTENT_FENCE;
305         f = &content_features(i);
306         f->light_propagates = true;
307         f->param_type = CPT_LIGHT;
308         f->is_ground_content = true;
309         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
310         f->solidness = 0; // drawn separately, makes no faces
311         f->air_equivalent = true; // grass grows underneath
312         f->setInventoryTexture("fence.png");
313         f->used_texturenames["fence.png"] = true;
314         setWoodLikeDiggingProperties(f->digging_properties, 0.75);
315
316         i = CONTENT_RAIL;
317         f = &content_features(i);
318         f->setInventoryTexture("rail.png");
319         f->used_texturenames["rail.png"] = true;
320         f->light_propagates = true;
321         f->param_type = CPT_LIGHT;
322         f->is_ground_content = true;
323         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
324         f->solidness = 0; // drawn separately, makes no faces
325         f->air_equivalent = true; // grass grows underneath
326         f->walkable = false;
327         setDirtLikeDiggingProperties(f->digging_properties, 0.75);
328
329         i = CONTENT_LADDER;
330         f = &content_features(i);
331         f->setInventoryTexture("ladder.png");
332         f->used_texturenames["ladder.png"] = true;
333         f->light_propagates = true;
334         f->param_type = CPT_LIGHT;
335         f->is_ground_content = true;
336         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
337         f->wall_mounted = true;
338         f->solidness = 0;
339         f->air_equivalent = true;
340         f->walkable = false;
341         f->climbable = true;
342         setWoodLikeDiggingProperties(f->digging_properties, 0.5);
343
344         // Deprecated
345         i = CONTENT_COALSTONE;
346         f = &content_features(i);
347         f->setAllTextures("stone.png^mineral_coal.png");
348         f->is_ground_content = true;
349         setStoneLikeDiggingProperties(f->digging_properties, 1.5);
350         
351         i = CONTENT_WOOD;
352         f = &content_features(i);
353         f->setAllTextures("wood.png");
354         f->setInventoryTextureCube("wood.png", "wood.png", "wood.png");
355         f->is_ground_content = true;
356         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
357         setWoodLikeDiggingProperties(f->digging_properties, 0.75);
358         
359         i = CONTENT_MESE;
360         f = &content_features(i);
361         f->setAllTextures("mese.png");
362         f->setInventoryTextureCube("mese.png", "mese.png", "mese.png");
363         f->is_ground_content = true;
364         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
365         setStoneLikeDiggingProperties(f->digging_properties, 0.5);
366         
367         i = CONTENT_CLOUD;
368         f = &content_features(i);
369         f->setAllTextures("cloud.png");
370         f->setInventoryTextureCube("cloud.png", "cloud.png", "cloud.png");
371         f->is_ground_content = true;
372         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
373         
374         i = CONTENT_AIR;
375         f = &content_features(i);
376         f->param_type = CPT_LIGHT;
377         f->light_propagates = true;
378         f->sunlight_propagates = true;
379         f->solidness = 0;
380         f->walkable = false;
381         f->pointable = false;
382         f->diggable = false;
383         f->buildable_to = true;
384         f->air_equivalent = true;
385         
386         i = CONTENT_WATER;
387         f = &content_features(i);
388         f->setInventoryTextureCube("water.png", "water.png", "water.png");
389         f->param_type = CPT_LIGHT;
390         f->light_propagates = true;
391         f->solidness = 0; // Drawn separately, makes no faces
392         f->visual_solidness = 1;
393         f->walkable = false;
394         f->pointable = false;
395         f->diggable = false;
396         f->buildable_to = true;
397         f->liquid_type = LIQUID_FLOWING;
398         f->liquid_alternative_flowing = CONTENT_WATER;
399         f->liquid_alternative_source = CONTENT_WATERSOURCE;
400         f->liquid_viscosity = WATER_VISC;
401 #ifndef SERVER
402         if(!opaque_water)
403                 f->vertex_alpha = WATER_ALPHA;
404         f->post_effect_color = video::SColor(64, 100, 100, 200);
405         if(f->special_material == NULL && g_texturesource)
406         {
407                 // Flowing water material
408                 f->special_material = new video::SMaterial;
409                 f->special_material->setFlag(video::EMF_LIGHTING, false);
410                 f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
411                 f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
412                 f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
413                 if(!opaque_water)
414                         f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
415                 AtlasPointer *pa_water1 = new AtlasPointer(g_texturesource->getTexture(
416                                 g_texturesource->getTextureId("water.png")));
417                 f->special_material->setTexture(0, pa_water1->atlas);
418
419                 // Flowing water material, backface culled
420                 f->special_material2 = new video::SMaterial;
421                 *f->special_material2 = *f->special_material;
422                 f->special_material2->setFlag(video::EMF_BACK_FACE_CULLING, true);
423                 
424                 f->special_atlas = pa_water1;
425         }
426 #endif
427         
428         i = CONTENT_WATERSOURCE;
429         f = &content_features(i);
430         //f->setInventoryTexture("water.png");
431         f->setInventoryTextureCube("water.png", "water.png", "water.png");
432         if(new_style_water)
433         {
434                 f->solidness = 0; // drawn separately, makes no faces
435         }
436         else // old style
437         {
438                 f->solidness = 1;
439 #ifndef SERVER
440                 TileSpec t;
441                 if(g_texturesource)
442                         t.texture = g_texturesource->getTexture("water.png");
443                 
444                 if(!opaque_water){
445                         t.alpha = WATER_ALPHA;
446                         t.material_type = MATERIAL_ALPHA_VERTEX;
447                 }
448                 t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
449                 f->setAllTiles(t);
450 #endif
451         }
452         f->param_type = CPT_LIGHT;
453         f->light_propagates = true;
454         f->walkable = false;
455         f->pointable = false;
456         f->diggable = false;
457         f->buildable_to = true;
458         f->liquid_type = LIQUID_SOURCE;
459         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
460         f->liquid_alternative_flowing = CONTENT_WATER;
461         f->liquid_alternative_source = CONTENT_WATERSOURCE;
462         f->liquid_viscosity = WATER_VISC;
463 #ifndef SERVER
464         if(!opaque_water)
465                 f->vertex_alpha = WATER_ALPHA;
466         f->post_effect_color = video::SColor(64, 100, 100, 200);
467         if(f->special_material == NULL && g_texturesource)
468         {
469                 // New-style water source material (mostly unused)
470                 f->special_material = new video::SMaterial;
471                 f->special_material->setFlag(video::EMF_LIGHTING, false);
472                 f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
473                 f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
474                 f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
475                 f->special_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
476                 AtlasPointer *pa_water1 = new AtlasPointer(g_texturesource->getTexture(
477                                 g_texturesource->getTextureId("water.png")));
478                 f->special_material->setTexture(0, pa_water1->atlas);
479                 f->special_atlas = pa_water1;
480         }
481 #endif
482         
483         i = CONTENT_LAVA;
484         f = &content_features(i);
485         f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
486         f->used_texturenames["lava.png"] = true;
487         f->param_type = CPT_LIGHT;
488         f->light_propagates = false;
489         f->light_source = LIGHT_MAX-1;
490         f->solidness = 0; // Drawn separately, makes no faces
491         f->visual_solidness = 1; // Does not completely cover block boundaries
492         f->walkable = false;
493         f->pointable = false;
494         f->diggable = false;
495         f->buildable_to = true;
496         f->liquid_type = LIQUID_FLOWING;
497         f->liquid_alternative_flowing = CONTENT_LAVA;
498         f->liquid_alternative_source = CONTENT_LAVASOURCE;
499         f->liquid_viscosity = LAVA_VISC;
500         f->damage_per_second = 4*2;
501 #ifndef SERVER
502         f->post_effect_color = video::SColor(192, 255, 64, 0);
503         if(f->special_material == NULL && g_texturesource)
504         {
505                 // Flowing lava material
506                 f->special_material = new video::SMaterial;
507                 f->special_material->setFlag(video::EMF_LIGHTING, false);
508                 f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
509                 f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
510                 f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
511                 f->special_material->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
512
513                 AtlasPointer *pa_lava1 = new AtlasPointer(
514                         g_texturesource->getTexture(
515                                 g_texturesource->getTextureId("lava.png")));
516                 f->special_material->setTexture(0, pa_lava1->atlas);
517
518                 // Flowing lava material, backface culled
519                 f->special_material2 = new video::SMaterial;
520                 *f->special_material2 = *f->special_material;
521                 f->special_material2->setFlag(video::EMF_BACK_FACE_CULLING, true);
522
523                 f->special_atlas = pa_lava1;
524         }
525 #endif
526         
527         i = CONTENT_LAVASOURCE;
528         f = &content_features(i);
529         f->setInventoryTextureCube("lava.png", "lava.png", "lava.png");
530         f->used_texturenames["ladder.png"] = true;
531         if(new_style_water)
532         {
533                 f->solidness = 0; // drawn separately, makes no faces
534         }
535         else // old style
536         {
537                 f->solidness = 2;
538 #ifndef SERVER
539                 TileSpec t;
540                 if(g_texturesource)
541                         t.texture = g_texturesource->getTexture("lava.png");
542                 
543                 //t.alpha = 255;
544                 //t.material_type = MATERIAL_ALPHA_VERTEX;
545                 //t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
546                 f->setAllTiles(t);
547 #endif
548         }
549         f->param_type = CPT_LIGHT;
550         f->light_propagates = false;
551         f->light_source = LIGHT_MAX-1;
552         f->walkable = false;
553         f->pointable = false;
554         f->diggable = false;
555         f->buildable_to = true;
556         f->liquid_type = LIQUID_SOURCE;
557         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
558         f->liquid_alternative_flowing = CONTENT_LAVA;
559         f->liquid_alternative_source = CONTENT_LAVASOURCE;
560         f->liquid_viscosity = LAVA_VISC;
561         f->damage_per_second = 4*2;
562 #ifndef SERVER
563         f->post_effect_color = video::SColor(192, 255, 64, 0);
564         if(f->special_material == NULL && g_texturesource)
565         {
566                 // New-style lava source material (mostly unused)
567                 f->special_material = new video::SMaterial;
568                 f->special_material->setFlag(video::EMF_LIGHTING, false);
569                 f->special_material->setFlag(video::EMF_BACK_FACE_CULLING, false);
570                 f->special_material->setFlag(video::EMF_BILINEAR_FILTER, false);
571                 f->special_material->setFlag(video::EMF_FOG_ENABLE, true);
572                 f->special_material->MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
573                 AtlasPointer *pa_lava1 = new AtlasPointer(
574                         g_texturesource->getTexture(
575                                 g_texturesource->getTextureId("lava.png")));
576                 f->special_material->setTexture(0, pa_lava1->atlas);
577
578                 f->special_atlas = pa_lava1;
579         }
580 #endif
581         
582         i = CONTENT_TORCH;
583         f = &content_features(i);
584         f->setInventoryTexture("torch_on_floor.png");
585         f->used_texturenames["torch_on_floor.png"] = true;
586         f->used_texturenames["torch_on_ceiling.png"] = true;
587         f->used_texturenames["torch_on_floor.png"] = true;
588         f->used_texturenames["torch.png"] = true;
589         f->param_type = CPT_LIGHT;
590         f->light_propagates = true;
591         f->sunlight_propagates = true;
592         f->solidness = 0; // drawn separately, makes no faces
593         f->walkable = false;
594         f->wall_mounted = true;
595         f->air_equivalent = true;
596         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
597         f->light_source = LIGHT_MAX-1;
598         f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
599         
600         i = CONTENT_SIGN_WALL;
601         f = &content_features(i);
602         f->setInventoryTexture("sign_wall.png");
603         f->used_texturenames["sign_wall.png"] = true;
604         f->param_type = CPT_LIGHT;
605         f->light_propagates = true;
606         f->sunlight_propagates = true;
607         f->solidness = 0; // drawn separately, makes no faces
608         f->walkable = false;
609         f->wall_mounted = true;
610         f->air_equivalent = true;
611         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
612         if(f->initial_metadata == NULL)
613                 f->initial_metadata = new SignNodeMetadata("Some sign");
614         f->digging_properties.set("", DiggingProperties(true, 0.5, 0));
615         
616         i = CONTENT_CHEST;
617         f = &content_features(i);
618         f->param_type = CPT_FACEDIR_SIMPLE;
619         f->setAllTextures("chest_side.png");
620         f->setTexture(0, "chest_top.png");
621         f->setTexture(1, "chest_top.png");
622         f->setTexture(5, "chest_front.png"); // Z-
623         f->setInventoryTexture("chest_top.png");
624         //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
625         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
626         if(f->initial_metadata == NULL)
627                 f->initial_metadata = new ChestNodeMetadata();
628         setWoodLikeDiggingProperties(f->digging_properties, 1.0);
629         
630         i = CONTENT_LOCKABLE_CHEST;
631         f = &content_features(i);
632         f->param_type = CPT_FACEDIR_SIMPLE;
633         f->setAllTextures("chest_side.png");
634         f->setTexture(0, "chest_top.png");
635         f->setTexture(1, "chest_top.png");
636         f->setTexture(5, "chest_lock.png"); // Z-
637         f->setInventoryTexture("chest_lock.png");
638         //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
639         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
640         if(f->initial_metadata == NULL)
641                 f->initial_metadata = new LockingChestNodeMetadata();
642         setWoodLikeDiggingProperties(f->digging_properties, 1.0);
643
644         i = CONTENT_FURNACE;
645         f = &content_features(i);
646         f->param_type = CPT_FACEDIR_SIMPLE;
647         f->setAllTextures("furnace_side.png");
648         f->setTexture(5, "furnace_front.png"); // Z-
649         f->setInventoryTexture("furnace_front.png");
650         //f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
651         f->dug_item = std::string("MaterialItem2 ")+itos(CONTENT_COBBLE)+" 6";
652         if(f->initial_metadata == NULL)
653                 f->initial_metadata = new FurnaceNodeMetadata();
654         setStoneLikeDiggingProperties(f->digging_properties, 3.0);
655         
656         i = CONTENT_COBBLE;
657         f = &content_features(i);
658         f->setAllTextures("cobble.png");
659         f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png");
660         f->param_type = CPT_NONE;
661         f->is_ground_content = true;
662         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
663         setStoneLikeDiggingProperties(f->digging_properties, 0.9);
664
665         i = CONTENT_MOSSYCOBBLE;
666         f = &content_features(i);
667         f->setAllTextures("mossycobble.png");
668         f->setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png");
669         f->param_type = CPT_NONE;
670         f->is_ground_content = true;
671         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
672         setStoneLikeDiggingProperties(f->digging_properties, 0.8);
673         
674         i = CONTENT_STEEL;
675         f = &content_features(i);
676         f->setAllTextures("steel_block.png");
677         f->setInventoryTextureCube("steel_block.png", "steel_block.png",
678                         "steel_block.png");
679         f->param_type = CPT_NONE;
680         f->is_ground_content = true;
681         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
682         setStoneLikeDiggingProperties(f->digging_properties, 5.0);
683         
684         i = CONTENT_NC;
685         f = &content_features(i);
686         f->param_type = CPT_FACEDIR_SIMPLE;
687         f->setAllTextures("nc_side.png");
688         f->setTexture(5, "nc_front.png"); // Z-
689         f->setTexture(4, "nc_back.png"); // Z+
690         f->setInventoryTexture("nc_front.png");
691         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
692         setStoneLikeDiggingProperties(f->digging_properties, 3.0);
693         
694         i = CONTENT_NC_RB;
695         f = &content_features(i);
696         f->setAllTextures("nc_rb.png");
697         f->setInventoryTexture("nc_rb.png");
698         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
699         setStoneLikeDiggingProperties(f->digging_properties, 3.0);
700
701         i = CONTENT_SAPLING;
702         f = &content_features(i);
703         f->param_type = CPT_LIGHT;
704         f->setAllTextures("sapling.png");
705         f->setInventoryTexture("sapling.png");
706         f->used_texturenames["sapling.png"] = true;
707         f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
708         f->light_propagates = true;
709         f->air_equivalent = false;
710         f->solidness = 0; // drawn separately, makes no faces
711         f->walkable = false;
712         f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
713         
714         i = CONTENT_APPLE;
715         f = &content_features(i);
716         f->setInventoryTexture("apple.png");
717         f->used_texturenames["apple.png"] = true;
718         f->param_type = CPT_LIGHT;
719         f->light_propagates = true;
720         f->sunlight_propagates = true;
721         f->solidness = 0; // drawn separately, makes no faces
722         f->walkable = false;
723         f->air_equivalent = true;
724         f->dug_item = std::string("CraftItem apple 1");
725         f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
726         
727         // NOTE: Remember to add frequently used stuff to the texture atlas in tile.cpp
728         
729
730         /*
731                 Add MesePick to everything
732         */
733         for(u16 i=0; i<=MAX_CONTENT; i++)
734         {
735                 content_features(i).digging_properties.set("MesePick",
736                                 DiggingProperties(true, 0.0, 65535./1337));
737         }
738
739 }
740
741 void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
742 {
743         list.set("",
744                         DiggingProperties(true, 15.0*toughness, 0));
745         
746         list.set("WPick",
747                         DiggingProperties(true, 1.3*toughness, 65535./30.*toughness));
748         list.set("STPick",
749                         DiggingProperties(true, 0.75*toughness, 65535./100.*toughness));
750         list.set("SteelPick",
751                         DiggingProperties(true, 0.50*toughness, 65535./333.*toughness));
752
753         /*list.set("MesePick",
754                         DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/
755 }
756
757 void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
758 {
759         list.set("",
760                         DiggingProperties(true, 0.75*toughness, 0));
761         
762         list.set("WShovel",
763                         DiggingProperties(true, 0.4*toughness, 65535./50.*toughness));
764         list.set("STShovel",
765                         DiggingProperties(true, 0.2*toughness, 65535./150.*toughness));
766         list.set("SteelShovel",
767                         DiggingProperties(true, 0.15*toughness, 65535./400.*toughness));
768 }
769
770 void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
771 {
772         list.set("",
773                         DiggingProperties(true, 3.0*toughness, 0));
774         
775         list.set("WAxe",
776                         DiggingProperties(true, 1.5*toughness, 65535./30.*toughness));
777         list.set("STAxe",
778                         DiggingProperties(true, 0.75*toughness, 65535./100.*toughness));
779         list.set("SteelAxe",
780                         DiggingProperties(true, 0.5*toughness, 65535./333.*toughness));
781 }
782
783