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