/* Minetest Copyright (C) 2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser 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 VOXEL_HEADER #define VOXEL_HEADER #include "irrlichttypes.h" #include "irr_v3d.h" #include #include "debug.h" #include "exceptions.h" #include "mapnode.h" #include #include #include class INodeDefManager; // For VC++ #undef min #undef max /* A fast voxel manipulator class. In normal operation, it fetches more map when it is requested. It can also be used so that all allowed area is fetched at the start, using ManualMapVoxelManipulator. Not thread-safe. */ /* Debug stuff */ extern u32 emerge_time; extern u32 emerge_load_time; /* This class resembles aabbox3d a lot, but has inclusive edges for saner handling of integer sizes */ class VoxelArea { public: // Starts as zero sized VoxelArea(): MinEdge(1,1,1), MaxEdge(0,0,0) { } VoxelArea(v3s16 min_edge, v3s16 max_edge): MinEdge(min_edge), MaxEdge(max_edge) { } VoxelArea(v3s16 p): MinEdge(p), MaxEdge(p) { } /* Modifying methods */ void addArea(const VoxelArea &a) { if (hasEmptyExtent()) { *this = a; return; } if(a.MinEdge.X < MinEdge.X) MinEdge.X = a.MinEdge.X; if(a.MinEdge.Y < MinEdge.Y) MinEdge.Y = a.MinEdge.Y; if(a.MinEdge.Z < MinEdge.Z) MinEdge.Z = a.MinEdge.Z; if(a.MaxEdge.X > MaxEdge.X) MaxEdge.X = a.MaxEdge.X; if(a.MaxEdge.Y > MaxEdge.Y) MaxEdge.Y = a.MaxEdge.Y; if(a.MaxEdge.Z > MaxEdge.Z) MaxEdge.Z = a.MaxEdge.Z; } void addPoint(const v3s16 &p) { if(hasEmptyExtent()) { MinEdge = p; MaxEdge = p; return; } if(p.X < MinEdge.X) MinEdge.X = p.X; if(p.Y < MinEdge.Y) MinEdge.Y = p.Y; if(p.Z < MinEdge.Z) MinEdge.Z = p.Z; if(p.X > MaxEdge.X) MaxEdge.X = p.X; if(p.Y > MaxEdge.Y) MaxEdge.Y = p.Y; if(p.Z > MaxEdge.Z) MaxEdge.Z = p.Z; } // Pad with d nodes void pad(const v3s16 &d) { MinEdge -= d; MaxEdge += d; } /*void operator+=(v3s16 off) { MinEdge += off; MaxEdge += off; } void operator-=(v3s16 off) { MinEdge -= off; MaxEdge -= off; }*/ /* const methods */ v3s16 getExtent() const { return MaxEdge - MinEdge + v3s16(1,1,1); } /* Because MaxEdge and MinEdge are included in the voxel area an empty extent * is not represented by (0, 0, 0), but instead (-1, -1, -1) */ bool hasEmptyExtent() const { return MaxEdge - MinEdge == v3s16(-1, -1, -1); } s32 getVolume() const { v3s16 e = getExtent(); return (s32)e.X * (s32)e.Y * (s32)e.Z; } bool contains(const VoxelArea &a) const { // No area contains an empty area // NOTE: Algorithms depend on this, so do not change. if(a.hasEmptyExtent()) return false; return( a.MinEdge.X >= MinEdge.X && a.MaxEdge.X <= MaxEdge.X && a.MinEdge.Y >= MinEdge.Y && a.MaxEdge.Y <= MaxEdge.Y && a.MinEdge.Z >= MinEdge.Z && a.MaxEdge.Z <= MaxEdge.Z ); } bool contains(v3s16 p) const { return( p.X >= MinEdge.X && p.X <= MaxEdge.X && p.Y >= MinEdge.Y && p.Y <= MaxEdge.Y && p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z ); } bool contains(s32 i) const { return (i >= 0 && i < getVolume()); } bool operator==(const VoxelArea &other) const { return (MinEdge == other.MinEdge && MaxEdge == other.MaxEdge); } VoxelArea operator+(v3s16 off) const { return VoxelArea(MinEdge+off, MaxEdge+off); } VoxelArea operator-(v3s16 off) const { return VoxelArea(MinEdge-off, MaxEdge-off); } /* Returns 0-6 non-overlapping areas that can be added to a to make up this area. a: area inside *this */ void diff(const VoxelArea &a, std::list &result) { /* This can result in a maximum of 6 areas */ // If a is an empty area, return the current area as a whole if(a.getExtent() == v3s16(0,0,0)) { VoxelArea b = *this; if(b.getVolume() != 0) result.push_back(b); return; } assert(contains(a)); // pre-condition /* Minetest Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser 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 S_ENV_H_ #define S_ENV_H_ #include "cpp_api/s_base.h" #include "irr_v3d.h" class ServerEnvironment; struct ScriptCallbackState; class ScriptApiEnv : virtual public ScriptApiBase { public: // Called on environment step void environment_Step(float dtime); // Called after generating a piece of map void environment_OnGenerated(v3s16 minp, v3s16 maxp, u32 blockseed); // Called on player event void player_event(ServerActiveObject *player, std::string type); // Called after emerge of a block queued from core.emerge_area() void on_emerge_area_completion(v3s16 blockpos, int action, ScriptCallbackState *state); void initializeEnvironment(ServerEnvironment *env); }; #endif /* S_ENV_H_ */ p) { VoxelArea voxel_area(p); addArea(voxel_area); if(m_flags[m_area.index(p)] & VOXELFLAG_NO_DATA) { return MapNode(CONTENT_IGNORE); } return m_data[m_area.index(p)]; } MapNode getNodeNoExNoEmerge(v3s16 p) { if(m_area.contains(p) == false) return MapNode(CONTENT_IGNORE); if(m_flags[m_area.index(p)] & VOXELFLAG_NO_DATA) return MapNode(CONTENT_IGNORE); return m_data[m_area.index(p)]; } // Stuff explodes if non-emerged area is touched with this. // Emerge first, and check VOXELFLAG_NO_DATA if appropriate. MapNode & getNodeRefUnsafe(const v3s16 &p) { return m_data[m_area.index(p)]; } const MapNode & getNodeRefUnsafeCheckFlags(const v3s16 &p) { s32 index = m_area.index(p); if (m_flags[index] & VOXELFLAG_NO_DATA) return ContentIgnoreNode; return m_data[index]; } u8 & getFlagsRefUnsafe(v3s16 p) { return m_flags[m_area.index(p)]; } bool exists(v3s16 p) { return m_area.contains(p) && !(getFlagsRefUnsafe(p) & VOXELFLAG_NO_DATA); } MapNode & getNodeRef(v3s16 p) { VoxelArea voxel_area(p); addArea(voxel_area); if(getFlagsRefUnsafe(p) & VOXELFLAG_NO_DATA) { /*dstream<<"EXCEPT: VoxelManipulator::getNode(): " <<"p=("< & light_sources, INodeDefManager *nodemgr); void unspreadLight(enum LightBank bank, std::map & from_nodes, std::set & light_sources, INodeDefManager *nodemgr); void spreadLight(enum LightBank bank, v3s16 p, INodeDefManager *nodemgr); void spreadLight(enum LightBank bank, std::set & from_nodes, INodeDefManager *nodemgr); /* Virtual functions */ /* Member variables */ /* The area that is stored in m_data. addInternalBox should not be used if getExtent() == v3s16(0,0,0) MaxEdge is 1 higher than maximum allowed position */ VoxelArea m_area; /* NULL if data size is 0 (extent (0,0,0)) Data is stored as [z*h*w + y*h + x] */ MapNode *m_data; /* Flags of all nodes */ u8 *m_flags; static const MapNode ContentIgnoreNode; //TODO: Use these or remove them //TODO: Would these make any speed improvement? //bool m_pressure_route_valid; //v3s16 m_pressure_route_surface; /* Some settings */ //bool m_disable_water_climb; private: }; #endif