f498d9e75548a7b5a59b36db843948db9c160e31
[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_SIGN_WALL;
292         f = &g_content_features[i];
293         f->setInventoryTexture("sign_wall.png");
294         f->param_type = CPT_LIGHT;
295         f->light_propagates = true;
296         f->sunlight_propagates = true;
297         f->solidness = 0; // drawn separately, makes no faces
298         f->walkable = false;
299         f->wall_mounted = true;
300         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
301         if(f->initial_metadata == NULL)
302                 f->initial_metadata = new SignNodeMetadata("Some sign");
303         
304         i = CONTENT_CHEST;
305         f = &g_content_features[i];
306         f->param_type = CPT_FACEDIR_SIMPLE;
307         f->setAllTextures("chest_side.png");
308         f->setTexture(0, "chest_top.png");
309         f->setTexture(1, "chest_top.png");
310         f->setTexture(5, "chest_front.png"); // Z-
311         f->setInventoryTexture("chest_top.png");
312         //f->setInventoryTextureCube("chest_top.png", "chest_side.png", "chest_side.png");
313         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
314         if(f->initial_metadata == NULL)
315                 f->initial_metadata = new ChestNodeMetadata();
316         
317         i = CONTENT_FURNACE;
318         f = &g_content_features[i];
319         f->param_type = CPT_FACEDIR_SIMPLE;
320         f->setAllTextures("furnace_side.png");
321         f->setTexture(5, "furnace_front.png"); // Z-
322         f->setInventoryTexture("furnace_front.png");
323         f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
324         
325 }
326
327 v3s16 facedir_rotate(u8 facedir, v3s16 dir)
328 {
329         /*
330                 Face 2 (normally Z-) direction:
331                 facedir=0: Z-
332                 facedir=1: X-
333                 facedir=2: Z+
334                 facedir=3: X+
335         */
336         v3s16 newdir;
337         if(facedir==0) // Same
338                 newdir = v3s16(dir.X, dir.Y, dir.Z);
339         else if(facedir == 1) // Face is taken from rotXZccv(-90)
340                 newdir = v3s16(-dir.Z, dir.Y, dir.X);
341         else if(facedir == 2) // Face is taken from rotXZccv(180)
342                 newdir = v3s16(-dir.X, dir.Y, -dir.Z);
343         else if(facedir == 3) // Face is taken from rotXZccv(90)
344                 newdir = v3s16(dir.Z, dir.Y, -dir.X);
345         else
346                 newdir = dir;
347         return newdir;
348 }
349
350 TileSpec MapNode::getTile(v3s16 dir)
351 {
352         if(content_features(d).param_type == CPT_FACEDIR_SIMPLE)
353                 dir = facedir_rotate(param1, dir);
354         
355         TileSpec spec;
356         
357         s32 dir_i = -1;
358         
359         if(dir == v3s16(0,0,0))
360                 dir_i = -1;
361         else if(dir == v3s16(0,1,0))
362                 dir_i = 0;
363         else if(dir == v3s16(0,-1,0))
364                 dir_i = 1;
365         else if(dir == v3s16(1,0,0))
366                 dir_i = 2;
367         else if(dir == v3s16(-1,0,0))
368                 dir_i = 3;
369         else if(dir == v3s16(0,0,1))
370                 dir_i = 4;
371         else if(dir == v3s16(0,0,-1))
372                 dir_i = 5;
373         
374         if(dir_i == -1)
375                 // Non-directional
376                 spec = content_features(d).tiles[0];
377         else 
378                 spec = content_features(d).tiles[dir_i];
379         
380         /*
381                 If it contains some mineral, change texture id
382         */
383         if(content_features(d).param_type == CPT_MINERAL && g_texturesource)
384         {
385                 u8 mineral = param & 0x1f;
386                 std::string mineral_texture_name = mineral_block_texture(mineral);
387                 if(mineral_texture_name != "")
388                 {
389                         u32 orig_id = spec.texture.id;
390                         std::string texture_name = g_texturesource->getTextureName(orig_id);
391                         //texture_name += "^blit:";
392                         texture_name += "^";
393                         texture_name += mineral_texture_name;
394                         u32 new_id = g_texturesource->getTextureId(texture_name);
395                         spec.texture = g_texturesource->getTexture(new_id);
396                 }
397         }
398
399         return spec;
400 }
401
402 u8 MapNode::getMineral()
403 {
404         if(content_features(d).param_type == CPT_MINERAL)
405         {
406                 return param & 0x1f;
407         }
408
409         return MINERAL_NONE;
410 }
411
412 // Pointers to c_str()s g_content_features[i].inventory_image_path
413 //const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
414
415 void init_content_inventory_texture_paths()
416 {
417         dstream<<"DEPRECATED "<<__FUNCTION_NAME<<std::endl;
418         /*for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
419         {
420                 g_content_inventory_texture_paths[i] =
421                                 g_content_features[i].inventory_image_path.c_str();
422         }*/
423 }
424