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