From 9f882bf74d452521cb7fb1806ab453aaa28da343 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Wed, 26 Jan 2011 00:41:06 +0200 Subject: [PATCH] Reworked texture, material, mineral and whatever handling --- data/coalstone.png | Bin 1523 -> 0 bytes data/grass.png | Bin 855 -> 1599 bytes data/lump_of_coal.png | Bin 0 -> 933 bytes data/lump_of_iron.png | Bin 0 -> 936 bytes data/mineral_coal.png | Bin 0 -> 1620 bytes data/mineral_iron.png | Bin 0 -> 1616 bytes data/sand.png | Bin 0 -> 659 bytes makepackage_binary.sh | 6 +- minetest.vcproj | 2 +- src/client.cpp | 1 + src/client.h | 35 +++ src/inventory.h | 28 +- src/irrlichtwrapper.cpp | 309 ++++++++++++++----- src/irrlichtwrapper.h | 95 +----- src/map.cpp | 145 ++++++--- src/map.h | 17 +- src/mapblock.cpp | 74 ++--- src/mapnode.cpp | 228 ++++++++++++--- src/mapnode.h | 300 +++++++++++-------- src/mineral.h | 60 ++++ src/server.cpp | 28 +- src/tile.cpp | 117 +------- src/tile.h | 94 ++---- src/utility.cpp | 35 +++ src/utility.h | 11 + src/voxel.cpp | 635 +--------------------------------------- src/voxel.h | 56 ---- 27 files changed, 952 insertions(+), 1324 deletions(-) delete mode 100644 data/coalstone.png create mode 100644 data/lump_of_coal.png create mode 100644 data/lump_of_iron.png create mode 100644 data/mineral_coal.png create mode 100644 data/mineral_iron.png create mode 100644 data/sand.png create mode 100644 src/mineral.h diff --git a/data/coalstone.png b/data/coalstone.png deleted file mode 100644 index 0c62a192f605f02f7b24079808e034961b037885..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1523 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 literal 0 HcmV?d00001 diff --git a/data/mineral_iron.png b/data/mineral_iron.png new file mode 100644 index 0000000000000000000000000000000000000000..9698aa0060e42df0d33f8e8e6994b377aa1d4988 GIT binary patch literal 1616 zcmZuw2~ZR^6iopIg%!^M1p#YN#8!pUDNtRc97_-pkQOhL(>osZLW_&yAR-7DL=n)6 zmgSH`L{kxw>cF(P2q6d|1AqcR0Kfns z0HBB(bj28;6c7S11_%N8DJKRP1(X1S0Y(5p@zS8M!SI|?MhL~2AcP_0gfNULLPXdY zGlZxx5Mp8#R5_!J5=t<^2qTCf<&-djDMkcA3<)QgVMGxm5Oa)}@PLRT*c;E-05n8t zUqDRAM@*s52Ux*HgDmg|i^n--j8G~95yrxUFor2bga{imCf*kYVoa=%4`R=U}-B(b~b$3#9L7>PZc%WA~mq zrG8q!B!0d34^hcQhiYo=l=$u!6%`FPlgjIhXMUbxFniPTTP>NBXGBIEzWDmvuvhTK zHCVFx$ZB}QJv?PsY23_6a@ao0>QbR@U16Z(M5C6h_^dXaC%Y0tWvk9rjCirh$@1(C z!#|^{jONsNm`~Cw7}r%dG4}NL;myxsRAIw4uk1E`nQ!E@-20wY*C(y-Hai&_s@SHO zqBuv}GjqTEL#3zI9%U8nk+FC}Ih(zE^=Qj{ch#0Rxf|@p+s=Q`-EClCymd}Z+|3~l zQhD0%{%^gT_q@(4ef%cX#A=CacFWF}ZrNIF97r#7SmtE$azTZ4&(jMf6HUtRxp#C- zw)t^_%e>nctc}ai*noc{vNos4P|VLxGTpLNhiQ(1s9;5o>iq3G`|=I3PA`>Vers&^ zC%#pmiO+pBt6{@2-z^EnmG7e^Mz4O^KYrMq&Ucwx_mqTVWKs@@QPSe$t(zep{}$Z_UGt zb+kUq&j`0wEi^5j;R&j}BqfX4k!fFFOU-uMT%#J};+vY5Z!)P%1 z`0SErRJ1gXO=PG2tzSG)7OR(4?w5vz{PU}QM8`Y_<(R8h_06^x4=bOWNu|rr?sH6g zd=-}lGzK@TR#`QiRS$~^$@6mW2+dJ7y~_Klpt&nEX`}L%r{94c59RUccP;YrngaB% zth+?`owd&_ZFYwF$)oG((!$@Rwq$c5a-`Qi=XuQ$@$+2t!AmGtMKb aBt1j#opOyiP$LP_{14>j?OOC*Q1t)p`Uo@t literal 0 HcmV?d00001 diff --git a/data/sand.png b/data/sand.png new file mode 100644 index 0000000000000000000000000000000000000000..89149add2f20f0afb7e8451ed899329ce10aaaef GIT binary patch literal 659 zcmV;E0&M+>P)CFbuU;rPS^1Z7HSJx~?ndd>95IrBq7g zoKs4i^TXkwweI_V-}jV~F$N(NW9+&v=iFK&DJ4qjG)+n==UlCI+cp5$_Z?$wj8RHy ztxu;D0BEh*vMiKRt#z%{Ifp5+)^g6JlwH@=S^z_|4-}gcYgwX5j>o5$)m|Cm%{(L?==Q!uy`kd)H8t}#X_<=x#~t<_pfDMbjCQlyln6pZox{rxmelu|O! z^Ei(4JckhWeV=cpumi;;LP#MpLc%uQ7xW z004l);lLO}2$9xWYi-~6Yx>8>hcPClq?DTH8Drda-Q{xOoMVhb2xMK?zVEO5bUHcb t#&P`q{sw?6<9Iv@A*{8ZpP%RR`5&a+fO=QPCT#!!002ovPDHLkV1jztGMfMZ literal 0 HcmV?d00001 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 @@ 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 data(datasize); diff --git a/src/client.h b/src/client.h index 9110d33f8..00fd3a5ed 100644 --- a/src/client.h +++ b/src/client.h @@ -197,6 +197,40 @@ public: //void updateSomeExpiredMeshes(); + void setTempMod(v3s16 p, NodeMod mod) + { + JMutexAutoLock envlock(m_env_mutex); + assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); + + core::map affected_blocks; + ((ClientMap&)m_env.getMap()).setTempMod(p, mod, + &affected_blocks); + + for(core::map::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 affected_blocks; + ((ClientMap&)m_env.getMap()).clearTempMod(p, + &affected_blocks); + + for(core::map::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); @@ -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<getTexture(os.str()); + + /*// Make texture name for the new texture with a progress bar std::ostringstream os; os<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 + GetRequest request = m_get_texture_queue.pop(); - dstream<<"got texture request with key.name=" - < + GetResult 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) -{ - video::IVideoDriver* driver = m_device->getVideoDriver(); - - if(spec.mod == NULL) - { - dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture " - <getTexture(spec.path.c_str()); - } +/* + Texture modifier functions +*/ - dstream<<"IrrlichtWrapper::getTextureDirect: Loading and modifying " - "texture "<getTexture(spec.path.c_str()); - video::ITexture *result = spec.mod->make(base, spec.name.c_str(), driver); - - delete spec.mod; - - return result; -} - -video::ITexture * CrackTextureMod::make(video::ITexture *original, +// blitted_name = eg. "mineral_coal.png" +video::ITexture * make_blitname(const std::string &blitted_name, + video::ITexture *original, const char *newname, video::IVideoDriver* driver) { + if(original == NULL) + return NULL; + + // Size of the base image + core::dimension2d dim(16, 16); + // Position to copy the blitted to in the base image + core::position2d pos_base(0, 0); + // Position to copy the blitted from in the blitted image + core::position2d pos_other(0, 0); + + video::IImage *baseimage = driver->createImage(original, pos_base, dim); + assert(baseimage); + + 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(pos_other, dim), + video::SColor(255,255,255,255), + NULL); + + blittedimage->drop(); + + // Create texture from resulting image + + video::ITexture *newtexture = driver->addTexture(newname, baseimage); + + baseimage->drop(); + + return newtexture; +} + +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 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 " - <getSize().Width<<"x" - <getSize().Height<createImage( - other, core::position2d(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 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 pos_base(0, 0); core::dimension2d 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 \""<= 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 \""<= spec.size()) + break; + } + + /*if(spec.mod == NULL) + { + dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture " + <getTexture(spec.path.c_str()); + } + + dstream<<"IrrlichtWrapper::getTextureDirect: Loading and modifying " + "texture "<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 m_get_texture_queue; + RequestQueue 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 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"<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); + } + } + } + + /* + 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; igetNode(cp+g_27dirs[i]).d == CONTENT_STONE) + if(myrand()%8 == 0) + block->setNode(cp+g_27dirs[i], n); } } } @@ -3012,26 +3041,23 @@ continue_generating: <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 "< *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 *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; } } - 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; } 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. */ diff --git a/src/map.h b/src/map.h index 787e1240f..9140d4bf2 100644 --- a/src/map.h +++ b/src/map.h @@ -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 *affected_blocks=NULL); + bool clearTempMod(v3s16 p, + core::map *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"<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; - 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); - } + 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 +#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 +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; + } + } + + return spec; +} + +u8 MapNode::getMineral() +{ + 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}; -const char * g_content_inventory_texture_paths_base[USEFUL_CONTENT_COUNT] = -{ - "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", -}; - void init_content_inventory_texture_paths() { for(u16 i=0; i 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) +/*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) -{ - 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 &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 &dirs) -{ - u8 b = 0; - for(core::list::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< + +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 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) <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 +//#include "main.h" +//#include -/* - 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; igetTexture(TextureSpec(path + mod_postfix, - path, mod)); - } - g_tile_texture_paths[i] = path + mod_postfix; - } - } - - for(s32 i=0; igetTexture(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" - -// 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 -{ - bool operator==(TileCrackParam &other) - { - return progression == other.progression; - } - - u16 progression; -}; +//#include "utility.h" +#include struct TileSpec { - TileSpec() + TileSpec(): + alpha(255) + { + } + + TileSpec(const std::string &a_name): + name(a_name), + alpha(255) + { + } + + TileSpec(const char *a_name): + name(a_name), + alpha(255) { - id = TILE_NONE; - feature = TILEFEAT_NONE; } bool operator==(TileSpec &other) { - 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; + return (name == other.name && alpha == other.alpha); } - - u16 id; // Id in g_tile_materials, TILE_NONE=none - enum TileSpecialFeature feature; - union - { - TileCrackParam crack; - } param; + + // 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 &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=(" - < 255) - pr = 255; - - /*dstream<<"WARNING: Pressure at (" - < &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="<= 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:"<= stoptime || overflow) - { - dstream<<"flowWater: stoptime reached"<=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 &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"<::Node - *n = active_nodes.getIterator().getNode(); -#endif - -#if 1 - - core::map::Iterator - i = active_nodes.getIterator().getNode(); - for(s32 j=0; j::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"< & 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 &active_nodes, - int recur_count); - - /* - VOXELFLAG_CHECKED3s must usually be cleared before calling. - */ - void updateAreaWaterPressure(VoxelArea a, - core::map &active_nodes, - bool checked3_is_clear=false); - - /* - Returns true if moved something - */ - bool flowWater(v3s16 removed_pos, - core::map &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 &active_nodes, - int recursion_depth=0, - bool debugprint=false, - u32 timelimit=50 - ); -#endif - /* Virtual functions */