#include "ban.h"
#include "environment.h"
#include "map.h"
-#include "jthread/jmutexautolock.h"
+#include "threading/mutex_auto_lock.h"
#include "constants.h"
#include "voxel.h"
#include "config.h"
{}
};
-class ServerThread : public JThread
+class ServerThread : public Thread
{
- Server *m_server;
-
public:
ServerThread(Server *server):
- JThread(),
+ Thread("Server"),
m_server(server)
- {
- }
+ {}
- void * Thread();
+ void *run();
+
+private:
+ Server *m_server;
};
-void * ServerThread::Thread()
+void *ServerThread::run()
{
- log_register_thread("ServerThread");
-
DSTACK(__FUNCTION_NAME);
BEGIN_DEBUG_EXCEPTION_HANDLER
m_server->AsyncRunStep(true);
- ThreadStarted();
-
- porting::setThreadName("ServerThread");
-
- while(!StopRequested())
- {
- try{
+ while (!stopRequested()) {
+ try {
//TimeTaker timer("AsyncRunStep() + Receive()");
m_server->AsyncRunStep();
m_server->Receive();
- }
- catch(con::NoIncomingDataException &e)
- {
- }
- catch(con::PeerNotFoundException &e)
- {
+ } catch (con::NoIncomingDataException &e) {
+ } catch (con::PeerNotFoundException &e) {
infostream<<"Server: PeerNotFoundException"<<std::endl;
- }
- catch(ClientNotFoundException &e)
- {
- }
- catch(con::ConnectionBindFailed &e)
- {
- m_server->setAsyncFatalError(e.what());
- }
- catch(LuaError &e)
- {
+ } catch (ClientNotFoundException &e) {
+ } catch (con::ConnectionBindFailed &e) {
m_server->setAsyncFatalError(e.what());
+ } catch (LuaError &e) {
+ m_server->setAsyncFatalError("Lua: " + std::string(e.what()));
}
}
errorstream << std::endl;
}
- // Lock environment
- JMutexAutoLock envlock(m_env_mutex);
+ //lock environment
+ MutexAutoLock envlock(m_env_mutex);
// Load mapgen params from Settings
m_emerge->loadMapgenParams();
// Print mods
infostream << "Server: Loading mods: ";
for(std::vector<ModSpec>::iterator i = m_mods.begin();
- i != m_mods.end(); i++) {
+ i != m_mods.end(); ++i) {
const ModSpec &mod = *i;
infostream << mod.name << " ";
}
infostream << std::endl;
// Load and run "mod" scripts
for (std::vector<ModSpec>::iterator i = m_mods.begin();
- i != m_mods.end(); i++) {
+ i != m_mods.end(); ++i) {
const ModSpec &mod = *i;
if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
std::ostringstream err;
SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
{
- JMutexAutoLock envlock(m_env_mutex);
+ MutexAutoLock envlock(m_env_mutex);
// Execute script shutdown hooks
m_script->on_shutdown();
// Delete detached inventories
for (std::map<std::string, Inventory*>::iterator
i = m_detached_inventories.begin();
- i != m_detached_inventories.end(); i++) {
+ i != m_detached_inventories.end(); ++i) {
delete i->second;
}
}
<< bind_addr.serializeString() <<"..."<<std::endl;
// Stop thread if already running
- m_thread->Stop();
+ m_thread->stop();
// Initialize connection
m_con.SetTimeoutMs(30);
m_con.Serve(bind_addr);
// Start thread
- m_thread->Start();
+ m_thread->start();
// ASCII art for the win!
actionstream
infostream<<"Server: Stopping and waiting threads"<<std::endl;
// Stop threads (set run=false first so both start stopping)
- m_thread->Stop();
+ m_thread->stop();
//m_emergethread.setRun(false);
- m_thread->Wait();
+ m_thread->wait();
//m_emergethread.stop();
infostream<<"Server: Threads stopped"<<std::endl;
if(dtime > 2.0)
dtime = 2.0;
{
- JMutexAutoLock lock(m_step_dtime_mutex);
+ MutexAutoLock lock(m_step_dtime_mutex);
m_step_dtime += dtime;
}
// Throw if fatal error occurred in thread
float dtime;
{
- JMutexAutoLock lock1(m_step_dtime_mutex);
+ MutexAutoLock lock1(m_step_dtime_mutex);
dtime = m_step_dtime;
}
//infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
{
- JMutexAutoLock lock1(m_step_dtime_mutex);
+ MutexAutoLock lock1(m_step_dtime_mutex);
m_step_dtime -= dtime;
}
}
{
- JMutexAutoLock lock(m_env_mutex);
+ MutexAutoLock lock(m_env_mutex);
// Figure out and report maximum lag to environment
float max_lag = m_env->getMaxLagEstimate();
max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
static const float map_timer_and_unload_dtime = 2.92;
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
{
- JMutexAutoLock lock(m_env_mutex);
+ MutexAutoLock lock(m_env_mutex);
// Run Map's timers and unload unused data
ScopeProfiler sp(g_profiler, "Server: map timer and unload");
m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
- g_settings->getFloat("server_unload_unused_data_timeout"));
+ g_settings->getFloat("server_unload_unused_data_timeout"),
+ (u32)-1);
}
/*
{
m_liquid_transform_timer -= m_liquid_transform_every;
- JMutexAutoLock lock(m_env_mutex);
+ MutexAutoLock lock(m_env_mutex);
ScopeProfiler sp(g_profiler, "Server: liquid transform");
*/
{
//infostream<<"Server: Checking added and deleted active objects"<<std::endl;
- JMutexAutoLock envlock(m_env_mutex);
+ MutexAutoLock envlock(m_env_mutex);
- m_clients.Lock();
+ m_clients.lock();
std::map<u16, RemoteClient*> clients = m_clients.getClientList();
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
<< added_objects.size() << " added, "
<< "packet size is " << pktSize << std::endl;
}
- m_clients.Unlock();
+ m_clients.unlock();
}
/*
Send object messages
*/
{
- JMutexAutoLock envlock(m_env_mutex);
+ MutexAutoLock envlock(m_env_mutex);
ScopeProfiler sp(g_profiler, "Server: sending object messages");
// Key = object id
message_list->push_back(aom);
}
- m_clients.Lock();
+ m_clients.lock();
std::map<u16, RemoteClient*> clients = m_clients.getClientList();
// Route data to every client
for (std::map<u16, RemoteClient*>::iterator
SendActiveObjectMessages(client->peer_id, unreliable_data, false);
}
}
- m_clients.Unlock();
+ m_clients.unlock();
// Clear buffered_messages
for(std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
*/
{
// We will be accessing the environment
- JMutexAutoLock lock(m_env_mutex);
+ MutexAutoLock lock(m_env_mutex);
// Don't send too many at a time
//u32 count = 0;
if(counter >= g_settings->getFloat("server_map_save_interval"))
{
counter = 0.0;
- JMutexAutoLock lock(m_env_mutex);
+ MutexAutoLock lock(m_env_mutex);
ScopeProfiler sp(g_profiler, "Server: saving stuff");
{
std::string playername = "";
PlayerSAO *playersao = NULL;
- m_clients.Lock();
+ m_clients.lock();
try {
RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
if (client != NULL) {
playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
}
} catch (std::exception &e) {
- m_clients.Unlock();
+ m_clients.unlock();
throw;
}
- m_clients.Unlock();
+ m_clients.unlock();
RemotePlayer *player =
static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
actionstream<<player->getName() <<" joins game. List of players: ";
for (std::vector<std::string>::iterator i = names.begin();
- i != names.end(); i++) {
+ i != names.end(); ++i) {
actionstream << *i << " ";
}
{
DSTACK(__FUNCTION_NAME);
// Environment is locked first.
- JMutexAutoLock envlock(m_env_mutex);
+ MutexAutoLock envlock(m_env_mutex);
ScopeProfiler sp(g_profiler, "Server::ProcessData");
u32 peer_id = pkt->getPeerId();
void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
{
std::vector<u16> clients = m_clients.getClientIDs();
- m_clients.Lock();
+ m_clients.lock();
// Set the modified blocks unsent for all the clients
for (std::vector<u16>::iterator i = clients.begin();
i != clients.end(); ++i) {
if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
client->SetBlocksNotSent(block);
}
- m_clients.Unlock();
+ m_clients.unlock();
}
void Server::peerAdded(con::Peer *peer)
)
{
*state = m_clients.getClientState(peer_id);
- m_clients.Lock();
+ m_clients.lock();
RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
if (client == NULL) {
- m_clients.Unlock();
+ m_clients.unlock();
return false;
}
*patch = client->getPatch();
*vers_string = client->getPatch();
- m_clients.Unlock();
+ m_clients.unlock();
return true;
}
pkt << (u16) privs.size();
for(std::set<std::string>::const_iterator i = privs.begin();
- i != privs.end(); i++) {
+ i != privs.end(); ++i) {
pkt << (*i);
}
<< (u8) params.type << pos << params.object << params.loop;
for(std::vector<u16>::iterator i = dst_clients.begin();
- i != dst_clients.end(); i++) {
+ i != dst_clients.end(); ++i) {
psound.clients.insert(*i);
m_clients.send(*i, 0, &pkt, true);
}
pkt << handle;
for(std::set<u16>::iterator i = psound.clients.begin();
- i != psound.clients.end(); i++) {
+ i != psound.clients.end(); ++i) {
// Send as reliable
m_clients.send(*i, 0, &pkt, true);
}
}
NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
- m_clients.Lock();
+ m_clients.lock();
RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
if (client != 0) {
pkt << p << n.param0 << n.param1 << n.param2
}
}
}
- m_clients.Unlock();
+ m_clients.unlock();
// Send as reliable
if (pkt.getSize() > 0)
void Server::setBlockNotSent(v3s16 p)
{
std::vector<u16> clients = m_clients.getClientIDs();
- m_clients.Lock();
+ m_clients.lock();
for(std::vector<u16>::iterator i = clients.begin();
i != clients.end(); ++i) {
RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
client->SetBlockNotSent(p);
}
- m_clients.Unlock();
+ m_clients.unlock();
}
void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
{
DSTACK(__FUNCTION_NAME);
- JMutexAutoLock envlock(m_env_mutex);
+ MutexAutoLock envlock(m_env_mutex);
//TODO check if one big lock could be faster then multiple small ones
ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
std::vector<u16> clients = m_clients.getClientIDs();
- m_clients.Lock();
+ m_clients.lock();
for(std::vector<u16>::iterator i = clients.begin();
i != clients.end(); ++i) {
RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
total_sending += client->SendingCount();
client->GetNextBlocks(m_env,m_emerge, dtime, queue);
}
- m_clients.Unlock();
+ m_clients.unlock();
}
// Sort.
// Lowest is most important.
std::sort(queue.begin(), queue.end());
- m_clients.Lock();
+ m_clients.lock();
for(u32 i=0; i<queue.size(); i++)
{
//TODO: Calculate limit dynamically
client->SentBlock(q.pos);
total_sending++;
}
- m_clients.Unlock();
+ m_clients.unlock();
}
void Server::fillMediaCache()
// Collect all media file paths
std::vector<std::string> paths;
for(std::vector<ModSpec>::iterator i = m_mods.begin();
- i != m_mods.end(); i++) {
+ i != m_mods.end(); ++i) {
const ModSpec &mod = *i;
paths.push_back(mod.path + DIR_DELIM + "textures");
paths.push_back(mod.path + DIR_DELIM + "sounds");
// Collect media file information from paths into cache
for(std::vector<std::string>::iterator i = paths.begin();
- i != paths.end(); i++) {
+ i != paths.end(); ++i) {
std::string mediapath = *i;
std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
for (u32 j = 0; j < dirlist.size(); j++) {
}
}
-struct SendableMediaAnnouncement
-{
- std::string name;
- std::string sha1_digest;
-
- SendableMediaAnnouncement(const std::string &name_="",
- const std::string &sha1_digest_=""):
- name(name_),
- sha1_digest(sha1_digest_)
- {}
-};
-
void Server::sendMediaAnnouncement(u16 peer_id)
{
DSTACK(__FUNCTION_NAME);
- verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
- <<std::endl;
-
- std::vector<SendableMediaAnnouncement> file_announcements;
-
- for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
- i != m_media.end(); i++){
- // Put in list
- file_announcements.push_back(
- SendableMediaAnnouncement(i->first, i->second.sha1_digest));
- }
+ verbosestream << "Server: Announcing files to id(" << peer_id << ")"
+ << std::endl;
// Make packet
std::ostringstream os(std::ios_base::binary);
NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
- pkt << (u16) file_announcements.size();
+ pkt << (u16) m_media.size();
- for (std::vector<SendableMediaAnnouncement>::iterator
- j = file_announcements.begin();
- j != file_announcements.end(); ++j) {
- pkt << j->name << j->sha1_digest;
+ for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
+ i != m_media.end(); ++i) {
+ pkt << i->first << i->second.sha1_digest;
}
pkt << g_settings->get("remote_media");
for(std::map<std::string, Inventory*>::iterator
i = m_detached_inventories.begin();
- i != m_detached_inventories.end(); i++) {
+ i != m_detached_inventories.end(); ++i) {
const std::string &name = i->first;
//Inventory *inv = i->second;
sendDetachedInventory(name, peer_id);
if(psound.clients.empty())
m_playing_sounds.erase(i++);
else
- i++;
+ ++i;
}
Player *player = m_env->getPlayer(peer_id);
}
}
{
- JMutexAutoLock env_lock(m_env_mutex);
+ MutexAutoLock env_lock(m_env_mutex);
m_clients.DeleteClient(peer_id);
}
}
void Server::notifyPlayer(const char *name, const std::wstring &msg)
{
+ // m_env will be NULL if the server is initializing
+ if (!m_env)
+ return;
+
Player *player = m_env->getPlayer(name);
if (!player)
return;
bool Server::showFormspec(const char *playername, const std::string &formspec,
const std::string &formname)
{
+ // m_env will be NULL if the server is initializing
+ if (!m_env)
+ return false;
+
Player *player = m_env->getPlayer(playername);
if (!player)
return false;
SendChatMessage(PEER_ID_INEXISTENT,msg);
}
-void Server::spawnParticle(const char *playername, v3f pos,
+void Server::spawnParticle(const std::string &playername, v3f pos,
v3f velocity, v3f acceleration,
float expirationtime, float size, bool
collisiondetection, bool vertical, const std::string &texture)
{
- Player *player = m_env->getPlayer(playername);
- if(!player)
+ // m_env will be NULL if the server is initializing
+ if (!m_env)
return;
- SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
- expirationtime, size, collisiondetection, vertical, texture);
-}
-void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
- float expirationtime, float size,
- bool collisiondetection, bool vertical, const std::string &texture)
-{
- SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
+ u16 peer_id = PEER_ID_INEXISTENT;
+ if (playername != "") {
+ Player* player = m_env->getPlayer(playername.c_str());
+ if (!player)
+ return;
+ peer_id = player->peer_id;
+ }
+
+ SendSpawnParticle(peer_id, pos, velocity, acceleration,
expirationtime, size, collisiondetection, vertical, texture);
}
-u32 Server::addParticleSpawner(const char *playername, u16 amount, float spawntime,
+u32 Server::addParticleSpawner(u16 amount, float spawntime,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize,
- bool collisiondetection, bool vertical, const std::string &texture)
+ bool collisiondetection, bool vertical, const std::string &texture,
+ const std::string &playername)
{
- Player *player = m_env->getPlayer(playername);
- if(!player)
+ // m_env will be NULL if the server is initializing
+ if (!m_env)
return -1;
- u32 id = 0;
- for(;;) // look for unused particlespawner id
- {
- id++;
- if (std::find(m_particlespawner_ids.begin(),
- m_particlespawner_ids.end(), id)
- == m_particlespawner_ids.end())
- {
- m_particlespawner_ids.push_back(id);
- break;
- }
+ u16 peer_id = PEER_ID_INEXISTENT;
+ if (playername != "") {
+ Player* player = m_env->getPlayer(playername.c_str());
+ if (!player)
+ return -1;
+ peer_id = player->peer_id;
}
- SendAddParticleSpawner(player->peer_id, amount, spawntime,
- minpos, maxpos, minvel, maxvel, minacc, maxacc,
- minexptime, maxexptime, minsize, maxsize,
- collisiondetection, vertical, texture, id);
-
- return id;
-}
-
-u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
- v3f minpos, v3f maxpos,
- v3f minvel, v3f maxvel,
- v3f minacc, v3f maxacc,
- float minexptime, float maxexptime,
- float minsize, float maxsize,
- bool collisiondetection, bool vertical, const std::string &texture)
-{
u32 id = 0;
for(;;) // look for unused particlespawner id
{
}
}
- SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
+ SendAddParticleSpawner(peer_id, amount, spawntime,
minpos, maxpos, minvel, maxvel, minacc, maxacc,
minexptime, maxexptime, minsize, maxsize,
collisiondetection, vertical, texture, id);
return id;
}
-void Server::deleteParticleSpawner(const char *playername, u32 id)
+void Server::deleteParticleSpawner(const std::string &playername, u32 id)
{
- Player *player = m_env->getPlayer(playername);
- if(!player)
- return;
+ // m_env will be NULL if the server is initializing
+ if (!m_env)
+ throw ServerError("Can't delete particle spawners during initialisation!");
- m_particlespawner_ids.erase(
- std::remove(m_particlespawner_ids.begin(),
- m_particlespawner_ids.end(), id),
- m_particlespawner_ids.end());
- SendDeleteParticleSpawner(player->peer_id, id);
-}
+ u16 peer_id = PEER_ID_INEXISTENT;
+ if (playername != "") {
+ Player* player = m_env->getPlayer(playername.c_str());
+ if (!player)
+ return;
+ peer_id = player->peer_id;
+ }
-void Server::deleteParticleSpawnerAll(u32 id)
-{
m_particlespawner_ids.erase(
std::remove(m_particlespawner_ids.begin(),
m_particlespawner_ids.end(), id),
m_particlespawner_ids.end());
- SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
+ SendDeleteParticleSpawner(peer_id, id);
}
Inventory* Server::createDetachedInventory(const std::string &name)
for(std::list<RollbackAction>::const_iterator
i = actions.begin();
- i != actions.end(); i++)
+ i != actions.end(); ++i)
{
const RollbackAction &action = *i;
num_tried++;