#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()));
}
}
m_uptime(0),
m_clients(&m_con),
m_shutdown_requested(false),
+ m_shutdown_ask_reconnect(false),
m_ignore_map_edit_events(false),
m_ignore_map_edit_events_peer_id(0),
m_next_sound_id(0)
m_mods = modconf.getMods();
std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
// complain about mods with unsatisfied dependencies
- if(!modconf.isConsistent())
- {
+ if(!modconf.isConsistent()) {
for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
- it != unsatisfied_mods.end(); ++it)
- {
+ it != unsatisfied_mods.end(); ++it) {
ModSpec mod = *it;
errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
std::vector<std::string> names = worldmt_settings.getNames();
std::set<std::string> load_mod_names;
for(std::vector<std::string>::iterator it = names.begin();
- it != names.end(); ++it)
- {
+ it != names.end(); ++it) {
std::string name = *it;
if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
load_mod_names.insert(name.substr(9));
for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
it != unsatisfied_mods.end(); ++it)
load_mod_names.erase((*it).name);
- if(!load_mod_names.empty())
- {
+ if(!load_mod_names.empty()) {
errorstream << "The following mods could not be found:";
for(std::set<std::string>::iterator it = load_mod_names.begin();
it != load_mod_names.end(); ++it)
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();
m_script = new GameScripting(this);
std::string script_path = getBuiltinLuaPath() + DIR_DELIM "init.lua";
+ std::string error_msg;
- if (!m_script->loadMod(script_path, BUILTIN_MOD_NAME)) {
- throw ModError("Failed to load and run " + script_path);
- }
+ if (!m_script->loadMod(script_path, BUILTIN_MOD_NAME, &error_msg))
+ throw ModError("Failed to load and run " + script_path
+ + "\nError from Lua:\n" + error_msg);
// 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)) {
- errorstream << "Error loading mod \"" << mod.name
+ std::ostringstream err;
+ err << "Error loading mod \"" << mod.name
<< "\": mod_name does not follow naming conventions: "
<< "Only chararacters [a-z0-9_] are allowed." << std::endl;
- throw ModError("Mod \"" + mod.name + "\" does not follow naming conventions.");
+ errorstream << err.str().c_str();
+ throw ModError(err.str());
}
std::string script_path = mod.path + DIR_DELIM "init.lua";
infostream << " [" << padStringRight(mod.name, 12) << "] [\""
<< script_path << "\"]" << std::endl;
- if (!m_script->loadMod(script_path, mod.name)) {
+ if (!m_script->loadMod(script_path, mod.name, &error_msg)) {
errorstream << "Server: Failed to load and run "
<< script_path << std::endl;
- throw ModError("Failed to load and run " + script_path);
+ throw ModError("Failed to load and run " + script_path
+ + "\nError from Lua:\n" + error_msg);
}
}
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();
- infostream<<"Server: Saving players"<<std::endl;
+ infostream << "Server: Saving players" << std::endl;
m_env->saveLoadedPlayers();
- infostream<<"Server: Saving environment metadata"<<std::endl;
+ infostream << "Server: Kicking players" << std::endl;
+ std::string kick_msg;
+ bool reconnect = false;
+ if (getShutdownRequested()) {
+ reconnect = m_shutdown_ask_reconnect;
+ kick_msg = m_shutdown_msg;
+ }
+ if (kick_msg == "") {
+ kick_msg = g_settings->get("kick_msg_shutdown");
+ }
+ m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
+ kick_msg, reconnect);
+
+ infostream << "Server: Saving environment metadata" << std::endl;
m_env->saveMeta();
}
// 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
throw ServerError(async_err);
}
else {
+ m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
+ g_settings->get("kick_msg_crash"),
+ g_settings->getBool("ask_reconnect_on_crash"));
errorstream << "UNRECOVERABLE error occurred. Stopping server. "
<< "Please fix the following error:" << std::endl
<< async_err << std::endl;
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) {
playername = client->getName();
- playersao = emergePlayer(playername.c_str(), peer_id);
+ 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()));
SendInventory(playersao);
// Send HP
- SendPlayerHPOrDie(peer_id, playersao->getHP() == 0);
+ SendPlayerHPOrDie(playersao);
// Send Breath
SendPlayerBreath(peer_id);
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();
<< ban_name << std::endl;
// This actually doesn't seem to transfer to the client
DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
- + narrow_to_wide(ban_name));
+ + utf8_to_wide(ban_name));
return;
}
}
if (command >= TOSERVER_NUM_MSG_TYPES) {
infostream << "Server: Ignoring unknown command "
<< command << std::endl;
+ return;
}
if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
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;
}
Send(&pkt);
}
+void Server::SendPlayerHPOrDie(PlayerSAO *playersao)
+{
+ if (!g_settings->getBool("enable_damage"))
+ return;
+
+ u16 peer_id = playersao->getPeerID();
+ bool is_alive = playersao->getHP() > 0;
+
+ if (is_alive)
+ SendPlayerHP(peer_id);
+ else
+ DiePlayer(peer_id);
+}
+
void Server::SendHP(u16 peer_id, u8 hp)
{
DSTACK(__FUNCTION_NAME);
Send(&pkt);
}
-void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
+void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
+ const std::string &custom_reason, bool reconnect)
{
- DSTACK(__FUNCTION_NAME);
+ assert(reason < SERVER_ACCESSDENIED_MAX);
NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
- pkt << (u8) reason;
-
- if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING) {
+ pkt << (u8)reason;
+ if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
pkt << custom_reason;
- }
+ else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
+ reason == SERVER_ACCESSDENIED_CRASH)
+ pkt << custom_reason << (u8)reconnect;
Send(&pkt);
}
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);
playersao->setPos(pos);
}
}
+
+
void Server::DenySudoAccess(u16 peer_id)
{
DSTACK(__FUNCTION_NAME);
Send(&pkt);
}
+
+void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
+ const std::string &str_reason, bool reconnect)
+{
+ if (proto_ver >= 25) {
+ SendAccessDenied(peer_id, reason, str_reason);
+ } else {
+ std::wstring wreason = utf8_to_wide(
+ reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
+ accessDeniedStrings[(u8)reason]);
+ SendAccessDenied_Legacy(peer_id, wreason);
+ }
+
+ m_clients.event(peer_id, CSE_SetDenied);
+ m_con.DisconnectPeer(peer_id);
+}
+
+
void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
{
DSTACK(__FUNCTION_NAME);
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);
}
}
ItemStack preview;
InventoryLocation loc;
loc.setPlayer(player->getName());
- getCraftingResult(&player->inventory, preview, false, this);
+ std::vector<ItemStack> output_replacements;
+ getCraftingResult(&player->inventory, preview, output_replacements, false, this);
m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
// Put the new preview in
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)
+ if (!player)
return;
if (player->peer_id == PEER_ID_INEXISTENT)
SendChatMessage(player->peer_id, msg);
}
-bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
+bool Server::showFormspec(const char *playername, const std::string &formspec,
+ const std::string &formname)
{
- Player *player = m_env->getPlayer(playername);
+ // m_env will be NULL if the server is initializing
+ if (!m_env)
+ return false;
- if(!player)
- {
- infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
+ Player *player = m_env->getPlayer(playername);
+ if (!player)
return false;
- }
SendShowFormspecMessage(player->peer_id, formspec, formname);
return true;
}
-u32 Server::hudAdd(Player *player, HudElement *form) {
+u32 Server::hudAdd(Player *player, HudElement *form)
+{
if (!player)
return -1;
return true;
}
-bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
+bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data)
+{
if (!player)
return false;
return true;
}
-bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
+bool Server::hudSetFlags(Player *player, u32 flags, u32 mask)
+{
if (!player)
return false;
return true;
}
-bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
+bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount)
+{
if (!player)
return false;
if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
return true;
}
-s32 Server::hudGetHotbarItemcount(Player *player) {
+s32 Server::hudGetHotbarItemcount(Player *player)
+{
if (!player)
return 0;
return player->getHotbarItemcount();
}
-void Server::hudSetHotbarImage(Player *player, std::string name) {
+void Server::hudSetHotbarImage(Player *player, std::string name)
+{
if (!player)
return;
SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
}
-std::string Server::hudGetHotbarImage(Player *player) {
+std::string Server::hudGetHotbarImage(Player *player)
+{
if (!player)
return "";
return player->getHotbarImage();
}
-void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
+void Server::hudSetHotbarSelectedImage(Player *player, std::string name)
+{
if (!player)
return;
SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
}
-std::string Server::hudGetHotbarSelectedImage(Player *player) {
+std::string Server::hudGetHotbarSelectedImage(Player *player)
+{
if (!player)
return "";
return player->getHotbarSelectedImage();
}
-bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
+bool Server::setLocalPlayerAnimations(Player *player,
+ v2s32 animation_frames[4], f32 frame_speed)
{
if (!player)
return false;
}
bool Server::setSky(Player *player, const video::SColor &bgcolor,
- const std::string &type, const std::vector<std::string> ¶ms)
+ const std::string &type, const std::vector<std::string> ¶ms)
{
if (!player)
return false;
}
bool Server::overrideDayNightRatio(Player *player, bool do_override,
- float ratio)
+ float ratio)
{
if (!player)
return false;
SendChatMessage(PEER_ID_INEXISTENT,msg);
}
-void Server::spawnParticle(const char *playername, v3f pos,
- v3f velocity, v3f acceleration,
- float expirationtime, float size, bool
- collisiondetection, bool vertical, std::string texture)
+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, 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,
- v3f minpos, v3f maxpos,
- v3f minvel, v3f maxvel,
- v3f minacc, v3f maxacc,
- float minexptime, float maxexptime,
- float minsize, float maxsize,
- bool collisiondetection, bool vertical, std::string texture)
+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,
+ 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, 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)
return inv;
}
-class BoolScopeSet
-{
-public:
- BoolScopeSet(bool *dst, bool val):
- m_dst(dst)
- {
- m_orig_state = *m_dst;
- *m_dst = val;
- }
- ~BoolScopeSet()
- {
- *m_dst = m_orig_state;
- }
-private:
- bool *m_dst;
- bool m_orig_state;
-};
-
// actions: time-reversed list
// Return value: success/failure
bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
for(std::list<RollbackAction>::const_iterator
i = actions.begin();
- i != actions.end(); i++)
+ i != actions.end(); ++i)
{
const RollbackAction &action = *i;
num_tried++;
// IGameDef interface
// Under envlock
-IItemDefManager* Server::getItemDefManager()
+IItemDefManager *Server::getItemDefManager()
{
return m_itemdef;
}
-INodeDefManager* Server::getNodeDefManager()
+
+INodeDefManager *Server::getNodeDefManager()
{
return m_nodedef;
}
-ICraftDefManager* Server::getCraftDefManager()
+
+ICraftDefManager *Server::getCraftDefManager()
{
return m_craftdef;
}
-ITextureSource* Server::getTextureSource()
+ITextureSource *Server::getTextureSource()
{
return NULL;
}
-IShaderSource* Server::getShaderSource()
+IShaderSource *Server::getShaderSource()
{
return NULL;
}
-scene::ISceneManager* Server::getSceneManager()
+scene::ISceneManager *Server::getSceneManager()
{
return NULL;
}
{
return m_nodedef->allocateDummy(name);
}
-ISoundManager* Server::getSoundManager()
+
+ISoundManager *Server::getSoundManager()
{
return &dummySoundManager;
}
-MtEventManager* Server::getEventManager()
+
+MtEventManager *Server::getEventManager()
{
return m_event;
}
-IWritableItemDefManager* Server::getWritableItemDefManager()
+IWritableItemDefManager *Server::getWritableItemDefManager()
{
return m_itemdef;
}
-IWritableNodeDefManager* Server::getWritableNodeDefManager()
+
+IWritableNodeDefManager *Server::getWritableNodeDefManager()
{
return m_nodedef;
}
-IWritableCraftDefManager* Server::getWritableCraftDefManager()
+
+IWritableCraftDefManager *Server::getWritableCraftDefManager()
{
return m_craftdef;
}
-const ModSpec* Server::getModSpec(const std::string &modname) const
+const ModSpec *Server::getModSpec(const std::string &modname) const
{
- for(std::vector<ModSpec>::const_iterator i = m_mods.begin();
- i != m_mods.end(); i++){
- const ModSpec &mod = *i;
- if(mod.name == modname)
+ std::vector<ModSpec>::const_iterator it;
+ for (it = m_mods.begin(); it != m_mods.end(); ++it) {
+ const ModSpec &mod = *it;
+ if (mod.name == modname)
return &mod;
}
return NULL;
}
+
void Server::getModNames(std::vector<std::string> &modlist)
{
- for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++) {
- modlist.push_back(i->name);
- }
+ std::vector<ModSpec>::iterator it;
+ for (it = m_mods.begin(); it != m_mods.end(); ++it)
+ modlist.push_back(it->name);
}
+
std::string Server::getBuiltinLuaPath()
{
return porting::path_share + DIR_DELIM + "builtin";
return intToFloat(nodepos, BS);
}
-PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
+PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
{
bool newplayer = false;
getPlayerEffectivePrivs(player->getName()),
isSingleplayer());
+ player->protocol_version = proto_version;
+
/* Clean up old HUD elements from previous sessions */
player->clearHud();