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