aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clientobject.cpp9
-rw-r--r--src/game.cpp38
-rw-r--r--src/main.cpp6
-rw-r--r--src/mapblockobject.cpp6
-rw-r--r--src/mapblockobject.h4
-rw-r--r--src/mineral.cpp2
-rw-r--r--src/mineral.h3
-rw-r--r--src/player.cpp4
-rw-r--r--src/texture.h134
-rw-r--r--src/tile.cpp62
-rw-r--r--src/tile.h18
-rw-r--r--src/utility.h12
12 files changed, 108 insertions, 190 deletions
diff --git a/src/clientobject.cpp b/src/clientobject.cpp
index 9e4bf757c..402535ffc 100644
--- a/src/clientobject.cpp
+++ b/src/clientobject.cpp
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h"
#include "utility.h"
#include "environment.h"
+#include "tile.h"
/*
ClientActiveObject
@@ -114,7 +115,7 @@ void TestCAO::addToScene(scene::ISceneManager *smgr)
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
buf->getMaterial().setTexture
- (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
+ (0, driver->getTexture(getTexturePath("rat.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -237,7 +238,7 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr)
//buf->getMaterial().setTexture(0, NULL);
// Initialize with the stick texture
buf->getMaterial().setTexture
- (0, driver->getTexture(porting::getDataPath("stick.png").c_str()));
+ (0, driver->getTexture(getTexturePath("stick.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -443,7 +444,7 @@ void RatCAO::addToScene(scene::ISceneManager *smgr)
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
//buf->getMaterial().setTexture(0, NULL);
buf->getMaterial().setTexture
- (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
+ (0, driver->getTexture(getTexturePath("rat.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -604,7 +605,7 @@ void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
//buf->getMaterial().setTexture(0, NULL);
buf->getMaterial().setTexture
- (0, driver->getTexture(porting::getDataPath("oerkki1.png").c_str()));
+ (0, driver->getTexture(getTexturePath("oerkki1.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
diff --git a/src/game.cpp b/src/game.cpp
index 69e673fa4..b1a804ae3 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -345,7 +345,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
*/
{
video::ITexture *heart_texture =
- driver->getTexture(porting::getDataPath("heart.png").c_str());
+ driver->getTexture(getTexturePath("heart.png").c_str());
v2s32 p = pos + v2s32(0, -20);
for(s32 i=0; i<halfheartcount/2; i++)
{
@@ -597,32 +597,32 @@ void update_skybox(video::IVideoDriver* driver,
if(brightness >= 0.5)
{
skybox = smgr->addSkyBoxSceneNode(
- driver->getTexture(porting::getDataPath("skybox2.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox3.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1.png").c_str()));
+ driver->getTexture(getTexturePath("skybox2.png").c_str()),
+ driver->getTexture(getTexturePath("skybox3.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1.png").c_str()));
}
else if(brightness >= 0.2)
{
skybox = smgr->addSkyBoxSceneNode(
- driver->getTexture(porting::getDataPath("skybox2_dawn.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox3_dawn.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_dawn.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_dawn.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_dawn.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_dawn.png").c_str()));
+ driver->getTexture(getTexturePath("skybox2_dawn.png").c_str()),
+ driver->getTexture(getTexturePath("skybox3_dawn.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()));
}
else
{
skybox = smgr->addSkyBoxSceneNode(
- driver->getTexture(porting::getDataPath("skybox2_night.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox3_night.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_night.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_night.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_night.png").c_str()),
- driver->getTexture(porting::getDataPath("skybox1_night.png").c_str()));
+ driver->getTexture(getTexturePath("skybox2_night.png").c_str()),
+ driver->getTexture(getTexturePath("skybox3_night.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_night.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_night.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_night.png").c_str()),
+ driver->getTexture(getTexturePath("skybox1_night.png").c_str()));
}
}
diff --git a/src/main.cpp b/src/main.cpp
index 184643b9f..7b33bdb84 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -913,7 +913,7 @@ void drawMenuBackground(video::IVideoDriver* driver)
core::dimension2d<u32> screensize = driver->getScreenSize();
video::ITexture *bgtexture =
- driver->getTexture(porting::getDataPath("mud.png").c_str());
+ driver->getTexture(getTexturePath("mud.png").c_str());
if(bgtexture)
{
s32 texturesize = 128;
@@ -933,7 +933,7 @@ void drawMenuBackground(video::IVideoDriver* driver)
}
video::ITexture *logotexture =
- driver->getTexture(porting::getDataPath("menulogo.png").c_str());
+ driver->getTexture(getTexturePath("menulogo.png").c_str());
if(logotexture)
{
v2s32 logosize(logotexture->getOriginalSize().Width,
@@ -1288,7 +1288,7 @@ int main(int argc, char *argv[])
guienv = device->getGUIEnvironment();
gui::IGUISkin* skin = guienv->getSkin();
- gui::IGUIFont* font = guienv->getFont(porting::getDataPath("fontlucida.png").c_str());
+ gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str());
if(font)
skin->setFont(font);
else
diff --git a/src/mapblockobject.cpp b/src/mapblockobject.cpp
index d05eee808..009163a18 100644
--- a/src/mapblockobject.cpp
+++ b/src/mapblockobject.cpp
@@ -283,7 +283,7 @@ void RatObject::addToScene(scene::ISceneManager *smgr)
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
buf->getMaterial().setTexture
- (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
+ (0, driver->getTexture(getTexturePath("rat.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -413,7 +413,7 @@ void PlayerObject::addToScene(scene::ISceneManager *smgr)
// Set material
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
- buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player.png").c_str()));
+ buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
//buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -437,7 +437,7 @@ void PlayerObject::addToScene(scene::ISceneManager *smgr)
// Set material
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
- buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player_back.png").c_str()));
+ buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
diff --git a/src/mapblockobject.h b/src/mapblockobject.h
index db8006fd9..804494715 100644
--- a/src/mapblockobject.h
+++ b/src/mapblockobject.h
@@ -432,7 +432,7 @@ public:
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
buf->getMaterial().setTexture
- (0, driver->getTexture(porting::getDataPath("sign.png").c_str()));
+ (0, driver->getTexture(getTexturePath("sign.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
@@ -456,7 +456,7 @@ public:
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
buf->getMaterial().setTexture
- (0, driver->getTexture(porting::getDataPath("sign_back.png").c_str()));
+ (0, driver->getTexture(getTexturePath("sign_back.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
diff --git a/src/mineral.cpp b/src/mineral.cpp
index e61c25c1e..038251fa3 100644
--- a/src/mineral.cpp
+++ b/src/mineral.cpp
@@ -27,7 +27,6 @@ const char *mineral_filenames[MINERAL_COUNT] =
"mineral_iron.png"
};
-//textureid_t mineral_textures[MINERAL_COUNT] = {0};
std::string mineral_textures[MINERAL_COUNT];
void init_mineral()
@@ -40,7 +39,6 @@ void init_mineral()
}
}
-//textureid_t mineral_block_texture(u8 mineral)
std::string mineral_block_texture(u8 mineral)
{
if(mineral >= MINERAL_COUNT)
diff --git a/src/mineral.h b/src/mineral.h
index fcc1bd123..970ff1f78 100644
--- a/src/mineral.h
+++ b/src/mineral.h
@@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MINERAL_HEADER
#include "inventory.h"
-#include "texture.h"
+#include "tile.h"
/*
Minerals
@@ -39,7 +39,6 @@ void init_mineral();
#define MINERAL_COUNT 3
-//textureid_t mineral_block_texture(u8 mineral);
std::string mineral_block_texture(u8 mineral);
inline CraftItem * getDiggedMineralItem(u8 mineral)
diff --git a/src/player.cpp b/src/player.cpp
index 539244709..12f18de75 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -261,7 +261,7 @@ RemotePlayer::RemotePlayer(
// Set material
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
- buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player.png").c_str()));
+ buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
//buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@@ -285,7 +285,7 @@ RemotePlayer::RemotePlayer(
// Set material
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
//buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
- buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player_back.png").c_str()));
+ buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str()));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
diff --git a/src/texture.h b/src/texture.h
deleted file mode 100644
index d8310789d..000000000
--- a/src/texture.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-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 TEXTURE_HEADER
-#define TEXTURE_HEADER
-
-// This file now contains all that was here
-#include "tile.h"
-
-// TODO: Remove this
-typedef u16 textureid_t;
-
-#if 0
-
-#include "common_irrlicht.h"
-//#include "utility.h"
-#include "debug.h"
-
-/*
- All textures are given a "texture id".
- 0 = nothing (a NULL pointer texture)
-*/
-typedef u16 textureid_t;
-
-/*
- Every texture in the game can be specified by this.
-
- It exists instead of specification strings because arbitary
- texture combinations for map nodes are handled using this,
- and strings are too slow for that purpose.
-
- Plain texture pointers are not used because they don't contain
- content information by themselves. A texture can be completely
- reconstructed by just looking at this, while this also is a
- fast unique key to containers.
-*/
-
-#define TEXTURE_SPEC_TEXTURE_COUNT 4
-
-struct TextureSpec
-{
- TextureSpec()
- {
- clear();
- }
-
- TextureSpec(textureid_t id0)
- {
- clear();
- tids[0] = id0;
- }
-
- TextureSpec(textureid_t id0, textureid_t id1)
- {
- clear();
- tids[0] = id0;
- tids[1] = id1;
- }
-
- void clear()
- {
- for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
- {
- tids[i] = 0;
- }
- }
-
- bool empty() const
- {
- for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
- {
- if(tids[i] != 0)
- return false;
- }
- return true;
- }
-
- void addTid(textureid_t tid)
- {
- for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
- {
- if(tids[i] == 0)
- {
- tids[i] = tid;
- return;
- }
- }
- // Too many textures
- assert(0);
- }
-
- bool operator==(const TextureSpec &other) const
- {
- for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
- {
- if(tids[i] != other.tids[i])
- return false;
- }
- return true;
- }
-
- bool operator<(const TextureSpec &other) const
- {
- for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
- {
- if(tids[i] >= other.tids[i])
- return false;
- }
- return true;
- }
-
- // Ids of textures. They are blit on each other.
- textureid_t tids[TEXTURE_SPEC_TEXTURE_COUNT];
-};
-
-#endif
-
-#endif
diff --git a/src/tile.cpp b/src/tile.cpp
index 5b89c6932..dabc1dcf3 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -1,6 +1,6 @@
/*
Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2010-2011 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
@@ -21,6 +21,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "debug.h"
#include "main.h" // for g_settings
#include "filesys.h"
+#include "utility.h"
+
+/*
+ A cache from texture name to texture path
+*/
+MutexedMap<std::string, std::string> g_texturename_to_path_cache;
/*
Replaces the filename extension.
@@ -30,7 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
-> image = "a/image.jpg"
Returns true on success.
*/
-inline bool replace_ext(std::string &path, const char *ext)
+static bool replace_ext(std::string &path, const char *ext)
{
if(ext == NULL)
return false;
@@ -61,7 +67,7 @@ inline bool replace_ext(std::string &path, const char *ext)
If failed, return "".
*/
-inline std::string getImagePath(std::string path)
+static std::string getImagePath(std::string path)
{
// A NULL-ended list of possible image extensions
const char *extensions[] = {
@@ -86,25 +92,55 @@ inline std::string getImagePath(std::string path)
/*
Gets the path to a texture by first checking if the texture exists
in texture_path and if not, using the data path.
+
+ Checks all supported extensions by replacing the original extension.
+
+ If not found, returns "".
+
+ Utilizes a thread-safe cache.
*/
-inline std::string getTexturePath(std::string filename)
+std::string getTexturePath(const std::string &filename)
{
+ std::string fullpath = "";
+ /*
+ Check from cache
+ */
+ bool incache = g_texturename_to_path_cache.get(filename, &fullpath);
+ if(incache)
+ return fullpath;
+
+ /*
+ Check from texture_path
+ */
std::string texture_path = g_settings.get("texture_path");
if(texture_path != "")
{
- std::string fullpath = texture_path + '/' + filename;
- // Check all filename extensions
- fullpath = getImagePath(fullpath);
- // If found, return it
- if(fullpath != "")
- return fullpath;
+ std::string testpath = texture_path + '/' + filename;
+ // Check all filename extensions. Returns "" if not found.
+ fullpath = getImagePath(testpath);
}
- std::string fullpath = porting::getDataPath(filename.c_str());
- // Check all filename extensions
- fullpath = getImagePath(fullpath);
+
+ /*
+ Check from default data directory
+ */
+ if(fullpath == "")
+ {
+ std::string testpath = porting::getDataPath(filename.c_str());
+ // Check all filename extensions. Returns "" if not found.
+ fullpath = getImagePath(testpath);
+ }
+
+ // Add to cache (also an empty result is cached)
+ g_texturename_to_path_cache.set(filename, fullpath);
+
+ // Finally return it
return fullpath;
}
+/*
+ TextureSource
+*/
+
TextureSource::TextureSource(IrrlichtDevice *device):
m_device(device),
m_main_atlas_image(NULL),
diff --git a/src/tile.h b/src/tile.h
index f06285960..216d76508 100644
--- a/src/tile.h
+++ b/src/tile.h
@@ -1,6 +1,6 @@
/*
Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2010-2011 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
@@ -26,6 +26,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
/*
+ tile.{h,cpp}: Texture handling stuff.
+*/
+
+/*
+ Gets the path to a texture by first checking if the texture exists
+ in texture_path and if not, using the data path.
+
+ Checks all supported extensions by replacing the original extension.
+
+ If not found, returns "".
+
+ Utilizes a thread-safe cache.
+*/
+std::string getTexturePath(const std::string &filename);
+
+/*
Specifies a texture in an atlas.
This is used to specify single textures also.
diff --git a/src/utility.h b/src/utility.h
index 84838c0c7..cc8891a07 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -1766,12 +1766,12 @@ private:
core::list<Value> m_list;
};
-#if 0
+#if 1
template<typename Key, typename Value>
-class MutexedCache
+class MutexedMap
{
public:
- MutexedCache()
+ MutexedMap()
{
m_mutex.Init();
assert(m_mutex.IsInitialized());
@@ -1793,8 +1793,10 @@ public:
if(n == NULL)
return false;
-
- *result = n->getValue();
+
+ if(result != NULL)
+ *result = n->getValue();
+
return true;
}
l opt">*MAP_BLOCKSIZE + p.X] = n; } } MapNode MapBlock::getNodeParentNoEx(v3s16 p) { if(isValidPosition(p) == false) { try{ return m_parent->getNode(getPosRelative() + p); } catch(InvalidPositionException &e) { return MapNode(CONTENT_IGNORE); } } else { if(data == NULL) { return MapNode(CONTENT_IGNORE); } return data[p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X]; } } #ifndef SERVER #if 1 void MapBlock::updateMesh(u32 daynight_ratio) { #if 0 /* DEBUG: If mesh has been generated, don't generate it again */ { JMutexAutoLock meshlock(mesh_mutex); if(mesh != NULL) return; } #endif MeshMakeData data; data.fill(daynight_ratio, this); scene::SMesh *mesh_new = makeMapBlockMesh(&data); /* Replace the mesh */ replaceMesh(mesh_new); } #endif void MapBlock::replaceMesh(scene::SMesh *mesh_new) { mesh_mutex.Lock(); //scene::SMesh *mesh_old = mesh[daynight_i]; //mesh[daynight_i] = mesh_new; scene::SMesh *mesh_old = mesh; mesh = mesh_new; setMeshExpired(false); if(mesh_old != NULL) { // Remove hardware buffers of meshbuffers of mesh // NOTE: No way, this runs in a different thread and everything /*u32 c = mesh_old->getMeshBufferCount(); for(u32 i=0; i<c; i++) { IMeshBuffer *buf = mesh_old->getMeshBuffer(i); }*/ /*dstream<<"mesh_old->getReferenceCount()=" <<mesh_old->getReferenceCount()<<std::endl; u32 c = mesh_old->getMeshBufferCount(); for(u32 i=0; i<c; i++) { scene::IMeshBuffer *buf = mesh_old->getMeshBuffer(i); dstream<<"buf->getReferenceCount()=" <<buf->getReferenceCount()<<std::endl; }*/ // Drop the mesh mesh_old->drop(); //delete mesh_old; } mesh_mutex.Unlock(); } #endif // !SERVER /* Propagates sunlight down through the block. Doesn't modify nodes that are not affected by sunlight. Returns false if sunlight at bottom block is invalid. Returns true if sunlight at bottom block is valid. Returns true if bottom block doesn't exist. If there is a block above, continues from it. If there is no block above, assumes there is sunlight, unless is_underground is set or highest node is water. All sunlighted nodes are added to light_sources. if remove_light==true, sets non-sunlighted nodes black. if black_air_left!=NULL, it is set to true if non-sunlighted air is left in block. */ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources, bool remove_light, bool *black_air_left) { // Whether the sunlight at the top of the bottom block is valid bool block_below_is_valid = true; v3s16 pos_relative = getPosRelative(); for(s16 x=0; x<MAP_BLOCKSIZE; x++) { for(s16 z=0; z<MAP_BLOCKSIZE; z++) { #if 1 bool no_sunlight = false; bool no_top_block = false; // Check if node above block has sunlight try{ MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); if(n.getContent() == CONTENT_IGNORE) { // Trust heuristics no_sunlight = is_underground; } else if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN) { no_sunlight = true; } } catch(InvalidPositionException &e) { no_top_block = true; // NOTE: This makes over-ground roofed places sunlighted // Assume sunlight, unless is_underground==true if(is_underground) { no_sunlight = true; } else { MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z)); //if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE) if(content_features(n).sunlight_propagates == false) { no_sunlight = true; } } // NOTE: As of now, this just would make everything dark. // No sunlight here //no_sunlight = true; } #endif #if 0 // Doesn't work; nothing gets light. bool no_sunlight = true; bool no_top_block = false; // Check if node above block has sunlight try{ MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); if(n.getLight(LIGHTBANK_DAY) == LIGHT_SUN) { no_sunlight = false; } } catch(InvalidPositionException &e) { no_top_block = true; } #endif /*std::cout<<"("<<x<<","<<z<<"): " <<"no_top_block="<<no_top_block <<", is_underground="<<is_underground <<", no_sunlight="<<no_sunlight <<std::endl;*/ s16 y = MAP_BLOCKSIZE-1; // This makes difference to diminishing in water. bool stopped_to_solid_object = false; u8 current_light = no_sunlight ? 0 : LIGHT_SUN; for(; y >= 0; y--) { v3s16 pos(x, y, z); MapNode &n = getNodeRef(pos); if(current_light == 0) { // Do nothing } else if(current_light == LIGHT_SUN && n.sunlight_propagates()) { // Do nothing: Sunlight is continued } else if(n.light_propagates() == false) { /*// DEPRECATED TODO: REMOVE if(grow_grass) { bool upper_is_air = false; try { if(getNodeParent(pos+v3s16(0,1,0)).getContent() == CONTENT_AIR) upper_is_air = true; } catch(InvalidPositionException &e) { } // Turn mud into grass if(upper_is_air && n.getContent() == CONTENT_MUD && current_light == LIGHT_SUN) { n.d = CONTENT_GRASS; } }*/ // A solid object is on the way. stopped_to_solid_object = true; // Light stops. current_light = 0; } else { // Diminish light current_light = diminish_light(current_light); } u8 old_light = n.getLight(LIGHTBANK_DAY); if(current_light > old_light || remove_light) { n.setLight(LIGHTBANK_DAY, current_light); } if(diminish_light(current_light) != 0) { light_sources.insert(pos_relative + pos, true); } if(current_light == 0 && stopped_to_solid_object) { if(black_air_left) { *black_air_left = true; } } } // Whether or not the block below should see LIGHT_SUN bool sunlight_should_go_down = (current_light == LIGHT_SUN); /* If the block below hasn't already been marked invalid: Check if the node below the block has proper sunlight at top. If not, the block below is invalid. Ignore non-transparent nodes as they always have no light */ try { if(block_below_is_valid) { MapNode n = getNodeParent(v3s16(x, -1, z)); if(n.light_propagates()) { if(n.getLight(LIGHTBANK_DAY) == LIGHT_SUN && sunlight_should_go_down == false) block_below_is_valid = false; else if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN && sunlight_should_go_down == true) block_below_is_valid = false; } }//if }//try catch(InvalidPositionException &e) { /*std::cout<<"InvalidBlockException for bottom block node" <<std::endl;*/ // Just no block below, no need to panic. } } } return block_below_is_valid; } void MapBlock::copyTo(VoxelManipulator &dst) { v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE); VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1)); // Copy from data to VoxelManipulator dst.copyFrom(data, data_area, v3s16(0,0,0), getPosRelative(), data_size); } void MapBlock::copyFrom(VoxelManipulator &dst) { v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE); VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1)); // Copy from VoxelManipulator to data dst.copyTo(data, data_area, v3s16(0,0,0), getPosRelative(), data_size); } void MapBlock::updateDayNightDiff() { if(data == NULL) { m_day_night_differs = false; return; } bool differs = false; /* Check if any lighting value differs */ for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) { MapNode &n = data[i]; if(n.getLight(LIGHTBANK_DAY) != n.getLight(LIGHTBANK_NIGHT)) { differs = true; break; } } /* If some lighting values differ, check if the whole thing is just air. If it is, differ = false */ if(differs) { bool only_air = true; for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) { MapNode &n = data[i]; if(n.getContent() != CONTENT_AIR) { only_air = false; break; } } if(only_air) differs = false; } // Set member variable m_day_night_differs = differs; } s16 MapBlock::getGroundLevel(v2s16 p2d) { if(isDummy()) return -3; try { s16 y = MAP_BLOCKSIZE-1; for(; y>=0; y--) { MapNode n = getNodeRef(p2d.X, y, p2d.Y); if(content_features(n).walkable) { if(y == MAP_BLOCKSIZE-1) return -2; else return y; } } return -1; } catch(InvalidPositionException &e) { return -3; } } /* Serialization */ void MapBlock::serialize(std::ostream &os, u8 version) { if(!ser_ver_supported(version)) throw VersionMismatchException("ERROR: MapBlock format not supported"); if(data == NULL) { throw SerializationError("ERROR: Not writing dummy block."); } // These have no compression if(version <= 3 || version == 5 || version == 6) { u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; u32 buflen = 1 + nodecount * MapNode::serializedLength(version); SharedBuffer<u8> dest(buflen); dest[0] = is_underground; for(u32 i=0; i<nodecount; i++) { u32 s = 1 + i * MapNode::serializedLength(version); data[i].serialize(&dest[s], version); } os.write((char*)*dest, dest.getSize()); } else if(version <= 10) { /* With compression. Compress the materials and the params separately. */ // First byte os.write((char*)&is_underground, 1); u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; // Get and compress materials SharedBuffer<u8> materialdata(nodecount); for(u32 i=0; i<nodecount; i++) { materialdata[i] = data[i].param0; } compress(materialdata, os, version); // Get and compress lights SharedBuffer<u8> lightdata(nodecount); for(u32 i=0; i<nodecount; i++) { lightdata[i] = data[i].param1; } compress(lightdata, os, version); if(version >= 10) { // Get and compress param2 SharedBuffer<u8> param2data(nodecount); for(u32 i=0; i<nodecount; i++) { param2data[i] = data[i].param2; } compress(param2data, os, version); } } // All other versions (newest) else { // First byte u8 flags = 0; if(is_underground) flags |= 0x01; if(m_day_night_differs) flags |= 0x02; if(m_lighting_expired) flags |= 0x04; if(version >= 18) { if(m_generated == false) flags |= 0x08; } os.write((char*)&flags, 1); u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; /* Get data */ // Serialize nodes SharedBuffer<u8> databuf_nodelist(nodecount*3); for(u32 i=0; i<nodecount; i++) { data[i].serialize(&databuf_nodelist[i*3], version); } // Create buffer with different parameters sorted SharedBuffer<u8> databuf(nodecount*3); for(u32 i=0; i<nodecount; i++) { databuf[i] = databuf_nodelist[i*3]; databuf[i+nodecount] = databuf_nodelist[i*3+1]; databuf[i+nodecount*2] = databuf_nodelist[i*3+2]; } /* Compress data to output stream */ compress(databuf, os, version); /* NodeMetadata */ if(version >= 14) { if(version <= 15) { try{ std::ostringstream oss(std::ios_base::binary); m_node_metadata.serialize(oss); os<<serializeString(oss.str()); }