utility.h: Change Buffer's interface to be more compatible with SharedBuffer's interf...
[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         u8 c1 = content_solidness(m1);
400         u8 c2 = content_solidness(m2);
401         
402         /*
403                 Special case for half-transparent content.
404
405                 This makes eg. the water (solidness=1) surrounding an underwater
406                 glass block (solidness=0, visual_solidness=1) not get drawn.
407         */
408         if(c1 == 1 && c2 == 0 && content_features(m2).visual_solidness != 0)
409                 return 0;
410         if(c2 == 1 && c1 == 0 && content_features(m1).visual_solidness != 0)
411                 return 0;
412
413         if(c1 > c2)
414                 return 1;
415         else
416                 return 2;
417 }
418
419 /*
420         Packs directions like (1,0,0), (1,-1,0)
421 */
422 inline u8 packDir(v3s16 dir)
423 {
424         u8 b = 0;
425
426         if(dir.X > 0)
427                 b |= (1<<0);
428         else if(dir.X < 0)
429                 b |= (1<<1);
430
431         if(dir.Y > 0)
432                 b |= (1<<2);
433         else if(dir.Y < 0)
434                 b |= (1<<3);
435
436         if(dir.Z > 0)
437                 b |= (1<<4);
438         else if(dir.Z < 0)
439                 b |= (1<<5);
440         
441         return b;
442 }
443 inline v3s16 unpackDir(u8 b)
444 {
445         v3s16 d(0,0,0);
446
447         if(b & (1<<0))
448                 d.X = 1;
449         else if(b & (1<<1))
450                 d.X = -1;
451
452         if(b & (1<<2))
453                 d.Y = 1;
454         else if(b & (1<<3))
455                 d.Y = -1;
456
457         if(b & (1<<4))
458                 d.Z = 1;
459         else if(b & (1<<5))
460                 d.Z = -1;
461         
462         return d;
463 }
464
465 /*
466         facedir: CPT_FACEDIR_SIMPLE param1 value
467         dir: The face for which stuff is wanted
468         return value: The face from which the stuff is actually found
469
470         NOTE: Currently this uses 2 bits for Z-,X-,Z+,X+, should there be Y+
471               and Y- too?
472 */
473 v3s16 facedir_rotate(u8 facedir, v3s16 dir);
474
475 enum LightBank
476 {
477         LIGHTBANK_DAY,
478         LIGHTBANK_NIGHT
479 };
480
481 /*
482         Masks for MapNode.param2 of flowing liquids
483  */
484 #define LIQUID_LEVEL_MASK 0x07
485 #define LIQUID_FLOW_DOWN_MASK 0x08
486
487 /* maximum amount of liquid in a block */
488 #define LIQUID_LEVEL_MAX LIQUID_LEVEL_MASK
489 #define LIQUID_LEVEL_SOURCE (LIQUID_LEVEL_MAX+1)
490
491 /*
492         This is the stuff what the whole world consists of.
493 */
494
495
496 struct MapNode
497 {
498         /*
499                 Main content
500                 0x00-0x7f: Short content type
501                 0x80-0xff: Long content type (param2>>4 makes up low bytes)
502         */
503         union
504         {
505                 u8 param0;
506                 //u8 d;
507         };
508
509         /*
510                 Misc parameter. Initialized to 0.
511                 - For light_propagates() blocks, this is light intensity,
512                   stored logarithmically from 0 to LIGHT_MAX.
513                   Sunlight is LIGHT_SUN, which is LIGHT_MAX+1.
514                   - Contains 2 values, day- and night lighting. Each takes 4 bits.
515                 - Mineral content (should be removed from here)
516                 - Uhh... well, most blocks have light or nothing in here.
517         */
518         union
519         {
520                 u8 param1;
521                 //s8 param;
522         };
523         
524         /*
525                 The second parameter. Initialized to 0.
526                 E.g. direction for torches and flowing water.
527                 If param0 >= 0x80, bits 0xf0 of this is extended content type data
528         */
529         union
530         {
531                 u8 param2;
532                 //u8 dir;
533         };
534
535         MapNode(const MapNode & n)
536         {
537                 *this = n;
538         }
539         
540         MapNode(content_t content=CONTENT_AIR, u8 a_param1=0, u8 a_param2=0)
541         {
542                 //param0 = a_param0;
543                 param1 = a_param1;
544                 param2 = a_param2;
545                 // Set after other params because this needs to override part of param2
546                 setContent(content);
547         }
548
549         bool operator==(const MapNode &other)
550         {
551                 return (param0 == other.param0
552                                 && param1 == other.param1
553                                 && param2 == other.param2);
554         }
555         
556         // To be used everywhere
557         content_t getContent()
558         {
559                 if(param0 < 0x80)
560                         return param0;
561                 else
562                         return (param0<<4) + (param2>>4);
563         }
564         void setContent(content_t c)
565         {
566                 if(c < 0x80)
567                 {
568                         if(param0 >= 0x80)
569                                 param2 &= ~(0xf0);
570                         param0 = c;
571                 }
572                 else
573                 {
574                         param0 = c>>4;
575                         param2 &= ~(0xf0);
576                         param2 |= (c&0x0f)<<4;
577                 }
578         }
579         
580         /*
581                 These four are DEPRECATED I guess. -c55
582         */
583         bool light_propagates()
584         {
585                 return light_propagates_content(getContent());
586         }
587         bool sunlight_propagates()
588         {
589                 return sunlight_propagates_content(getContent());
590         }
591         u8 solidness()
592         {
593                 return content_solidness(getContent());
594         }
595         u8 light_source()
596         {
597                 return content_features(*this).light_source;
598         }
599
600         u8 getLightBanksWithSource()
601         {
602                 // Select the brightest of [light source, propagated light]
603                 u8 lightday = 0;
604                 u8 lightnight = 0;
605                 if(content_features(*this).param_type == CPT_LIGHT)
606                 {
607                         lightday = param1 & 0x0f;
608                         lightnight = (param1>>4)&0x0f;
609                 }
610                 if(light_source() > lightday)
611                         lightday = light_source();
612                 if(light_source() > lightnight)
613                         lightnight = light_source();
614                 return (lightday&0x0f) | ((lightnight<<4)&0xf0);
615         }
616
617         u8 getLight(enum LightBank bank)
618         {
619                 // Select the brightest of [light source, propagated light]
620                 u8 light = 0;
621                 if(content_features(*this).param_type == CPT_LIGHT)
622                 {
623                         if(bank == LIGHTBANK_DAY)
624                                 light = param1 & 0x0f;
625                         else if(bank == LIGHTBANK_NIGHT)
626                                 light = (param1>>4)&0x0f;
627                         else
628                                 assert(0);
629                 }
630                 if(light_source() > light)
631                         light = light_source();
632                 return light;
633         }
634         
635         // 0 <= daylight_factor <= 1000
636         // 0 <= return value <= LIGHT_SUN
637         u8 getLightBlend(u32 daylight_factor)
638         {
639                 u8 l = ((daylight_factor * getLight(LIGHTBANK_DAY)
640                         + (1000-daylight_factor) * getLight(LIGHTBANK_NIGHT))
641                         )/1000;
642                 u8 max = LIGHT_MAX;
643                 if(getLight(LIGHTBANK_DAY) == LIGHT_SUN)
644                         max = LIGHT_SUN;
645                 if(l > max)
646                         l = max;
647                 return l;
648         }
649         /*// 0 <= daylight_factor <= 1000
650         // 0 <= return value <= 255
651         u8 getLightBlend(u32 daylight_factor)
652         {
653                 u8 daylight = decode_light(getLight(LIGHTBANK_DAY));
654                 u8 nightlight = decode_light(getLight(LIGHTBANK_NIGHT));
655                 u8 mix = ((daylight_factor * daylight
656                         + (1000-daylight_factor) * nightlight)
657                         )/1000;
658                 return mix;
659         }*/
660
661         void setLight(enum LightBank bank, u8 a_light)
662         {
663                 // If node doesn't contain light data, ignore this
664                 if(content_features(*this).param_type != CPT_LIGHT)
665                         return;
666                 if(bank == LIGHTBANK_DAY)
667                 {
668                         param1 &= 0xf0;
669                         param1 |= a_light & 0x0f;
670                 }
671                 else if(bank == LIGHTBANK_NIGHT)
672                 {
673                         param1 &= 0x0f;
674                         param1 |= (a_light & 0x0f)<<4;
675                 }
676                 else
677                         assert(0);
678         }
679         
680         // In mapnode.cpp
681 #ifndef SERVER
682         /*
683                 Get tile of a face of the node.
684                 dir: direction of face
685                 Returns: TileSpec. Can contain miscellaneous texture coordinates,
686                          which must be obeyed so that the texture atlas can be used.
687         */
688         TileSpec getTile(v3s16 dir);
689 #endif
690         
691         /*
692                 Gets mineral content of node, if there is any.
693                 MINERAL_NONE if doesn't contain or isn't able to contain mineral.
694         */
695         u8 getMineral();
696         
697         /*
698                 Serialization functions
699         */
700
701         static u32 serializedLength(u8 version);
702         void serialize(u8 *dest, u8 version);
703         void deSerialize(u8 *source, u8 version);
704         
705 };
706
707 /*
708         Gets lighting value at face of node
709         
710         Parameters must consist of air and !air.
711         Order doesn't matter.
712
713         If either of the nodes doesn't exist, light is 0.
714         
715         parameters:
716                 daynight_ratio: 0...1000
717                 n: getNodeParent(p)
718                 n2: getNodeParent(p + face_dir)
719                 face_dir: axis oriented unit vector from p to p2
720         
721         returns encoded light value.
722 */
723 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
724                 v3s16 face_dir);
725
726 #endif
727