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);
179 u32 m_daynight_ratio;
180 NodeModMap m_temp_mods;
181 VoxelManipulator m_vmanip;
185 Copy central data directly from block, and other data from
188 void fill(u32 daynight_ratio, MapBlock *block);
191 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
194 scene::SMesh* makeMapBlockMesh(MeshMakeData *data);
200 class MapBlock : public NodeContainer
203 MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false);
206 virtual u16 nodeContainerId() const
208 return NODECONTAINER_ID_MAPBLOCK;
211 NodeContainer * getParent()
220 u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
221 data = new MapNode[l];
222 for(u32 i=0; i<l; i++){
234 return (data == NULL);
242 bool getChangedFlag()
246 void resetChangedFlag()
250 void setChangedFlag()
255 bool getIsUnderground()
257 return is_underground;
260 void setIsUnderground(bool a_is_underground)
262 is_underground = a_is_underground;
267 void setMeshExpired(bool expired)
269 m_mesh_expired = expired;
272 bool getMeshExpired()
274 return m_mesh_expired;
278 void setLightingExpired(bool expired)
280 m_lighting_expired = expired;
283 bool getLightingExpired()
285 return m_lighting_expired;
288 /*bool isFullyGenerated()
290 return !m_not_fully_generated;
292 void setFullyGenerated(bool b)
295 m_not_fully_generated = !b;
300 if(m_lighting_expired)
316 v3s16 getPosRelative()
318 return m_pos * MAP_BLOCKSIZE;
321 core::aabbox3d<s16> getBox()
323 return core::aabbox3d<s16>(getPosRelative(),
325 + v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE)
330 Regular MapNode get-setters
333 bool isValidPosition(v3s16 p)
337 return (p.X >= 0 && p.X < MAP_BLOCKSIZE
338 && p.Y >= 0 && p.Y < MAP_BLOCKSIZE
339 && p.Z >= 0 && p.Z < MAP_BLOCKSIZE);
342 MapNode getNode(s16 x, s16 y, s16 z)
345 throw InvalidPositionException();
346 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
347 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
348 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
349 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
352 MapNode getNode(v3s16 p)
354 return getNode(p.X, p.Y, p.Z);
357 void setNode(s16 x, s16 y, s16 z, MapNode & n)
360 throw InvalidPositionException();
361 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
362 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
363 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
364 data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
368 void setNode(v3s16 p, MapNode & n)
370 setNode(p.X, p.Y, p.Z, n);
374 Non-checking variants of the above
377 MapNode getNodeNoCheck(s16 x, s16 y, s16 z)
380 throw InvalidPositionException();
381 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
384 MapNode getNodeNoCheck(v3s16 p)
386 return getNodeNoCheck(p.X, p.Y, p.Z);
389 void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n)
392 throw InvalidPositionException();
393 data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
397 void setNodeNoCheck(v3s16 p, MapNode & n)
399 setNodeNoCheck(p.X, p.Y, p.Z, n);
403 These functions consult the parent container if the position
404 is not valid on this MapBlock.
406 bool isValidPositionParent(v3s16 p);
407 MapNode getNodeParent(v3s16 p);
408 void setNodeParent(v3s16 p, MapNode & n);
409 MapNode getNodeParentNoEx(v3s16 p);
411 void drawbox(s16 x0, s16 y0, s16 z0, s16 w, s16 h, s16 d, MapNode node)
413 for(u16 z=0; z<d; z++)
414 for(u16 y=0; y<h; y++)
415 for(u16 x=0; x<w; x++)
416 setNode(x0+x, y0+y, z0+z, node);
420 Graphics-related methods
423 /*// A quick version with nodes passed as parameters
424 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
426 /*// A more convenient version
427 u8 getFaceLight(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
429 return getFaceLight(daynight_ratio,
430 getNodeParentNoEx(p),
431 getNodeParentNoEx(p + face_dir),
434 u8 getFaceLight2(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
436 return getFaceLight(daynight_ratio,
437 getNodeParentNoEx(p),
438 getNodeParentNoEx(p + face_dir),
444 /*static void makeFastFace(TileSpec tile, u8 light, v3f p,
445 v3s16 dir, v3f scale, v3f posRelative_f,
446 core::array<FastFace> &dest);*/
448 /*TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
449 NodeModMap &temp_mods);*/
450 /*u8 getNodeContent(v3s16 p, MapNode mn,
451 NodeModMap &temp_mods);*/
454 Generates the FastFaces of a node row. This has a
455 ridiculous amount of parameters because that way they
456 can be precalculated by the caller.
458 translate_dir: unit vector with only one of x, y or z
459 face_dir: unit vector with only one of x, y or z
461 /*void updateFastFaceRow(
470 core::array<FastFace> &dest,
471 NodeModMap &temp_mods);*/
474 Thread-safely updates the whole mesh of the mapblock.
477 void updateMesh(u32 daynight_ratio);
480 void replaceMesh(scene::SMesh *mesh_new);
484 // See comments in mapblock.cpp
485 bool propagateSunlight(core::map<v3s16, bool> & light_sources,
486 bool remove_light=false, bool *black_air_left=NULL,
487 bool grow_grass=false);
489 // Copies data to VoxelManipulator to getPosRelative()
490 void copyTo(VoxelManipulator &dst);
491 // Copies data from VoxelManipulator getPosRelative()
492 void copyFrom(VoxelManipulator &dst);
498 void serializeObjects(std::ostream &os, u8 version)
500 m_objects.serialize(os, version);
502 // If smgr!=NULL, new objects are added to the scene
503 void updateObjects(std::istream &is, u8 version,
504 scene::ISceneManager *smgr, u32 daynight_ratio)
506 m_objects.update(is, version, smgr, daynight_ratio);
516 void addObject(MapBlockObject *object)
517 throw(ContainerFullException, AlreadyExistsException)
519 m_objects.add(object);
523 void removeObject(s16 id)
525 m_objects.remove(id);
529 MapBlockObject * getObject(s16 id)
531 return m_objects.get(id);
533 JMutexAutoLock * getObjectLock()
535 return m_objects.getLock();
539 Moves objects, deletes objects and spawns new objects
541 void stepObjects(float dtime, bool server, u32 daynight_ratio);
543 /*void wrapObject(MapBlockObject *object)
545 m_objects.wrapObject(object);
550 // origin is relative to block
551 void getObjects(v3f origin, f32 max_d,
552 core::array<DistanceSortedObject> &dest)
554 m_objects.getObjects(origin, max_d, dest);
559 return m_objects.getCount();
564 Methods for setting temporary modifications to nodes for
567 returns true if the mod was different last time
569 bool setTempMod(v3s16 p, const NodeMod &mod)
571 /*dstream<<"setTempMod called on block"
572 <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
573 <<", mod.type="<<mod.type
574 <<", mod.param="<<mod.param
576 JMutexAutoLock lock(m_temp_mods_mutex);
578 return m_temp_mods.set(p, mod);
580 // Returns true if there was one
581 bool getTempMod(v3s16 p, NodeMod *mod)
583 JMutexAutoLock lock(m_temp_mods_mutex);
585 return m_temp_mods.get(p, mod);
587 bool clearTempMod(v3s16 p)
589 JMutexAutoLock lock(m_temp_mods_mutex);
591 return m_temp_mods.clear(p);
595 JMutexAutoLock lock(m_temp_mods_mutex);
597 return m_temp_mods.clear();
599 void copyTempMods(NodeModMap &dst)
601 JMutexAutoLock lock(m_temp_mods_mutex);
602 m_temp_mods.copy(dst);
607 Update day-night lighting difference flag.
609 Sets m_day_night_differs to appropriate value.
611 These methods don't care about neighboring blocks.
612 It means that to know if a block really doesn't need a mesh
613 update between day and night, the neighboring blocks have
614 to be taken into account. Use Map::dayNightDiffed().
616 void updateDayNightDiff();
618 bool dayNightDiffed()
620 return m_day_night_differs;
628 Tries to measure ground level.
633 0...MAP_BLOCKSIZE-1 = ground level
635 s16 getGroundLevel(v2s16 p2d);
641 // Doesn't write version by itself
642 void serialize(std::ostream &os, u8 version);
644 void deSerialize(std::istream &is, u8 version);
652 Used only internally, because changes can't be tracked
655 MapNode & getNodeRef(s16 x, s16 y, s16 z)
658 throw InvalidPositionException();
659 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
660 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
661 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
662 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
664 MapNode & getNodeRef(v3s16 &p)
666 return getNodeRef(p.X, p.Y, p.Z);
671 Public member variables
679 NodeMetadataList m_node_metadata;
683 Private member variables
686 // NOTE: Lots of things rely on this being the Map
687 NodeContainer *m_parent;
688 // Position in blocks on parent
692 If NULL, block is a dummy block.
693 Dummy blocks are used for caching not-found-on-disk blocks.
698 - On the server, this is used for telling whether the
699 block has been changed from the one on disk.
700 - On the client, this is used for nothing.
705 When propagating sunlight and the above block doesn't exist,
706 sunlight is assumed if this is false.
708 In practice this is set to true if the block is completely
709 undeground with nothing visible above the ground except
715 Set to true if changes has been made that make the old lighting
716 values wrong but the lighting hasn't been actually updated.
718 If this is false, lighting is exactly right.
719 If this is true, lighting might be wrong or right.
721 bool m_lighting_expired;
723 // Whether day and night lighting differs
724 bool m_day_night_differs;
726 MapBlockObjectList m_objects;
728 // Object spawning stuff
731 #ifndef SERVER // Only on client
733 Set to true if the mesh has been ordered to be updated
734 sometime in the background.
735 In practice this is set when the day/night lighting switches.
739 // Temporary modifications to nodes
740 // These are only used when drawing
741 NodeModMap m_temp_mods;
742 JMutex m_temp_mods_mutex;
746 inline bool blockpos_over_limit(v3s16 p)
749 (p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
750 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
751 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
752 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
753 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
754 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE);
758 Returns the position of the block where the node is located
760 inline v3s16 getNodeBlockPos(v3s16 p)
762 return getContainerPos(p, MAP_BLOCKSIZE);
765 inline v2s16 getNodeSectorPos(v2s16 p)
767 return getContainerPos(p, MAP_BLOCKSIZE);
770 inline s16 getNodeBlockY(s16 y)
772 return getContainerPos(y, MAP_BLOCKSIZE);