3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #ifndef MAPBLOCK_HEADER
21 #define MAPBLOCK_HEADER
24 #include <jmutexautolock.h>
27 #include "common_irrlicht.h"
29 #include "exceptions.h"
30 #include "serialization.h"
31 #include "constants.h"
32 #include "mapblockobject.h"
34 #include "nodemetadata.h"
37 // Named by looking towards z+
50 video::S3DVertex vertices[4]; // Precalculated vertices
56 NODEMOD_CHANGECONTENT, //param is content id
57 NODEMOD_CRACK // param is crack progression
62 NodeMod(enum NodeModType a_type=NODEMOD_NONE, u16 a_param=0)
67 bool operator==(const NodeMod &other)
69 return (type == other.type && param == other.param);
71 enum NodeModType type;
79 returns true if the mod was different last time
81 bool set(v3s16 p, const NodeMod &mod)
83 // See if old is different, cancel if it is not different.
84 core::map<v3s16, NodeMod>::Node *n = m_mods.find(p);
87 NodeMod old = n->getValue();
95 m_mods.insert(p, mod);
100 // Returns true if there was one
101 bool get(v3s16 p, NodeMod *mod)
103 core::map<v3s16, NodeMod>::Node *n;
108 *mod = n->getValue();
122 if(m_mods.size() == 0)
127 void copy(NodeModMap &dest)
131 for(core::map<v3s16, NodeMod>::Iterator
132 i = m_mods.getIterator();
133 i.atEnd() == false; i++)
135 dest.m_mods.insert(i.getNode()->getKey(), i.getNode()->getValue());
140 core::map<v3s16, NodeMod> m_mods;
145 NODECONTAINER_ID_MAPBLOCK,
146 NODECONTAINER_ID_MAPSECTOR,
147 NODECONTAINER_ID_MAP,
148 NODECONTAINER_ID_MAPBLOCKCACHE,
149 NODECONTAINER_ID_VOXELMANIPULATOR,
155 virtual bool isValidPosition(v3s16 p) = 0;
156 virtual MapNode getNode(v3s16 p) = 0;
157 virtual void setNode(v3s16 p, MapNode & n) = 0;
158 virtual u16 nodeContainerId() const = 0;
160 MapNode getNodeNoEx(v3s16 p)
165 catch(InvalidPositionException &e){
166 return MapNode(CONTENT_IGNORE);
181 u32 m_daynight_ratio;
182 NodeModMap m_temp_mods;
183 VoxelManipulator m_vmanip;
187 Copy central data directly from block, and other data from
190 void fill(u32 daynight_ratio, MapBlock *block);
193 scene::SMesh* makeMapBlockMesh(MeshMakeData *data);
197 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
204 class MapBlock : public NodeContainer
207 MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false);
210 virtual u16 nodeContainerId() const
212 return NODECONTAINER_ID_MAPBLOCK;
215 NodeContainer * getParent()
224 u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
225 data = new MapNode[l];
226 for(u32 i=0; i<l; i++){
238 return (data == NULL);
246 bool getChangedFlag()
250 void resetChangedFlag()
254 void setChangedFlag()
259 bool getIsUnderground()
261 return is_underground;
264 void setIsUnderground(bool a_is_underground)
266 is_underground = a_is_underground;
271 void setMeshExpired(bool expired)
273 m_mesh_expired = expired;
276 bool getMeshExpired()
278 return m_mesh_expired;
282 void setLightingExpired(bool expired)
284 m_lighting_expired = expired;
287 bool getLightingExpired()
289 return m_lighting_expired;
292 /*bool isFullyGenerated()
294 return !m_not_fully_generated;
296 void setFullyGenerated(bool b)
299 m_not_fully_generated = !b;
304 if(m_lighting_expired)
320 v3s16 getPosRelative()
322 return m_pos * MAP_BLOCKSIZE;
325 core::aabbox3d<s16> getBox()
327 return core::aabbox3d<s16>(getPosRelative(),
329 + v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE)
334 Regular MapNode get-setters
337 bool isValidPosition(v3s16 p)
341 return (p.X >= 0 && p.X < MAP_BLOCKSIZE
342 && p.Y >= 0 && p.Y < MAP_BLOCKSIZE
343 && p.Z >= 0 && p.Z < MAP_BLOCKSIZE);
346 MapNode getNode(s16 x, s16 y, s16 z)
349 throw InvalidPositionException();
350 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
351 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
352 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
353 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
356 MapNode getNode(v3s16 p)
358 return getNode(p.X, p.Y, p.Z);
361 void setNode(s16 x, s16 y, s16 z, MapNode & n)
364 throw InvalidPositionException();
365 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
366 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
367 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
368 data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
372 void setNode(v3s16 p, MapNode & n)
374 setNode(p.X, p.Y, p.Z, n);
378 Non-checking variants of the above
381 MapNode getNodeNoCheck(s16 x, s16 y, s16 z)
384 throw InvalidPositionException();
385 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
388 MapNode getNodeNoCheck(v3s16 p)
390 return getNodeNoCheck(p.X, p.Y, p.Z);
393 void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n)
396 throw InvalidPositionException();
397 data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
401 void setNodeNoCheck(v3s16 p, MapNode & n)
403 setNodeNoCheck(p.X, p.Y, p.Z, n);
407 These functions consult the parent container if the position
408 is not valid on this MapBlock.
410 bool isValidPositionParent(v3s16 p);
411 MapNode getNodeParent(v3s16 p);
412 void setNodeParent(v3s16 p, MapNode & n);
413 MapNode getNodeParentNoEx(v3s16 p);
415 void drawbox(s16 x0, s16 y0, s16 z0, s16 w, s16 h, s16 d, MapNode node)
417 for(u16 z=0; z<d; z++)
418 for(u16 y=0; y<h; y++)
419 for(u16 x=0; x<w; x++)
420 setNode(x0+x, y0+y, z0+z, node);
424 Graphics-related methods
427 /*// A quick version with nodes passed as parameters
428 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
430 /*// A more convenient version
431 u8 getFaceLight(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
433 return getFaceLight(daynight_ratio,
434 getNodeParentNoEx(p),
435 getNodeParentNoEx(p + face_dir),
438 u8 getFaceLight2(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
440 return getFaceLight(daynight_ratio,
441 getNodeParentNoEx(p),
442 getNodeParentNoEx(p + face_dir),
448 /*static void makeFastFace(TileSpec tile, u8 light, v3f p,
449 v3s16 dir, v3f scale, v3f posRelative_f,
450 core::array<FastFace> &dest);*/
452 /*TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
453 NodeModMap &temp_mods);*/
454 /*u8 getNodeContent(v3s16 p, MapNode mn,
455 NodeModMap &temp_mods);*/
458 Generates the FastFaces of a node row. This has a
459 ridiculous amount of parameters because that way they
460 can be precalculated by the caller.
462 translate_dir: unit vector with only one of x, y or z
463 face_dir: unit vector with only one of x, y or z
465 /*void updateFastFaceRow(
474 core::array<FastFace> &dest,
475 NodeModMap &temp_mods);*/
478 Thread-safely updates the whole mesh of the mapblock.
481 void updateMesh(u32 daynight_ratio);
484 void replaceMesh(scene::SMesh *mesh_new);
488 // See comments in mapblock.cpp
489 bool propagateSunlight(core::map<v3s16, bool> & light_sources,
490 bool remove_light=false, bool *black_air_left=NULL,
491 bool grow_grass=false);
493 // Copies data to VoxelManipulator to getPosRelative()
494 void copyTo(VoxelManipulator &dst);
495 // Copies data from VoxelManipulator getPosRelative()
496 void copyFrom(VoxelManipulator &dst);
502 void serializeObjects(std::ostream &os, u8 version)
504 m_objects.serialize(os, version);
506 // If smgr!=NULL, new objects are added to the scene
507 void updateObjects(std::istream &is, u8 version,
508 scene::ISceneManager *smgr, u32 daynight_ratio)
510 m_objects.update(is, version, smgr, daynight_ratio);
520 void addObject(MapBlockObject *object)
521 throw(ContainerFullException, AlreadyExistsException)
523 m_objects.add(object);
527 void removeObject(s16 id)
529 m_objects.remove(id);
533 MapBlockObject * getObject(s16 id)
535 return m_objects.get(id);
537 JMutexAutoLock * getObjectLock()
539 return m_objects.getLock();
543 Moves objects, deletes objects and spawns new objects
545 void stepObjects(float dtime, bool server, u32 daynight_ratio);
547 /*void wrapObject(MapBlockObject *object)
549 m_objects.wrapObject(object);
554 // origin is relative to block
555 void getObjects(v3f origin, f32 max_d,
556 core::array<DistanceSortedObject> &dest)
558 m_objects.getObjects(origin, max_d, dest);
563 return m_objects.getCount();
568 Methods for setting temporary modifications to nodes for
571 returns true if the mod was different last time
573 bool setTempMod(v3s16 p, const NodeMod &mod)
575 /*dstream<<"setTempMod called on block"
576 <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
577 <<", mod.type="<<mod.type
578 <<", mod.param="<<mod.param
580 JMutexAutoLock lock(m_temp_mods_mutex);
582 return m_temp_mods.set(p, mod);
584 // Returns true if there was one
585 bool getTempMod(v3s16 p, NodeMod *mod)
587 JMutexAutoLock lock(m_temp_mods_mutex);
589 return m_temp_mods.get(p, mod);
591 bool clearTempMod(v3s16 p)
593 JMutexAutoLock lock(m_temp_mods_mutex);
595 return m_temp_mods.clear(p);
599 JMutexAutoLock lock(m_temp_mods_mutex);
601 return m_temp_mods.clear();
603 void copyTempMods(NodeModMap &dst)
605 JMutexAutoLock lock(m_temp_mods_mutex);
606 m_temp_mods.copy(dst);
611 Update day-night lighting difference flag.
613 Sets m_day_night_differs to appropriate value.
615 These methods don't care about neighboring blocks.
616 It means that to know if a block really doesn't need a mesh
617 update between day and night, the neighboring blocks have
618 to be taken into account. Use Map::dayNightDiffed().
620 void updateDayNightDiff();
622 bool dayNightDiffed()
624 return m_day_night_differs;
632 Tries to measure ground level.
637 0...MAP_BLOCKSIZE-1 = ground level
639 s16 getGroundLevel(v2s16 p2d);
645 // Doesn't write version by itself
646 void serialize(std::ostream &os, u8 version);
648 void deSerialize(std::istream &is, u8 version);
656 Used only internally, because changes can't be tracked
659 MapNode & getNodeRef(s16 x, s16 y, s16 z)
662 throw InvalidPositionException();
663 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
664 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
665 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
666 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
668 MapNode & getNodeRef(v3s16 &p)
670 return getNodeRef(p.X, p.Y, p.Z);
675 Public member variables
683 NodeMetadataList m_node_metadata;
687 Private member variables
690 // NOTE: Lots of things rely on this being the Map
691 NodeContainer *m_parent;
692 // Position in blocks on parent
696 If NULL, block is a dummy block.
697 Dummy blocks are used for caching not-found-on-disk blocks.
702 - On the server, this is used for telling whether the
703 block has been changed from the one on disk.
704 - On the client, this is used for nothing.
709 When propagating sunlight and the above block doesn't exist,
710 sunlight is assumed if this is false.
712 In practice this is set to true if the block is completely
713 undeground with nothing visible above the ground except
719 Set to true if changes has been made that make the old lighting
720 values wrong but the lighting hasn't been actually updated.
722 If this is false, lighting is exactly right.
723 If this is true, lighting might be wrong or right.
725 bool m_lighting_expired;
727 // Whether day and night lighting differs
728 bool m_day_night_differs;
730 MapBlockObjectList m_objects;
732 // Object spawning stuff
735 #ifndef SERVER // Only on client
737 Set to true if the mesh has been ordered to be updated
738 sometime in the background.
739 In practice this is set when the day/night lighting switches.
743 // Temporary modifications to nodes
744 // These are only used when drawing
745 NodeModMap m_temp_mods;
746 JMutex m_temp_mods_mutex;
750 inline bool blockpos_over_limit(v3s16 p)
753 (p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
754 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
755 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
756 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
757 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
758 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE);
762 Returns the position of the block where the node is located
764 inline v3s16 getNodeBlockPos(v3s16 p)
766 return getContainerPos(p, MAP_BLOCKSIZE);
769 inline v2s16 getNodeSectorPos(v2s16 p)
771 return getContainerPos(p, MAP_BLOCKSIZE);
774 inline s16 getNodeBlockY(s16 y)
776 return getContainerPos(y, MAP_BLOCKSIZE);