ebca3755a020fde3b04defe363e2d6c663a651d4
[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 #include "materials.h"
31
32 /*
33         Naming scheme:
34         - Material = irrlicht's Material class
35         - Content = (u8) content of a node
36         - Tile = TileSpec at some side of a node of some content type
37 */
38
39 /*
40         Ranges:
41                 0x000...0x07f: param2 is fully usable
42                 0x800...0xfff: param2 lower 4 bytes are free
43 */
44 typedef u16 content_t;
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 class MapNode;
101 class NodeMetadata;
102
103 struct ContentFeatures
104 {
105         // If non-NULL, content is translated to this when deserialized
106         //MapNode *translate_to;
107
108         // Type of MapNode::param
109         ContentParamType param_type;
110
111         /*
112                 0: up
113                 1: down
114                 2: right
115                 3: left
116                 4: back
117                 5: front
118         */
119         TileSpec tiles[6];
120         
121         video::ITexture *inventory_texture;
122         
123         // True for all ground-like things like stone and mud, false for eg. trees
124         bool is_ground_content;
125         bool light_propagates;
126         bool sunlight_propagates;
127         u8 solidness; // Used when choosing which face is drawn
128         // This is used for collision detection.
129         // Also for general solidness queries.
130         bool walkable;
131         // Player can point to these
132         bool pointable;
133         // Player can dig these
134         bool diggable;
135         // Player can build on these
136         bool buildable_to;
137         // Whether the node has no liquid, source liquid or flowing liquid
138         enum LiquidType liquid_type;
139         // If true, param2 is set to direction when placed. Used for torches.
140         // NOTE: the direction format is quite inefficient and should be changed
141         bool wall_mounted;
142         // If true, node is equivalent to air. Torches are, air is. Water is not.
143         // Is used for example to check whether a mud block can have grass on.
144         bool air_equivalent;
145         
146         // Inventory item string as which the node appears in inventory when dug.
147         // Mineral overrides this.
148         std::string dug_item;
149         
150         // Initial metadata is cloned from this
151         NodeMetadata *initial_metadata;
152         
153         // If the content is liquid, this is the flowing version of the liquid.
154         // If content is flowing liquid, this is the same content.
155         u8 liquid_alternative_flowing;
156         // If the content is liquid, this is the source version of the liquid.
157         u8 liquid_alternative_source;
158         
159         // Amount of light the node emits
160         u8 light_source;
161         
162         // Digging properties for different tools
163         DiggingPropertiesList digging_properties;
164         
165         // NOTE: Move relevant properties to here from elsewhere
166
167         void reset()
168         {
169                 //translate_to = NULL;
170                 param_type = CPT_NONE;
171                 inventory_texture = NULL;
172                 is_ground_content = false;
173                 light_propagates = false;
174                 sunlight_propagates = false;
175                 solidness = 2;
176                 walkable = true;
177                 pointable = true;
178                 diggable = true;
179                 buildable_to = false;
180                 liquid_type = LIQUID_NONE;
181                 wall_mounted = false;
182                 air_equivalent = false;
183                 dug_item = "";
184                 initial_metadata = NULL;
185                 liquid_alternative_flowing = CONTENT_IGNORE;
186                 light_source = 0;
187                 digging_properties.clear();
188         }
189
190         ContentFeatures()
191         {
192                 reset();
193         }
194
195         ~ContentFeatures();
196         
197         /*
198                 Quickhands for simple materials
199         */
200         
201         void setTexture(u16 i, std::string name, u8 alpha=255);
202
203         void setAllTextures(std::string name, u8 alpha=255)
204         {
205                 for(u16 i=0; i<6; i++)
206                 {
207                         setTexture(i, name, alpha);
208                 }
209                 // Force inventory texture too
210                 setInventoryTexture(name);
211         }
212
213         void setTile(u16 i, const TileSpec &tile)
214         {
215                 tiles[i] = tile;
216         }
217         void setAllTiles(const TileSpec &tile)
218         {
219                 for(u16 i=0; i<6; i++)
220                 {
221                         setTile(i, tile);
222                 }
223         }
224
225         void setInventoryTexture(std::string imgname);
226         
227         void setInventoryTextureCube(std::string top,
228                         std::string left, std::string right);
229 };
230
231 /*
232         Call this to access the ContentFeature list
233 */
234 ContentFeatures & content_features(u8 i);
235
236
237 /*
238         Here is a bunch of DEPRECATED functions.
239 */
240
241 /*
242         If true, the material allows light propagation and brightness is stored
243         in param.
244         NOTE: Don't use, use "content_features(m).whatever" instead
245 */
246 inline bool light_propagates_content(u8 m)
247 {
248         return content_features(m).light_propagates;
249 }
250 /*
251         If true, the material allows lossless sunlight propagation.
252         NOTE: It doesn't seem to go through torches regardlessly of this
253         NOTE: Don't use, use "content_features(m).whatever" instead
254 */
255 inline bool sunlight_propagates_content(u8 m)
256 {
257         return content_features(m).sunlight_propagates;
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 }
271 // Objects collide with walkable contents
272 // NOTE: Don't use, use "content_features(m).whatever" instead
273 inline bool content_walkable(u8 m)
274 {
275         return content_features(m).walkable;
276 }
277 // NOTE: Don't use, use "content_features(m).whatever" instead
278 inline bool content_liquid(u8 m)
279 {
280         return content_features(m).liquid_type != LIQUID_NONE;
281 }
282 // NOTE: Don't use, use "content_features(m).whatever" instead
283 inline bool content_flowing_liquid(u8 m)
284 {
285         return content_features(m).liquid_type == LIQUID_FLOWING;
286 }
287 // NOTE: Don't use, use "content_features(m).whatever" instead
288 inline bool content_liquid_source(u8 m)
289 {
290         return content_features(m).liquid_type == LIQUID_SOURCE;
291 }
292 // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
293 // CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
294 // NOTE: Don't use, use "content_features(m).whatever" instead
295 inline u8 make_liquid_flowing(u8 m)
296 {
297         u8 c = content_features(m).liquid_alternative_flowing;
298         assert(c != CONTENT_IGNORE);
299         return c;
300 }
301 // Pointable contents can be pointed to in the map
302 // NOTE: Don't use, use "content_features(m).whatever" instead
303 inline bool content_pointable(u8 m)
304 {
305         return content_features(m).pointable;
306 }
307 // NOTE: Don't use, use "content_features(m).whatever" instead
308 inline bool content_diggable(u8 m)
309 {
310         return content_features(m).diggable;
311 }
312 // NOTE: Don't use, use "content_features(m).whatever" instead
313 inline bool content_buildable_to(u8 m)
314 {
315         return content_features(m).buildable_to;
316 }
317
318 /*
319         Nodes make a face if contents differ and solidness differs.
320         Return value:
321                 0: No face
322                 1: Face uses m1's content
323                 2: Face uses m2's content
324 */
325 inline u8 face_contents(u8 m1, u8 m2)
326 {
327         if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
328                 return 0;
329         
330         bool contents_differ = (m1 != m2);
331         
332         // Contents don't differ for different forms of same liquid
333         if(content_liquid(m1) && content_liquid(m2)
334                         && make_liquid_flowing(m1) == make_liquid_flowing(m2))
335                 contents_differ = false;
336         
337         bool solidness_differs = (content_solidness(m1) != content_solidness(m2));
338         bool makes_face = contents_differ && solidness_differs;
339
340         if(makes_face == false)
341                 return 0;
342
343         if(content_solidness(m1) > content_solidness(m2))
344                 return 1;
345         else
346                 return 2;
347 }
348
349 /*
350         Packs directions like (1,0,0), (1,-1,0)
351 */
352 inline u8 packDir(v3s16 dir)
353 {
354         u8 b = 0;
355
356         if(dir.X > 0)
357                 b |= (1<<0);
358         else if(dir.X < 0)
359                 b |= (1<<1);
360
361         if(dir.Y > 0)
362                 b |= (1<<2);
363         else if(dir.Y < 0)
364                 b |= (1<<3);
365
366         if(dir.Z > 0)
367                 b |= (1<<4);
368         else if(dir.Z < 0)
369                 b |= (1<<5);
370         
371         return b;
372 }
373 inline v3s16 unpackDir(u8 b)
374 {
375         v3s16 d(0,0,0);
376
377         if(b & (1<<0))
378                 d.X = 1;
379         else if(b & (1<<1))
380                 d.X = -1;
381
382         if(b & (1<<2))
383                 d.Y = 1;
384         else if(b & (1<<3))
385                 d.Y = -1;
386
387         if(b & (1<<4))
388                 d.Z = 1;
389         else if(b & (1<<5))
390                 d.Z = -1;
391         
392         return d;
393 }
394
395 /*
396         facedir: CPT_FACEDIR_SIMPLE param1 value
397         dir: The face for which stuff is wanted
398         return value: The face from which the stuff is actually found
399 */
400 v3s16 facedir_rotate(u8 facedir, v3s16 dir);
401
402 enum LightBank
403 {
404         LIGHTBANK_DAY,
405         LIGHTBANK_NIGHT
406 };
407
408 /*
409         Masks for MapNode.param2 of flowing liquids
410  */
411 #define LIQUID_LEVEL_MASK 0x07
412 #define LIQUID_FLOW_DOWN_MASK 0x08
413
414 /*
415         This is the stuff what the whole world consists of.
416 */
417
418
419 struct MapNode
420 {
421         /*
422                 Main content
423                 0x00-0x7f: Short content type
424                 0x80-0xff: Long content type (param2>>4 makes up low bytes)
425         */
426         union
427         {
428                 u8 param0;
429                 u8 d;
430         };
431
432         /*
433                 Misc parameter. Initialized to 0.
434                 - For light_propagates() blocks, this is light intensity,
435                   stored logarithmically from 0 to LIGHT_MAX.
436                   Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
437                   - Contains 2 values, day- and night lighting. Each takes 4 bits.
438                 - Mineral content (should be removed from here)
439                 - Uhh... well, most blocks have light or nothing in here.
440         */
441         union
442         {
443                 u8 param1;
444                 s8 param;
445         };
446         
447         /*
448                 The second parameter. Initialized to 0.
449                 E.g. direction for torches and flowing water.
450         */
451         union
452         {
453                 u8 param2;
454                 u8 dir;
455         };
456
457         MapNode(const MapNode & n)
458         {
459                 *this = n;
460         }
461         
462         MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_param2=0)
463         {
464                 d = data;
465                 param = a_param;
466                 param2 = a_param2;
467         }
468
469         bool operator==(const MapNode &other)
470         {
471                 return (d == other.d
472                                 && param == other.param
473                                 && param2 == other.param2);
474         }
475         
476         // To be used everywhere
477         content_t getContent()
478         {
479                 return d;
480         }
481         void setContent(content_t c)
482         {
483                 d = c;
484         }
485         
486         /*
487                 These four are DEPRECATED I guess. -c55
488         */
489         bool light_propagates()
490         {
491                 return light_propagates_content(d);
492         }
493         bool sunlight_propagates()
494         {
495                 return sunlight_propagates_content(d);
496         }
497         u8 solidness()
498         {
499                 return content_solidness(d);
500         }
501         u8 light_source()
502         {
503                 return content_features(d).light_source;
504         }
505
506         u8 getLightBanksWithSource()
507         {
508                 // Select the brightest of [light source, propagated light]
509                 u8 lightday = 0;
510                 u8 lightnight = 0;
511                 if(content_features(d).param_type == CPT_LIGHT)
512                 {
513                         lightday = param & 0x0f;
514                         lightnight = (param>>4)&0x0f;
515                 }
516                 if(light_source() > lightday)
517                         lightday = light_source();
518                 if(light_source() > lightnight)
519                         lightnight = light_source();
520                 return (lightday&0x0f) | ((lightnight<<4)&0xf0);
521         }
522
523         u8 getLight(enum LightBank bank)
524         {
525                 // Select the brightest of [light source, propagated light]
526                 u8 light = 0;
527                 if(content_features(d).param_type == CPT_LIGHT)
528                 {
529                         if(bank == LIGHTBANK_DAY)
530                                 light = param & 0x0f;
531                         else if(bank == LIGHTBANK_NIGHT)
532                                 light = (param>>4)&0x0f;
533                         else
534                                 assert(0);
535                 }
536                 if(light_source() > light)
537                         light = light_source();
538                 return light;
539         }
540         
541         // 0 <= daylight_factor <= 1000
542         // 0 <= return value <= LIGHT_SUN
543         u8 getLightBlend(u32 daylight_factor)
544         {
545                 u8 l = ((daylight_factor * getLight(LIGHTBANK_DAY)
546                         + (1000-daylight_factor) * getLight(LIGHTBANK_NIGHT))
547                         )/1000;
548                 u8 max = LIGHT_MAX;
549                 if(getLight(LIGHTBANK_DAY) == LIGHT_SUN)
550                         max = LIGHT_SUN;
551                 if(l > max)
552                         l = max;
553                 return l;
554         }
555         /*// 0 <= daylight_factor <= 1000
556         // 0 <= return value <= 255
557         u8 getLightBlend(u32 daylight_factor)
558         {
559                 u8 daylight = decode_light(getLight(LIGHTBANK_DAY));
560                 u8 nightlight = decode_light(getLight(LIGHTBANK_NIGHT));
561                 u8 mix = ((daylight_factor * daylight
562                         + (1000-daylight_factor) * nightlight)
563                         )/1000;
564                 return mix;
565         }*/
566
567         void setLight(enum LightBank bank, u8 a_light)
568         {
569                 // If node doesn't contain light data, ignore this
570                 if(content_features(d).param_type != CPT_LIGHT)
571                         return;
572                 if(bank == LIGHTBANK_DAY)
573                 {
574                         param &= 0xf0;
575                         param |= a_light & 0x0f;
576                 }
577                 else if(bank == LIGHTBANK_NIGHT)
578                 {
579                         param &= 0x0f;
580                         param |= (a_light & 0x0f)<<4;
581                 }
582                 else
583                         assert(0);
584         }
585         
586         // In mapnode.cpp
587         /*
588                 Get tile of a face of the node.
589                 dir: direction of face
590                 Returns: TileSpec. Can contain miscellaneous texture coordinates,
591                          which must be obeyed so that the texture atlas can be used.
592         */
593         TileSpec getTile(v3s16 dir);
594         
595         /*
596                 Gets mineral content of node, if there is any.
597                 MINERAL_NONE if doesn't contain or isn't able to contain mineral.
598         */
599         u8 getMineral();
600         
601         /*
602                 Serialization functions
603         */
604
605         static u32 serializedLength(u8 version);
606         void serialize(u8 *dest, u8 version);
607         void deSerialize(u8 *source, u8 version);
608         
609 };
610
611 /*
612         Gets lighting value at face of node
613         
614         Parameters must consist of air and !air.
615         Order doesn't matter.
616
617         If either of the nodes doesn't exist, light is 0.
618         
619         parameters:
620                 daynight_ratio: 0...1000
621                 n: getNodeParent(p)
622                 n2: getNodeParent(p + face_dir)
623                 face_dir: axis oriented unit vector from p to p2
624         
625         returns encoded light value.
626 */
627 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
628                 v3s16 face_dir);
629
630 #endif
631