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"
35 #include "staticobject.h"
38 // Named by looking towards z+
51 video::S3DVertex vertices[4]; // Precalculated vertices
57 NODEMOD_CHANGECONTENT, //param is content id
58 NODEMOD_CRACK // param is crack progression
63 NodeMod(enum NodeModType a_type=NODEMOD_NONE, u16 a_param=0)
68 bool operator==(const NodeMod &other)
70 return (type == other.type && param == other.param);
72 enum NodeModType type;
80 returns true if the mod was different last time
82 bool set(v3s16 p, const NodeMod &mod)
84 // See if old is different, cancel if it is not different.
85 core::map<v3s16, NodeMod>::Node *n = m_mods.find(p);
88 NodeMod old = n->getValue();
96 m_mods.insert(p, mod);
101 // Returns true if there was one
102 bool get(v3s16 p, NodeMod *mod)
104 core::map<v3s16, NodeMod>::Node *n;
109 *mod = n->getValue();
123 if(m_mods.size() == 0)
128 void copy(NodeModMap &dest)
132 for(core::map<v3s16, NodeMod>::Iterator
133 i = m_mods.getIterator();
134 i.atEnd() == false; i++)
136 dest.m_mods.insert(i.getNode()->getKey(), i.getNode()->getValue());
141 core::map<v3s16, NodeMod> m_mods;
146 NODECONTAINER_ID_MAPBLOCK,
147 NODECONTAINER_ID_MAPSECTOR,
148 NODECONTAINER_ID_MAP,
149 NODECONTAINER_ID_MAPBLOCKCACHE,
150 NODECONTAINER_ID_VOXELMANIPULATOR,
156 virtual bool isValidPosition(v3s16 p) = 0;
157 virtual MapNode getNode(v3s16 p) = 0;
158 virtual void setNode(v3s16 p, MapNode & n) = 0;
159 virtual u16 nodeContainerId() const = 0;
161 MapNode getNodeNoEx(v3s16 p)
166 catch(InvalidPositionException &e){
167 return MapNode(CONTENT_IGNORE);
182 u32 m_daynight_ratio;
183 NodeModMap m_temp_mods;
184 VoxelManipulator m_vmanip;
188 Copy central data directly from block, and other data from
191 void fill(u32 daynight_ratio, MapBlock *block);
194 scene::SMesh* makeMapBlockMesh(MeshMakeData *data);
198 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
205 class MapBlock : public NodeContainer
208 MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false);
211 virtual u16 nodeContainerId() const
213 return NODECONTAINER_ID_MAPBLOCK;
216 NodeContainer * getParent()
225 u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
226 data = new MapNode[l];
227 for(u32 i=0; i<l; i++){
239 return (data == NULL);
247 bool getChangedFlag()
251 void resetChangedFlag()
255 void setChangedFlag()
260 bool getIsUnderground()
262 return is_underground;
265 void setIsUnderground(bool a_is_underground)
267 is_underground = a_is_underground;
272 void setMeshExpired(bool expired)
274 m_mesh_expired = expired;
277 bool getMeshExpired()
279 return m_mesh_expired;
283 void setLightingExpired(bool expired)
285 m_lighting_expired = expired;
288 bool getLightingExpired()
290 return m_lighting_expired;
293 /*bool isFullyGenerated()
295 return !m_not_fully_generated;
297 void setFullyGenerated(bool b)
300 m_not_fully_generated = !b;
305 if(m_lighting_expired)
321 v3s16 getPosRelative()
323 return m_pos * MAP_BLOCKSIZE;
326 core::aabbox3d<s16> getBox()
328 return core::aabbox3d<s16>(getPosRelative(),
330 + v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE)
335 Regular MapNode get-setters
338 bool isValidPosition(v3s16 p)
342 return (p.X >= 0 && p.X < MAP_BLOCKSIZE
343 && p.Y >= 0 && p.Y < MAP_BLOCKSIZE
344 && p.Z >= 0 && p.Z < MAP_BLOCKSIZE);
347 MapNode getNode(s16 x, s16 y, s16 z)
350 throw InvalidPositionException();
351 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
352 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
353 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
354 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
357 MapNode getNode(v3s16 p)
359 return getNode(p.X, p.Y, p.Z);
362 void setNode(s16 x, s16 y, s16 z, MapNode & n)
365 throw InvalidPositionException();
366 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
367 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
368 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
369 data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
373 void setNode(v3s16 p, MapNode & n)
375 setNode(p.X, p.Y, p.Z, n);
379 Non-checking variants of the above
382 MapNode getNodeNoCheck(s16 x, s16 y, s16 z)
385 throw InvalidPositionException();
386 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
389 MapNode getNodeNoCheck(v3s16 p)
391 return getNodeNoCheck(p.X, p.Y, p.Z);
394 void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n)
397 throw InvalidPositionException();
398 data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
402 void setNodeNoCheck(v3s16 p, MapNode & n)
404 setNodeNoCheck(p.X, p.Y, p.Z, n);
408 These functions consult the parent container if the position
409 is not valid on this MapBlock.
411 bool isValidPositionParent(v3s16 p);
412 MapNode getNodeParent(v3s16 p);
413 void setNodeParent(v3s16 p, MapNode & n);
414 MapNode getNodeParentNoEx(v3s16 p);
416 void drawbox(s16 x0, s16 y0, s16 z0, s16 w, s16 h, s16 d, MapNode node)
418 for(u16 z=0; z<d; z++)
419 for(u16 y=0; y<h; y++)
420 for(u16 x=0; x<w; x++)
421 setNode(x0+x, y0+y, z0+z, node);
425 Graphics-related methods
428 /*// A quick version with nodes passed as parameters
429 u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
431 /*// A more convenient version
432 u8 getFaceLight(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
434 return getFaceLight(daynight_ratio,
435 getNodeParentNoEx(p),
436 getNodeParentNoEx(p + face_dir),
439 u8 getFaceLight2(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
441 return getFaceLight(daynight_ratio,
442 getNodeParentNoEx(p),
443 getNodeParentNoEx(p + face_dir),
449 /*static void makeFastFace(TileSpec tile, u8 light, v3f p,
450 v3s16 dir, v3f scale, v3f posRelative_f,
451 core::array<FastFace> &dest);*/
453 /*TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
454 NodeModMap &temp_mods);*/
455 /*u8 getNodeContent(v3s16 p, MapNode mn,
456 NodeModMap &temp_mods);*/
459 Generates the FastFaces of a node row. This has a
460 ridiculous amount of parameters because that way they
461 can be precalculated by the caller.
463 translate_dir: unit vector with only one of x, y or z
464 face_dir: unit vector with only one of x, y or z
466 /*void updateFastFaceRow(
475 core::array<FastFace> &dest,
476 NodeModMap &temp_mods);*/
479 Thread-safely updates the whole mesh of the mapblock.
482 void updateMesh(u32 daynight_ratio);
485 void replaceMesh(scene::SMesh *mesh_new);
489 // See comments in mapblock.cpp
490 bool propagateSunlight(core::map<v3s16, bool> & light_sources,
491 bool remove_light=false, bool *black_air_left=NULL,
492 bool grow_grass=false);
494 // Copies data to VoxelManipulator to getPosRelative()
495 void copyTo(VoxelManipulator &dst);
496 // Copies data from VoxelManipulator getPosRelative()
497 void copyFrom(VoxelManipulator &dst);
503 void serializeObjects(std::ostream &os, u8 version)
505 m_objects.serialize(os, version);
507 // If smgr!=NULL, new objects are added to the scene
508 void updateObjects(std::istream &is, u8 version,
509 scene::ISceneManager *smgr, u32 daynight_ratio)
511 m_objects.update(is, version, smgr, daynight_ratio);
521 void addObject(MapBlockObject *object)
522 throw(ContainerFullException, AlreadyExistsException)
524 m_objects.add(object);
528 void removeObject(s16 id)
530 m_objects.remove(id);
534 MapBlockObject * getObject(s16 id)
536 return m_objects.get(id);
538 JMutexAutoLock * getObjectLock()
540 return m_objects.getLock();
544 Moves objects, deletes objects and spawns new objects
546 void stepObjects(float dtime, bool server, u32 daynight_ratio);
548 /*void wrapObject(MapBlockObject *object)
550 m_objects.wrapObject(object);
555 // origin is relative to block
556 void getObjects(v3f origin, f32 max_d,
557 core::array<DistanceSortedObject> &dest)
559 m_objects.getObjects(origin, max_d, dest);
564 return m_objects.getCount();
569 Methods for setting temporary modifications to nodes for
572 returns true if the mod was different last time
574 bool setTempMod(v3s16 p, const NodeMod &mod)
576 /*dstream<<"setTempMod called on block"
577 <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
578 <<", mod.type="<<mod.type
579 <<", mod.param="<<mod.param
581 JMutexAutoLock lock(m_temp_mods_mutex);
583 return m_temp_mods.set(p, mod);
585 // Returns true if there was one
586 bool getTempMod(v3s16 p, NodeMod *mod)
588 JMutexAutoLock lock(m_temp_mods_mutex);
590 return m_temp_mods.get(p, mod);
592 bool clearTempMod(v3s16 p)
594 JMutexAutoLock lock(m_temp_mods_mutex);
596 return m_temp_mods.clear(p);
600 JMutexAutoLock lock(m_temp_mods_mutex);
602 return m_temp_mods.clear();
604 void copyTempMods(NodeModMap &dst)
606 JMutexAutoLock lock(m_temp_mods_mutex);
607 m_temp_mods.copy(dst);
612 Update day-night lighting difference flag.
614 Sets m_day_night_differs to appropriate value.
616 These methods don't care about neighboring blocks.
617 It means that to know if a block really doesn't need a mesh
618 update between day and night, the neighboring blocks have
619 to be taken into account. Use Map::dayNightDiffed().
621 void updateDayNightDiff();
623 bool dayNightDiffed()
625 return m_day_night_differs;
633 Tries to measure ground level.
638 0...MAP_BLOCKSIZE-1 = ground level
640 s16 getGroundLevel(v2s16 p2d);
646 // Doesn't write version by itself
647 void serialize(std::ostream &os, u8 version);
649 void deSerialize(std::istream &is, u8 version);
657 Used only internally, because changes can't be tracked
660 MapNode & getNodeRef(s16 x, s16 y, s16 z)
663 throw InvalidPositionException();
664 if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException();
665 if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
666 if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
667 return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x];
669 MapNode & getNodeRef(v3s16 &p)
671 return getNodeRef(p.X, p.Y, p.Z);
676 Public member variables
684 NodeMetadataList m_node_metadata;
685 StaticObjectList m_static_objects;
689 Private member variables
692 // NOTE: Lots of things rely on this being the Map
693 NodeContainer *m_parent;
694 // Position in blocks on parent
698 If NULL, block is a dummy block.
699 Dummy blocks are used for caching not-found-on-disk blocks.
704 - On the server, this is used for telling whether the
705 block has been changed from the one on disk.
706 - On the client, this is used for nothing.
711 When propagating sunlight and the above block doesn't exist,
712 sunlight is assumed if this is false.
714 In practice this is set to true if the block is completely
715 undeground with nothing visible above the ground except
721 Set to true if changes has been made that make the old lighting
722 values wrong but the lighting hasn't been actually updated.
724 If this is false, lighting is exactly right.
725 If this is true, lighting might be wrong or right.
727 bool m_lighting_expired;
729 // Whether day and night lighting differs
730 bool m_day_night_differs;
733 MapBlockObjectList m_objects;
735 // Object spawning stuff
736 //float m_spawn_timer;
738 #ifndef SERVER // Only on client
740 Set to true if the mesh has been ordered to be updated
741 sometime in the background.
742 In practice this is set when the day/night lighting switches.
746 // Temporary modifications to nodes
747 // These are only used when drawing
748 NodeModMap m_temp_mods;
749 JMutex m_temp_mods_mutex;
753 inline bool blockpos_over_limit(v3s16 p)
756 (p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
757 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
758 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
759 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
760 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
761 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE);
765 Returns the position of the block where the node is located
767 inline v3s16 getNodeBlockPos(v3s16 p)
769 return getContainerPos(p, MAP_BLOCKSIZE);
772 inline v2s16 getNodeSectorPos(v2s16 p)
774 return getContainerPos(p, MAP_BLOCKSIZE);
777 inline s16 getNodeBlockY(s16 y)
779 return getContainerPos(y, MAP_BLOCKSIZE);