diff options
author | Perttu Ahola <celeron55@gmail.com> | 2011-01-26 00:41:06 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2011-01-26 00:41:06 +0200 |
commit | 9f882bf74d452521cb7fb1806ab453aaa28da343 (patch) | |
tree | a5676871bd8f3adf44fade49162ea0342d49ac4d | |
parent | 035345f13d2da9eced87a426a671d3bc4df392b5 (diff) | |
download | minetest-9f882bf74d452521cb7fb1806ab453aaa28da343.tar.gz minetest-9f882bf74d452521cb7fb1806ab453aaa28da343.tar.bz2 minetest-9f882bf74d452521cb7fb1806ab453aaa28da343.zip |
Reworked texture, material, mineral and whatever handling
-rw-r--r-- | data/coalstone.png | bin | 1523 -> 0 bytes | |||
-rw-r--r-- | data/grass.png | bin | 855 -> 1599 bytes | |||
-rw-r--r-- | data/lump_of_coal.png | bin | 0 -> 933 bytes | |||
-rw-r--r-- | data/lump_of_iron.png | bin | 0 -> 936 bytes | |||
-rw-r--r-- | data/mineral_coal.png | bin | 0 -> 1620 bytes | |||
-rw-r--r-- | data/mineral_iron.png | bin | 0 -> 1616 bytes | |||
-rw-r--r-- | data/sand.png | bin | 0 -> 659 bytes | |||
-rwxr-xr-x | makepackage_binary.sh | 6 | ||||
-rw-r--r-- | minetest.vcproj | 2 | ||||
-rw-r--r-- | src/client.cpp | 1 | ||||
-rw-r--r-- | src/client.h | 35 | ||||
-rw-r--r-- | src/inventory.h | 28 | ||||
-rw-r--r-- | src/irrlichtwrapper.cpp | 297 | ||||
-rw-r--r-- | src/irrlichtwrapper.h | 95 | ||||
-rw-r--r-- | src/map.cpp | 143 | ||||
-rw-r--r-- | src/map.h | 17 | ||||
-rw-r--r-- | src/mapblock.cpp | 74 | ||||
-rw-r--r-- | src/mapnode.cpp | 226 | ||||
-rw-r--r-- | src/mapnode.h | 298 | ||||
-rw-r--r-- | src/mineral.h | 60 | ||||
-rw-r--r-- | src/server.cpp | 28 | ||||
-rw-r--r-- | src/tile.cpp | 117 | ||||
-rw-r--r-- | src/tile.h | 88 | ||||
-rw-r--r-- | src/utility.cpp | 35 | ||||
-rw-r--r-- | src/utility.h | 11 | ||||
-rw-r--r-- | src/voxel.cpp | 635 | ||||
-rw-r--r-- | src/voxel.h | 56 |
27 files changed, 940 insertions, 1312 deletions
diff --git a/data/coalstone.png b/data/coalstone.png Binary files differdeleted file mode 100644 index 0c62a192f..000000000 --- a/data/coalstone.png +++ /dev/null diff --git a/data/grass.png b/data/grass.png Binary files differindex 91cc0c0fc..88336c013 100644 --- a/data/grass.png +++ b/data/grass.png diff --git a/data/lump_of_coal.png b/data/lump_of_coal.png Binary files differnew file mode 100644 index 000000000..bad901efa --- /dev/null +++ b/data/lump_of_coal.png diff --git a/data/lump_of_iron.png b/data/lump_of_iron.png Binary files differnew file mode 100644 index 000000000..edb931018 --- /dev/null +++ b/data/lump_of_iron.png diff --git a/data/mineral_coal.png b/data/mineral_coal.png Binary files differnew file mode 100644 index 000000000..58a4d2b79 --- /dev/null +++ b/data/mineral_coal.png diff --git a/data/mineral_iron.png b/data/mineral_iron.png Binary files differnew file mode 100644 index 000000000..9698aa006 --- /dev/null +++ b/data/mineral_iron.png diff --git a/data/sand.png b/data/sand.png Binary files differnew file mode 100644 index 000000000..89149add2 --- /dev/null +++ b/data/sand.png diff --git a/makepackage_binary.sh b/makepackage_binary.sh index c5248b79b..f00ec608c 100755 --- a/makepackage_binary.sh +++ b/makepackage_binary.sh @@ -39,7 +39,6 @@ cp -r data/torch.png $PACKAGEPATH/data/ cp -r data/torch_on_floor.png $PACKAGEPATH/data/ cp -r data/torch_on_ceiling.png $PACKAGEPATH/data/ cp -r data/tree_top.png $PACKAGEPATH/data/ -#cp -r data/mud_with_grass.png $PACKAGEPATH/data/ cp -r data/coalstone.png $PACKAGEPATH/data/ cp -r data/crack.png $PACKAGEPATH/data/ cp -r data/wood.png $PACKAGEPATH/data/ @@ -48,6 +47,11 @@ cp -r data/tool_wpick.png $PACKAGEPATH/data/ cp -r data/tool_stpick.png $PACKAGEPATH/data/ cp -r data/tool_mesepick.png $PACKAGEPATH/data/ cp -r data/grass_side.png $PACKAGEPATH/data/ +cp -r data/lump_of_coal.png $PACKAGEPATH/data/ +cp -r data/lump_of_iron.png $PACKAGEPATH/data/ +cp -r data/mineral_coal.png $PACKAGEPATH/data/ +cp -r data/mineral_iron.png $PACKAGEPATH/data/ +cp -r data/sand.png $PACKAGEPATH/data/ #cp -r data/pauseMenu.gui $PACKAGEPATH/data/ diff --git a/minetest.vcproj b/minetest.vcproj index 53481add7..71dc5763a 100644 --- a/minetest.vcproj +++ b/minetest.vcproj @@ -137,7 +137,7 @@ <Tool
Name="VCLinkerTool"
AdditionalLibraryDirectories=""C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib";"..\irrlicht\irrlicht-1.7.1\lib\Win32-visualstudio";..\zlib125dll\dll32"
- IgnoreDefaultLibraryNames="libcmtd.lib"
+ IgnoreDefaultLibraryNames="libcmtd.dll"
GenerateDebugInformation="false"
LinkTimeCodeGeneration="1"
/>
diff --git a/src/client.cpp b/src/client.cpp index 36e0f3c7c..915c745b7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1273,6 +1273,7 @@ void Client::groundAction(u8 action, v3s16 nodepos_undersurface, 0: start digging 1: place block 2: stop digging (all parameters ignored) + 3: digging completed */ u8 datasize = 2 + 1 + 6 + 6 + 2; SharedBuffer<u8> data(datasize); diff --git a/src/client.h b/src/client.h index 9110d33f8..00fd3a5ed 100644 --- a/src/client.h +++ b/src/client.h @@ -201,6 +201,40 @@ public: { JMutexAutoLock envlock(m_env_mutex); assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); + + core::map<v3s16, MapBlock*> affected_blocks; + ((ClientMap&)m_env.getMap()).setTempMod(p, mod, + &affected_blocks); + + for(core::map<v3s16, MapBlock*>::Iterator + i = affected_blocks.getIterator(); + i.atEnd() == false; i++) + { + i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio()); + } + } + void clearTempMod(v3s16 p) + { + JMutexAutoLock envlock(m_env_mutex); + assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); + + core::map<v3s16, MapBlock*> affected_blocks; + ((ClientMap&)m_env.getMap()).clearTempMod(p, + &affected_blocks); + + for(core::map<v3s16, MapBlock*>::Iterator + i = affected_blocks.getIterator(); + i.atEnd() == false; i++) + { + i.getNode()->getValue()->updateMesh(m_env.getDayNightRatio()); + } + } + +#if 0 + void setTempMod(v3s16 p, NodeMod mod) + { + JMutexAutoLock envlock(m_env_mutex); + assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); bool changed = false; v3s16 blockpos = ((ClientMap&)m_env.getMap()).setTempMod(p, mod, &changed); if(changed) @@ -215,6 +249,7 @@ public: if(changed) m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio()); } +#endif float getAvgRtt() { diff --git a/src/inventory.h b/src/inventory.h index 84ccd5bd6..797a67509 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -122,12 +122,6 @@ public: #ifndef SERVER video::ITexture * getImage() { - /*if(m_content == CONTENT_TORCH) - return g_texturecache.get("torch_on_floor"); - - u16 tile = content_tile(m_content, v3s16(1,0,0)); - return g_tile_contents[tile].getTexture(0);*/ - if(m_content >= USEFUL_CONTENT_COUNT) return NULL; @@ -257,15 +251,18 @@ public: video::ITexture * getImage() { std::string basename; + if(m_subname == "Stick") - basename = porting::getDataPath("stick.png").c_str(); - // Default to cloud texture + basename = porting::getDataPath("stick.png"); + else if(m_subname == "lump_of_coal") + basename = porting::getDataPath("lump_of_coal.png"); + else if(m_subname == "lump_of_iron") + basename = porting::getDataPath("lump_of_iron.png"); else - basename = tile_texture_path_get(TILE_CLOUD); + basename = porting::getDataPath("cloud.png[[mod:crack3"); // Get such a texture return g_irrlicht->getTexture(basename); - //return g_irrlicht->getTexture(TextureSpec(finalname, basename, mod)); } #endif std::string getText() @@ -340,7 +337,8 @@ public: basename = porting::getDataPath("tool_mesepick.png").c_str(); // Default to cloud texture else - basename = tile_texture_path_get(TILE_CLOUD); + basename = porting::getDataPath("cloud.png").c_str(); + //basename = tile_texture_path_get(TILE_CLOUD); /* Calculate some progress value with sane amount of @@ -350,6 +348,12 @@ public: u32 toolprogress = (65535-m_wear)/(65535/maxprogress); // Make texture name for the new texture with a progress bar + float value_f = (float)toolprogress / (float)maxprogress; + std::ostringstream os; + os<<basename<<"[[mod:progressbar"<<value_f; + return g_irrlicht->getTexture(os.str()); + + /*// Make texture name for the new texture with a progress bar std::ostringstream os; os<<basename<<"-toolprogress-"<<toolprogress; std::string finalname = os.str(); @@ -358,7 +362,7 @@ public: // Get such a texture TextureMod *mod = new ProgressBarTextureMod(value_f); - return g_irrlicht->getTexture(TextureSpec(finalname, basename, mod)); + return g_irrlicht->getTexture(TextureSpec(finalname, basename, mod));*/ } #endif std::string getText() diff --git a/src/irrlichtwrapper.cpp b/src/irrlichtwrapper.cpp index e26cbfd15..4e1ebdd74 100644 --- a/src/irrlichtwrapper.cpp +++ b/src/irrlichtwrapper.cpp @@ -1,5 +1,7 @@ #include "irrlichtwrapper.h" #include "constants.h" +#include "string.h" +#include "strfnd.h" IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device) { @@ -15,13 +17,13 @@ void IrrlichtWrapper::Run() */ if(m_get_texture_queue.size() > 0) { - GetRequest<TextureSpec, video::ITexture*, u8, u8> + GetRequest<std::string, video::ITexture*, u8, u8> request = m_get_texture_queue.pop(); - dstream<<"got texture request with key.name=" - <<request.key.name<<std::endl; + dstream<<"got texture request with key=" + <<request.key<<std::endl; - GetResult<TextureSpec, video::ITexture*, u8, u8> + GetResult<std::string, video::ITexture*, u8, u8> result; result.key = request.key; result.callers = request.callers; @@ -31,38 +33,41 @@ void IrrlichtWrapper::Run() } } -video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec) +video::ITexture* IrrlichtWrapper::getTexture(const std::string &spec) { - video::ITexture *t = m_texturecache.get(spec.name); + if(spec == "") + return NULL; + + video::ITexture *t = m_texturecache.get(spec); if(t != NULL) return t; if(get_current_thread_id() == m_main_thread) { - dstream<<"Getting texture directly: name=" - <<spec.name<<std::endl; + dstream<<"Getting texture directly: spec=" + <<spec<<std::endl; t = getTextureDirect(spec); } else { // We're gonna ask the result to be put into here - ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue; + ResultQueue<std::string, video::ITexture*, u8, u8> result_queue; // Throw a request in m_get_texture_queue.add(spec, 0, 0, &result_queue); dstream<<"Waiting for texture from main thread: " - <<spec.name<<std::endl; + <<spec<<std::endl; try { // Wait result for a second - GetResult<TextureSpec, video::ITexture*, u8, u8> + GetResult<std::string, video::ITexture*, u8, u8> result = result_queue.pop_front(1000); // Check that at least something worked OK - assert(result.key.name == spec.name); + assert(result.key == spec); t = result.item; } @@ -74,44 +79,63 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec) } // Add to cache and return - m_texturecache.set(spec.name, t); + m_texturecache.set(spec, t); return t; } -video::ITexture* IrrlichtWrapper::getTexture(const std::string &path) -{ - return getTexture(TextureSpec(path, path, NULL)); -} - /* Non-thread-safe functions */ -video::ITexture* IrrlichtWrapper::getTextureDirect(TextureSpec spec) +/* + Texture modifier functions +*/ + +// blitted_name = eg. "mineral_coal.png" +video::ITexture * make_blitname(const std::string &blitted_name, + video::ITexture *original, + const char *newname, video::IVideoDriver* driver) { - video::IVideoDriver* driver = m_device->getVideoDriver(); + if(original == NULL) + return NULL; - if(spec.mod == NULL) - { - dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture " - <<spec.path<<std::endl; - return driver->getTexture(spec.path.c_str()); - } - - dstream<<"IrrlichtWrapper::getTextureDirect: Loading and modifying " - "texture "<<spec.path<<" to make "<<spec.name<<std::endl; + // Size of the base image + core::dimension2d<u32> dim(16, 16); + // Position to copy the blitted to in the base image + core::position2d<s32> pos_base(0, 0); + // Position to copy the blitted from in the blitted image + core::position2d<s32> pos_other(0, 0); - video::ITexture *base = driver->getTexture(spec.path.c_str()); - video::ITexture *result = spec.mod->make(base, spec.name.c_str(), driver); + video::IImage *baseimage = driver->createImage(original, pos_base, dim); + assert(baseimage); - delete spec.mod; + video::IImage *blittedimage = driver->createImageFromFile(porting::getDataPath(blitted_name.c_str()).c_str()); + assert(blittedimage); + + // Then copy the right part of blittedimage to baseimage + + blittedimage->copyToWithAlpha(baseimage, v2s32(0,0), + core::rect<s32>(pos_other, dim), + video::SColor(255,255,255,255), + NULL); - return result; + blittedimage->drop(); + + // Create texture from resulting image + + video::ITexture *newtexture = driver->addTexture(newname, baseimage); + + baseimage->drop(); + + return newtexture; } -video::ITexture * CrackTextureMod::make(video::ITexture *original, +video::ITexture * make_crack(u16 progression, video::ITexture *original, const char *newname, video::IVideoDriver* driver) { + if(original == NULL) + return NULL; + // Size of the base image core::dimension2d<u32> dim(16, 16); // Size of the crack image @@ -127,36 +151,6 @@ video::ITexture * CrackTextureMod::make(video::ITexture *original, video::IImage *crackimage = driver->createImageFromFile(porting::getDataPath("crack.png").c_str()); assert(crackimage); -#if 0 - video::ITexture *other = driver->getTexture(porting::getDataPath("crack.png").c_str()); - - dstream<<__FUNCTION_NAME<<": crack texture size is " - <<other->getSize().Width<<"x" - <<other->getSize().Height<<std::endl; - - // We have to get the whole texture because getting a smaller area - // messes the whole thing. It is probably a bug in Irrlicht. - // NOTE: This doesn't work probably because some systems scale - // the image to fit a texture or something... - video::IImage *otherimage = driver->createImage( - other, core::position2d<s32>(0,0), other->getSize()); - - assert(otherimage); - - // Now, the image might be 80 or 128 high depending on the computer - // Let's make an image of the right size and copy the possibly - // wrong sized one with scaling - // NOTE: This is an ugly hack. - - video::IImage *crackimage = driver->createImage( - baseimage->getColorFormat(), dim_crack); - - assert(crackimage); - - otherimage->copyToScaling(crackimage); - otherimage->drop(); -#endif - // Then copy the right part of crackimage to baseimage crackimage->copyToWithAlpha(baseimage, v2s32(0,0), @@ -175,9 +169,13 @@ video::ITexture * CrackTextureMod::make(video::ITexture *original, return newtexture; } -video::ITexture * SideGrassTextureMod::make(video::ITexture *original, +#if 0 +video::ITexture * make_sidegrass(video::ITexture *original, const char *newname, video::IVideoDriver* driver) { + if(original == NULL) + return NULL; + // Size of the base image core::dimension2d<u32> dim(16, 16); // Position to copy the grass to in the base image @@ -208,10 +206,14 @@ video::ITexture * SideGrassTextureMod::make(video::ITexture *original, return newtexture; } +#endif -video::ITexture * ProgressBarTextureMod::make(video::ITexture *original, +video::ITexture * make_progressbar(float value, video::ITexture *original, const char *newname, video::IVideoDriver* driver) { + if(original == NULL) + return NULL; + core::position2d<s32> pos_base(0, 0); core::dimension2d<u32> dim = original->getOriginalSize(); @@ -251,3 +253,166 @@ video::ITexture * ProgressBarTextureMod::make(video::ITexture *original, return newtexture; } +/* + Texture fetcher/maker function, called always from the main thread +*/ + +video::ITexture* IrrlichtWrapper::getTextureDirect(const std::string &spec) +{ + if(spec == "") + return NULL; + + video::IVideoDriver* driver = m_device->getVideoDriver(); + + /* + Input (spec) is something like this: + "/usr/share/minetest/stone.png[[mod:mineral0[[mod:crack3" + */ + + video::ITexture* t = NULL; + std::string modmagic = "[[mod:"; + Strfnd f(spec); + std::string path = f.next(modmagic); + t = driver->getTexture(path.c_str()); + std::string texture_name = path; + while(f.atend() == false) + { + std::string mod = f.next(modmagic); + texture_name += modmagic + mod; + dstream<<"Making texture \""<<texture_name<<"\""<<std::endl; + /*if(mod == "sidegrass") + { + t = make_sidegrass(t, texture_name.c_str(), driver); + } + else*/ + if(mod.substr(0, 9) == "blitname:") + { + //t = make_sidegrass(t, texture_name.c_str(), driver); + t = make_blitname(mod.substr(9), t, texture_name.c_str(), driver); + } + else if(mod.substr(0,5) == "crack") + { + u16 prog = stoi(mod.substr(5)); + t = make_crack(prog, t, texture_name.c_str(), driver); + } + else if(mod.substr(0,11) == "progressbar") + { + float value = stof(mod.substr(11)); + t = make_progressbar(value, t, texture_name.c_str(), driver); + } + else + { + dstream<<"Invalid texture mod: \""<<mod<<"\""<<std::endl; + } + } + return t; + +#if 0 + video::ITexture* t = NULL; + const char *modmagic = "[[mod:"; + const s32 modmagic_len = 6; + enum{ + READMODE_PATH, + READMODE_MOD + } readmode = READMODE_PATH; + s32 specsize = spec.size()+1; + char *strcache = (char*)malloc(specsize); + assert(strcache); + char *path = NULL; + s32 length = 0; + // Next index of modmagic to be found + s32 modmagic_i = 0; + u32 i=0; + for(;;) + { + strcache[length++] = spec[i]; + + bool got_modmagic = false; + + /* + Check modmagic + */ + if(spec[i] == modmagic[modmagic_i]) + { + modmagic_i++; + if(modmagic_i == modmagic_len) + { + got_modmagic = true; + modmagic_i = 0; + length -= modmagic_len; + } + } + else + modmagic_i = 0; + + // Set i to be the length of read string + i++; + + if(got_modmagic || i >= spec.size()) + { + strcache[length] = '\0'; + // Now our string is in strcache, ending in \0 + + if(readmode == READMODE_PATH) + { + // Get initial texture (strcache is path) + assert(t == NULL); + t = driver->getTexture(strcache); + readmode = READMODE_MOD; + path = strcache; + strcache = (char*)malloc(specsize); + assert(strcache); + } + else + { + dstream<<"Parsing mod \""<<strcache<<"\""<<std::endl; + // The name of the result of adding this mod. + // This doesn't have to be fast so std::string is used. + std::string name(path); + name += "[[mod:"; + name += strcache; + dstream<<"Name of modded texture is \""<<name<<"\"" + <<std::endl; + // Sidegrass + if(strcmp(strcache, "sidegrass") == 0) + { + t = make_sidegrass(t, name.c_str(), driver); + } + else + { + dstream<<"Invalid texture mod"<<std::endl; + } + } + + length = 0; + } + + if(i >= spec.size()) + break; + } + + /*if(spec.mod == NULL) + { + dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture " + <<spec.path<<std::endl; + return driver->getTexture(spec.path.c_str()); + } + + dstream<<"IrrlichtWrapper::getTextureDirect: Loading and modifying " + "texture "<<spec.path<<" to make "<<spec.name<<std::endl; + + video::ITexture *base = driver->getTexture(spec.path.c_str()); + video::ITexture *result = spec.mod->make(base, spec.name.c_str(), driver); + + delete spec.mod;*/ + + if(strcache) + free(strcache); + if(path) + free(path); + + return t; +#endif +} + + diff --git a/src/irrlichtwrapper.h b/src/irrlichtwrapper.h index 97607e579..2506af012 100644 --- a/src/irrlichtwrapper.h +++ b/src/irrlichtwrapper.h @@ -56,7 +56,7 @@ public: m_textures[name] = texture; } - video::ITexture* get(std::string name) + video::ITexture* get(const std::string &name) { JMutexAutoLock lock(m_mutex); @@ -74,86 +74,6 @@ private: JMutex m_mutex; }; -struct TextureMod -{ - /* - Returns a new texture which can be based on the original. - Shall not modify or delete the original texture. - */ - virtual video::ITexture * make(video::ITexture *original, - const char *newname, video::IVideoDriver* driver) = 0; -}; - -struct CrackTextureMod: public TextureMod -{ - CrackTextureMod(u16 a_progression) - { - progression = a_progression; - } - - virtual video::ITexture * make(video::ITexture *original, - const char *newname, video::IVideoDriver* driver); - - u16 progression; -}; - -struct SideGrassTextureMod: public TextureMod -{ - SideGrassTextureMod() - { - } - - virtual video::ITexture * make(video::ITexture *original, - const char *newname, video::IVideoDriver* driver); -}; - -struct ProgressBarTextureMod: public TextureMod -{ - // value is from 0.0 to 1.0 - ProgressBarTextureMod(float a_value) - { - value = a_value; - } - - virtual video::ITexture * make(video::ITexture *original, - const char *newname, video::IVideoDriver* driver); - - float value; -}; - -/* - A class for specifying a requested texture -*/ -struct TextureSpec -{ - TextureSpec() - { - mod = NULL; - } - TextureSpec(const std::string &a_name, const std::string &a_path, - TextureMod *a_mod) - { - name = a_name; - path = a_path; - mod = a_mod;; - } - ~TextureSpec() - { - } - bool operator==(const TextureSpec &other) - { - return name == other.name; - } - // An unique name for the texture. Usually the same as the path. - // Note that names and paths reside the same namespace. - std::string name; - // This is the path of the base texture - std::string path; - // Modification to do to the base texture - // NOTE: This is deleted by the one who processes the request - TextureMod *mod; -}; - /* A thread-safe wrapper for irrlicht, to be accessed from background worker threads. @@ -183,14 +103,17 @@ public: return m_device->getTimer()->getRealTime(); } - video::ITexture* getTexture(TextureSpec spec); - video::ITexture* getTexture(const std::string &path); - + /* + Path can contain stuff like + "/usr/share/minetest/stone.png[[mod:mineral0[[mod:crack3" + */ + video::ITexture* getTexture(const std::string &spec); + private: /* Non-thread-safe variants of stuff, for internal use */ - video::ITexture* getTextureDirect(TextureSpec spec); + video::ITexture* getTextureDirect(const std::string &spec); /* Members @@ -203,7 +126,7 @@ private: TextureCache m_texturecache; - RequestQueue<TextureSpec, video::ITexture*, u8, u8> m_get_texture_queue; + RequestQueue<std::string, video::ITexture*, u8, u8> m_get_texture_queue; }; #endif diff --git a/src/map.cpp b/src/map.cpp index 0b5872e05..2782cef03 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "utility.h" #include "voxel.h" #include "porting.h" +#include "mineral.h" /* Map @@ -627,9 +628,8 @@ void Map::updateLighting(enum LightBank bank, //TimeTaker timer("updateLighting"); // For debugging - bool debug=true; - - u32 count_was = modified_blocks.size(); + //bool debug=true; + //u32 count_was = modified_blocks.size(); core::map<v3s16, bool> light_sources; @@ -1835,9 +1835,18 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): randfactor = 0.5; }*/ - baseheight = 0; - randmax = 15; - randfactor = 0.63; + if(myrand()%3 < 2) + { + baseheight = 10; + randmax = 30; + randfactor = 0.7; + } + else + { + baseheight = 0; + randmax = 15; + randfactor = 0.63; + } list_baseheight->addPoint(p, Attribute(baseheight)); list_randmax->addPoint(p, Attribute(randmax)); @@ -2699,7 +2708,7 @@ continue_generating: +ued*(y0*ued/MAP_BLOCKSIZE) +(x0*ued/MAP_BLOCKSIZE)]) { - if(is_ground_content(n.d)) + if(content_features(n.d).walkable/*is_ground_content(n.d)*/) { // Has now caves has_dungeons = true; @@ -2755,17 +2764,11 @@ continue_generating: MapNode n; n.d = CONTENT_MESE; - //if(is_ground_content(block->getNode(cp).d)) - if(block->getNode(cp).d == CONTENT_STONE) - if(myrand()%8 == 0) - block->setNode(cp, n); - - for(u16 i=0; i<26; i++) + for(u16 i=0; i<27; i++) { - //if(is_ground_content(block->getNode(cp+g_26dirs[i]).d)) - if(block->getNode(cp+g_26dirs[i]).d == CONTENT_STONE) + if(block->getNode(cp+g_27dirs[i]).d == CONTENT_STONE) if(myrand()%8 == 0) - block->setNode(cp+g_26dirs[i], n); + block->setNode(cp+g_27dirs[i], n); } } } @@ -2790,21 +2793,47 @@ continue_generating: ); MapNode n; - n.d = CONTENT_COALSTONE; + n.d = CONTENT_STONE; + n.param = MINERAL_COAL; - //dstream<<"Adding coalstone"<<std::endl; - - //if(is_ground_content(block->getNode(cp).d)) - if(block->getNode(cp).d == CONTENT_STONE) - if(myrand()%8 == 0) - block->setNode(cp, n); + for(u16 i=0; i<27; i++) + { + if(block->getNode(cp+g_27dirs[i]).d == CONTENT_STONE) + if(myrand()%8 == 0) + block->setNode(cp+g_27dirs[i], n); + } + } + } + + /* + Add iron + */ + //TODO: change to iron_amount or whatever + u16 iron_amount = 30.0 * g_settings.getFloat("coal_amount"); + u16 iron_rareness = 60 / iron_amount; + if(iron_rareness == 0) + iron_rareness = 1; + if(myrand()%iron_rareness == 0) + { + u16 a = myrand() % 16; + u16 amount = iron_amount * a*a*a / 1000; + for(s16 i=0; i<amount; i++) + { + v3s16 cp( + (myrand()%(MAP_BLOCKSIZE-2))+1, + (myrand()%(MAP_BLOCKSIZE-2))+1, + (myrand()%(MAP_BLOCKSIZE-2))+1 + ); + + MapNode n; + n.d = CONTENT_STONE; + n.param = MINERAL_IRON; - for(u16 i=0; i<26; i++) + for(u16 i=0; i<27; i++) { - //if(is_ground_content(block->getNode(cp+g_26dirs[i]).d)) - if(block->getNode(cp+g_26dirs[i]).d == CONTENT_STONE) + if(block->getNode(cp+g_27dirs[i]).d == CONTENT_STONE) if(myrand()%8 == 0) - block->setNode(cp+g_26dirs[i], n); + block->setNode(cp+g_27dirs[i], n); } } } @@ -3012,26 +3041,23 @@ continue_generating: <<std::endl;*/ { v3s16 p2 = p + v3s16(x,y,z-2); - if(is_ground_content(sector->getNode(p2).d) - && !is_mineral(sector->getNode(p2).d)) + //if(is_ground_content(sector->getNode(p2).d)) + if(content_features(sector->getNode(p2).d).walkable) sector->setNode(p2, n); } { v3s16 p2 = p + v3s16(x,y,z-1); - if(is_ground_content(sector->getNode(p2).d) - && !is_mineral(sector->getNode(p2).d)) + if(content_features(sector->getNode(p2).d).walkable) sector->setNode(p2, n2); } { v3s16 p2 = p + v3s16(x,y,z+0); - if(is_ground_content(sector->getNode(p2).d) - && !is_mineral(sector->getNode(p2).d)) + if(content_features(sector->getNode(p2).d).walkable) sector->setNode(p2, n2); } { v3s16 p2 = p + v3s16(x,y,z+1); - if(is_ground_content(sector->getNode(p2).d) - && !is_mineral(sector->getNode(p2).d)) + if(content_features(sector->getNode(p2).d).walkable) sector->setNode(p2, n); } @@ -4027,8 +4053,10 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) <<", rendered "<<vertex_count<<" vertices."<<std::endl;*/ } -v3s16 ClientMap::setTempMod(v3s16 p, NodeMod mod, bool *changed) +bool ClientMap::setTempMod(v3s16 p, NodeMod mod, + core::map<v3s16, MapBlock*> *affected_blocks) { + bool changed = false; /* Add it to all blocks touching it */ @@ -4053,14 +4081,29 @@ v3s16 ClientMap::setTempMod(v3s16 p, NodeMod mod, bool *changed) v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; if(blockref->setTempMod(relpos, mod)) { - if(changed != NULL) - *changed = true; + changed = true; } } - return getNodeBlockPos(p); + if(changed && affected_blocks!=NULL) + { + for(u16 i=0; i<7; i++) + { + v3s16 p2 = p + dirs[i]; + // Block position of neighbor (or requested) node + v3s16 blockpos = getNodeBlockPos(p2); + MapBlock * blockref = getBlockNoCreateNoEx(blockpos); + if(blockref == NULL) + continue; + affected_blocks->insert(blockpos, blockref); + } + } + return changed; } -v3s16 ClientMap::clearTempMod(v3s16 p, bool *changed) + +bool ClientMap::clearTempMod(v3s16 p, + core::map<v3s16, MapBlock*> *affected_blocks) { + bool changed = false; v3s16 dirs[7] = { v3s16(0,0,0), // this v3s16(0,0,1), // back @@ -4082,11 +4125,23 @@ v3s16 ClientMap::clearTempMod(v3s16 p, bool *changed) v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; if(blockref->clearTempMod(relpos)) { - if(changed != NULL) - *changed = true; + changed = true; + } + } + if(changed && affected_blocks!=NULL) + { + for(u16 i=0; i<7; i++) + { + v3s16 p2 = p + dirs[i]; + // Block position of neighbor (or requested) node + v3s16 blockpos = getNodeBlockPos(p2); + MapBlock * blockref = getBlockNoCreateNoEx(blockpos); + if(blockref == NULL) + continue; + affected_blocks->insert(blockpos, blockref); } } - return getNodeBlockPos(p); + return changed; } void ClientMap::PrintInfo(std::ostream &out) @@ -4216,7 +4271,7 @@ void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id) /* - TODO: Add an option to only update eg. water and air nodes. + SUGG: Add an option to only update eg. water and air nodes. This will make it interfere less with important stuff if run on background. */ @@ -204,10 +204,13 @@ public: void expireMeshes(bool only_daynight_diffed); /* - Updates the faces of the given block and blocks on the + Update the faces of the given block and blocks on the leading edge. */ void updateMeshes(v3s16 blockpos, u32 daynight_ratio); + + // Update meshes that touch the node + //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio); #endif /* @@ -483,10 +486,16 @@ public: /* Methods for setting temporary modifications to nodes for drawing. - Return value is position of changed block. + + Returns true if something changed. + + All blocks whose mesh could have been changed are inserted + to affected_blocks. */ - v3s16 setTempMod(v3s16 p, NodeMod mod, bool *changed=NULL); - v3s16 clearTempMod(v3s16 p, bool *changed=NULL); + bool setTempMod(v3s16 p, NodeMod mod, + core::map<v3s16, MapBlock*> *affected_blocks=NULL); + bool clearTempMod(v3s16 p, + core::map<v3s16, MapBlock*> *affected_blocks=NULL); // Efficient implementation needs a cache of TempMods //void clearTempMods(); diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 3eb65b4da..484821d50 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -264,12 +264,10 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p, //u8 li = decode_light(light); u8 li = light; - u8 alpha = 255; - + u8 alpha = tile.alpha; + /*u8 alpha = 255; if(tile.id == TILE_WATER) - { - alpha = WATER_ALPHA; - } + alpha = WATER_ALPHA;*/ video::SColor c = video::SColor(alpha,li,li,li); @@ -297,17 +295,8 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p, TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir) { TileSpec spec; - - /*//DEBUG - { - spec.id = TILE_STONE; - return spec; - }*/ - - spec.feature = TILEFEAT_NONE; - //spec.id = TILE_STONE; - spec.id = mn.getTile(face_dir); - + spec = mn.getTile(face_dir); + /* Check temporary modifications on this node */ @@ -320,12 +309,15 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir) struct NodeMod mod = n->getValue(); if(mod.type == NODEMOD_CHANGECONTENT) { - spec.id = content_tile(mod.param, face_dir); + //spec = content_tile(mod.param, face_dir); + MapNode mn2(mod.param); + spec = mn2.getTile(face_dir); } if(mod.type == NODEMOD_CRACK) { - spec.feature = TILEFEAT_CRACK; - spec.param.crack.progression = mod.param; + std::ostringstream os; + os<<"[[mod:crack"<<mod.param; + spec.name += os.str(); } } @@ -675,36 +667,19 @@ void MapBlock::updateMesh(u32 daynight_ratio) FastFace &f = fastfaces_new[i]; const u16 indices[] = {0,1,2,2,3,0}; - - if(f.tile.feature == TILEFEAT_NONE) - { - collector.append(tile_material_get(f.tile.id), f.vertices, 4, - indices, 6); - } - else if(f.tile.feature == TILEFEAT_CRACK) - { - const char *path = tile_texture_path_get(f.tile.id); - - u16 progression = f.tile.param.crack.progression; - std::string name = (std::string)path + "_cracked_" - + (char)('0' + progression); - - TextureMod *mod = new CrackTextureMod(progression); - - video::ITexture *texture = g_irrlicht->getTexture( - TextureSpec(name, path, mod)); - - video::SMaterial material = tile_material_get(f.tile.id); - material.setTexture(0, texture); - - collector.append(material, f.vertices, 4, indices, 6); - } - else - { - // No such feature - assert(0); - } + video::ITexture *texture = g_irrlicht->getTexture(f.tile.name); + video::SMaterial material; + material.Lighting = false; + material.BackfaceCulling = false; + material.setFlag(video::EMF_BILINEAR_FILTER, false); + material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF); + material.setFlag(video::EMF_FOG_ENABLE, true); + material.setTexture(0, texture); + if(f.tile.alpha != 255) + material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; + + collector.append(material, f.vertices, 4, indices, 6); } } @@ -1427,7 +1402,8 @@ s16 MapBlock::getGroundLevel(v2s16 p2d) s16 y = MAP_BLOCKSIZE-1; for(; y>=0; y--) { - if(is_ground_content(getNodeRef(p2d.X, y, p2d.Y).d)) + //if(is_ground_content(getNodeRef(p2d.X, y, p2d.Y).d)) + if(content_features(getNodeRef(p2d.X, y, p2d.Y).d).walkable) { if(y == MAP_BLOCKSIZE-1) return -2; diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 59e40935c..ebae055db 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -21,61 +21,197 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "tile.h" #include "porting.h" #include <string> +#include "mineral.h" -/* - Face directions: - 0: up - 1: down - 2: right - 3: left - 4: back - 5: front -*/ -u16 g_content_tiles[USEFUL_CONTENT_COUNT][6] = +ContentFeatures::~ContentFeatures() { - {TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE}, - {TILE_GRASS,TILE_MUD,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS}, - //{TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER}, - {TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE}, - {TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE}, - {TILE_TREE_TOP,TILE_TREE_TOP,TILE_TREE,TILE_TREE,TILE_TREE,TILE_TREE}, - {TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES}, - {TILE_GRASS_FOOTSTEPS,TILE_MUD,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS}, - {TILE_MESE,TILE_MESE,TILE_MESE,TILE_MESE,TILE_MESE,TILE_MESE}, - {TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD}, - {TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER}, // ocean - {TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD}, - {TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE}, - {TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD}, -}; + if(translate_to) + delete translate_to; +} -std::string g_content_inventory_texture_strings[USEFUL_CONTENT_COUNT]; -// Pointers to c_str()s of the above -const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0}; +struct ContentFeatures g_content_features[256]; + +void init_mapnode() +{ + u8 i; + ContentFeatures *f = NULL; + + i = CONTENT_STONE; + f = &g_content_features[i]; + f->setAllTextures("stone.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + + i = CONTENT_GRASS; + f = &g_content_features[i]; + //f->setAllTextures("mud.png[[mod:sidegrass"); + f->setAllTextures("mud.png[[mod:blitname:grass_side.png"); + f->setTexture(0, "grass.png"); + f->setTexture(1, "mud.png"); + f->setInventoryImage("grass.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + + i = CONTENT_GRASS_FOOTSTEPS; + f = &g_content_features[i]; + //f->setAllTextures("mud.png[[mod:sidegrass"); + f->setAllTextures("mud.png[[mod:blitname:grass_side.png"); + f->setTexture(0, "grass_footsteps.png"); + f->setTexture(1, "mud.png"); + f->setInventoryImage("grass_footsteps.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + + i = CONTENT_MUD; + f = &g_content_features[i]; + f->setAllTextures("mud.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + + i = CONTENT_SAND; + f = &g_content_features[i]; + f->setAllTextures("mud.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + + i = CONTENT_TREE; + f = &g_content_features[i]; + f->setAllTextures("tree.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + + i = CONTENT_LEAVES; + f = &g_content_features[i]; + f->setAllTextures("leaves.png"); + f->param_type = CPT_MINERAL; + f->is_ground_content = true; + + i = CONTENT_COALSTONE; + f = &g_content_features[i]; + f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL); + /*f->setAllTextures("coalstone.png"); + f->is_ground_content = true;*/ + + i = CONTENT_WOOD; + f = &g_content_features[i]; + f->setAllTextures("wood.png"); + f->is_ground_content = true; + + i = CONTENT_MESE; + f = &g_content_features[i]; + f->setAllTextures("mese.png"); + f->is_ground_content = true; + + i = CONTENT_CLOUD; + f = &g_content_features[i]; + f->setAllTextures("cloud.png"); + f->is_ground_content = true; + + i = CONTENT_AIR; + f = &g_content_features[i]; + f->param_type = CPT_LIGHT; + f->light_propagates = true; + f->sunlight_propagates = true; + f->solidness = 0; + f->walkable = false; + f->pointable = false; + f->diggable = false; + f->buildable_to = true; + + i = CONTENT_WATER; + f = &g_content_features[i]; + f->setInventoryImage("water.png"); + f->param_type = CPT_LIGHT; + f->light_propagates = true; + f->solidness = 0; // Drawn separately, makes no faces + f->walkable = false; + f->pointable = false; + f->diggable = false; + f->buildable_to = true; + f->liquid_type = LIQUID_FLOWING; + + i = CONTENT_WATERSOURCE; + f = &g_content_features[i]; + f->setTexture(0, "water.png", WATER_ALPHA); + f->setInventoryImage("water.png"); + f->param_type = CPT_LIGHT; + f->light_propagates = true; + f->solidness = 1; + f->walkable = false; + f->pointable = false; + f->diggable = false; + f->buildable_to = true; + f->liquid_type = LIQUID_SOURCE; + + i = CONTENT_TORCH; + f = &g_content_features[i]; + f->setInventoryImage("torch_on_floor.png"); + f->param_type = CPT_LIGHT; + f->light_propagates = true; + f->solidness = 0; // drawn separately, makes no faces + f->walkable = false; + f->wall_mounted = true; + +} + +TileSpec MapNode::getTile(v3s16 dir) +{ + TileSpec spec; + + s32 dir_i = -1; + + if(dir == v3s16(0,1,0)) + dir_i = 0; + else if(dir == v3s16(0,-1,0)) + dir_i = 1; + else if(dir == v3s16(1,0,0)) + dir_i = 2; + else if(dir == v3s16(-1,0,0)) + dir_i = 3; + else if(dir == v3s16(0,0,1)) + dir_i = 4; + else if(dir == v3s16(0,0,-1)) + dir_i = 5; + + if(dir_i == -1) + // Non-directional + spec = content_features(d).tiles[0]; + else + spec = content_features(d).tiles[dir_i]; + + if(content_features(d).param_type == CPT_MINERAL) + { + u8 mineral = param & 0x1f; + const char *ts = mineral_block_texture(mineral); + if(ts[0] != 0) + { + spec.name += "[[mod:blitname:"; + spec.name += ts; + } + } -const char * g_content_inventory_texture_paths_base[USEFUL_CONTENT_COUNT] = + return spec; +} + +u8 MapNode::getMineral() { - "stone.png", - "grass.png", - "water.png", - "torch_on_floor.png", - "tree_top.png", - "leaves.png", - "grass_footsteps.png", - "mese.png", - "mud.png", - "water.png", //ocean - "cloud.png", - "coalstone.png", - "wood.png", -}; + if(content_features(d).param_type == CPT_MINERAL) + { + return param & 0x1f; + } + + return MINERAL_NONE; +} + +// Pointers to c_str()s g_content_features[i].inventory_image_path +const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0}; void init_content_inventory_texture_paths() { for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++) { - g_content_inventory_texture_strings[i] = porting::getDataPath(g_content_inventory_texture_paths_base[i]); - g_content_inventory_texture_paths[i] = g_content_inventory_texture_strings[i].c_str(); + g_content_inventory_texture_paths[i] = + g_content_features[i].inventory_image_path.c_str(); } } diff --git a/src/mapnode.h b/src/mapnode.h index 69a5a08cd..c69436c9e 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -28,6 +28,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" #include "tile.h" +// Initializes all kind of stuff in here. +// Doesn't depend on anything else. +// Many things depend on this. +void init_mapnode(); + +// Initializes g_content_inventory_texture_paths +void init_content_inventory_texture_paths(); + + +// NOTE: This is not used appropriately everywhere. #define MATERIALS_COUNT 256 /* @@ -69,33 +79,143 @@ with this program; if not, write to the Free Software Foundation, Inc., #define CONTENT_MESE 7 #define CONTENT_MUD 8 #define CONTENT_WATERSOURCE 9 +// Pretty much useless, clouds won't be drawn this way #define CONTENT_CLOUD 10 #define CONTENT_COALSTONE 11 #define CONTENT_WOOD 12 +#define CONTENT_SAND 13 + +/* + This is used by all kinds of things to allocate memory for all + contents except CONTENT_AIR and CONTENT_IGNORE +*/ +#define USEFUL_CONTENT_COUNT 14 + +/* + Content feature list +*/ + +enum ContentParamType +{ + CPT_NONE, + CPT_LIGHT, + CPT_MINERAL +}; + +enum LiquidType +{ + LIQUID_NONE, + LIQUID_FLOWING, + LIQUID_SOURCE +}; + +class MapNode; + +struct ContentFeatures +{ + // If non-NULL, content is translated to this when deserialized + MapNode *translate_to; + + // Type of MapNode::param + ContentParamType param_type; + + /* + 0: up + 1: down + 2: right + 3: left + 4: back + 5: front + */ + TileSpec tiles[6]; + + std::string inventory_image_path; + + bool is_ground_content; //TODO: Remove, use walkable instead + bool light_propagates; + bool sunlight_propagates; + u8 solidness; // Used when choosing which face is drawn + bool walkable; + bool pointable; + bool diggable; + bool buildable_to; + enum LiquidType liquid_type; + bool wall_mounted; // If true, param2 is set to direction when placed + + //TODO: Move more properties here + + ContentFeatures() + { + translate_to = NULL; + param_type = CPT_NONE; + is_ground_content = false; + light_propagates = false; + sunlight_propagates = false; + solidness = 2; + walkable = true; + pointable = true; + diggable = true; + buildable_to = false; + liquid_type = LIQUID_NONE; + wall_mounted = false; + } + + ~ContentFeatures(); -#define USEFUL_CONTENT_COUNT 13 + void setAllTextures(std::string imgname, u8 alpha=255) + { + for(u16 i=0; i<6; i++) + { + tiles[i].name = porting::getDataPath(imgname.c_str()); + tiles[i].alpha = alpha; + } + + // Set this too so it can be left as is most times + if(inventory_image_path == "") + inventory_image_path = porting::getDataPath(imgname.c_str()); + } + void setTexture(u16 i, std::string imgname, u8 alpha=255) + { + tiles[i].name = porting::getDataPath(imgname.c_str()); + tiles[i].alpha = alpha; + } + + void setInventoryImage(std::string imgname) + { + inventory_image_path = porting::getDataPath(imgname.c_str()); + } +}; + +// Initialized by init_mapnode() +extern struct ContentFeatures g_content_features[256]; + +inline ContentFeatures & content_features(u8 i) +{ + return g_content_features[i]; +} -extern u16 g_content_tiles[USEFUL_CONTENT_COUNT][6]; extern const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT]; -// Initializes g_content_inventory_texture_paths -void init_content_inventory_texture_paths(); /* If true, the material allows light propagation and brightness is stored in param. + NOTE: Don't use, use "content_features(m).whatever" instead */ inline bool light_propagates_content(u8 m) { - return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE); + return g_content_features[m].light_propagates; + //return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE); } /* If true, the material allows lossless sunlight propagation. NOTE: It doesn't seem to go through torches regardlessly of this + NOTE: Don't use, use "content_features(m).whatever" instead */ inline bool sunlight_propagates_content(u8 m) { - return (m == CONTENT_AIR || m == CONTENT_TORCH); + return g_content_features[m].sunlight_propagates; + //return (m == CONTENT_AIR || m == CONTENT_TORCH); } /* @@ -104,36 +224,46 @@ inline bool sunlight_propagates_content(u8 m) 0: Invisible 1: Transparent 2: Opaque + NOTE: Don't use, use "content_features(m).whatever" instead */ inline u8 content_solidness(u8 m) { - // As of now, every pseudo node like torches are added to this + return g_content_features[m].solidness; + /*// As of now, every pseudo node like torches are added to this if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER) return 0; if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE) return 1; - return 2; + return 2;*/ } // Objects collide with walkable contents +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_walkable(u8 m) { - return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH); + return g_content_features[m].walkable; + //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH); } +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_liquid(u8 m) { - return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE); + return g_content_features[m].liquid_type != LIQUID_NONE; + //return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE); } +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_flowing_liquid(u8 m) { - return (m == CONTENT_WATER); + return g_content_features[m].liquid_type == LIQUID_FLOWING; + //return (m == CONTENT_WATER); } +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_liquid_source(u8 m) { - return (m == CONTENT_WATERSOURCE); + return g_content_features[m].liquid_type == LIQUID_SOURCE; + //return (m == CONTENT_WATERSOURCE); } // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER @@ -146,57 +276,35 @@ inline u8 make_liquid_flowing(u8 m) } // Pointable contents can be pointed to in the map +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_pointable(u8 m) { - return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE); + return g_content_features[m].pointable; + //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE); } +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_diggable(u8 m) { - return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE); + return g_content_features[m].diggable; + //return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE); } +// NOTE: Don't use, use "content_features(m).whatever" instead inline bool content_buildable_to(u8 m) { - return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE); + return g_content_features[m].buildable_to; + //return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE); } /* Returns true for contents that form the base ground that follows the main heightmap */ -inline bool is_ground_content(u8 m) -{ - return ( - m != CONTENT_IGNORE - && m != CONTENT_AIR - && m != CONTENT_WATER - && m != CONTENT_TORCH - && m != CONTENT_TREE - && m != CONTENT_LEAVES - && m != CONTENT_WATERSOURCE - && m != CONTENT_CLOUD - ); -} - -inline bool is_mineral(u8 c) -{ - return(c == CONTENT_MESE - || c == CONTENT_COALSTONE); -} - -inline bool liquid_replaces_content(u8 c) -{ - return (c == CONTENT_AIR || c == CONTENT_TORCH); -} - -/* - When placing a node, drection info is added to it if this is true -*/ -inline bool content_directional(u8 c) +/*inline bool is_ground_content(u8 m) { - return (c == CONTENT_TORCH); -} + return g_content_features[m].is_ground_content; +}*/ /* Nodes make a face if contents differ and solidness differs. @@ -275,87 +383,15 @@ inline v3s16 unpackDir(u8 b) return d; } -inline u16 content_tile(u8 c, v3s16 dir) -{ - if(c == CONTENT_IGNORE || c == CONTENT_AIR - || c >= USEFUL_CONTENT_COUNT) - return TILE_NONE; - - s32 dir_i = -1; - - if(dir == v3s16(0,1,0)) - dir_i = 0; - else if(dir == v3s16(0,-1,0)) - dir_i = 1; - else if(dir == v3s16(1,0,0)) - dir_i = 2; - else if(dir == v3s16(-1,0,0)) - dir_i = 3; - else if(dir == v3s16(0,0,1)) - dir_i = 4; - else if(dir == v3s16(0,0,-1)) - dir_i = 5; - - /*if(dir_i == -1) - return TILE_NONE;*/ - assert(dir_i != -1); - - return g_content_tiles[c][dir_i]; -} - enum LightBank { LIGHTBANK_DAY, LIGHTBANK_NIGHT }; -#if 0 -#define DIR_PX 1 //X+ -#define DIR_NX 2 //X- -#define DIR_PZ 4 //Z+ -#define DIR_NZ 8 //Z- -#define DIR_PY 16 //Y+ -#define DIR_NY 32 //Y- - -inline void decode_dirs(u8 b, core::list<v3s16> &dirs) -{ - if(b & DIR_PX) - dirs.push_back(v3s16(1,0,0)); - if(b & DIR_NX) - dirs.push_back(v3s16(-1,0,0)); - if(b & DIR_PZ) - dirs.push_back(v3s16(0,0,1)); - if(b & DIR_NZ) - dirs.push_back(v3s16(0,0,-1)); - if(b & DIR_PY) - dirs.push_back(v3s16(0,1,0)); - if(b & DIR_NY) - dirs.push_back(v3s16(0,-1,0)); -} - -inline u8 encode_dirs(core::list<v3s16> &dirs) -{ - u8 b = 0; - for(core::list<v3s16>::Iterator - i = dirs.begin(); - i != dirs.end(); i++) - { - if(*i == v3s16(1,0,0)) - b += DIR_PX; - else if(*i == v3s16(-1,0,0)) - b += DIR_NX; - else if(*i == v3s16(0,0,1)) - b += DIR_PZ; - else if(*i == v3s16(0,0,-1)) - b += DIR_NZ; - else if(*i == v3s16(0,1,0)) - b += DIR_PY; - else if(*i == v3s16(0,-1,0)) - b += DIR_NY; - } - return b; -} -#endif +/* + This is the stuff what the whole world consists of. +*/ struct MapNode { @@ -511,11 +547,11 @@ struct MapNode else assert(0); } + + // In mapnode.cpp + TileSpec getTile(v3s16 dir); - u16 getTile(v3s16 dir) - { - return content_tile(d, dir); - } + u8 getMineral(); /* These serialization functions are used when informing client @@ -584,6 +620,15 @@ struct MapNode param = source[1]; param2 = source[2]; } + + // Translate deprecated stuff + MapNode *translate_to = g_content_features[d].translate_to; + if(translate_to) + { + dstream<<"MapNode: WARNING: Translating "<<d<<" to " + <<translate_to->d<<std::endl; + *this = *translate_to; + } } }; @@ -600,6 +645,9 @@ inline v3s16 floatToInt(v3f p) return p2; } +/* + The same thing backwards +*/ inline v3f intToFloat(v3s16 p) { v3f p2( diff --git a/src/mineral.h b/src/mineral.h new file mode 100644 index 000000000..e43e48ab8 --- /dev/null +++ b/src/mineral.h @@ -0,0 +1,60 @@ +/* +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 MINERAL_HEADER +#define MINERAL_HEADER + +#include "inventory.h" + +/* + Minerals + + Value is stored in the lowest 5 bits of a MapNode's CPT_MINERAL + type param. +*/ + +#define MINERAL_NONE 0 +#define MINERAL_COAL 1 +#define MINERAL_IRON 2 + +inline const char * mineral_block_texture(u8 mineral) +{ + switch(mineral) + { + case MINERAL_COAL: + return "mineral_coal.png"; + case MINERAL_IRON: + return "mineral_iron.png"; + default: + return ""; + } +} + +inline CraftItem * getDiggedMineralItem(u8 mineral) +{ + if(mineral == MINERAL_COAL) + return new CraftItem("lump_of_coal", 1); + else if(mineral == MINERAL_IRON) + return new CraftItem("lump_of_iron", 1); + + return NULL; +} + +#endif + diff --git a/src/server.cpp b/src/server.cpp index 505e9730f..541582b65 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "voxel.h" #include "materials.h" +#include "mineral.h" #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0) @@ -1951,11 +1952,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) core::map<v3s16, MapBlock*> modified_blocks; u8 material; + u8 mineral = MINERAL_NONE; try { + MapNode n = m_env.getMap().getNode(p_under); // Get material at position - material = m_env.getMap().getNode(p_under).d; + material = n.d; // If it's not diggable, do nothing if(content_diggable(material) == false) { @@ -1963,6 +1966,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<std::endl; return; } + // Get mineral + mineral = n.getMineral(); } catch(InvalidPositionException &e) { @@ -1974,8 +1979,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } - //TODO: Send to only other clients - /* Send the removal to all other clients */ @@ -2047,7 +2050,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) /* Add digged item to inventory */ - InventoryItem *item = new MaterialItem(material, 1); + + InventoryItem *item = NULL; + + if(mineral != MINERAL_NONE) + item = getDiggedMineralItem(mineral); + + if(item == NULL) + item = new MaterialItem(material, 1); + player->inventory.addItem("main", item); /* @@ -2134,7 +2145,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) MaterialItem *mitem = (MaterialItem*)item; MapNode n; n.d = mitem->getMaterial(); - if(content_directional(n.d)) + if(content_features(n.d).wall_mounted) n.dir = packDir(p_under - p_over); #if 1 @@ -2939,7 +2950,7 @@ void Server::SendInventory(u16 peer_id) if(!found) { ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COALSTONE); + specs[0] = ItemSpec(ITEM_CRAFT, "Coal"); specs[3] = ItemSpec(ITEM_CRAFT, "Stick"); if(checkItemCombination(items, specs)) { @@ -3300,6 +3311,11 @@ Player *Server::emergePlayer(const char *name, const char *password, } else { + { + InventoryItem *item = new ToolItem("WPick", 32000); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } /*{ InventoryItem *item = new MaterialItem(CONTENT_MESE, 6); void* r = player->inventory.addItem("main", item); diff --git a/src/tile.cpp b/src/tile.cpp index 18a2f155a..60e9873c0 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -18,119 +18,10 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "tile.h" -#include "porting.h" +//#include "porting.h" // For IrrlichtWrapper -#include "main.h" -#include <string> +//#include "main.h" +//#include <string> -/* - These can either be real paths or generated names of preloaded - textures (like "mud.png_sidegrass") -*/ -std::string g_tile_texture_paths[TILES_COUNT]; - -const char * tile_texture_path_get(u32 i) -{ - assert(i < TILES_COUNT); - - //return g_tile_texture_paths[i]; - return g_tile_texture_paths[i].c_str(); -} - -// A mapping from tiles to materials -// Initialized at run-time. -video::SMaterial g_tile_materials[TILES_COUNT]; - -enum TileTextureModID -{ - TTMID_NONE, - TTMID_SIDEGRASS, -}; - -struct TileTextureSpec -{ - const char *filename; - enum TileTextureModID mod; -}; - -/* - Initializes g_tile_texture_paths with paths of textures, - generates generated textures and creates the tile material array. -*/ -void init_tile_textures() -{ - TileTextureSpec tile_texture_specs[TILES_COUNT] = - { - {NULL, TTMID_NONE}, - {"stone.png", TTMID_NONE}, - {"water.png", TTMID_NONE}, - {"grass.png", TTMID_NONE}, - {"tree.png", TTMID_NONE}, - {"leaves.png", TTMID_NONE}, - {"grass_footsteps.png", TTMID_NONE}, - {"mese.png", TTMID_NONE}, - {"mud.png", TTMID_NONE}, - {"tree_top.png", TTMID_NONE}, - {"mud.png", TTMID_SIDEGRASS}, - {"cloud.png", TTMID_NONE}, - {"coalstone.png", TTMID_NONE}, - {"wood.png", TTMID_NONE}, - }; - - for(s32 i=0; i<TILES_COUNT; i++) - { - const char *filename = tile_texture_specs[i].filename; - enum TileTextureModID mod_id = tile_texture_specs[i].mod; - - if(filename != NULL && std::string("") != filename) - { - std::string path = porting::getDataPath(filename); - std::string mod_postfix = ""; - if(mod_id == TTMID_SIDEGRASS) - { - mod_postfix = "_sidegrass"; - // Generate texture - TextureMod *mod = new SideGrassTextureMod(); - g_irrlicht->getTexture(TextureSpec(path + mod_postfix, - path, mod)); - } - g_tile_texture_paths[i] = path + mod_postfix; - } - } - - for(s32 i=0; i<TILES_COUNT; i++) - { - const char *path = tile_texture_path_get(i); - - video::ITexture *t = NULL; - - if(path != NULL && std::string("") != path) - { - t = g_irrlicht->getTexture(path); - assert(t != NULL); - } - - g_tile_materials[i].Lighting = false; - g_tile_materials[i].BackfaceCulling = false; - g_tile_materials[i].setFlag(video::EMF_BILINEAR_FILTER, false); - g_tile_materials[i].setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF); - //if(i != TILE_WATER) - g_tile_materials[i].setFlag(video::EMF_FOG_ENABLE, true); - - //g_tile_materials[i].setFlag(video::EMF_TEXTURE_WRAP, video::ETC_REPEAT); - //g_tile_materials[i].setFlag(video::EMF_ANISOTROPIC_FILTER, false); - - g_tile_materials[i].setTexture(0, t); - } - - g_tile_materials[TILE_WATER].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; - //g_tile_materials[TILE_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; -} - -video::SMaterial & tile_material_get(u32 i) -{ - assert(i < TILES_COUNT); - - return g_tile_materials[i]; -} +// Nothing here diff --git a/src/tile.h b/src/tile.h index 5869c03ee..b903d92a8 100644 --- a/src/tile.h +++ b/src/tile.h @@ -21,88 +21,36 @@ with this program; if not, write to the Free Software Foundation, Inc., #define TILE_HEADER #include "common_irrlicht.h" -#include "utility.h" +//#include "utility.h" +#include <string> -// TileID is supposed to be stored in a u16 - -enum TileID -{ - TILE_NONE, // Nothing shown - TILE_STONE, - TILE_WATER, - TILE_GRASS, - TILE_TREE, - TILE_LEAVES, - TILE_GRASS_FOOTSTEPS, - TILE_MESE, - TILE_MUD, - TILE_TREE_TOP, - TILE_MUD_WITH_GRASS, - TILE_CLOUD, - TILE_COALSTONE, - TILE_WOOD, - - // Count of tile ids - TILES_COUNT -}; - -enum TileSpecialFeature -{ - TILEFEAT_NONE, - TILEFEAT_CRACK, -}; - -struct TileCrackParam +struct TileSpec { - bool operator==(TileCrackParam &other) + TileSpec(): + alpha(255) { - return progression == other.progression; } - u16 progression; -}; - -struct TileSpec -{ - TileSpec() + TileSpec(const std::string &a_name): + name(a_name), + alpha(255) { - id = TILE_NONE; - feature = TILEFEAT_NONE; } - bool operator==(TileSpec &other) + TileSpec(const char *a_name): + name(a_name), + alpha(255) { - if(id != other.id) - return false; - if(feature != other.feature) - return false; - if(feature == TILEFEAT_NONE) - return true; - if(feature == TILEFEAT_CRACK) - { - return param.crack == other.param.crack; - } - // Invalid feature - assert(0); - return false; } - u16 id; // Id in g_tile_materials, TILE_NONE=none - enum TileSpecialFeature feature; - union + bool operator==(TileSpec &other) { - TileCrackParam crack; - } param; + return (name == other.name && alpha == other.alpha); + } + + // path + mods + std::string name; + u8 alpha; }; -/* - Functions -*/ - -void init_tile_textures(); - -const char * tile_texture_path_get(u32 i); - -video::SMaterial & tile_material_get(u32 i); - #endif diff --git a/src/utility.cpp b/src/utility.cpp index 8befaaeec..65615f9c9 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -88,6 +88,41 @@ const v3s16 g_26dirs[26] = // 26 }; +const v3s16 g_27dirs[27] = +{ + // +right, +top, +back + v3s16( 0, 0, 1), // back + v3s16( 0, 1, 0), // top + v3s16( 1, 0, 0), // right + v3s16( 0, 0,-1), // front + v3s16( 0,-1, 0), // bottom + v3s16(-1, 0, 0), // left + // 6 + v3s16(-1, 1, 0), // top left + v3s16( 1, 1, 0), // top right + v3s16( 0, 1, 1), // top back + v3s16( 0, 1,-1), // top front + v3s16(-1, 0, 1), // back left + v3s16( 1, 0, 1), // back right + v3s16(-1, 0,-1), // front left + v3s16( 1, 0,-1), // front right + v3s16(-1,-1, 0), // bottom left + v3s16( 1,-1, 0), // bottom right + v3s16( 0,-1, 1), // bottom back + v3s16( 0,-1,-1), // bottom front + // 18 + v3s16(-1, 1, 1), // top back-left + v3s16( 1, 1, 1), // top back-right + v3s16(-1, 1,-1), // top front-left + v3s16( 1, 1,-1), // top front-right + v3s16(-1,-1, 1), // bottom back-left + v3s16( 1,-1, 1), // bottom back-right + v3s16(-1,-1,-1), // bottom front-left + v3s16( 1,-1,-1), // bottom front-right + // 26 + v3s16(0,0,0), +}; + static unsigned long next = 1; /* RAND_MAX assumed to be 32767 */ diff --git a/src/utility.h b/src/utility.h index fd2881cff..785ff167c 100644 --- a/src/utility.h +++ b/src/utility.h @@ -36,6 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc., extern const v3s16 g_26dirs[26]; +// 26th is (0,0,0) +extern const v3s16 g_27dirs[27]; + inline void writeU32(u8 *data, u32 i) { data[0] = ((i>>24)&0xff); @@ -666,6 +669,14 @@ inline s32 stoi(std::string s) return atoi(s.c_str()); } +inline float stof(std::string s) +{ + float f; + std::istringstream ss(s); + ss>>f; + return f; +} + inline std::string itos(s32 i) { std::ostringstream o; diff --git a/src/voxel.cpp b/src/voxel.cpp index 272e11ccc..d68a8db02 100644 --- a/src/voxel.cpp +++ b/src/voxel.cpp @@ -110,7 +110,7 @@ void VoxelManipulator::print(std::ostream &o, VoxelPrintMode mode) if(pr <= 9) c = pr + '0'; } - else if(liquid_replaces_content(m)) + else if(m == CONTENT_AIR) { c = ' '; } @@ -653,637 +653,4 @@ void VoxelManipulator::spreadLight(enum LightBank bank, } #endif -#if 0 -int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count) -{ - m_flags[m_area.index(p)] |= VOXELFLAG_CHECKED2; - - if(p.Y > highest_y) - highest_y = p.Y; - - /*if(recur_count > 1000) - throw ProcessingLimitException - ("getWaterPressure recur_count limit reached");*/ - - if(recur_count > 10000) - return -1; - - recur_count++; - - v3s16 dirs[6] = { - v3s16(0,1,0), // top - v3s16(0,0,1), // back - v3s16(0,0,-1), // front - v3s16(1,0,0), // right - v3s16(-1,0,0), // left - v3s16(0,-1,0), // bottom - }; - - // Load neighboring nodes - emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)), 1); - - s32 i; - for(i=0; i<6; i++) - { - v3s16 p2 = p + dirs[i]; - u8 f = m_flags[m_area.index(p2)]; - // Ignore inexistent or checked nodes - if(f & (VOXELFLAG_INEXISTENT | VOXELFLAG_CHECKED2)) - continue; - MapNode &n = m_data[m_area.index(p2)]; - // Ignore non-liquid nodes - if(content_liquid(n.d) == false) - continue; - - int pr; - - // If at ocean surface - if(n.pressure == 1 && n.d == CONTENT_WATERSOURCE) - //if(n.pressure == 1) // Causes glitches but is fast - { - pr = 1; - } - // Otherwise recurse more - else - { - pr = getWaterPressure(p2, highest_y, recur_count); - if(pr == -1) - continue; - } - - // If block is at top, pressure here is one higher - if(i == 0) - { - if(pr < 255) - pr++; - } - // If block is at bottom, pressure here is one lower - else if(i == 5) - { - if(pr > 1) - pr--; - } - - // Node is on the pressure route - m_flags[m_area.index(p)] |= VOXELFLAG_CHECKED4; - - // Got pressure - return pr; - } - - // Nothing useful found - return -1; -} - -void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr, - VoxelArea request_area, - core::map<v3s16, u8> &active_nodes, - int recur_count) -{ - //if(recur_count > 10000) - /*throw ProcessingLimitException - ("spreadWaterPressure recur_count limit reached");*/ - if(recur_count > 10) - return; - recur_count++; - - /*dstream<<"spreadWaterPressure: p=(" - <<p.X<<","<<p.Y<<","<<p.Z<<")" - <<", oldpr="<<(int)m_data[m_area.index(p)].pressure - <<", pr="<<pr - <<", recur_count="<<recur_count - <<", request_area="; - request_area.print(dstream); - dstream<<std::endl;*/ - - m_flags[m_area.index(p)] |= VOXELFLAG_CHECKED3; - m_data[m_area.index(p)].pressure = pr; - - v3s16 dirs[6] = { - v3s16(0,1,0), // top - v3s16(-1,0,0), // left - v3s16(1,0,0), // right - v3s16(0,0,-1), // front - v3s16(0,0,1), // back - v3s16(0,-1,0), // bottom - }; - - // Load neighboring nodes - emerge(VoxelArea(p - v3s16(1,1,1), p + v3s16(1,1,1)), 2); - - s32 i; - for(i=0; i<6; i++) - { - v3s16 p2 = p + dirs[i]; - - u8 f = m_flags[m_area.index(p2)]; - - // Ignore inexistent and checked nodes - if(f & (VOXELFLAG_INEXISTENT | VOXELFLAG_CHECKED3)) - continue; - - MapNode &n = m_data[m_area.index(p2)]; - - /* - If material is air: - add to active_nodes if there is flow-causing pressure. - NOTE: Do not remove anything from there. We cannot know - here if some other neighbor of it causes flow. - */ - if(liquid_replaces_content(n.d)) - { - bool pressure_causes_flow = false; - // If empty block is at top - if(i == 0) - { - if(m_disable_water_climb) - continue; - - //if(pr >= PRESERVE_WATER_VOLUME ? 3 : 2) - if(pr >= 3) - pressure_causes_flow = true; - } - // If block is at bottom - else if(i == 5) - { - pressure_causes_flow = true; - } - // If block is at side - else - { - //if(pr >= PRESERVE_WATER_VOLUME ? 2 : 1) - if(pr >= 2) - pressure_causes_flow = true; - } - - if(pressure_causes_flow) - { - active_nodes[p2] = 1; - } - - continue; - } - - // Ignore non-liquid nodes - if(content_liquid(n.d) == false) - continue; - - int pr2 = pr; - // If block is at top, pressure there is lower - if(i == 0) - { - if(pr2 > 0) - pr2--; - } - // If block is at bottom, pressure there is higher - else if(i == 5) - { - if(pr2 < 255) - pr2++; - } - - /*if(m_disable_water_climb) - { - if(pr2 > 3) - pr2 = 3; - }*/ - - // Ignore if correct pressure is already set and is not on - // request_area. - // Thus, request_area can be used for updating as much - // pressure info in some area as possible to possibly - // make some calls to getWaterPressure unnecessary. - if(n.pressure == pr2 && request_area.contains(p2) == false) - continue; - - spreadWaterPressure(p2, pr2, request_area, active_nodes, recur_count); - } -} - -void VoxelManipulator::updateAreaWaterPressure(VoxelArea a, - core::map<v3s16, u8> &active_nodes, - bool checked3_is_clear) -{ - TimeTaker timer("updateAreaWaterPressure", &updateareawaterpressure_time); - - emerge(a, 3); - - bool checked2_clear = false; - - if(checked3_is_clear == false) - { - //clearFlag(VOXELFLAG_CHECKED3); - - clearFlag(VOXELFLAG_CHECKED3 | VOXELFLAG_CHECKED2); - checked2_clear = true; - } - - - for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++) - for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++) - for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++) - { - v3s16 p(x,y,z); - - u8 f = m_flags[m_area.index(p)]; - // Ignore inexistent or checked nodes - if(f & (VOXELFLAG_INEXISTENT | VOXELFLAG_CHECKED3)) - continue; - MapNode &n = m_data[m_area.index(p)]; - // Ignore non-liquid nodes - if(content_liquid(n.d) == false) - continue; - - if(checked2_clear == false) - { - clearFlag(VOXELFLAG_CHECKED2); - checked2_clear = true; - } - - checked2_clear = false; - - s16 highest_y = -32768; - int recur_count = 0; - int pr = -1; - - try - { - // 0-1ms @ recur_count <= 100 - //TimeTaker timer("getWaterPressure", g_irrlicht); - pr = getWaterPressure(p, highest_y, recur_count); - } - catch(ProcessingLimitException &e) - { - //dstream<<"getWaterPressure ProcessingLimitException"<<std::endl; - } - - if(pr == -1) - { - assert(highest_y != -32768); - - pr = highest_y - p.Y + 1; - if(pr > 255) - pr = 255; - - /*dstream<<"WARNING: Pressure at (" - <<p.X<<","<<p.Y<<","<<p.Z<<")" - <<" = "<<pr - //<<" and highest_y == -32768" - <<std::endl; - assert(highest_y != -32768); - continue;*/ - } - - try - { - // 0ms - //TimeTaker timer("spreadWaterPressure", g_irrlicht); - spreadWaterPressure(p, pr, a, active_nodes, 0); - } - catch(ProcessingLimitException &e) - { - //dstream<<"getWaterPressure ProcessingLimitException"<<std::endl; - } - } -} - -bool VoxelManipulator::flowWater(v3s16 removed_pos, - core::map<v3s16, u8> &active_nodes, - int recursion_depth, bool debugprint, - u32 stoptime) -{ - v3s16 dirs[6] = { - v3s16(0,1,0), // top - v3s16(0,0,-1), // front - v3s16(0,0,1), // back - v3s16(-1,0,0), // left - v3s16(1,0,0), // right - v3s16(0,-1,0), // bottom - }; - - recursion_depth++; - - v3s16 p; - bool from_ocean = false; - - // Randomize horizontal order - static s32 cs = 0; - if(cs < 3) - cs++; - else - cs = 0; - s16 s1 = (cs & 1) ? 1 : -1; - s16 s2 = (cs & 2) ? 1 : -1; - //dstream<<"s1="<<s1<<", s2="<<s2<<std::endl; - - { - TimeTaker timer1("flowWater pre", &flowwater_pre_time); - - // Load neighboring nodes - emerge(VoxelArea(removed_pos - v3s16(1,1,1), removed_pos + v3s16(1,1,1)), 4); - - // Ignore incorrect removed_pos - { - u8 f = m_flags[m_area.index(removed_pos)]; - // Ignore inexistent or checked node - if(f & (VOXELFLAG_INEXISTENT | VOXELFLAG_CHECKED)) - return false; - MapNode &n = m_data[m_area.index(removed_pos)]; - // Ignore nodes to which the water can't go - if(liquid_replaces_content(n.d) == false) - return false; - } - - s32 i; - for(i=0; i<6; i++) - { - // Don't raise water from bottom - if(m_disable_water_climb && i == 5) - continue; - - p = removed_pos + v3s16(s1*dirs[i].X, dirs[i].Y, s2*dirs[i].Z); - - u8 f = m_flags[m_area.index(p)]; - // Inexistent or checked nodes can't move - if(f & (VOXELFLAG_INEXISTENT | VOXELFLAG_CHECKED)) - continue; - MapNode &n = m_data[m_area.index(p)]; - // Only liquid nodes can move - if(content_liquid(n.d) == false) - continue; - // If block is at top, select it always - if(i == 0) - { - break; - } - // If block is at bottom, select it if it has enough pressure - if(i == 5) - { - //if(n.pressure >= PRESERVE_WATER_VOLUME ? 3 : 2) - if(n.pressure >= 3) - break; - continue; - } - // Else block is at some side. Select it if it has enough pressure - //if(n.pressure >= PRESERVE_WATER_VOLUME ? 2 : 1) - if(n.pressure >= 2) - { - break; - } - } - - // If there is nothing to move, return - if(i==6) - return false; - - /* - Move water and bubble - */ - - u8 m = m_data[m_area.index(p)].d; - u8 f = m_flags[m_area.index(p)]; - - if(m == CONTENT_WATERSOURCE) - from_ocean = true; - - // Move air bubble if not taking water from ocean - if(from_ocean == false) - { - m_data[m_area.index(p)].d = m_data[m_area.index(removed_pos)].d; - m_flags[m_area.index(p)] = m_flags[m_area.index(removed_pos)]; - } - - /* - This has to be done to copy the brightness of a light source - correctly. Otherwise unspreadLight will fuck up when water - has replaced a light source. - */ - u8 light = m_data[m_area.index(removed_pos)].getLightBanksWithSource(); - - m_data[m_area.index(removed_pos)].d = m; - m_flags[m_area.index(removed_pos)] = f; - - m_data[m_area.index(removed_pos)].setLightBanks(light); - - // Mark removed_pos checked - m_flags[m_area.index(removed_pos)] |= VOXELFLAG_CHECKED; - - // If block was dropped from surface, increase pressure - if(i == 0 && m_data[m_area.index(removed_pos)].pressure == 1) - { - m_data[m_area.index(removed_pos)].pressure = 2; - } - - /* - NOTE: This does not work as-is - if(m == CONTENT_WATERSOURCE) - { - // If block was raised to surface, increase pressure of - // source node - if(i == 5 && m_data[m_area.index(p)].pressure == 1) - { - m_data[m_area.index(p)].pressure = 2; - } - }*/ - - /*if(debugprint) - { - dstream<<"VoxelManipulator::flowWater(): Moved bubble:"<<std::endl; - print(dstream, VOXELPRINT_WATERPRESSURE); - }*/ - - // Update pressure - VoxelArea a; - a.addPoint(p - v3s16(1,1,1)); - a.addPoint(p + v3s16(1,1,1)); - a.addPoint(removed_pos - v3s16(1,1,1)); - a.addPoint(removed_pos + v3s16(1,1,1)); - updateAreaWaterPressure(a, active_nodes); - - /*if(debugprint) - { - dstream<<"VoxelManipulator::flowWater(): Pressure updated:"<<std::endl; - print(dstream, VOXELPRINT_WATERPRESSURE); - //std::cin.get(); - }*/ - - if(debugprint) - { - dstream<<"VoxelManipulator::flowWater(): step done:"<<std::endl; - print(dstream, VOXELPRINT_WATERPRESSURE); - //std::cin.get(); - } - - }//timer1 - - //if(PRESERVE_WATER_VOLUME) - if(from_ocean == false) - { - // Flow water to the newly created empty position - /*flowWater(p, active_nodes, recursion_depth, - debugprint, counter, counterlimit);*/ - flowWater(p, active_nodes, recursion_depth, - debugprint, stoptime); - } - - if(stoptime != 0) - { - u32 timenow = getTimeMs(); - // Well, it is a bit hard to guess because we don't know the - // start time... - bool overflow = timenow < stoptime - 100000; - if(timenow >= stoptime || overflow) - { - dstream<<"flowWater: stoptime reached"<<std::endl; - throw ProcessingLimitException("flowWater stoptime reached"); - } - } - -find_again: - - // Try flowing water to empty positions around removed_pos. - // They are checked in reverse order compared to the previous loop. - for(s32 i=5; i>=0; i--) - { - // Don't try to flow to top - if(m_disable_water_climb && i == 0) - continue; - - //v3s16 p = removed_pos + dirs[i]; - p = removed_pos + v3s16(s1*dirs[i].X, dirs[i].Y, s2*dirs[i].Z); - - u8 f = m_flags[m_area.index(p)]; - // Water can't move to inexistent nodes - if(f & VOXELFLAG_INEXISTENT) - continue; - MapNode &n = m_data[m_area.index(p)]; - // Water can only move to air - if(liquid_replaces_content(n.d) == false) - continue; - - // Flow water to node - bool moved = - flowWater(p, active_nodes, recursion_depth, - debugprint, stoptime); - /*flowWater(p, active_nodes, recursion_depth, - debugprint, counter, counterlimit);*/ - - if(moved) - { - // Search again from all neighbors - goto find_again; - } - } - - return true; -} - -void VoxelManipulator::flowWater( - core::map<v3s16, u8> &active_nodes, - int recursion_depth, bool debugprint, - u32 timelimit) -{ - addarea_time = 0; - emerge_time = 0; - emerge_load_time = 0; - clearflag_time = 0; - updateareawaterpressure_time = 0; - flowwater_pre_time = 0; - - if(active_nodes.size() == 0) - { - dstream<<"flowWater: no active nodes"<<std::endl; - return; - } - - //TimeTaker timer1("flowWater (active_nodes)", g_irrlicht); - - //dstream<<"active_nodes.size() = "<<active_nodes.size()<<std::endl; - - - u32 stoptime = 0; - stoptime = getTimeMs() + timelimit; - - // Count of handled active nodes - u32 handled_count = 0; - - try - { - - /* - Take random one at first - - This is randomized only at the first time so that all - subsequent nodes will be taken at roughly the same position - */ - s32 k = 0; - if(active_nodes.size() != 0) - k = (s32)myrand() % (s32)active_nodes.size(); - - // Flow water to active nodes - for(;;) - //for(s32 h=0; h<1; h++) - { - if(active_nodes.size() == 0) - break; - - handled_count++; - - // Clear check flags - clearFlag(VOXELFLAG_CHECKED); - - //dstream<<"Selecting a new active_node"<<std::endl; - -#if 0 - // Take first one - core::map<v3s16, u8>::Node - *n = active_nodes.getIterator().getNode(); -#endif - -#if 1 - - core::map<v3s16, u8>::Iterator - i = active_nodes.getIterator().getNode(); - for(s32 j=0; j<k; j++) - { - i++; - } - core::map<v3s16, u8>::Node *n = i.getNode(); - - // Decrement index if less than 0. - // This keeps us in existing indices always. - if(k > 0) - k--; -#endif - - v3s16 p = n->getKey(); - active_nodes.remove(p); - flowWater(p, active_nodes, recursion_depth, - debugprint, stoptime); - } - - } - catch(ProcessingLimitException &e) - { - //dstream<<"getWaterPressure ProcessingLimitException"<<std::endl; - } - - /*v3s16 e = m_area.getExtent(); - s32 v = m_area.getVolume(); - dstream<<"flowWater (active): " - <<"area ended up as " - <<e.X<<"x"<<e.Y<<"x"<<e.Z<<" = "<<v - <<", handled a_node count: "<<handled_count - <<", active_nodes.size() = "<<active_nodes.size() - <<std::endl; - dstream<<"addarea_time: "<<addarea_time - <<", emerge_time: "<<emerge_time - <<", emerge_load_time: "<<emerge_load_time - <<", clearflag_time: "<<clearflag_time - <<", flowwater_pre_time: "<<flowwater_pre_time - <<", updateareawaterpressure_time: "<<updateareawaterpressure_time - <<std::endl;*/ -} -#endif - //END diff --git a/src/voxel.h b/src/voxel.h index 80d292891..ff5d534cb 100644 --- a/src/voxel.h +++ b/src/voxel.h @@ -411,62 +411,6 @@ public: void spreadLight(enum LightBank bank, core::map<v3s16, bool> & from_nodes); -#if 0 - // VOXELFLAG_CHECKED2s must usually be cleared before calling - // -1: dead end, 0-255: pressure - // highest_y: Highest found water y is stored here. - // Must be initialized to -32768 - int getWaterPressure(v3s16 p, s16 &highest_y, int recur_count); - - /* - VOXELFLAG_CHECKED3s must usually be cleared before calling. - - active_nodes: surface-touching air nodes with flow-causing - pressure. set-like dummy map container. - - Spreads pressure pr at node p to request_area or as far as - there is invalid pressure. - */ - void spreadWaterPressure(v3s16 p, int pr, - VoxelArea request_area, - core::map<v3s16, u8> &active_nodes, - int recur_count); - - /* - VOXELFLAG_CHECKED3s must usually be cleared before calling. - */ - void updateAreaWaterPressure(VoxelArea a, - core::map<v3s16, u8> &active_nodes, - bool checked3_is_clear=false); - - /* - Returns true if moved something - */ - bool flowWater(v3s16 removed_pos, - core::map<v3s16, u8> &active_nodes, - int recursion_depth=0, - bool debugprint=false, - u32 stoptime=0 - ); - - /* - To flow some water, call this with the target node in - active_nodes - TODO: Make the active_nodes map to contain some vectors - that are properly sorted according to water flow order. - The current order makes water flow strangely if the - first one is always taken. - No, active_nodes should preserve the order stuff is - added to it, in addition to adhering the water flow - order. - */ - void flowWater(core::map<v3s16, u8> &active_nodes, - int recursion_depth=0, - bool debugprint=false, - u32 timelimit=50 - ); -#endif - /* Virtual functions */ |