/* Minetest-c55 Copyright (C) 2010 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef MAPBLOCK_HEADER #define MAPBLOCK_HEADER #include #include #include #include "debug.h" #include "common_irrlicht.h" #include "mapnode.h" #include "exceptions.h" #include "serialization.h" #include "constants.h" #include "mapblockobject.h" #include "voxel.h" #define MAP_BLOCKSIZE 16 // Named by looking towards z+ enum{ FACE_BACK=0, FACE_TOP, FACE_RIGHT, FACE_FRONT, FACE_BOTTOM, FACE_LEFT }; struct FastFace { TileSpec tile; video::S3DVertex vertices[4]; // Precalculated vertices }; enum NodeModType { NODEMOD_NONE, NODEMOD_CHANGECONTENT, //param is content id NODEMOD_CRACK // param is crack progression }; struct NodeMod { NodeMod(enum NodeModType a_type=NODEMOD_NONE, u16 a_param=0) { type = a_type; param = a_param; } enum NodeModType type; u16 param; }; enum { NODECONTAINER_ID_MAPBLOCK, NODECONTAINER_ID_MAPSECTOR, NODECONTAINER_ID_MAP, NODECONTAINER_ID_MAPBLOCKCACHE, NODECONTAINER_ID_VOXELMANIPULATOR, }; class NodeContainer { public: virtual bool isValidPosition(v3s16 p) = 0; virtual MapNode getNode(v3s16 p) = 0; virtual void setNode(v3s16 p, MapNode & n) = 0; virtual u16 nodeContainerId() const = 0; }; class MapBlock : public NodeContainer { public: MapBlock(NodeContainer *parent, v3s16 pos, bool dummy=false); ~MapBlock(); virtual u16 nodeContainerId() const { return NODECONTAINER_ID_MAPBLOCK; } NodeContainer * getParent() { return m_parent; } bool isDummy() { return (data == NULL); } void unDummify() { assert(isDummy()); reallocate(); } bool getChangedFlag() { return changed; } void resetChangedFlag() { changed = false; } void setChangedFlag() { changed = true; } #ifndef SERVER void setMeshExpired(bool expired) { m_mesh_expired = expired; } bool getMeshExpired() { return m_mesh_expired; } #endif v3s16 getPos() { return m_pos; } v3s16 getPosRelative() { return m_pos * MAP_BLOCKSIZE; } bool getIsUnderground() { return is_underground; } void setIsUnderground(bool a_is_underground) { is_underground = a_is_underground; setChangedFlag(); } core::aabbox3d getBox() { return core::aabbox3d(getPosRelative(), getPosRelative() + v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE) - v3s16(1,1,1)); } void reallocate() { if(data != NULL) delete[] data; u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; data = new MapNode[l]; for(u32 i=0; i= 0 && p.X < MAP_BLOCKSIZE && p.Y >= 0 && p.Y < MAP_BLOCKSIZE && p.Z >= 0 && p.Z < MAP_BLOCKSIZE); } /* Regular MapNode get-setters */ MapNode getNode(s16 x, s16 y, s16 z) { if(data == NULL) throw InvalidPositionException(); if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException(); if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException(); if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException(); return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x]; } MapNode getNode(v3s16 p) { return getNode(p.X, p.Y, p.Z); } void setNode(s16 x, s16 y, s16 z, MapNode & n) { if(data == NULL) throw InvalidPositionException(); if(x < 0 || x >= MAP_BLOCKSIZE) throw InvalidPositionException(); if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException(); if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException(); data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n; setChangedFlag(); } void setNode(v3s16 p, MapNode & n) { setNode(p.X, p.Y, p.Z, n); } /* Non-checking variants of the above */ MapNode getNodeNoCheck(s16 x, s16 y, s16 z) { if(data == NULL) throw InvalidPositionException(); return data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x]; } MapNode getNodeNoCheck(v3s16 p) { return getNodeNoCheck(p.X, p.Y, p.Z); } void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n) { if(data == NULL) throw InvalidPositionException(); data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n; setChangedFlag(); } void setNodeNoCheck(v3s16 p, MapNode & n) { setNodeNoCheck(p.X, p.Y, p.Z, n); } /* These functions consult the parent container if the position is not valid on this MapBlock. */ bool isValidPositionParent(v3s16 p); MapNode getNodeParent(v3s16 p); void setNodeParent(v3s16 p, MapNode & n); MapNode getNodeParentNoEx(v3s16 p); void drawbox(s16 x0, s16 y0, s16 z0, s16 w, s16 h, s16 d, MapNode node) { for(u16 z=0; z &dest); TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir); u8 getNodeContent(v3s16 p, MapNode mn); /* startpos: translate_dir: unit vector with only one of x, y or z face_dir: unit vector with only one of x, y or z */ void updateFastFaceRow( u32 daynight_ratio, v3f posRelative_f, v3s16 startpos, u16 length, v3s16 translate_dir, v3f translate_dir_f, v3s16 face_dir, v3f face_dir_f, core::array &dest); void updateMesh(u32 daynight_ratio); /*void updateMesh(s32 daynight_i); // Updates all DAYNIGHT_CACHE_COUNT meshes void updateMeshes(s32 first_i=0);*/ #endif // !SERVER bool propagateSunlight(core::map & light_sources); // Copies data to VoxelManipulator to getPosRelative() void copyTo(VoxelManipulator &dst); /* Object stuff */ void serializeObjects(std::ostream &os, u8 version) { m_objects.serialize(os, version); } // If smgr!=NULL, new objects are added to the scene void updateObjects(std::istream &is, u8 version, scene::ISceneManager *smgr, u32 daynight_ratio) { m_objects.update(is, version, smgr, daynight_ratio); setChangedFlag(); } void clearObjects() { m_objects.clear(); setChangedFlag(); } void addObject(MapBlockObject *object) throw(ContainerFullException, AlreadyExistsException) { m_objects.add(object); setChangedFlag(); } void removeObject(s16 id) { m_objects.remove(id); setChangedFlag(); } MapBlockObject * getObject(s16 id) { return m_objects.get(id); } JMutexAutoLock * getObjectLock() { return m_objects.getLock(); } /* Moves objects, deletes objects and spawns new objects */ void stepObjects(float dtime, bool server, u32 daynight_ratio); /*void wrapObject(MapBlockObject *object) { m_objects.wrapObject(object); setChangedFlag(); }*/ // origin is relative to block void getObjects(v3f origin, f32 max_d, core::array &dest) { m_objects.getObjects(origin, max_d, dest); } /*void getPseudoObjects(v3f origin, f32 max_d, core::array &dest);*/ s32 getObjectCount() { return m_objects.getCount(); } #ifndef SERVER /* Methods for setting temporary modifications to nodes for drawing */ void setTempMod(v3s16 p, NodeMod mod) { /*dstream<<"setTempMod called on block" <<" ("<