fb7244322421bc8fc5bfabd6d08e8356f89688fe
[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 "exceptions.h"
27 #include "serialization.h"
28 #include "materials.h"
29 #ifndef SERVER
30 #include "tile.h"
31 #endif
32
33 /*
34         Naming scheme:
35         - Material = irrlicht's Material class
36         - Content = (content_t) content of a node
37         - Tile = TileSpec at some side of a node of some content type
38
39         Content ranges:
40                 0x000...0x07f: param2 is fully usable
41                 0x800...0xfff: param2 lower 4 bytes are free
42 */
43 typedef u16 content_t;
44 #define MAX_CONTENT 0xfff
45
46 /*
47         Initializes all kind of stuff in here.
48         Many things depend on this.
49
50         This accesses g_texturesource; if it is non-NULL, textures are set.
51
52         Client first calls this with g_texturesource=NULL to run some
53         unit tests and stuff, then it runs this again with g_texturesource
54         defined to get the textures.
55
56         Server only calls this once with g_texturesource=NULL.
57 */
58 void init_mapnode();
59
60 /*
61         Ignored node.
62
63         Anything that stores MapNodes doesn't have to preserve parameters
64         associated with this material.
65         
66         Doesn't create faces with anything and is considered being
67         out-of-map in the game map.
68 */
69 //#define CONTENT_IGNORE 255
70 #define CONTENT_IGNORE 127
71 #define CONTENT_IGNORE_DEFAULT_PARAM 0
72
73 /*
74         The common material through which the player can walk and which
75         is transparent to light
76 */
77 //#define CONTENT_AIR 254
78 #define CONTENT_AIR 126
79
80 /*
81         Content feature list
82 */
83
84 enum ContentParamType
85 {
86         CPT_NONE,
87         CPT_LIGHT,
88         CPT_MINERAL,
89         // Direction for chests and furnaces and such
90         CPT_FACEDIR_SIMPLE
91 };
92
93 enum LiquidType
94 {
95         LIQUID_NONE,
96         LIQUID_FLOWING,
97         LIQUID_SOURCE
98 };
99
100 struct MapNode;
101 class NodeMetadata;
102
103 struct ContentFeatures
104 {
105 #ifndef SERVER
106         /*
107                 0: up
108                 1: down
109                 2: right
110                 3: left
111                 4: back
112                 5: front
113         */
114         TileSpec tiles[6];
115         
116         video::ITexture *inventory_texture;
117
118         // Used currently for flowing liquids
119         u8 vertex_alpha;
120         // Post effect color, drawn when the camera is inside the node.
121         video::SColor post_effect_color;
122         // Special irrlicht material, used sometimes
123         video::SMaterial *special_material;
124         AtlasPointer *special_atlas;
125 #endif
126
127         // List of all block textures that have been used (value is dummy)
128         // Exists on server too for cleaner code in content_mapnode.cpp
129         core::map<std::string, bool> used_texturenames;
130         
131         // Type of MapNode::param1
132         ContentParamType param_type;
133         // True for all ground-like things like stone and mud, false for eg. trees
134         bool is_ground_content;
135         bool light_propagates;
136         bool sunlight_propagates;
137         u8 solidness; // Used when choosing which face is drawn
138         u8 visual_solidness; // When solidness=0, this tells how it looks like
139         // This is used for collision detection.
140         // Also for general solidness queries.
141         bool walkable;
142         // Player can point to these
143         bool pointable;
144         // Player can dig these
145         bool diggable;
146         // Player can climb these
147         bool climbable;
148         // Player can build on these
149         bool buildable_to;
150         // Whether the node has no liquid, source liquid or flowing liquid
151         enum LiquidType liquid_type;
152         // If true, param2 is set to direction when placed. Used for torches.
153         // NOTE: the direction format is quite inefficient and should be changed
154         bool wall_mounted;
155         // If true, node is equivalent to air. Torches are, air is. Water is not.
156         // Is used for example to check whether a mud block can have grass on.
157         bool air_equivalent;
158         // Whether this content type often contains mineral.
159         // Used for texture atlas creation.
160         // Currently only enabled for CONTENT_STONE.
161         bool often_contains_mineral;
162         
163         // Inventory item string as which the node appears in inventory when dug.
164         // Mineral overrides this.
165         std::string dug_item;
166
167         // Extra dug item and its rarity
168         std::string extra_dug_item;
169         s32 extra_dug_item_rarity;
170
171         // Initial metadata is cloned from this
172         NodeMetadata *initial_metadata;
173         
174         // If the content is liquid, this is the flowing version of the liquid.
175         // If content is liquid, this is the same content.
176         content_t liquid_alternative_flowing;
177         // If the content is liquid, this is the source version of the liquid.
178         content_t liquid_alternative_source;
179         // Viscosity for fluid flow, ranging from 1 to 7, with
180         // 1 giving almost instantaneous propagation and 7 being
181         // the slowest possible
182         u8 liquid_viscosity;
183         
184         // Amount of light the node emits
185         u8 light_source;
186         
187         // Digging properties for different tools
188         DiggingPropertiesList digging_properties;
189
190         u32 damage_per_second;
191         
192         // NOTE: Move relevant properties to here from elsewhere
193
194         void reset()
195         {
196 #ifndef SERVER
197                 inventory_texture = NULL;
198                 
199                 vertex_alpha = 255;
200                 post_effect_color = video::SColor(0, 0, 0, 0);
201                 special_material = NULL;
202                 special_atlas = NULL;
203 #endif
204                 param_type = CPT_NONE;
205                 is_ground_content = false;
206                 light_propagates = false;
207                 sunlight_propagates = false;
208                 solidness = 2;
209                 visual_solidness = 0;
210                 walkable = true;
211                 pointable = true;
212                 diggable = true;
213                 climbable = false;
214                 buildable_to = false;
215                 liquid_type = LIQUID_NONE;
216                 wall_mounted = false;
217                 air_equivalent = false;
218                 often_contains_mineral = false;
219                 dug_item = "";
220                 initial_metadata = NULL;
221                 liquid_alternative_flowing = CONTENT_IGNORE;
222                 liquid_alternative_source = CONTENT_IGNORE;
223                 liquid_viscosity = 0;
224                 light_source = 0;
225                 digging_properties.clear();
226                 damage_per_second = 0;
227         }
228
229         ContentFeatures()
230         {
231                 reset();
232         }
233
234         ~ContentFeatures();
235         
236         /*
237                 Quickhands for simple materials
238         */
239         
240 #ifdef SERVER
241         void setTexture(u16 i, std::string name, u8 alpha=255)
242         {}
243         void setAllTextures(std::string name, u8 alpha=255)
244         {}
245 #else
246         void setTexture(u16 i, std::string name, u8 alpha=255);
247
248         void setAllTextures(std::string name, u8 alpha=255)
249         {
250                 for(u16 i=0; i<6; i++)
251                 {
252                         setTexture(i, name, alpha);
253                 }
254                 // Force inventory texture too
255                 setInventoryTexture(name);
256         }
257 #endif
258
259 #ifndef SERVER
260         void setTile(u16 i, const TileSpec &tile)
261         {
262                 tiles[i] = tile;
263         }
264         void setAllTiles(const TileSpec &tile)
265         {
266                 for(u16 i=0; i<6; i++)
267                 {
268                         setTile(i, tile);
269                 }
270         }
271 #endif
272
273 #ifdef SERVER
274         void setInventoryTexture(std::string imgname)
275         {}
276         void setInventoryTextureCube(std::string top,
277                         std::string left, std::string right)
278         {}
279 #else
280         void setInventoryTexture(std::string imgname);
281         
282         void setInventoryTextureCube(std::string top,
283                         std::string left, std::string right);
284 #endif
285 };
286
287 /*
288         Call this to access the ContentFeature list
289 */
290 ContentFeatures & content_features(content_t i);
291 ContentFeatures & content_features(MapNode &n);
292
293 /*
294         Here is a bunch of DEPRECATED functions.
295 */
296
297 /*
298         If true, the material allows light propagation and brightness is stored
299         in param.
300         NOTE: Don't use, use "content_features(m).whatever" instead
301 */
302 inline bool light_propagates_content(content_t m)
303 {
304         return content_features(m).light_propagates;
305 }
306 /*
307         If true, the material allows lossless sunlight propagation.
308         NOTE: It doesn't seem to go through torches regardlessly of this
309         NOTE: Don't use, use "content_features(m).whatever" instead
310 */
311 inline bool sunlight_propagates_content(content_t m)
312 {
313         return content_features(m).sunlight_propagates;
314 }
315 /*
316         On a node-node surface, the material of the node with higher solidness
317         is used for drawing.
318         0: Invisible
319         1: Transparent
320         2: Opaque
321         NOTE: Don't use, use "content_features(m).whatever" instead
322 */
323 inline u8 content_solidness(content_t m)
324 {
325         return content_features(m).solidness;
326 }
327 // Objects collide with walkable contents
328 // NOTE: Don't use, use "content_features(m).whatever" instead
329 inline bool content_walkable(content_t m)
330 {
331         return content_features(m).walkable;
332 }
333 // NOTE: Don't use, use "content_features(m).whatever" instead
334 inline bool content_liquid(content_t m)
335 {
336         return content_features(m).liquid_type != LIQUID_NONE;
337 }
338 // NOTE: Don't use, use "content_features(m).whatever" instead
339 inline bool content_flowing_liquid(content_t m)
340 {
341         return content_features(m).liquid_type == LIQUID_FLOWING;
342 }
343 // NOTE: Don't use, use "content_features(m).whatever" instead
344 inline bool content_liquid_source(content_t m)
345 {
346         return content_features(m).liquid_type == LIQUID_SOURCE;
347 }
348 // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
349 // CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
350 // NOTE: Don't use, use "content_features(m).whatever" instead
351 inline content_t make_liquid_flowing(content_t m)
352 {
353         u8 c = content_features(m).liquid_alternative_flowing;
354         assert(c != CONTENT_IGNORE);
355         return c;
356 }
357 // Pointable contents can be pointed to in the map
358 // NOTE: Don't use, use "content_features(m).whatever" instead
359 inline bool content_pointable(content_t m)
360 {
361         return content_features(m).pointable;
362 }
363 // NOTE: Don't use, use "content_features(m).whatever" instead
364 inline bool content_diggable(content_t m)
365 {
366         return content_features(m).diggable;
367 }
368 // NOTE: Don't use, use "content_features(m).whatever" instead
369 inline bool content_buildable_to(content_t m)
370 {
371         return content_features(m).buildable_to;
372 }
373
374 /*
375         Nodes make a face if contents differ and solidness differs.
376         Return value:
377                 0: No face
378                 1: Face uses m1's content
379                 2: Face uses m2's content
380 */
381 inline u8 face_contents(content_t m1, content_t m2)
382 {
383         if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
384                 return 0;
385         
386         bool contents_differ = (m1 != m2);
387         
388         // Contents don't differ for different forms of same liquid
389         if(content_liquid(m1) && content_liquid(m2)
390                         && make_liquid_flowing(m1) == make_liquid_flowing(m2))
391                 contents_differ = false;
392         
393         bool solidness_differs = (content_solidness(m1) != content_solidness(m2));
394         bool makes_face = contents_differ && solidness_differs;
395
396         if(makes_face == false)
397                 return 0;
398
399         if(content_solidness(m1) > content_solidness(m2))
400                 return 1;
401         else
402                 return 2;
403 }
404
405 /*
406         Packs directions like (1,0,0), (1,-1,0)
407 */
408 inline u8 packDir(v3s16 dir)
409 {
410         u8 b = 0;
411
412         if(dir.X > 0)
413                 b |= (1<<0);
414         else if(dir.X < 0)
415                 b |= (1<<1);
416
417         if(dir.Y > 0)
418                 b |= (1<<2);
419         else if(dir.Y < 0)
420                 b |= (1<<3);
421
422         if(dir.Z > 0)
423                 b |= (1<<4);
424         else if(dir.Z < 0)
425                 b |= (1<<5);
426         
427         return b;
428 }
429 inline v3s16 unpackDir(u8 b)
430 {
431         v3s16 d(0,0,0);
432
433         if(b & (1<<0))
434                 d.X = 1;
435         else if(b & (1<<1))
436                 d.X = -1;
437
438         if(b & (1<<2))
439                 d.Y = 1;
440         else if(b & (1<<3))
441                 d.Y = -1;
442
443         if(b & (1<<4))
444                 d.Z = 1;
445         else if(b & (1<<5))
446                 d.Z = -1;
447         
448         return d;
449 }
450
451 /*
452         facedir: CPT_FACEDIR_SIMPLE param1 value
453         dir: The face for which stuff is wanted
454         return value: The face from which the stuff is actually found
455
456         NOTE: Currently this uses 2 bits for Z-,X-,Z+,X+, should there be Y+
457               and Y- too?
458 */
459 v3s16 facedir_rotate(u8 facedir, v3s16 dir);
460
461 enum LightBank
462 {
463         LIGHTBANK_DAY,
464         LIGHTBANK_NIGHT
465 };
466
467 /*
468         Masks for MapNode.param2 of flowing liquids
469  */
470 #define LIQUID_LEVEL_MASK 0x07
471 #define LIQUID_FLOW_DOWN_MASK 0x08
472
473 /* maximum amount of liquid in a block */
474 #define LIQUID_LEVEL_MAX LIQUID_LEVEL_MASK
475 #define LIQUID_LEVEL_SOURCE (LIQUID_LEVEL_MAX+1)
476
477 /*
478         This is the stuff what the whole world consists of.
479 */
480
481
482 struct MapNode
483 {
484         /*
485                 Main content
486                 0x00-0x7f: Short content type
487                 0x80-0xff: Long content type (param2>>4 makes up low bytes)
488         */
489         union
490         {
491                 u8 param0;
492                 //u8 d;
493         };
494
495         /*
496                 Misc parameter. Initialized to 0.
497                 - For light_propagates() blocks, this is light intensity,
498                   stored logarithmically from 0 to LIGHT_MAX.
499                   Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
500                   - Contains 2 values, day- and night lighting. Each takes 4 bits.
501                 - Mineral content (should be removed from here)
502                 - Uhh... well, most blocks have light or nothing in here.
503         */
504         union
505         {
506                 u8 param1;
507                 //s8 param;
508         };
509         
510         /*
511                 The second parameter. Initialized to 0.
512                 E.g. direction for torches and flowing water.
513                 If param0 >= 0x80, bits 0xf0 of this is extended content type data
514         */
515         union
516         {
517                 u8 param2;
518                 //u8 dir;
519         };
520
521         MapNode(const MapNode & n)
522         {
523                 *this = n;
524         }
525         
526         MapNode(content_t content=CONTENT_AIR, u8 a_param1=0, u8 a_param2=0)
527         {
528                 //param0 = a_param0;
529                 param1 = a_param1;
530                 param2 = a_param2;
531                 // Set after other params because this needs to override part of param2
532                 setContent(content);
533         }
534
535         bool operator==(const MapNode &other)
536         {
537                 return (param0 == other.param0
538                                 && param1 == other.param1
539                                 && param2 == other.param2);
540         }
541         
542         // To be used everywhere
543         content_t getContent()
544         {
545                 if(param0 < 0x80)
546                         return param0;
547                 else
548                         return (param0<<4) + (param2>>4);
549         }
550         void setContent(content_t c)
551         {
552                 if(c < 0x80)
553                 {
554                         if(param0 >= 0x80)
555                                 param2 &= ~(0xf0);
556                         param0 = c;
557                 }
558                 else
559                 {
560                         param0 = c>>4;
561                         param2 &= ~(0xf0);
562                         param2 |= (c&0x0f)<<4;
563                 }
564         }
565         
566         /*
567                 These four are DEPRECATED I guess. -c55
568         */
569         bool light_propagates()
570         {
571                 return light_propagates_content(getContent());
572         }
573         bool sunlight_propagates()
574         {
575                 return sunlight_propagates_content(getContent());
576         }
577         u8 solidness()
578         {
579                 return content_solidness(getContent());
580         }
581         u8 light_source()
582         {
583                 return content_features(*this).light_source;
584         }
585
586         u8 getLightBanksWithSource()
587         {
588                 // Select the brightest of [light source, propagated light]
589                 u8 lightday = 0;
590                 u8 lightnight = 0;
591                 if(content_features(*this).param_type == CPT_LIGHT)
592                 {
593                         lightday = param1 & 0x0f;
594                         lightnight = (param1>>4)&0x0f;
595                 }
596                 if(light_source() > lightday)
597                         lightday = light_source();
598                 if(light_source() > lightnight)
599                         lightnight = light_source();
600                 return (lightday&0x0f) | ((lightnight<<4)&0xf0);
601         }
602
603         u8 getLight(enum LightBank bank)
604         {
605                 // Select the brightest of [light source, propagated light]
606                 u8 light = 0;
607                 if(content_features(*this).param_type == CPT_LIGHT)
608                 {
609                         if(bank == LIGHTBANK_DAY)
610                                 light = param1 & 0x0f;
611                         else if(bank == LIGHTBANK_NIGHT)
612                                 light = (param1>>4)&0x0f;
613                         else
614                                 assert(0);
615                 }
616                 if(light_source() > light)
617                         light = light_source();
618                 return light;
619         }
620         
621         // 0 <= daylight_factor <= 1000
622         // 0 <= return value <= LIGHT_SUN
623         u8 getLightBlend(u32 daylight_factor)
624         {
625                 u8 l = ((daylight_factor * getLight(LIGHTBANK_DAY)
626                         + (1000-daylight_factor) * getLight(LIGHTBANK_NIGHT))
627                         )/1000;
628                 u8 max = LIGHT_MAX;
629                 if(getLight(LIGHTBANK_DAY) == LIGHT_SUN)
630                         max = LIGHT_SUN;
631                 if(l > max)
632                         l = max;
633                 return l;
634         }
635         /*// 0 <= daylight_factor <= 1000
636         // 0 <= return value <= 255
637         u8 getLightBlend(u32 daylight_factor)
638         {
639                 u8 daylight = decode_light(getLight(LIGHTBANK_DAY));
640                 u8 nightlight = decode_light(getLight(LIGHTBANK_NIGHT));
641                 u8 mix = ((daylight_factor * daylight
642                         + (1000-daylight_factor) * nightlight)
643                         )/1000;
644                 return mix;
645         }*/
646
647         void setLight(enum LightBank bank, u8 a_light)
648         {
649                 // If node doesn't contain light data, ignore this
650                 if(content_features(*this).param_type != CPT_LIGHT)
651                         return;
652                 if(bank == LIGHTBANK_DAY)
653                 {
654                         param1 &= 0xf0;
655                         param1 |= a_light & 0x0f;
656                 }
657                 else if(bank == LIGHTBANK_NIGHT)
658                 {
659                         param1 &= 0x0f;
660                         param1 |= (a_light & 0x0f)<<4;
661                 }
662                 else
663                         assert(0);
664         }
665         
666         // In mapnode.cpp
667 #ifndef SERVER
668         /*
669                 Get tile of a face of the node.
670                 dir: direction of face
671                 Returns: TileSpec. Can contain miscellaneous texture coordinates,
672                          which must be obeyed so that the texture atlas can be used.
673         */
674         TileSpec getTile(v3s16 dir);
675 #endif
676         
677         /*
678                 Gets mineral content of node, if there is any.
679                 MINERAL_NONE if doesn't contain or isn't able to contain mineral.
680         */
681         u8 getMineral();
682         
683         /*
684                 Serialization functions
685         */
686
687         static u32 serializedLength(u8 version);
688         void serialize(u8 *dest, u8 version);
689         void deSerialize(u8 *source, u8 version);
690         
691 };
692
693 /*
694         Gets lighting value at face of node
695         
696         Parameters must consist of air and !air.
697         Order doesn't matter.
698
699         If either of the nodes doesn't exist, light is 0.
700         
701         parameters:
702                 daynight_ratio: 0...1000
703                 n: getNodeParent(p)
704                 n2: getNodeParent(p + face_dir)
705                 face_dir: axis oriented unit vector from p to p2
706         
707         returns encoded light value.
708 */
709 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
710                 v3s16 face_dir);
711
712 #endif
713