/* 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" #include "nodemetadata.h" #include "staticobject.h" #include "mapblock_nodemod.h" #ifndef SERVER #include "mapblock_mesh.h" #endif class Map; #define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff /*// Named by looking towards z+ enum{ FACE_BACK=0, FACE_TOP, FACE_RIGHT, FACE_FRONT, FACE_BOTTOM, FACE_LEFT };*/ enum ModifiedState { // Has not been modified. MOD_STATE_CLEAN = 0, MOD_RESERVED1 = 1, // Has been modified, and will be saved when being unloaded. MOD_STATE_WRITE_AT_UNLOAD = 2, MOD_RESERVED3 = 3, // Has been modified, and will be saved as soon as possible. MOD_STATE_WRITE_NEEDED = 4, MOD_RESERVED5 = 5, }; // NOTE: If this is enabled, set MapBlock to be initialized with // CONTENT_IGNORE. /*enum BlockGenerationStatus { // Completely non-generated (filled with CONTENT_IGNORE). BLOCKGEN_UNTOUCHED=0, // Trees or similar might have been blitted from other blocks to here. // Otherwise, the block contains CONTENT_IGNORE BLOCKGEN_FROM_NEIGHBORS=2, // Has been generated, but some neighbors might put some stuff in here // when they are generated. // Does not contain any CONTENT_IGNORE BLOCKGEN_SELF_GENERATED=4, // The block and all its neighbors have been generated BLOCKGEN_FULLY_GENERATED=6 };*/ #if 0 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; MapNode getNodeNoEx(v3s16 p) { try{ return getNode(p); } catch(InvalidPositionException &e){ return MapNode(CONTENT_IGNORE); } } }; #endif /* MapBlock itself */ class MapBlock /*: public NodeContainer*/ { public: MapBlock(Map *parent, v3s16 pos, bool dummy=false); ~MapBlock(); /*virtual u16 nodeContainerId() const { return NODECONTAINER_ID_MAPBLOCK; }*/ Map * getParent() { return m_parent; } void reallocate() { if(data != NULL) delete[] data; u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; data = new MapNode[l]; for(u32 i=0; i getBox() { return core::aabbox3d(getPosRelative(), getPosRelative() + v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE) - v3s16(1,1,1)); } /* Regular MapNode get-setters */ bool isValidPosition(v3s16 p) { if(data == NULL) return false; return (p.X >= 0 && p.X < MAP_BLOCKSIZE && p.Y >= 0 && p.Y < MAP_BLOCKSIZE && p.Z >= 0 && p.Z < MAP_BLOCKSIZE); } 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); } MapNode getNodeNoEx(v3s16 p) { try{ return getNode(p.X, p.Y, p.Z); }catch(InvalidPositionException &e){ return MapNode(CONTENT_IGNORE); } } 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; raiseModified(MOD_STATE_WRITE_NEEDED); } 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; raiseModified(MOD_STATE_WRITE_NEEDED); } 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 & light_sources, bool remove_light=false, bool *black_air_left=NULL); // Copies data to VoxelManipulator to getPosRelative() void copyTo(VoxelManipulator &dst); // Copies data from VoxelManipulator getPosRelative() void copyFrom(VoxelManipulator &dst); /* MapBlockObject stuff DEPRECATED */ /*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); raiseModified(MOD_STATE_WRITE_NEEDED); } void clearObjects() { m_objects.clear(); raiseModified(MOD_STATE_WRITE_NEEDED); } void addObject(MapBlockObject *object) throw(ContainerFullException, AlreadyExistsException) { m_objects.add(object); raiseModified(MOD_STATE_WRITE_NEEDED); } void removeObject(s16 id) { m_objects.remove(id); raiseModified(MOD_STATE_WRITE_NEEDED); } 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); // origin is relative to block void getObjects(v3f origin, f32 max_d, core::array &dest) { m_objects.getObjects(origin, max_d, dest); } s32 getObjectCount() { return m_objects.getCount(); } #ifndef SERVER // Only on client /* Methods for setting temporary modifications to nodes for drawing returns true if the mod was different last time */ bool setTempMod(v3s16 p, const NodeMod &mod) { /*dstream<<"setTempMod called on block" <<" ("<