diff options
-rw-r--r-- | data/crack.png | bin | 0 -> 1039 bytes | |||
-rw-r--r-- | src/client.cpp | 88 | ||||
-rw-r--r-- | src/client.h | 25 | ||||
-rw-r--r-- | src/constants.h | 6 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 2 | ||||
-rw-r--r-- | src/irrlichtwrapper.cpp | 71 | ||||
-rw-r--r-- | src/irrlichtwrapper.h | 12 | ||||
-rw-r--r-- | src/main.cpp | 161 | ||||
-rw-r--r-- | src/map.cpp | 30 | ||||
-rw-r--r-- | src/map.h | 12 | ||||
-rw-r--r-- | src/mapblock.cpp | 50 | ||||
-rw-r--r-- | src/mapblock.h | 10 | ||||
-rw-r--r-- | src/server.cpp | 12 | ||||
-rw-r--r-- | src/tile.cpp | 7 | ||||
-rw-r--r-- | src/tile.h | 2 | ||||
-rw-r--r-- | src/utility.h | 33 |
16 files changed, 232 insertions, 289 deletions
diff --git a/data/crack.png b/data/crack.png Binary files differnew file mode 100644 index 000000000..e39b74da0 --- /dev/null +++ b/data/crack.png diff --git a/src/client.cpp b/src/client.cpp index b612c9c44..4979829d1 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -398,45 +398,10 @@ void Client::step(float dtime) } } -#if 0 - /* - Clear old entries from fetchblock history - */ - { - JMutexAutoLock lock(m_fetchblock_mutex); - - core::list<v3s16> remove_queue; - core::map<v3s16, float>::Iterator i; - i = m_fetchblock_history.getIterator(); - for(; i.atEnd() == false; i++) - { - float value = i.getNode()->getValue(); - value += dtime; - i.getNode()->setValue(value); - if(value >= 60.0) - remove_queue.push_back(i.getNode()->getKey()); - } - core::list<v3s16>::Iterator j; - j = remove_queue.begin(); - for(; j != remove_queue.end(); j++) - { - m_fetchblock_history.remove(*j); - } - } -#endif - /*{ JMutexAutoLock lock(m_step_dtime_mutex); m_step_dtime += dtime; }*/ - - /* - BEGIN TEST CODE - */ - - /* - END OF TEST CODE - */ } float Client::asyncStep() @@ -975,7 +940,11 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) if(abs_to_delete.find(p) != NULL) abs_to_delete.remove(p); - // Update objects of block + /* + Update objects of block + + NOTE: Be sure this is done in the main thread. + */ block->updateObjects(is, m_server_ser_ver, m_device->getSceneManager()); } @@ -1482,11 +1451,11 @@ void Client::addNodeFromInventory(v3s16 nodepos, u16 i) } #endif -void Client::pressGround(u8 button, v3s16 nodepos_undersurface, +void Client::groundAction(u8 action, v3s16 nodepos_undersurface, v3s16 nodepos_oversurface, u16 item) { if(connectedAndInitialized() == false){ - dout_client<<DTIME<<"Client::pressGround() " + dout_client<<DTIME<<"Client::groundAction() " "cancelled (not connected)" <<std::endl; return; @@ -1507,7 +1476,7 @@ void Client::pressGround(u8 button, v3s16 nodepos_undersurface, u8 datasize = 2 + 1 + 6 + 6 + 2; SharedBuffer<u8> data(datasize); writeU16(&data[0], TOSERVER_GROUND_ACTION); - writeU8(&data[2], button); + writeU8(&data[2], action); writeV3S16(&data[3], nodepos_undersurface); writeV3S16(&data[9], nodepos_oversurface); writeU16(&data[15], item); @@ -1540,37 +1509,6 @@ void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item) Send(0, data, true); } -void Client::stopDigging() -{ - if(connectedAndInitialized() == false){ - dout_client<<DTIME<<"Client::release() " - "cancelled (not connected)" - <<std::endl; - return; - } - - /* - length: 17 - [0] u16 command - [2] u8 action - [3] v3s16 nodepos_undersurface - [9] v3s16 nodepos_abovesurface - [15] u16 item - actions: - 0: start digging - 1: place block - 2: stop digging (all parameters ignored) - */ - u8 datasize = 2 + 1 + 6 + 6 + 2; - SharedBuffer<u8> data(datasize); - writeU16(&data[0], TOSERVER_GROUND_ACTION); - writeU8(&data[2], 2); - writeV3S16(&data[3], v3s16(0,0,0)); - writeV3S16(&data[9], v3s16(0,0,0)); - writeU16(&data[15], 0); - Send(0, data, true); -} - void Client::sendSignText(v3s16 blockpos, s16 id, std::string text) { /* @@ -1671,17 +1609,23 @@ MapNode Client::getNode(v3s16 p) return m_env.getMap().getNode(p); } +/*void Client::getNode(v3s16 p, MapNode n) +{ + JMutexAutoLock envlock(m_env_mutex); + m_env.getMap().setNode(p, n); +}*/ + /*f32 Client::getGroundHeight(v2s16 p) { JMutexAutoLock envlock(m_env_mutex); return m_env.getMap().getGroundHeight(p); }*/ -bool Client::isNodeUnderground(v3s16 p) +/*bool Client::isNodeUnderground(v3s16 p) { JMutexAutoLock envlock(m_env_mutex); return m_env.getMap().isNodeUnderground(p); -} +}*/ /*Player * Client::getLocalPlayer() { diff --git a/src/client.h b/src/client.h index a1ee3f762..a3d43997c 100644 --- a/src/client.h +++ b/src/client.h @@ -185,12 +185,9 @@ public: // Pops out a packet from the packet queue IncomingPacket getPacket(); - /*void removeNode(v3s16 nodepos); - void addNodeFromInventory(v3s16 nodepos, u16 i);*/ - void pressGround(u8 button, v3s16 nodepos_undersurface, + void groundAction(u8 action, v3s16 nodepos_undersurface, v3s16 nodepos_oversurface, u16 item); void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item); - void stopDigging(); void sendSignText(v3s16 blockpos, s16 id, std::string text); @@ -199,9 +196,12 @@ public: // Returns InvalidPositionException if not found MapNode getNode(v3s16 p); // Returns InvalidPositionException if not found + //void setNode(v3s16 p, MapNode n); + + // Returns InvalidPositionException if not found //f32 getGroundHeight(v2s16 p); // Returns InvalidPositionException if not found - bool isNodeUnderground(v3s16 p); + //bool isNodeUnderground(v3s16 p); // Note: The players should not be exposed outside // Return value is valid until client is destroyed @@ -236,6 +236,21 @@ public: //void updateSomeExpiredMeshes(); + void setTempMod(v3s16 p, NodeMod mod) + { + JMutexAutoLock envlock(m_env_mutex); + assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); + v3s16 blockpos = ((ClientMap&)m_env.getMap()).setTempMod(p, mod); + m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio()); + } + void clearTempMod(v3s16 p) + { + JMutexAutoLock envlock(m_env_mutex); + assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); + v3s16 blockpos = ((ClientMap&)m_env.getMap()).clearTempMod(p); + m_env.getMap().updateMeshes(blockpos, m_env.getDayNightRatio()); + } + private: // Virtual methods from con::PeerHandler diff --git a/src/constants.h b/src/constants.h index c3fca432f..7668c7451 100644 --- a/src/constants.h +++ b/src/constants.h @@ -39,12 +39,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PI 3.14159 -//#define SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT (60*10) -#define SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT (60) -#define SERVER_MAP_SAVE_INTERVAL (60) -/*#define SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT (10) -#define SERVER_MAP_SAVE_INTERVAL (10)*/ - // This is the same as in minecraft and everything else #define FOV_ANGLE (PI/2.5) diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 04cdf16bc..6888fa497 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -56,5 +56,7 @@ void set_default_settings() g_settings.setDefault("max_block_generate_distance", "4"); g_settings.setDefault("time_send_interval", "20"); g_settings.setDefault("time_speed", "360"); + g_settings.setDefault("server_unload_unused_sectors_timeout", "60"); + g_settings.setDefault("server_map_save_interval", "60"); } diff --git a/src/irrlichtwrapper.cpp b/src/irrlichtwrapper.cpp index 69b08a6d8..51511eb34 100644 --- a/src/irrlichtwrapper.cpp +++ b/src/irrlichtwrapper.cpp @@ -17,7 +17,8 @@ void IrrlichtWrapper::Run() GetRequest<TextureSpec, video::ITexture*, u8, u8> request = m_get_texture_queue.pop(); - dstream<<"got request with key.name="<<request.key.name<<std::endl; + dstream<<"got texture request with key.name=" + <<request.key.name<<std::endl; GetResult<TextureSpec, video::ITexture*, u8, u8> result; @@ -37,7 +38,9 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec) if(get_current_thread_id() == m_main_thread) { - dstream<<"Loading texture directly: "<<spec.name<<std::endl; + dstream<<"Getting texture directly: name=" + <<spec.name<<std::endl; + t = getTextureDirect(spec); } else @@ -52,7 +55,7 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec) // Wait result GetResult<TextureSpec, video::ITexture*, u8, u8> - result = result_queue.pop_front(true); + result = result_queue.pop_front(1000); // Check that at least something worked OK assert(result.key.name == spec.name); @@ -67,10 +70,6 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec) video::ITexture* IrrlichtWrapper::getTexture(const std::string &path) { - /*TextureSpec spec; - spec.name = path; - spec.path = path; - return getTexture(spec);*/ return getTexture(TextureSpec(path, path, NULL)); } @@ -81,21 +80,61 @@ video::ITexture* IrrlichtWrapper::getTexture(const std::string &path) video::ITexture* IrrlichtWrapper::getTextureDirect(TextureSpec spec) { video::IVideoDriver* driver = m_device->getVideoDriver(); - //TODO - if(spec.mod != NULL) + + if(spec.mod == NULL) { - dstream<<"IrrlichtWrapper::getTextureDirect: Modified textures" - " not supported"<<std::endl; + dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture " + <<spec.path<<std::endl; + return driver->getTexture(spec.path.c_str()); } - 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; + + return result; } video::ITexture * CrackTextureMod::make(video::ITexture *original, - video::IVideoDriver* driver) + const char *newname, video::IVideoDriver* driver) { - //TODO - dstream<<__FUNCTION_NAME<<std::endl; - return NULL; + core::dimension2d<u32> dim(16, 16); + core::position2d<s32> pos_base(0, 0); + core::position2d<s32> pos_other(0, 16 * progression); + + video::IImage *baseimage = driver->createImage(original, pos_base, dim); + assert(baseimage); + + video::ITexture *other = driver->getTexture("../data/crack.png"); + // We have to get the whole texture because getting a smaller area + // messes the whole thing. It is probably a bug in Irrlicht. + video::IImage *otherimage = driver->createImage( + other, core::position2d<s32>(0,0), other->getSize()); + + assert(otherimage); + + /*core::rect<s32> clip_rect(v2s32(0,0), dim); + otherimage->copyToWithAlpha(baseimage, v2s32(0,0), + core::rect<s32>(pos_other, dim), + video::SColor(255,255,255,255), + &clip_rect);*/ + + otherimage->copyToWithAlpha(baseimage, v2s32(0,0), + core::rect<s32>(pos_other, dim), + video::SColor(255,255,255,255), + NULL); + + otherimage->drop(); + + video::ITexture *newtexture = driver->addTexture(newname, baseimage); + + baseimage->drop(); + + return newtexture; } #if 0 diff --git a/src/irrlichtwrapper.h b/src/irrlichtwrapper.h index a78edfe78..981e3377f 100644 --- a/src/irrlichtwrapper.h +++ b/src/irrlichtwrapper.h @@ -48,6 +48,9 @@ public: void set(std::string name, video::ITexture *texture) { + if(texture == NULL) + return; + JMutexAutoLock lock(m_mutex); m_textures[name] = texture; @@ -78,7 +81,7 @@ struct TextureMod Shall not modify or delete the original texture. */ virtual video::ITexture * make(video::ITexture *original, - video::IVideoDriver* driver) = 0; + const char *newname, video::IVideoDriver* driver) = 0; }; struct CrackTextureMod: public TextureMod @@ -89,7 +92,7 @@ struct CrackTextureMod: public TextureMod } virtual video::ITexture * make(video::ITexture *original, - video::IVideoDriver* driver); + const char *newname, video::IVideoDriver* driver); u16 progression; }; @@ -149,10 +152,11 @@ public: These are called from other threads */ - // Not exactly thread-safe but this needs to be fast + // Not exactly thread-safe but this needs to be fast. + // getTimer()->getRealTime() only reads one variable anyway. u32 getTime() { - return m_device->getTimer()->getTime(); + return m_device->getTimer()->getRealTime(); } video::ITexture* getTexture(TextureSpec spec); diff --git a/src/main.cpp b/src/main.cpp index 56e725722..6b5455965 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -179,12 +179,6 @@ TODO: TOSERVER_LEAVE Doing now:
======================================================================
-TODO: Node cracking animation when digging
- - TODO: A way to generate new textures by combining textures
- - TODO: Mesh update to fetch cracked faces from the former
-
-TODO: A thread-safe wrapper for irrlicht for threads, to get rid of
- g_device
======================================================================
@@ -1164,7 +1158,7 @@ int main(int argc, char *argv[]) <<std::endl;
std::cout<<std::endl;
- char templine[100];
+ //char templine[100];
// Port?
u16 port = 30000;
@@ -1271,70 +1265,6 @@ int main(int argc, char *argv[]) u16 screenW = atoi(g_settings.get("screenW").c_str());
u16 screenH = atoi(g_settings.get("screenH").c_str());
-#if 0
- u16 screenW;
- u16 screenH;
- bool fullscreen = false;
-
- if(g_settings.get("screenW") != "" && g_settings.get("screenH") != "")
- {
- screenW = atoi(g_settings.get("screenW").c_str());
- screenH = atoi(g_settings.get("screenH").c_str());
- }
- else
- {
- u16 resolutions[][3] = {
- //W, H, fullscreen
- {640,480, 0},
- {800,600, 0},
- {1024,768, 0},
- {1280,1024, 0},
- /*{640,480, 1},
- {800,600, 1},
- {1024,768, 1},
- {1280,1024, 1},*/
- };
-
- u16 res_count = sizeof(resolutions)/sizeof(resolutions[0]);
-
- for(u16 i=0; i<res_count; i++)
- {
- std::cout<<(i+1)<<": "<<resolutions[i][0]<<"x"
- <<resolutions[i][1];
- if(resolutions[i][2])
- std::cout<<" fullscreen"<<std::endl;
- else
- std::cout<<" windowed"<<std::endl;
- }
- std::cout<<"Select a window resolution number [empty = 2]: ";
- std::cin.getline(templine, 100);
-
- u16 r0;
- if(templine[0] == 0)
- r0 = 2;
- else
- r0 = atoi(templine);
-
- if(r0 > res_count || r0 == 0)
- r0 = 2;
-
- {
- u16 i = r0-1;
- std::cout<<"-> ";
- std::cout<<(i+1)<<": "<<resolutions[i][0]<<"x"
- <<resolutions[i][1];
- if(resolutions[i][2])
- std::cout<<" fullscreen"<<std::endl;
- else
- std::cout<<" windowed"<<std::endl;
- }
-
- screenW = resolutions[r0-1][0];
- screenH = resolutions[r0-1][1];
- fullscreen = resolutions[r0-1][2];
- }
-#endif
-
//
MyEventReceiver receiver;
@@ -1354,10 +1284,6 @@ int main(int argc, char *argv[]) device = createDevice(driverType,
core::dimension2d<u32>(screenW, screenH),
16, fullscreen, false, false, &receiver);
- // With vsync
- /*device = createDevice(driverType,
- core::dimension2d<u32>(screenW, screenH),
- 16, fullscreen, false, true, &receiver);*/
if (device == 0)
return 1; // could not create selected driver.
@@ -1380,10 +1306,10 @@ int main(int argc, char *argv[]) */
video::IVideoDriver* driver = device->getVideoDriver();
- // These make the textures not to show at all
- //driver->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT);
- //driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_SPEED );
+ /*
+ This changes the minimum allowed number of vertices in a VBO
+ */
//driver->setMinHardwareBufferVertexCount(1);
scene::ISceneManager* smgr = device->getSceneManager();
@@ -2147,48 +2073,69 @@ int main(int argc, char *argv[]) } // regular block
} // for coords
- /*static v3s16 oldnodepos;
- static bool oldnodefound = false;*/
-
if(nodefound)
{
- //std::cout<<DTIME<<"nodefound == true"<<std::endl;
- //std::cout<<DTIME<<"nodepos=("<<nodepos.X<<","<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
- //std::cout<<DTIME<<"neighbourpos=("<<neighbourpos.X<<","<<neighbourpos.Y<<","<<neighbourpos.Z<<")"<<std::endl;
+ static v3s16 nodepos_old(-32768,-32768,-32768);
+
+ static float dig_time = 0.0;
- static v3s16 nodepos_old(-1,-1,-1);
- if(nodepos != nodepos_old){
+ if(nodepos != nodepos_old)
+ {
std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","
<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
+
+ if(nodepos_old != v3s16(-32768,-32768,-32768))
+ {
+ client.clearTempMod(nodepos_old);
+ dig_time = 0.0;
+ }
}
hilightboxes.push_back(nodefacebox);
- //if(g_input->getLeftClicked())
+ if(g_input->getLeftReleased())
+ {
+ client.clearTempMod(nodepos);
+ dig_time = 0.0;
+ }
if(g_input->getLeftClicked() ||
(g_input->getLeftState() && nodepos != nodepos_old))
{
std::cout<<DTIME<<"Ground left-clicked"<<std::endl;
- client.pressGround(0, nodepos, neighbourpos, g_selected_item);
+ client.groundAction(0, nodepos, neighbourpos, g_selected_item);
+ }
+ if(g_input->getLeftClicked())
+ {
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));
}
+ if(g_input->getLeftState())
+ {
+ dig_time += dtime;
+
+ float dig_time_complete = 0.5;
+ MapNode n = client.getNode(nodepos);
+ if(n.d == CONTENT_STONE)
+ dig_time_complete = 1.5;
+
+ u16 dig_index = (u16)(3.99*dig_time/dig_time_complete);
+ if(dig_time > 0.2)
+ {
+ //dstream<<"dig_index="<<dig_index<<std::endl;
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));
+ }
+ }
+
if(g_input->getRightClicked())
- /*if(g_input->getRightClicked() ||
- (g_input->getRightState() && nodepos != nodepos_old))*/
{
std::cout<<DTIME<<"Ground right-clicked"<<std::endl;
- client.pressGround(1, nodepos, neighbourpos, g_selected_item);
+ client.groundAction(1, nodepos, neighbourpos, g_selected_item);
}
nodepos_old = nodepos;
}
else{
- //std::cout<<DTIME<<"nodefound == false"<<std::endl;
- //positiontextgui->setText(L"");
}
- /*oldnodefound = nodefound;
- oldnodepos = nodepos;*/
-
} // selected_object == NULL
g_input->resetLeftClicked();
@@ -2197,7 +2144,7 @@ int main(int argc, char *argv[]) if(g_input->getLeftReleased())
{
std::cout<<DTIME<<"Left released"<<std::endl;
- client.stopDigging();
+ client.groundAction(2, v3s16(0,0,0), v3s16(0,0,0), 0);
}
if(g_input->getRightReleased())
{
@@ -2214,26 +2161,6 @@ int main(int argc, char *argv[]) camera->setAspectRatio((f32)screensize.X / (f32)screensize.Y);
- // Background color is choosen based on whether the player is
- // much beyond the initial ground level
- /*video::SColor bgcolor;
- v3s16 p0 = Map::floatToInt(player_position);
- // Does this make short random delays?
- // NOTE: no need for this, sky doesn't show underground with
- // enough range
- bool is_underground = client.isNodeUnderground(p0);
- //bool is_underground = false;
- if(is_underground == false)
- bgcolor = video::SColor(255,90,140,200);
- else
- bgcolor = video::SColor(255,0,0,0);*/
-
- //video::SColor bgcolor = video::SColor(255,90,140,200);
- //video::SColor bgcolor = skycolor;
-
- //s32 daynight_i = client.getDayNightIndex();
- //video::SColor bgcolor = skycolor[daynight_i];
-
u32 daynight_ratio = client.getDayNightRatio();
video::SColor bgcolor = video::SColor(
255,
diff --git a/src/map.cpp b/src/map.cpp index 13db92651..2a517c544 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1622,6 +1622,7 @@ MapBlock * ServerMap::emergeBlock( } //dstream<<"Not found on disk, generating."<<std::endl; + //TimeTaker("emergeBlock()", g_irrlicht); /* Do not generate over-limit @@ -1668,7 +1669,7 @@ MapBlock * ServerMap::emergeBlock( underground_emptiness[i] = ((rand() % 5) == 0); } -#if 0 +#if 1 /* This is a messy hack to sort the emptiness a bit */ @@ -2235,20 +2236,15 @@ void ServerMap::save(bool only_changed) }//sectorlock - u32 deleted_count = 0; - deleted_count = deleteUnusedSectors( - SERVERMAP_DELETE_UNUSED_SECTORS_TIMEOUT); - /* Only print if something happened or saved whole map */ if(only_changed == false || sector_meta_count != 0 - || block_count != 0 || deleted_count != 0) + || block_count != 0) { dstream<<DTIME<<"ServerMap: Written: " <<sector_meta_count<<" sector metadata files, " - <<block_count<<" block files, " - <<deleted_count<<" sectors unloaded from memory." + <<block_count<<" block files" <<std::endl; } } @@ -2987,9 +2983,23 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) <<", rendered "<<vertex_count<<" vertices."<<std::endl;*/ } -void ClientMap::updateMesh() +v3s16 ClientMap::setTempMod(v3s16 p, NodeMod mod) { - //TODO: Remove this + v3s16 blockpos = getNodeBlockPos(p); + MapBlock * blockref = getBlockNoCreate(blockpos); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + + blockref->setTempMod(relpos, mod); + return blockpos; +} +v3s16 ClientMap::clearTempMod(v3s16 p) +{ + v3s16 blockpos = getNodeBlockPos(p); + MapBlock * blockref = getBlockNoCreate(blockpos); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + + blockref->clearTempMod(relpos); + return blockpos; } void ClientMap::PrintInfo(std::ostream &out) @@ -35,7 +35,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.h" #include "heightmap.h" -#include "loadstatus.h" #include "mapnode.h" #include "mapblock.h" #include "mapsector.h" @@ -593,8 +592,15 @@ public: void renderMap(video::IVideoDriver* driver, s32 pass); - // Update master heightmap mesh - void updateMesh(); + /* + Methods for setting temporary modifications to nodes for + drawing. + Return value is position of changed block. + */ + v3s16 setTempMod(v3s16 p, NodeMod mod); + v3s16 clearTempMod(v3s16 p); + // Efficient implementation needs a cache of TempMods + //void clearTempMods(); // For debug printing virtual void PrintInfo(std::ostream &out); diff --git a/src/mapblock.cpp b/src/mapblock.cpp index af08cadaa..e2262544c 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -300,6 +300,8 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir) } if(mod.type == NODEMOD_CRACK) { + spec.feature = TILEFEAT_CRACK; + spec.param.crack.progression = mod.param; } } @@ -646,14 +648,31 @@ void MapBlock::updateMesh(u32 daynight_ratio) if(f.tile.feature == TILEFEAT_NONE) { - /*collector.append(g_tile_materials[f.tile.id], f.vertices, 4, - indices, 6);*/ 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 { - // Not implemented + // No such feature assert(0); } } @@ -669,33 +688,12 @@ void MapBlock::updateMesh(u32 daynight_ratio) } /* - Clear temporary FastFaces - */ - - /*core::list<FastFace*>::Iterator i; - i = fastfaces_new->begin(); - for(; i != fastfaces_new->end(); i++) - { - delete *i; - } - fastfaces_new->clear(); - delete fastfaces_new;*/ - - /* Add special graphics: - torches TODO: Optimize by using same meshbuffer for same textures */ - /*scene::ISceneManager *smgr = NULL; - video::IVideoDriver* driver = NULL; - if(g_device) - { - smgr = g_device->getSceneManager(); - driver = smgr->getVideoDriver(); - }*/ - for(s16 z=0; z<MAP_BLOCKSIZE; z++) for(s16 y=0; y<MAP_BLOCKSIZE; y++) for(s16 x=0; x<MAP_BLOCKSIZE; x++) @@ -751,20 +749,16 @@ void MapBlock::updateMesh(u32 daynight_ratio) if(dir == v3s16(0,-1,0)) buf->getMaterial().setTexture(0, g_irrlicht->getTexture("../data/torch_on_floor.png")); - //g_texturecache.get("torch_on_floor")); else if(dir == v3s16(0,1,0)) buf->getMaterial().setTexture(0, g_irrlicht->getTexture("../data/torch_on_ceiling.png")); - //g_texturecache.get("torch_on_ceiling")); // For backwards compatibility else if(dir == v3s16(0,0,0)) buf->getMaterial().setTexture(0, g_irrlicht->getTexture("../data/torch_on_floor.png")); - //g_texturecache.get("torch_on_floor")); else buf->getMaterial().setTexture(0, g_irrlicht->getTexture("../data/torch.png")); - //buf->getMaterial().setTexture(0, g_texturecache.get("torch")); // Add to mesh mesh_new->addMeshBuffer(buf); diff --git a/src/mapblock.h b/src/mapblock.h index 2bdf639b7..b5126b822 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -59,9 +59,10 @@ enum NodeModType struct NodeMod { - NodeMod() + NodeMod(enum NodeModType a_type=NODEMOD_NONE, u16 a_param=0) { - type = NODEMOD_NONE; + type = a_type; + param = a_param; } enum NodeModType type; u16 param; @@ -393,6 +394,11 @@ public: */ void setTempMod(v3s16 p, NodeMod mod) { + /*dstream<<"setTempMod called on block" + <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")" + <<", mod.type="<<mod.type + <<", mod.param="<<mod.param + <<std::endl;*/ m_temp_mods[p] = mod; } void clearTempMod(v3s16 p) diff --git a/src/server.cpp b/src/server.cpp index 7260e21d3..7582024d1 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1321,13 +1321,23 @@ void Server::AsyncRunStep() { float &counter = m_savemap_timer; counter += dtime; - if(counter >= SERVER_MAP_SAVE_INTERVAL) + if(counter >= g_settings.getFloat("server_map_save_interval")) { counter = 0.0; JMutexAutoLock lock(m_env_mutex); + // Save only changed parts m_env.getMap().save(true); + + // Delete unused sectors + u32 deleted_count = m_env.getMap().deleteUnusedSectors( + g_settings.getFloat("server_unload_unused_sectors_timeout")); + if(deleted_count > 0) + { + dout_server<<"Server: Unloaded "<<deleted_count + <<" sectors from memory"<<std::endl; + } } } } diff --git a/src/tile.cpp b/src/tile.cpp index 174c72fdf..23b1638d1 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -37,6 +37,13 @@ const char * g_tile_texture_paths[TILES_COUNT] = "../data/cloud.png", }; +const char * tile_texture_path_get(u32 i) +{ + assert(i < TILES_COUNT); + + return g_tile_texture_paths[i]; +} + // A mapping from tiles to materials // Initialized at run-time. video::SMaterial g_tile_materials[TILES_COUNT]; diff --git a/src/tile.h b/src/tile.h index d97567661..68e87a77d 100644 --- a/src/tile.h +++ b/src/tile.h @@ -100,6 +100,8 @@ extern video::SMaterial g_tile_materials[TILES_COUNT];*/ Functions */ +const char * tile_texture_path_get(u32 i); + // Initializes g_tile_materials void tile_materials_preload(IrrlichtWrapper *irrlicht); diff --git a/src/utility.h b/src/utility.h index cde555760..bfee15e61 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1085,7 +1085,6 @@ public: MutexedQueue() { m_mutex.Init(); - m_is_empty_mutex.Init(); } u32 size() { @@ -1095,12 +1094,11 @@ public: { JMutexAutoLock lock(m_mutex); m_list.push_back(t); - - if(m_list.size() == 1) - m_is_empty_mutex.Unlock(); } - T pop_front(bool wait_if_empty=false) + T pop_front(u32 wait_time_max_ms=0) { + u32 wait_time_ms = 0; + for(;;) { { @@ -1108,24 +1106,19 @@ public: if(m_list.size() > 0) { - if(m_list.size() == 1) - m_is_empty_mutex.Lock(); - typename core::list<T>::Iterator begin = m_list.begin(); T t = *begin; m_list.erase(begin); return t; } - if(wait_if_empty == false) - throw ItemNotFoundException("MutexedQueue: item not found"); + if(wait_time_ms >= wait_time_max_ms) + throw ItemNotFoundException("MutexedQueue: queue is empty"); } - - // To wait for an empty list, we're gonna hang on this mutex - m_is_empty_mutex.Lock(); - m_is_empty_mutex.Unlock(); - // Then loop to the beginning and hopefully return something + // Wait a while before trying again + sleep_ms(10); + wait_time_ms += 10; } } @@ -1134,11 +1127,6 @@ public: return m_mutex; } - JMutex & getIsEmptyMutex() - { - return m_is_empty_mutex; - } - core::list<T> & getList() { return m_list; @@ -1146,8 +1134,6 @@ public: protected: JMutex m_mutex; - // This is locked always when the list is empty - JMutex m_is_empty_mutex; core::list<T> m_list; }; @@ -1262,9 +1248,6 @@ public: request.dest = dest; m_queue.getList().push_back(request); - - if(m_queue.getList().size() == 1) - m_queue.getIsEmptyMutex().Unlock(); } GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false) |