a8c951ab3414c75a6e00dceb669ffbda3744472d
[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
29 ContentFeatures::~ContentFeatures()
30 {
31         if(translate_to)
32                 delete translate_to;
33 }
34
35 void ContentFeatures::setTexture(u16 i, std::string name, u8 alpha)
36 {
37         if(g_texturesource)
38         {
39                 tiles[i].texture = g_texturesource->getTexture(name);
40         }
41         
42         if(alpha != 255)
43         {
44                 tiles[i].alpha = alpha;
45                 tiles[i].material_type = MATERIAL_ALPHA_VERTEX;
46         }
47
48         if(inventory_texture == NULL)
49                 setInventoryTexture(name);
50 }
51
52 void ContentFeatures::setInventoryTexture(std::string imgname)
53 {
54         if(g_texturesource == NULL)
55                 return;
56         
57         imgname += "^[forcesingle";
58         
59         inventory_texture = g_texturesource->getTextureRaw(imgname);
60 }
61
62 void ContentFeatures::setInventoryTextureCube(std::string top,
63                 std::string left, std::string right)
64 {
65         if(g_texturesource == NULL)
66                 return;
67         
68         str_replace_char(top, '^', '&');
69         str_replace_char(left, '^', '&');
70         str_replace_char(right, '^', '&');
71
72         std::string imgname_full;
73         imgname_full += "[inventorycube{";
74         imgname_full += top;
75         imgname_full += "{";
76         imgname_full += left;
77         imgname_full += "{";
78         imgname_full += right;
79         inventory_texture = g_texturesource->getTextureRaw(imgname_full);
80 }
81
82 struct ContentFeatures g_content_features[256];
83
84 ContentFeatures & content_features(u8 i)
85 {
86         return g_content_features[i];
87 }
88
89 /*
90         See mapnode.h for description.
91 */
92 void init_mapnode()
93 {
94         if(g_texturesource == NULL)
95         {
96                 dstream<<"INFO: Initial run of init_mapnode with "
97                                 "g_texturesource=NULL. If this segfaults, "
98                                 "there is a bug with something not checking for "
99                                 "the NULL value."<<std::endl;
100         }
101         else
102         {
103                 dstream<<"INFO: Full run of init_mapnode with "
104                                 "g_texturesource!=NULL"<<std::endl;
105         }
106
107         // Read some settings
108         bool new_style_water = g_settings.getBool("new_style_water");
109         bool new_style_leaves = g_settings.getBool("new_style_leaves");
110
111         /*
112                 Initialize content feature table
113         */
114         
115         /*
116                 Set initial material type to same in all tiles, so that the
117                 same material can be used in more stuff.
118                 This is set according to the leaves because they are the only
119                 differing material to which all materials can be changed to
120                 get this optimization.
121         */
122         u8 initial_material_type = MATERIAL_ALPHA_SIMPLE;
123         /*if(new_style_leaves)
124                 initial_material_type = MATERIAL_ALPHA_SIMPLE;
125         else
126                 initial_material_type = MATERIAL_ALPHA_NONE;*/
127         for(u16 i=0; i<256; i++)
128         {
129                 ContentFeatures *f = &g_content_features[i];
130                 for(u16 j=0; j<6; j++)
131                         f->tiles[j].material_type = initial_material_type;
132         }
133         
134         u8 i;
135         ContentFeatures *f = NULL;
136
137         i = CONTENT_STONE;
138         f = &g_content_features[i];
139         f->setAllTextures("stone.png");
140         f->setInventoryTextureCube("stone.png", "stone.png", "stone.png");
141         f->param_type = CPT_MINERAL;
142         f->is_ground_content = true;
143         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
144         
145         i = CONTENT_GRASS;
146         f = &g_content_features[i];
147         f->setAllTextures("mud.png^grass_side.png");
148         f->setTexture(0, "grass.png");
149         f->setTexture(1, "mud.png");
150         f->param_type = CPT_MINERAL;
151         f->is_ground_content = true;
152         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
153         
154         i = CONTENT_GRASS_FOOTSTEPS;
155         f = &g_content_features[i];
156         f->setAllTextures("mud.png^grass_side.png");
157         f->setTexture(0, "grass_footsteps.png");
158         f->setTexture(1, "mud.png");
159         f->param_type = CPT_MINERAL;
160         f->is_ground_content = true;
161         f->dug_item = std::string("MaterialItem ")+itos(CONTENT_MUD)+" 1";
162         
163         i = CONTENT_MUD;
164         f = &g_content_features[i];
165         f->setAllTextures("mud.png");
166         f->setInventoryTextureCube("mud.png", "mud.png", "mud.png");
167         f->param_type = CPT_MINERAL;
168         f->is_ground_content = true;
169         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
170         
171         i = CONTENT_SAND;
172         f = &g_content_features[i];
173         f->setAllTextures("sand.png");
174         f->param_type = CPT_MINERAL;
175         f->is_ground_content = true;
176         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
177         
178         i = CONTENT_TREE;
179         f = &g_content_features[i];
180         f->setAllTextures("tree.png");
181         f->setTexture(0, "tree_top.png");
182         f->setTexture(1, "tree_top.png");
183         f->param_type = CPT_MINERAL;
184         f->is_ground_content = true;
185         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
186         
187         i = CONTENT_LEAVES;
188         f = &g_content_features[i];
189         f->light_propagates = true;
190         //f->param_type = CPT_MINERAL;
191         f->param_type = CPT_LIGHT;
192         f->is_ground_content = true;
193         if(new_style_leaves)
194         {
195                 f->solidness = 0; // drawn separately, makes no faces
196                 f->setInventoryTextureCube("leaves.png", "leaves.png", "leaves.png");
197         }
198         else
199         {
200                 f->setAllTextures("[noalpha:leaves.png");
201         }
202         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
203         
204         // Deprecated
205         i = CONTENT_COALSTONE;
206         f = &g_content_features[i];
207         //f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
208         f->setAllTextures("stone.png^mineral_coal.png");
209         f->is_ground_content = true;
210         
211         i = CONTENT_WOOD;
212         f = &g_content_features[i];
213         f->setAllTextures("wood.png");
214         f->is_ground_content = true;
215         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
216         
217         i = CONTENT_MESE;
218         f = &g_content_features[i];
219         f->setAllTextures("mese.png");
220         f->is_ground_content = true;
221         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
222         
223         i = CONTENT_CLOUD;
224         f = &g_content_features[i];
225         f->setAllTextures("cloud.png");
226         f->is_ground_content = true;
227         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
228         
229         i = CONTENT_AIR;
230         f = &g_content_features[i];
231         f->param_type = CPT_LIGHT;
232         f->light_propagates = true;
233         f->sunlight_propagates = true;
234         f->solidness = 0;
235         f->walkable = false;
236         f->pointable = false;
237         f->diggable = false;
238         f->buildable_to = true;
239         
240         i = CONTENT_WATER;
241         f = &g_content_features[i];
242         f->setInventoryTextureCube("water.png", "water.png", "water.png");
243         f->param_type = CPT_LIGHT;
244         f->light_propagates = true;
245         f->solidness = 0; // Drawn separately, makes no faces
246         f->walkable = false;
247         f->pointable = false;
248         f->diggable = false;
249         f->buildable_to = true;
250         f->liquid_type = LIQUID_FLOWING;
251         
252         i = CONTENT_WATERSOURCE;
253         f = &g_content_features[i];
254         f->setInventoryTexture("water.png");
255         if(new_style_water)
256         {
257                 f->solidness = 0; // drawn separately, makes no faces
258         }
259         else // old style
260         {
261                 f->solidness = 1;
262
263                 TileSpec t;
264                 if(g_texturesource)
265                         t.texture = g_texturesource->getTexture("water.png");
266                 
267                 t.alpha = WATER_ALPHA;
268                 t.material_type = MATERIAL_ALPHA_VERTEX;
269                 t.material_flags &= ~MATERIAL_FLAG_BACKFACE_CULLING;
270                 f->setAllTiles(t);
271         }
272         f->param_type = CPT_LIGHT;
273         f->light_propagates = true;
274         f->walkable = false;
275         f->pointable = false;
276         f->diggable = false;
277         f->buildable_to = true;
278         f->liquid_type = LIQUID_SOURCE;
279         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
280         
281         i = CONTENT_TORCH;
282         f = &g_content_features[i];
283         f->setInventoryTexture("torch_on_floor.png");
284         f->param_type = CPT_LIGHT;
285         f->light_propagates = true;
286         f->solidness = 0; // drawn separately, makes no faces
287         f->walkable = false;
288         f->wall_mounted = true;
289         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
290         
291         i = CONTENT_FURNACE;
292         f = &g_content_features[i];
293         f->setAllTextures("furnace_side.png");
294         f->setTexture(2, "furnace_front.png");
295         f->setInventoryTexture("furnace_front.png");
296         f->param_type = CPT_NONE;
297         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
298         
299         i = CONTENT_SIGN_WALL;
300         f = &g_content_features[i];
301         f->setInventoryTexture("sign_wall.png");
302         f->param_type = CPT_LIGHT;
303         f->light_propagates = true;
304         f->sunlight_propagates = true;
305         f->solidness = 0; // drawn separately, makes no faces
306         f->walkable = false;
307         f->wall_mounted = true;
308         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
309         
310 }
311
312 TileSpec MapNode::getTile(v3s16 dir)
313 {
314         TileSpec spec;
315         
316         s32 dir_i = -1;
317         
318         if(dir == v3s16(0,0,0))
319                 dir_i = -1;
320         else if(dir == v3s16(0,1,0))
321                 dir_i = 0;
322         else if(dir == v3s16(0,-1,0))
323                 dir_i = 1;
324         else if(dir == v3s16(1,0,0))
325                 dir_i = 2;
326         else if(dir == v3s16(-1,0,0))
327                 dir_i = 3;
328         else if(dir == v3s16(0,0,1))
329                 dir_i = 4;
330         else if(dir == v3s16(0,0,-1))
331                 dir_i = 5;
332         
333         if(dir_i == -1)
334                 // Non-directional
335                 spec = content_features(d).tiles[0];
336         else 
337                 spec = content_features(d).tiles[dir_i];
338         
339         /*
340                 If it contains some mineral, change texture id
341         */
342         if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
343         {
344                 u8 mineral = param & 0x1f;
345                 std::string mineral_texture_name = mineral_block_texture(mineral);
346                 if(mineral_texture_name != "")
347                 {
348                         u32 orig_id = spec.texture.id;
349                         std::string texture_name = g_texturesource->getTextureName(orig_id);
350                         //texture_name += "^blit:";
351                         texture_name += "^";
352                         texture_name += mineral_texture_name;
353                         u32 new_id = g_texturesource->getTextureId(texture_name);
354                         spec.texture = g_texturesource->getTexture(new_id);
355                 }
356         }
357
358         return spec;
359 }
360
361 u8 MapNode::getMineral()
362 {
363         if(content_features(d).param_type == CPT_MINERAL)
364         {
365                 return param & 0x1f;
366         }
367
368         return MINERAL_NONE;
369 }
370
371 // Pointers to c_str()s g_content_features[i].inventory_image_path
372 //const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
373
374 void init_content_inventory_texture_paths()
375 {
376         dstream<<"DEPRECATED "<<__FUNCTION_NAME<<std::endl;
377         /*for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
378         {
379                 g_content_inventory_texture_paths[i] =
380                                 g_content_features[i].inventory_image_path.c_str();
381         }*/
382 }
383