#include "itemdef.h"
#include "craftdef.h"
#include "emerge.h"
-#include "mapgen.h"
-#include "mg_biome.h"
+#include "mapgen/mapgen.h"
+#include "mapgen/mg_biome.h"
#include "content_mapnode.h"
#include "content_nodemeta.h"
#include "content_sao.h"
#include "util/base64.h"
#include "util/sha1.h"
#include "util/hex.h"
-#include "database.h"
+#include "database/database.h"
#include "chatmessage.h"
#include "chat_interface.h"
#include "remoteplayer.h"
m_nodedef->updateAliases(m_itemdef);
// Apply texture overrides from texturepack/override.txt
- std::string texture_path = g_settings->get("texture_path");
- if (!texture_path.empty() && fs::IsDir(texture_path))
- m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt");
+ std::vector<std::string> paths;
+ fs::GetRecursiveDirs(paths, g_settings->get("texture_path"));
+ fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
+ for (const std::string &path : paths)
+ m_nodedef->applyTextureOverrides(path + DIR_DELIM + "override.txt");
m_nodedef->setNodeRegistrationStatus(true);
Server::~Server()
{
- infostream<<"Server destructing"<<std::endl;
+ infostream << "Server destructing" << std::endl;
// Send shutdown message
SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE,
{
MutexAutoLock envlock(m_env_mutex);
- // Execute script shutdown hooks
- m_script->on_shutdown();
-
infostream << "Server: Saving players" << std::endl;
m_env->saveLoadedPlayers();
}
m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
kick_msg, reconnect);
+ }
+
+ // Do this before stopping the server in case mapgen callbacks need to access
+ // server-controlled resources (like ModStorages). Also do them before
+ // shutdown callbacks since they may modify state that is finalized in a
+ // callback.
+ m_emerge->stopThreads();
+
+ {
+ MutexAutoLock envlock(m_env_mutex);
+
+ // Execute script shutdown hooks
+ infostream << "Executing shutdown hooks" << std::endl;
+ m_script->on_shutdown();
infostream << "Server: Saving environment metadata" << std::endl;
m_env->saveMeta();
stop();
delete m_thread;
- // stop all emerge threads before deleting players that may have
- // requested blocks to be emerged
- m_emerge->stopThreads();
-
// Delete things in the reverse order of creation
delete m_emerge;
delete m_env;
delete m_craftdef;
// Deinitialize scripting
- infostream<<"Server: Deinitializing scripting"<<std::endl;
+ infostream << "Server: Deinitializing scripting" << std::endl;
delete m_script;
// Delete detached inventories
// If failed, cancel
if (!playersao || !player) {
- if (player && player->peer_id != 0) {
+ if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
actionstream << "Server: Failed to emerge player \"" << playername
<< "\" (player allocated to an another client)" << std::endl;
DenyAccess_Legacy(peer_id, L"Another client is connected with this "
// Send information about server to player in chat
SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM, getStatusString()));
}
- Address addr = getPeerAddress(player->peer_id);
+ Address addr = getPeerAddress(player->getPeerId());
std::string ip_str = addr.serializeString();
actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
/*
}
void Server::SendNodeDef(session_t peer_id,
- INodeDefManager *nodedef, u16 protocol_version)
+ const NodeDefManager *nodedef, u16 protocol_version)
{
NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
if (formspec.empty()){
//the client should close the formspec
+ m_formspec_state_data.erase(peer_id);
pkt.putLongString("");
} else {
+ m_formspec_state_data[peer_id] = formname;
pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
}
pkt << formname;
Send(&pkt);
}
-void Server::SendCloudParams(session_t peer_id, float density,
- const video::SColor &color_bright,
- const video::SColor &color_ambient,
- float height,
- float thickness,
- const v2f &speed)
+void Server::SendCloudParams(session_t peer_id, const CloudParams ¶ms)
{
NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
- pkt << density << color_bright << color_ambient
- << height << thickness << speed;
-
+ pkt << params.density << params.color_bright << params.color_ambient
+ << params.height << params.thickness << params.speed;
Send(&pkt);
}
{
RemotePlayer *player = m_env->getPlayer(peer_id);
assert(player);
- if(player->peer_id == PEER_ID_INEXISTENT)
+ if(player->getPeerId() == PEER_ID_INEXISTENT)
return;
std::set<std::string> privs;
{
RemotePlayer *player = m_env->getPlayer(peer_id);
assert(player);
- if(player->peer_id == PEER_ID_INEXISTENT)
+ if(player->getPeerId() == PEER_ID_INEXISTENT)
return;
NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
<<"\" not found"<<std::endl;
return -1;
}
- if(player->peer_id == PEER_ID_INEXISTENT){
+ if (player->getPeerId() == PEER_ID_INEXISTENT) {
infostream<<"Server::playSound: Player \""<<params.to_player
<<"\" not connected"<<std::endl;
return -1;
}
- dst_clients.push_back(player->peer_id);
+ dst_clients.push_back(player->getPeerId());
} else {
std::vector<session_t> clients = m_clients.getClientIDs();
paths.push_back(mod.path + DIR_DELIM + "models");
paths.push_back(mod.path + DIR_DELIM + "locale");
}
- paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
+ fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
+ fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
// Collect media file information from paths into cache
for (const std::string &mediapath : paths) {
return m_clients.sendToAll(&pkt);
RemotePlayer *p = m_env->getPlayer(check.c_str());
if (p)
- m_clients.send(p->peer_id, 0, &pkt, true);
+ m_clients.send(p->getPeerId(), 0, &pkt, true);
} else {
if (check.empty() || getPlayerName(peer_id) == check)
Send(&pkt);
++i;
}
+ // clear formspec info so the next client can't abuse the current state
+ m_formspec_state_data.erase(peer_id);
+
RemotePlayer *player = m_env->getPlayer(peer_id);
/* Run scripts and remove from environment */
return ws.str();
}
case RPLAYER_CHATRESULT_KICK:
- DenyAccess_Legacy(player->peer_id,
+ DenyAccess_Legacy(player->getPeerId(),
L"You have been kicked due to message flooding.");
return L"";
case RPLAYER_CHATRESULT_OK:
if they are using protocol version >= 29
*/
- session_t peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
+ session_t peer_id_to_avoid_sending =
+ (player ? player->getPeerId() : PEER_ID_INEXISTENT);
+
if (player && player->protocol_version >= 29)
peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
RemotePlayer *player = m_env->getPlayer(name.c_str());
if (!player)
return;
- SendPlayerPrivileges(player->peer_id);
+ SendPlayerPrivileges(player->getPeerId());
PlayerSAO *sao = player->getPlayerSAO();
if(!sao)
return;
RemotePlayer *player = m_env->getPlayer(name.c_str());
if (!player)
return;
- SendPlayerInventoryFormspec(player->peer_id);
+ SendPlayerInventoryFormspec(player->getPeerId());
}
void Server::setIpBanned(const std::string &ip, const std::string &name)
return;
}
- if (player->peer_id == PEER_ID_INEXISTENT)
+ if (player->getPeerId() == PEER_ID_INEXISTENT)
return;
- SendChatMessage(player->peer_id, ChatMessage(msg));
+ SendChatMessage(player->getPeerId(), ChatMessage(msg));
}
bool Server::showFormspec(const char *playername, const std::string &formspec,
if (!player)
return false;
- SendShowFormspecMessage(player->peer_id, formspec, formname);
+ SendShowFormspecMessage(player->getPeerId(), formspec, formname);
return true;
}
u32 id = player->addHud(form);
- SendHUDAdd(player->peer_id, id, form);
+ SendHUDAdd(player->getPeerId(), id, form);
return id;
}
delete todel;
- SendHUDRemove(player->peer_id, id);
+ SendHUDRemove(player->getPeerId(), id);
return true;
}
if (!player)
return false;
- SendHUDChange(player->peer_id, id, stat, data);
+ SendHUDChange(player->getPeerId(), id, stat, data);
return true;
}
if (!player)
return false;
- SendHUDSetFlags(player->peer_id, flags, mask);
+ SendHUDSetFlags(player->getPeerId(), flags, mask);
player->hud_flags &= ~mask;
player->hud_flags |= flags;
player->setHotbarItemcount(hotbar_itemcount);
std::ostringstream os(std::ios::binary);
writeS32(os, hotbar_itemcount);
- SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
+ SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
return true;
}
-s32 Server::hudGetHotbarItemcount(RemotePlayer *player) const
-{
- return player->getHotbarItemcount();
-}
-
void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
{
if (!player)
return;
player->setHotbarImage(name);
- SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
-}
-
-std::string Server::hudGetHotbarImage(RemotePlayer *player)
-{
- if (!player)
- return "";
- return player->getHotbarImage();
+ SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
}
void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
return;
player->setHotbarSelectedImage(name);
- SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
-}
-
-const std::string& Server::hudGetHotbarSelectedImage(RemotePlayer *player) const
-{
- return player->getHotbarSelectedImage();
+ SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
}
Address Server::getPeerAddress(session_t peer_id)
return m_con->GetPeerAddress(peer_id);
}
-bool Server::setLocalPlayerAnimations(RemotePlayer *player,
+void Server::setLocalPlayerAnimations(RemotePlayer *player,
v2s32 animation_frames[4], f32 frame_speed)
{
- if (!player)
- return false;
-
+ sanity_check(player);
player->setLocalAnimations(animation_frames, frame_speed);
- SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
- return true;
+ SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
}
-bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
+void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
{
- if (!player)
- return false;
-
+ sanity_check(player);
player->eye_offset_first = first;
player->eye_offset_third = third;
- SendEyeOffset(player->peer_id, first, third);
- return true;
+ SendEyeOffset(player->getPeerId(), first, third);
}
-bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
+void Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
const std::string &type, const std::vector<std::string> ¶ms,
bool &clouds)
{
- if (!player)
- return false;
-
+ sanity_check(player);
player->setSky(bgcolor, type, params, clouds);
- SendSetSky(player->peer_id, bgcolor, type, params, clouds);
- return true;
+ SendSetSky(player->getPeerId(), bgcolor, type, params, clouds);
}
-bool Server::setClouds(RemotePlayer *player, float density,
- const video::SColor &color_bright,
- const video::SColor &color_ambient,
- float height,
- float thickness,
- const v2f &speed)
+void Server::setClouds(RemotePlayer *player, const CloudParams ¶ms)
{
- if (!player)
- return false;
-
- SendCloudParams(player->peer_id, density,
- color_bright, color_ambient, height,
- thickness, speed);
- return true;
+ sanity_check(player);
+ player->setCloudParams(params);
+ SendCloudParams(player->getPeerId(), params);
}
bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
return false;
player->overrideDayNightRatio(do_override, ratio);
- SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
+ SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
return true;
}
RemotePlayer *player = m_env->getPlayer(playername.c_str());
if (!player)
return;
- peer_id = player->peer_id;
+ peer_id = player->getPeerId();
proto_ver = player->protocol_version;
}
RemotePlayer *player = m_env->getPlayer(playername.c_str());
if (!player)
return -1;
- peer_id = player->peer_id;
+ peer_id = player->getPeerId();
proto_ver = player->protocol_version;
}
RemotePlayer *player = m_env->getPlayer(playername.c_str());
if (!player)
return;
- peer_id = player->peer_id;
+ peer_id = player->getPeerId();
}
m_env->deleteParticleSpawner(id);
return m_itemdef;
}
-INodeDefManager *Server::getNodeDefManager()
+const NodeDefManager *Server::getNodeDefManager()
{
return m_nodedef;
}
return m_itemdef;
}
-IWritableNodeDefManager *Server::getWritableNodeDefManager()
+NodeDefManager *Server::getWritableNodeDefManager()
{
return m_nodedef;
}
RemotePlayer *player = m_env->getPlayer(name);
// If player is already connected, cancel
- if (player && player->peer_id != 0) {
+ if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
infostream<<"emergePlayer(): Player already connected"<<std::endl;
return NULL;
}