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/
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/
<Tool\r
Name="VCLinkerTool"\r
AdditionalLibraryDirectories=""C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib";"..\irrlicht\irrlicht-1.7.1\lib\Win32-visualstudio";..\zlib125dll\dll32"\r
- IgnoreDefaultLibraryNames="libcmtd.lib"\r
+ IgnoreDefaultLibraryNames="libcmtd.dll"\r
GenerateDebugInformation="false"\r
LinkTimeCodeGeneration="1"\r
/>\r
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);
//void updateSomeExpiredMeshes();
+ void setTempMod(v3s16 p, NodeMod mod)
+ {
+ 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);
if(changed)
m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio());
}
+#endif
float getAvgRtt()
{
#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;
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()
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
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();
// 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()
#include "irrlichtwrapper.h"
#include "constants.h"
+#include "string.h"
+#include "strfnd.h"
IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device)
{
*/
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;
}
}
-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;
}
}
// 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
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),
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
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();
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
+}
+
+
m_textures[name] = texture;
}
- video::ITexture* get(std::string name)
+ video::ITexture* get(const std::string &name)
{
JMutexAutoLock lock(m_mutex);
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.
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
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
#include "utility.h"
#include "voxel.h"
#include "porting.h"
+#include "mineral.h"
/*
Map
//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;
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));
+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;
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);
}
}
}
);
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);
}
}
}
<<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);
}
<<", 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
*/
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
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)
/*
- 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.
*/
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
/*
/*
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();
//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);
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
*/
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();
}
}
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);
}
}
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;
#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();
}
}
#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
/*
#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);
}
/*
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
}
// 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.
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
{
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
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;
+ }
}
};
return p2;
}
+/*
+ The same thing backwards
+*/
inline v3f intToFloat(v3s16 p)
{
v3f p2(
--- /dev/null
+/*
+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
+
#include "constants.h"
#include "voxel.h"
#include "materials.h"
+#include "mineral.h"
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
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)
{
<<std::endl;
return;
}
+ // Get mineral
+ mineral = n.getMineral();
}
catch(InvalidPositionException &e)
{
return;
}
- //TODO: Send to only other clients
-
/*
Send the removal to all other clients
*/
/*
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);
/*
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
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))
{
}
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);
*/
#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
#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
// 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 */
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);
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;
if(pr <= 9)
c = pr + '0';
}
- else if(liquid_replaces_content(m))
+ else if(m == CONTENT_AIR)
{
c = ' ';
}
}
#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
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
*/