merged password change menu
[oweals/minetest.git] / src / mapnode.h
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 #ifndef MAPNODE_HEADER
21 #define MAPNODE_HEADER
22
23 #include <iostream>
24 #include "common_irrlicht.h"
25 #include "light.h"
26 #include "utility.h"
27 #include "exceptions.h"
28 #include "serialization.h"
29 #include "tile.h"
30
31 /*
32         Initializes all kind of stuff in here.
33         Many things depend on this.
34
35         This accesses g_texturesource; if it is non-NULL, textures are set.
36
37         Client first calls this with g_texturesource=NULL to run some
38         unit tests and stuff, then it runs this again with g_texturesource
39         defined to get the textures.
40
41         Server only calls this once with g_texturesource=NULL.
42 */
43 void init_mapnode();
44
45 // Initializes g_content_inventory_texture_paths
46 void init_content_inventory_texture_paths();
47
48
49 // NOTE: This is not used appropriately everywhere.
50 #define MATERIALS_COUNT 256
51
52 /*
53         Ignored node.
54
55         Anything that stores MapNodes doesn't have to preserve parameters
56         associated with this material.
57         
58         Doesn't create faces with anything and is considered being
59         out-of-map in the game map.
60 */
61 #define CONTENT_IGNORE 255
62 #define CONTENT_IGNORE_DEFAULT_PARAM 0
63
64 /*
65         The common material through which the player can walk and which
66         is transparent to light
67 */
68 #define CONTENT_AIR 254
69
70 /*
71         Suggested materials:
72         - Gravel
73         - Sand
74         
75         New naming scheme:
76         - Material = irrlicht's Material class
77         - Content = (u8) content of a node
78         - Tile = (u16) Material ID at some side of a node
79 */
80
81 #define CONTENT_STONE 0
82 #define CONTENT_GRASS 1
83 #define CONTENT_WATER 2
84 #define CONTENT_TORCH 3
85 #define CONTENT_TREE 4
86 #define CONTENT_LEAVES 5
87 #define CONTENT_GRASS_FOOTSTEPS 6
88 #define CONTENT_MESE 7
89 #define CONTENT_MUD 8
90 #define CONTENT_WATERSOURCE 9
91 // Pretty much useless, clouds won't be drawn this way
92 #define CONTENT_CLOUD 10
93 #define CONTENT_COALSTONE 11
94 #define CONTENT_WOOD 12
95 #define CONTENT_SAND 13
96 #define CONTENT_SIGN_WALL 14
97 #define CONTENT_CHEST 15
98 #define CONTENT_FURNACE 16
99 //#define CONTENT_WORKBENCH 17
100 #define CONTENT_COBBLE 18
101 #define CONTENT_STEEL 19
102 #define CONTENT_GLASS 20
103
104 /*
105         Content feature list
106 */
107
108 enum ContentParamType
109 {
110         CPT_NONE,
111         CPT_LIGHT,
112         CPT_MINERAL,
113         // Direction for chests and furnaces and such
114         CPT_FACEDIR_SIMPLE
115 };
116
117 enum LiquidType
118 {
119         LIQUID_NONE,
120         LIQUID_FLOWING,
121         LIQUID_SOURCE
122 };
123
124 class MapNode;
125 class NodeMetadata;
126
127 struct ContentFeatures
128 {
129         // If non-NULL, content is translated to this when deserialized
130         MapNode *translate_to;
131
132         // Type of MapNode::param
133         ContentParamType param_type;
134
135         /*
136                 0: up
137                 1: down
138                 2: right
139                 3: left
140                 4: back
141                 5: front
142         */
143         TileSpec tiles[6];
144         
145         video::ITexture *inventory_texture;
146
147         bool is_ground_content;
148         bool light_propagates;
149         bool sunlight_propagates;
150         u8 solidness; // Used when choosing which face is drawn
151         // This is used for collision detection.
152         // Also for general solidness queries.
153         bool walkable;
154         // Player can point to these
155         bool pointable;
156         // Player can dig these
157         bool diggable;
158         // Player can build on these
159         bool buildable_to;
160         // Whether the node has no liquid, source liquid or flowing liquid
161         enum LiquidType liquid_type;
162         // If true, param2 is set to direction when placed. Used for torches.
163         // NOTE: the direction format is quite inefficient and should be changed
164         bool wall_mounted;
165         // If true, node is equivalent to air. Torches are, air is. Water is not.
166         // Is used for example to check whether a mud block can have grass on.
167         bool air_equivalent;
168         
169         // Inventory item string as which the node appears in inventory when dug.
170         // Mineral overrides this.
171         std::string dug_item;
172         
173         // Initial metadata is cloned from this
174         NodeMetadata *initial_metadata;
175
176         //TODO: Move more properties here
177
178         ContentFeatures()
179         {
180                 translate_to = NULL;
181                 param_type = CPT_NONE;
182                 inventory_texture = NULL;
183                 is_ground_content = false;
184                 light_propagates = false;
185                 sunlight_propagates = false;
186                 solidness = 2;
187                 walkable = true;
188                 pointable = true;
189                 diggable = true;
190                 buildable_to = false;
191                 liquid_type = LIQUID_NONE;
192                 wall_mounted = false;
193                 air_equivalent = false;
194                 dug_item = "";
195                 initial_metadata = NULL;
196         }
197
198         ~ContentFeatures();
199         
200         /*
201                 Quickhands for simple materials
202         */
203         
204         void setTexture(u16 i, std::string name, u8 alpha=255);
205
206         void setAllTextures(std::string name, u8 alpha=255)
207         {
208                 for(u16 i=0; i<6; i++)
209                 {
210                         setTexture(i, name, alpha);
211                 }
212         }
213
214         void setTile(u16 i, const TileSpec &tile)
215         {
216                 tiles[i] = tile;
217         }
218         void setAllTiles(const TileSpec &tile)
219         {
220                 for(u16 i=0; i<6; i++)
221                 {
222                         setTile(i, tile);
223                 }
224         }
225
226         void setInventoryTexture(std::string imgname);
227         
228         void setInventoryTextureCube(std::string top,
229                         std::string left, std::string right);
230 };
231
232 /*
233         Call this to access the ContentFeature list
234 */
235 ContentFeatures & content_features(u8 i);
236
237 /*
238         If true, the material allows light propagation and brightness is stored
239         in param.
240         NOTE: Don't use, use "content_features(m).whatever" instead
241 */
242 inline bool light_propagates_content(u8 m)
243 {
244         return content_features(m).light_propagates;
245         //return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
246 }
247
248 /*
249         If true, the material allows lossless sunlight propagation.
250         NOTE: It doesn't seem to go through torches regardlessly of this
251         NOTE: Don't use, use "content_features(m).whatever" instead
252 */
253 inline bool sunlight_propagates_content(u8 m)
254 {
255         return content_features(m).sunlight_propagates;
256         //return (m == CONTENT_AIR || m == CONTENT_TORCH);
257 }
258
259 /*
260         On a node-node surface, the material of the node with higher solidness
261         is used for drawing.
262         0: Invisible
263         1: Transparent
264         2: Opaque
265         NOTE: Don't use, use "content_features(m).whatever" instead
266 */
267 inline u8 content_solidness(u8 m)
268 {
269         return content_features(m).solidness;
270         /*// As of now, every pseudo node like torches are added to this
271         if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER)
272                 return 0;
273         if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
274                 return 1;
275         return 2;*/
276 }
277
278 // Objects collide with walkable contents
279 // NOTE: Don't use, use "content_features(m).whatever" instead
280 inline bool content_walkable(u8 m)
281 {
282         return content_features(m).walkable;
283         //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH);
284 }
285
286 // NOTE: Don't use, use "content_features(m).whatever" instead
287 inline bool content_liquid(u8 m)
288 {
289         return content_features(m).liquid_type != LIQUID_NONE;
290         //return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
291 }
292
293 // NOTE: Don't use, use "content_features(m).whatever" instead
294 inline bool content_flowing_liquid(u8 m)
295 {
296         return content_features(m).liquid_type == LIQUID_FLOWING;
297         //return (m == CONTENT_WATER);
298 }
299
300 // NOTE: Don't use, use "content_features(m).whatever" instead
301 inline bool content_liquid_source(u8 m)
302 {
303         return content_features(m).liquid_type == LIQUID_SOURCE;
304         //return (m == CONTENT_WATERSOURCE);
305 }
306
307 // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
308 // CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
309 inline u8 make_liquid_flowing(u8 m)
310 {
311         if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
312                 return CONTENT_WATER;
313         assert(0);
314 }
315
316 // Pointable contents can be pointed to in the map
317 // NOTE: Don't use, use "content_features(m).whatever" instead
318 inline bool content_pointable(u8 m)
319 {
320         return content_features(m).pointable;
321         //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
322 }
323
324 // NOTE: Don't use, use "content_features(m).whatever" instead
325 inline bool content_diggable(u8 m)
326 {
327         return content_features(m).diggable;
328         //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
329 }
330
331 // NOTE: Don't use, use "content_features(m).whatever" instead
332 inline bool content_buildable_to(u8 m)
333 {
334         return content_features(m).buildable_to;
335         //return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
336 }
337
338 /*
339         Returns true for contents that form the base ground that
340         follows the main heightmap
341 */
342 /*inline bool is_ground_content(u8 m)
343 {
344         return content_features(m).is_ground_content;
345 }*/
346
347 /*
348         Nodes make a face if contents differ and solidness differs.
349         Return value:
350                 0: No face
351                 1: Face uses m1's content
352                 2: Face uses m2's content
353 */
354 inline u8 face_contents(u8 m1, u8 m2)
355 {
356         if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
357                 return 0;
358         
359         bool contents_differ = (m1 != m2);
360         
361         // Contents don't differ for different forms of same liquid
362         if(content_liquid(m1) && content_liquid(m2)
363                         && make_liquid_flowing(m1) == make_liquid_flowing(m2))
364                 contents_differ = false;
365         
366         bool solidness_differs = (content_solidness(m1) != content_solidness(m2));
367         bool makes_face = contents_differ && solidness_differs;
368
369         if(makes_face == false)
370                 return 0;
371
372         if(content_solidness(m1) > content_solidness(m2))
373                 return 1;
374         else
375                 return 2;
376 }
377
378 /*
379         Packs directions like (1,0,0), (1,-1,0)
380 */
381 inline u8 packDir(v3s16 dir)
382 {
383         u8 b = 0;
384
385         if(dir.X > 0)
386                 b |= (1<<0);
387         else if(dir.X < 0)
388                 b |= (1<<1);
389
390         if(dir.Y > 0)
391                 b |= (1<<2);
392         else if(dir.Y < 0)
393                 b |= (1<<3);
394
395         if(dir.Z > 0)
396                 b |= (1<<4);
397         else if(dir.Z < 0)
398                 b |= (1<<5);
399         
400         return b;
401 }
402 inline v3s16 unpackDir(u8 b)
403 {
404         v3s16 d(0,0,0);
405
406         if(b & (1<<0))
407                 d.X = 1;
408         else if(b & (1<<1))
409                 d.X = -1;
410
411         if(b & (1<<2))
412                 d.Y = 1;
413         else if(b & (1<<3))
414                 d.Y = -1;
415
416         if(b & (1<<4))
417                 d.Z = 1;
418         else if(b & (1<<5))
419                 d.Z = -1;
420         
421         return d;
422 }
423
424 /*
425         facedir: CPT_FACEDIR_SIMPLE param1 value
426         dir: The face for which stuff is wanted
427         return value: The face from which the stuff is actually found
428 */
429 v3s16 facedir_rotate(u8 facedir, v3s16 dir);
430
431 enum LightBank
432 {
433         LIGHTBANK_DAY,
434         LIGHTBANK_NIGHT
435 };
436
437 /*
438         This is the stuff what the whole world consists of.
439 */
440
441 struct MapNode
442 {
443         // Content
444         u8 d;
445
446         /*
447                 Misc parameter. Initialized to 0.
448                 - For light_propagates() blocks, this is light intensity,
449                   stored logarithmically from 0 to LIGHT_MAX.
450                   Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
451                 - Contains 2 values, day- and night lighting. Each takes 4 bits.
452         */
453         union
454         {
455                 s8 param;
456                 u8 param1;
457         };
458         
459         /*
460                 The second parameter. Initialized to 0.
461                 E.g. direction for torches and flowing water.
462         */
463         union
464         {
465                 u8 param2;
466                 u8 dir;
467         };
468
469         MapNode(const MapNode & n)
470         {
471                 *this = n;
472         }
473         
474         MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_param2=0)
475         {
476                 d = data;
477                 param = a_param;
478                 param2 = a_param2;
479         }
480
481         /*MapNode & operator=(const MapNode &other)
482         {
483                 d = other.d;
484                 param = other.param;
485                 param2 = other.param2;
486                 return *this;
487         }*/
488
489         bool operator==(const MapNode &other)
490         {
491                 return (d == other.d
492                                 && param == other.param
493                                 && param2 == other.param2);
494         }
495
496         bool light_propagates()
497         {
498                 return light_propagates_content(d);
499         }
500         
501         bool sunlight_propagates()
502         {
503                 return sunlight_propagates_content(d);
504         }
505         
506         u8 solidness()
507         {
508                 return content_solidness(d);
509         }
510
511         u8 light_source()
512         {
513                 /*
514                         Note that a block that isn't light_propagates() can be a light source.
515                 */
516                 if(d == CONTENT_TORCH)
517                         return LIGHT_MAX;
518                 
519                 return 0;
520         }
521
522         u8 getLightBanksWithSource()
523         {
524                 // Select the brightest of [light source, propagated light]
525                 u8 lightday = 0;
526                 u8 lightnight = 0;
527                 if(content_features(d).param_type == CPT_LIGHT)
528                 {
529                         lightday = param & 0x0f;
530                         lightnight = (param>>4)&0x0f;
531                 }
532                 if(light_source() > lightday)
533                         lightday = light_source();
534                 if(light_source() > lightnight)
535                         lightnight = light_source();
536                 return (lightday&0x0f) | ((lightnight<<4)&0xf0);
537         }
538
539         void setLightBanks(u8 a_light)
540         {
541                 param = a_light;
542         }
543
544         u8 getLight(enum LightBank bank)
545         {
546                 // Select the brightest of [light source, propagated light]
547                 u8 light = 0;
548                 if(content_features(d).param_type == CPT_LIGHT)
549                 {
550                         if(bank == LIGHTBANK_DAY)
551                                 light = param & 0x0f;
552                         else if(bank == LIGHTBANK_NIGHT)
553                                 light = (param>>4)&0x0f;
554                         else
555                                 assert(0);
556                 }
557                 if(light_source() > light)
558                         light = light_source();
559                 return light;
560         }
561         
562         // 0 <= daylight_factor <= 1000
563         // 0 <= return value <= LIGHT_SUN
564         u8 getLightBlend(u32 daylight_factor)
565         {
566                 u8 l = ((daylight_factor * getLight(LIGHTBANK_DAY)
567                         + (1000-daylight_factor) * getLight(LIGHTBANK_NIGHT))
568                         )/1000;
569                 u8 max = LIGHT_MAX;
570                 if(getLight(LIGHTBANK_DAY) == LIGHT_SUN)
571                         max = LIGHT_SUN;
572                 if(l > max)
573                         l = max;
574                 return l;
575         }
576         /*// 0 <= daylight_factor <= 1000
577         // 0 <= return value <= 255
578         u8 getLightBlend(u32 daylight_factor)
579         {
580                 u8 daylight = decode_light(getLight(LIGHTBANK_DAY));
581                 u8 nightlight = decode_light(getLight(LIGHTBANK_NIGHT));
582                 u8 mix = ((daylight_factor * daylight
583                         + (1000-daylight_factor) * nightlight)
584                         )/1000;
585                 return mix;
586         }*/
587
588         void setLight(enum LightBank bank, u8 a_light)
589         {
590                 // If node doesn't contain light data, ignore this
591                 if(content_features(d).param_type != CPT_LIGHT)
592                         return;
593                 if(bank == LIGHTBANK_DAY)
594                 {
595                         param &= 0xf0;
596                         param |= a_light & 0x0f;
597                 }
598                 else if(bank == LIGHTBANK_NIGHT)
599                 {
600                         param &= 0x0f;
601                         param |= (a_light & 0x0f)<<4;
602                 }
603                 else
604                         assert(0);
605         }
606         
607         // In mapnode.cpp
608         TileSpec getTile(v3s16 dir);
609
610         u8 getMineral();
611
612         /*
613                 These serialization functions are used when informing client
614                 of a single node add
615         */
616
617         static u32 serializedLength(u8 version)
618         {
619                 if(!ser_ver_supported(version))
620                         throw VersionMismatchException("ERROR: MapNode format not supported");
621                         
622                 if(version == 0)
623                         return 1;
624                 else if(version <= 9)
625                         return 2;
626                 else
627                         return 3;
628         }
629         void serialize(u8 *dest, u8 version)
630         {
631                 if(!ser_ver_supported(version))
632                         throw VersionMismatchException("ERROR: MapNode format not supported");
633                         
634                 if(version == 0)
635                 {
636                         dest[0] = d;
637                 }
638                 else if(version <= 9)
639                 {
640                         dest[0] = d;
641                         dest[1] = param;
642                 }
643                 else
644                 {
645                         dest[0] = d;
646                         dest[1] = param;
647                         dest[2] = param2;
648                 }
649         }
650         void deSerialize(u8 *source, u8 version)
651         {
652                 if(!ser_ver_supported(version))
653                         throw VersionMismatchException("ERROR: MapNode format not supported");
654                         
655                 if(version == 0)
656                 {
657                         d = source[0];
658                 }
659                 else if(version == 1)
660                 {
661                         d = source[0];
662                         // This version doesn't support saved lighting
663                         if(light_propagates() || light_source() > 0)
664                                 param = 0;
665                         else
666                                 param = source[1];
667                 }
668                 else if(version <= 9)
669                 {
670                         d = source[0];
671                         param = source[1];
672                 }
673                 else
674                 {
675                         d = source[0];
676                         param = source[1];
677                         param2 = source[2];
678                 }
679
680                 // Translate deprecated stuff
681                 // NOTE: This doesn't get used because MapBlock handles node
682                 // parameters directly
683                 MapNode *translate_to = content_features(d).translate_to;
684                 if(translate_to)
685                 {
686                         dstream<<"MapNode: WARNING: Translating "<<d<<" to "
687                                         <<translate_to->d<<std::endl;
688                         *this = *translate_to;
689                 }
690         }
691 };
692
693
694
695 #endif
696