}
}
-#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()
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());
}
}
#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;
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);
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)
{
/*
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()
{
// 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);
// 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
//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
#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)
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");
}
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;
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
// 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);
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));
}
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
void set(std::string name, video::ITexture *texture)
{
+ if(texture == NULL)
+ return;
+
JMutexAutoLock lock(m_mutex);
m_textures[name] = texture;
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
}
virtual video::ITexture * make(video::ITexture *original,
- video::IVideoDriver* driver);
+ const char *newname, video::IVideoDriver* driver);
u16 progression;
};
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);
Doing now:\r
======================================================================\r
\r
-TODO: Node cracking animation when digging\r
- - TODO: A way to generate new textures by combining textures\r
- - TODO: Mesh update to fetch cracked faces from the former\r
-\r
-TODO: A thread-safe wrapper for irrlicht for threads, to get rid of\r
- g_device\r
\r
======================================================================\r
\r
<<std::endl;\r
\r
std::cout<<std::endl;\r
- char templine[100];\r
+ //char templine[100];\r
\r
// Port?\r
u16 port = 30000;\r
u16 screenW = atoi(g_settings.get("screenW").c_str());\r
u16 screenH = atoi(g_settings.get("screenH").c_str());\r
\r
-#if 0\r
- u16 screenW;\r
- u16 screenH;\r
- bool fullscreen = false;\r
- \r
- if(g_settings.get("screenW") != "" && g_settings.get("screenH") != "")\r
- {\r
- screenW = atoi(g_settings.get("screenW").c_str());\r
- screenH = atoi(g_settings.get("screenH").c_str());\r
- }\r
- else\r
- {\r
- u16 resolutions[][3] = {\r
- //W, H, fullscreen\r
- {640,480, 0},\r
- {800,600, 0},\r
- {1024,768, 0},\r
- {1280,1024, 0},\r
- /*{640,480, 1},\r
- {800,600, 1},\r
- {1024,768, 1},\r
- {1280,1024, 1},*/\r
- };\r
-\r
- u16 res_count = sizeof(resolutions)/sizeof(resolutions[0]);\r
- \r
- for(u16 i=0; i<res_count; i++)\r
- {\r
- std::cout<<(i+1)<<": "<<resolutions[i][0]<<"x"\r
- <<resolutions[i][1];\r
- if(resolutions[i][2])\r
- std::cout<<" fullscreen"<<std::endl;\r
- else\r
- std::cout<<" windowed"<<std::endl;\r
- }\r
- std::cout<<"Select a window resolution number [empty = 2]: ";\r
- std::cin.getline(templine, 100);\r
-\r
- u16 r0;\r
- if(templine[0] == 0)\r
- r0 = 2;\r
- else\r
- r0 = atoi(templine);\r
-\r
- if(r0 > res_count || r0 == 0)\r
- r0 = 2;\r
- \r
- {\r
- u16 i = r0-1;\r
- std::cout<<"-> ";\r
- std::cout<<(i+1)<<": "<<resolutions[i][0]<<"x"\r
- <<resolutions[i][1];\r
- if(resolutions[i][2])\r
- std::cout<<" fullscreen"<<std::endl;\r
- else\r
- std::cout<<" windowed"<<std::endl;\r
- }\r
-\r
- screenW = resolutions[r0-1][0];\r
- screenH = resolutions[r0-1][1];\r
- fullscreen = resolutions[r0-1][2];\r
- }\r
-#endif\r
-\r
//\r
\r
MyEventReceiver receiver;\r
device = createDevice(driverType,\r
core::dimension2d<u32>(screenW, screenH),\r
16, fullscreen, false, false, &receiver);\r
- // With vsync\r
- /*device = createDevice(driverType,\r
- core::dimension2d<u32>(screenW, screenH),\r
- 16, fullscreen, false, true, &receiver);*/\r
\r
if (device == 0)\r
return 1; // could not create selected driver.\r
*/\r
\r
video::IVideoDriver* driver = device->getVideoDriver();\r
- // These make the textures not to show at all\r
- //driver->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT);\r
- //driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_SPEED );\r
\r
+ /*\r
+ This changes the minimum allowed number of vertices in a VBO\r
+ */\r
//driver->setMinHardwareBufferVertexCount(1);\r
\r
scene::ISceneManager* smgr = device->getSceneManager();\r
} // regular block\r
} // for coords\r
\r
- /*static v3s16 oldnodepos;\r
- static bool oldnodefound = false;*/\r
-\r
if(nodefound)\r
{\r
- //std::cout<<DTIME<<"nodefound == true"<<std::endl;\r
- //std::cout<<DTIME<<"nodepos=("<<nodepos.X<<","<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;\r
- //std::cout<<DTIME<<"neighbourpos=("<<neighbourpos.X<<","<<neighbourpos.Y<<","<<neighbourpos.Z<<")"<<std::endl;\r
+ static v3s16 nodepos_old(-32768,-32768,-32768);\r
+\r
+ static float dig_time = 0.0;\r
\r
- static v3s16 nodepos_old(-1,-1,-1);\r
- if(nodepos != nodepos_old){\r
+ if(nodepos != nodepos_old)\r
+ {\r
std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","\r
<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;\r
+\r
+ if(nodepos_old != v3s16(-32768,-32768,-32768))\r
+ {\r
+ client.clearTempMod(nodepos_old);\r
+ dig_time = 0.0;\r
+ }\r
}\r
\r
hilightboxes.push_back(nodefacebox);\r
\r
- //if(g_input->getLeftClicked())\r
+ if(g_input->getLeftReleased())\r
+ {\r
+ client.clearTempMod(nodepos);\r
+ dig_time = 0.0;\r
+ }\r
if(g_input->getLeftClicked() ||\r
(g_input->getLeftState() && nodepos != nodepos_old))\r
{\r
std::cout<<DTIME<<"Ground left-clicked"<<std::endl;\r
- client.pressGround(0, nodepos, neighbourpos, g_selected_item);\r
+ client.groundAction(0, nodepos, neighbourpos, g_selected_item);\r
+ }\r
+ if(g_input->getLeftClicked())\r
+ {\r
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));\r
}\r
+ if(g_input->getLeftState())\r
+ {\r
+ dig_time += dtime;\r
+ \r
+ float dig_time_complete = 0.5;\r
+ MapNode n = client.getNode(nodepos);\r
+ if(n.d == CONTENT_STONE)\r
+ dig_time_complete = 1.5;\r
+\r
+ u16 dig_index = (u16)(3.99*dig_time/dig_time_complete);\r
+ if(dig_time > 0.2)\r
+ {\r
+ //dstream<<"dig_index="<<dig_index<<std::endl;\r
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));\r
+ }\r
+ }\r
+ \r
if(g_input->getRightClicked())\r
- /*if(g_input->getRightClicked() ||\r
- (g_input->getRightState() && nodepos != nodepos_old))*/\r
{\r
std::cout<<DTIME<<"Ground right-clicked"<<std::endl;\r
- client.pressGround(1, nodepos, neighbourpos, g_selected_item);\r
+ client.groundAction(1, nodepos, neighbourpos, g_selected_item);\r
}\r
\r
nodepos_old = nodepos;\r
}\r
else{\r
- //std::cout<<DTIME<<"nodefound == false"<<std::endl;\r
- //positiontextgui->setText(L"");\r
}\r
\r
- /*oldnodefound = nodefound;\r
- oldnodepos = nodepos;*/\r
-\r
} // selected_object == NULL\r
\r
g_input->resetLeftClicked();\r
if(g_input->getLeftReleased())\r
{\r
std::cout<<DTIME<<"Left released"<<std::endl;\r
- client.stopDigging();\r
+ client.groundAction(2, v3s16(0,0,0), v3s16(0,0,0), 0);\r
}\r
if(g_input->getRightReleased())\r
{\r
\r
camera->setAspectRatio((f32)screensize.X / (f32)screensize.Y);\r
\r
- // Background color is choosen based on whether the player is\r
- // much beyond the initial ground level\r
- /*video::SColor bgcolor;\r
- v3s16 p0 = Map::floatToInt(player_position);\r
- // Does this make short random delays?\r
- // NOTE: no need for this, sky doesn't show underground with\r
- // enough range\r
- bool is_underground = client.isNodeUnderground(p0);\r
- //bool is_underground = false;\r
- if(is_underground == false)\r
- bgcolor = video::SColor(255,90,140,200);\r
- else\r
- bgcolor = video::SColor(255,0,0,0);*/\r
- \r
- //video::SColor bgcolor = video::SColor(255,90,140,200);\r
- //video::SColor bgcolor = skycolor;\r
- \r
- //s32 daynight_i = client.getDayNightIndex();\r
- //video::SColor bgcolor = skycolor[daynight_i];\r
-\r
u32 daynight_ratio = client.getDayNightRatio();\r
video::SColor bgcolor = video::SColor(\r
255,\r
}
//dstream<<"Not found on disk, generating."<<std::endl;
+ //TimeTaker("emergeBlock()", g_irrlicht);
/*
Do not generate over-limit
underground_emptiness[i] = ((rand() % 5) == 0);
}
-#if 0
+#if 1
/*
This is a messy hack to sort the emptiness a bit
*/
}//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;
}
}
<<", 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)
#include "common_irrlicht.h"
#include "heightmap.h"
-#include "loadstatus.h"
#include "mapnode.h"
#include "mapblock.h"
#include "mapsector.h"
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);
}
if(mod.type == NODEMOD_CRACK)
{
+ spec.feature = TILEFEAT_CRACK;
+ spec.param.crack.progression = mod.param;
}
}
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);
}
}
<<" materials (meshbuffers)"<<std::endl;*/
}
- /*
- 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++)
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);
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;
*/
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)
{
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;
+ }
}
}
}
"../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];
Functions
*/
+const char * tile_texture_path_get(u32 i);
+
// Initializes g_tile_materials
void tile_materials_preload(IrrlichtWrapper *irrlicht);
MutexedQueue()
{
m_mutex.Init();
- m_is_empty_mutex.Init();
}
u32 size()
{
{
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(;;)
{
{
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;
}
}
return m_mutex;
}
- JMutex & getIsEmptyMutex()
- {
- return m_is_empty_mutex;
- }
-
core::list<T> & getList()
{
return m_list;
protected:
JMutex m_mutex;
- // This is locked always when the list is empty
- JMutex m_is_empty_mutex;
core::list<T> m_list;
};
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)