/*
-(c) 2010 Perttu Ahola <celeron55@gmail.com>
+Minetest-c55
+Copyright (C) 2010 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 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 MAP_HEADER
#include "mapblock.h"
#include "mapsector.h"
#include "constants.h"
+#include "voxel.h"
-class InvalidFilenameException : public BaseException
+class Map;
+
+/*
+ A cache for short-term fast access to map data
+
+ NOTE: This doesn't really make anything more efficient
+ NOTE: Use VoxelManipulator, if possible
+ TODO: Get rid of this?
+ NOTE: CONFIRMED: THIS CACHE DOESN'T MAKE ANYTHING ANY FASTER
+*/
+class MapBlockPointerCache : public NodeContainer
{
public:
- InvalidFilenameException(const char *s):
- BaseException(s)
- {}
+ MapBlockPointerCache(Map *map);
+ ~MapBlockPointerCache();
+
+ virtual u16 nodeContainerId() const
+ {
+ return NODECONTAINER_ID_MAPBLOCKCACHE;
+ }
+
+ MapBlock * getBlockNoCreate(v3s16 p);
+
+ // virtual from NodeContainer
+ bool isValidPosition(v3s16 p)
+ {
+ v3s16 blockpos = getNodeBlockPos(p);
+ MapBlock *blockref;
+ try{
+ blockref = getBlockNoCreate(blockpos);
+ }
+ catch(InvalidPositionException &e)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ // virtual from NodeContainer
+ MapNode getNode(v3s16 p)
+ {
+ v3s16 blockpos = getNodeBlockPos(p);
+ MapBlock * blockref = getBlockNoCreate(blockpos);
+ v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
+
+ return blockref->getNodeNoCheck(relpos);
+ }
+
+ // virtual from NodeContainer
+ void setNode(v3s16 p, MapNode & n)
+ {
+ v3s16 blockpos = getNodeBlockPos(p);
+ MapBlock * block = getBlockNoCreate(blockpos);
+ v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
+ block->setNodeNoCheck(relpos, n);
+ m_modified_blocks[blockpos] = block;
+ }
+
+ core::map<v3s16, MapBlock*> m_modified_blocks;
+
+private:
+ Map *m_map;
+ core::map<v3s16, MapBlock*> m_blocks;
+
+ u32 m_from_cache_count;
+ u32 m_from_map_count;
+};
+
+class CacheLock
+{
+public:
+ CacheLock()
+ {
+ m_count = 0;
+ m_count_mutex.Init();
+ m_cache_mutex.Init();
+ m_waitcache_mutex.Init();
+ }
+
+ void cacheCreated()
+ {
+ //dstream<<"cacheCreated() begin"<<std::endl;
+ JMutexAutoLock waitcachelock(m_waitcache_mutex);
+ JMutexAutoLock countlock(m_count_mutex);
+
+ // If this is the first cache, grab the cache lock
+ if(m_count == 0)
+ m_cache_mutex.Lock();
+
+ m_count++;
+
+ //dstream<<"cacheCreated() end"<<std::endl;
+ }
+
+ void cacheRemoved()
+ {
+ //dstream<<"cacheRemoved() begin"<<std::endl;
+ JMutexAutoLock countlock(m_count_mutex);
+
+ assert(m_count > 0);
+
+ m_count--;
+
+ // If this is the last one, release the cache lock
+ if(m_count == 0)
+ m_cache_mutex.Unlock();
+
+ //dstream<<"cacheRemoved() end"<<std::endl;
+ }
+
+ /*
+ This lock should be taken when removing stuff that can be
+ pointed by the cache.
+
+ You'll want to grab this in a SharedPtr.
+ */
+ JMutexAutoLock * waitCaches()
+ {
+ //dstream<<"waitCaches() begin"<<std::endl;
+ JMutexAutoLock waitcachelock(m_waitcache_mutex);
+ JMutexAutoLock *lock = new JMutexAutoLock(m_cache_mutex);
+ //dstream<<"waitCaches() end"<<std::endl;
+ return lock;
+ }
+
+private:
+ // Count of existing caches
+ u32 m_count;
+ JMutex m_count_mutex;
+ // This is locked always when there are some caches
+ JMutex m_cache_mutex;
+ // Locked so that when waitCaches() is called, no more caches are created
+ JMutex m_waitcache_mutex;
};
#define MAPTYPE_BASE 0
public:
v3s16 drawoffset; // for drawbox()
+
+ /*
+ Used by MapBlockPointerCache.
+
+ waitCaches() can be called to remove all caches before continuing
+ */
+ CacheLock m_blockcachelock;
Map(std::ostream &dout);
virtual ~Map();
return MAPTYPE_BASE;
}
+ virtual void drop()
+ {
+ delete this;
+ }
+
void updateCamera(v3f pos, v3f dir)
{
JMutexAutoLock lock(m_camera_mutex);
MapBlock * blockref = getBlockNoCreate(blockpos);
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
- return blockref->getNode(relpos);
+ return blockref->getNodeNoCheck(relpos);
}
// virtual from NodeContainer
v3s16 blockpos = getNodeBlockPos(p);
MapBlock * blockref = getBlockNoCreate(blockpos);
v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
- blockref->setNode(relpos, n);
+ blockref->setNodeNoCheck(relpos, n);
}
/*MapNode getNodeGenerate(v3s16 p)
blockref->setNode(relpos, n);
}*/
- void unspreadLight(core::map<v3s16, u8> & from_nodes,
+ void unspreadLight(enum LightBank bank,
+ core::map<v3s16, u8> & from_nodes,
core::map<v3s16, bool> & light_sources,
core::map<v3s16, MapBlock*> & modified_blocks);
- void unLightNeighbors(v3s16 pos, u8 lightwas,
+ void unLightNeighbors(enum LightBank bank,
+ v3s16 pos, u8 lightwas,
core::map<v3s16, bool> & light_sources,
core::map<v3s16, MapBlock*> & modified_blocks);
- void spreadLight(core::map<v3s16, bool> & from_nodes,
+ void spreadLight(enum LightBank bank,
+ core::map<v3s16, bool> & from_nodes,
core::map<v3s16, MapBlock*> & modified_blocks);
- void lightNeighbors(v3s16 pos,
+ void lightNeighbors(enum LightBank bank,
+ v3s16 pos,
core::map<v3s16, MapBlock*> & modified_blocks);
- v3s16 getBrightestNeighbour(v3s16 p);
+ v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
s16 propagateSunlight(v3s16 start,
core::map<v3s16, MapBlock*> & modified_blocks);
+ void updateLighting(enum LightBank bank,
+ core::map<v3s16, MapBlock*> & a_blocks,
+ core::map<v3s16, MapBlock*> & modified_blocks);
+
void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
core::map<v3s16, MapBlock*> & modified_blocks);
void removeNodeAndUpdate(v3s16 p,
core::map<v3s16, MapBlock*> &modified_blocks);
+#ifndef SERVER
+ void expireMeshes(bool only_daynight_diffed);
+
/*
Updates the faces of the given block and blocks on the
leading edge.
*/
- void updateMeshes(v3s16 blockpos);
+ void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
+#endif
+
+ /*
+ Takes the blocks at the trailing edges into account
+ */
+ bool dayNightDiffed(v3s16 blockpos);
//core::aabbox3d<s16> getDisplayedBlockArea();
{
HMParams()
{
- heightmap_blocksize = 64;
- height_randmax = "constant 70.0";
- height_randfactor = "constant 0.6";
- height_base = "linear 0 80 0";
+ blocksize = 64;
+ randmax = "constant 70.0";
+ randfactor = "constant 0.6";
+ base = "linear 0 80 0";
}
- s16 heightmap_blocksize;
- std::string height_randmax;
- std::string height_randfactor;
- std::string height_base;
+ s16 blocksize;
+ std::string randmax;
+ std::string randfactor;
+ std::string base;
};
// Map parameters
MapParams()
{
plants_amount = 1.0;
+ ravines_amount = 1.0;
//max_objects_in_block = 30;
}
float plants_amount;
+ float ravines_amount;
//u16 max_objects_in_block;
};
bool m_map_saving_enabled;
};
+#ifndef SERVER
+
class Client;
class ClientMap : public Map, public scene::ISceneNode
public:
ClientMap(
Client *client,
- video::SMaterial *materials,
+ JMutex &range_mutex,
+ s16 &viewing_range_nodes,
+ bool &viewing_range_all,
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id
return MAPTYPE_CLIENT;
}
+ void drop()
+ {
+ ISceneNode::drop();
+ }
+
/*
Forcefully get a sector from somewhere
*/
ISceneNode methods
*/
- virtual void OnRegisterSceneNode()
- {
- if(IsVisible)
- {
- //SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
- SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
- SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
- }
-
- ISceneNode::OnRegisterSceneNode();
- }
+ virtual void OnRegisterSceneNode();
virtual void render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
- renderMap(driver, m_materials, SceneManager->getSceneNodeRenderPass());
+ renderMap(driver, SceneManager->getSceneNodeRenderPass());
}
virtual const core::aabbox3d<f32>& getBoundingBox() const
return m_box;
}
- void renderMap(video::IVideoDriver* driver,
- video::SMaterial *materials, s32 pass);
+ void renderMap(video::IVideoDriver* driver, s32 pass);
// Update master heightmap mesh
void updateMesh();
private:
Client *m_client;
- video::SMaterial *m_materials;
-
core::aabbox3d<f32> m_box;
// This is the master heightmap mesh
scene::SMesh *mesh;
JMutex mesh_mutex;
+
+ JMutex &m_range_mutex;
+ s16 &m_viewing_range_nodes;
+ bool &m_viewing_range_all;
+};
+
+#endif
+
+class MapVoxelManipulator : public VoxelManipulator
+{
+public:
+ MapVoxelManipulator(Map *map);
+ virtual ~MapVoxelManipulator();
+
+ virtual void clear()
+ {
+ VoxelManipulator::clear();
+ m_loaded_blocks.clear();
+ }
+
+ virtual void emerge(VoxelArea a, s32 caller_id=-1);
+
+ void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
+
+private:
+ Map *m_map;
+ /*
+ NOTE: This might be used or not
+ bool is dummy value
+ SUGG: How 'bout an another VoxelManipulator for storing the
+ information about which block is loaded?
+ */
+ core::map<v3s16, bool> m_loaded_blocks;
};
#endif