#include "server/serverinventorymgr.h"
#include "translation.h"
#include "database/database-sqlite3.h"
+#if USE_POSTGRESQL
+#include "database/database-postgresql.h"
+#endif
#include "database/database-files.h"
#include "database/database-dummy.h"
#include "gameparams.h"
m_mod_storage_database->beginSave();
m_modmgr = std::make_unique<ServerModManager>(m_path_world);
- std::vector<ModSpec> unsatisfied_mods = m_modmgr->getUnsatisfiedMods();
// complain about mods with unsatisfied dependencies
if (!m_modmgr->isConsistent()) {
- m_modmgr->printUnsatisfiedModsError();
-
- warningstream
- << "You have unsatisfied dependencies, loading your world anyway. "
- << "This will become a fatal error in the future." << std::endl;
+ std::string error = m_modmgr->getUnsatisfiedModsError();
+ throw ServerError(error);
}
//lock environment
m_inventory_mgr = std::make_unique<ServerInventoryManager>();
m_script->loadMod(getBuiltinLuaPath() + DIR_DELIM "init.lua", BUILTIN_MOD_NAME);
+ m_script->checkSetByBuiltin();
m_gamespec.checkAndLog();
m_modmgr->loadMods(m_script);
m_startup_server_map = nullptr; // Ownership moved to ServerEnvironment
m_env = new ServerEnvironment(servermap, m_script, this,
m_path_world, m_metrics_backend.get());
+ m_env->init();
m_inventory_mgr->setEnv(m_env);
m_clients.setEnv(m_env);
std::map<v3s16, MapBlock*> modified_blocks;
m_env->getServerMap().transformLiquids(modified_blocks, m_env);
- /*
- Set the modified blocks unsent for all the clients
- */
if (!modified_blocks.empty()) {
- SetBlocksNotSent(modified_blocks);
+ MapEditEvent event;
+ event.type = MEET_OTHER;
+ for (const auto &pair : modified_blocks) {
+ event.modified_blocks.insert(pair.first);
+ }
+ m_env->getMap().dispatchEvent(event);
}
}
m_clients.step(dtime);
if (!playersao || !player) {
if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
actionstream << "Server: Failed to emerge player \"" << playername
- << "\" (player allocated to an another client)" << std::endl;
+ << "\" (player allocated to another client)" << std::endl;
DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED);
} else {
errorstream << "Server: " << playername << ": Failed to emerge player"
m_unsent_map_edit_queue.push(new MapEditEvent(event));
}
-void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
-{
- std::vector<session_t> clients = m_clients.getClientIDs();
- ClientInterface::AutoLock clientlock(m_clients);
- // Set the modified blocks unsent for all the clients
- for (const session_t client_id : clients) {
- if (RemoteClient *client = m_clients.lockedGetClientNoEx(client_id))
- client->SetBlocksNotSent(block);
- }
-}
-
void Server::peerAdded(con::Peer *peer)
{
verbosestream<<"Server::peerAdded(): peer->id="
void Server::SendMovement(session_t peer_id)
{
- std::ostringstream os(std::ios_base::binary);
-
NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
pkt << g_settings->getFloat("movement_acceleration_default");
{
NetworkPacket pkt(TOCLIENT_SET_LIGHTING,
4, peer_id);
-
+
pkt << lighting.shadow_intensity;
Send(&pkt);
void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
float far_d_nodes)
{
- float maxd = far_d_nodes * BS;
v3f p_f = intToFloat(p, BS);
v3s16 block_pos = getNodeBlockPos(p);
NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
pkt << p;
- std::vector<session_t> clients = m_clients.getClientIDs();
- ClientInterface::AutoLock clientlock(m_clients);
-
- for (session_t client_id : clients) {
- RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
- if (!client)
- continue;
-
- RemotePlayer *player = m_env->getPlayer(client_id);
- PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
-
- // If player is far away, only set modified blocks not sent
- if (!client->isBlockSent(block_pos) || (sao &&
- sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
- if (far_players)
- far_players->emplace(client_id);
- else
- client->SetBlockNotSent(block_pos);
- continue;
- }
-
- // Send as reliable
- m_clients.send(client_id, 0, &pkt, true);
- }
+ sendNodeChangePkt(pkt, block_pos, p_f, far_d_nodes, far_players);
}
void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
float far_d_nodes, bool remove_metadata)
{
- float maxd = far_d_nodes * BS;
v3f p_f = intToFloat(p, BS);
v3s16 block_pos = getNodeBlockPos(p);
NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
pkt << p << n.param0 << n.param1 << n.param2
<< (u8) (remove_metadata ? 0 : 1);
+ sendNodeChangePkt(pkt, block_pos, p_f, far_d_nodes, far_players);
+}
+void Server::sendNodeChangePkt(NetworkPacket &pkt, v3s16 block_pos,
+ v3f p, float far_d_nodes, std::unordered_set<u16> *far_players)
+{
+ float maxd = far_d_nodes * BS;
std::vector<session_t> clients = m_clients.getClientIDs();
ClientInterface::AutoLock clientlock(m_clients);
// If player is far away, only set modified blocks not sent
if (!client->isBlockSent(block_pos) || (sao &&
- sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
+ sao->getBasePosition().getDistanceFrom(p) > maxd)) {
if (far_players)
far_players->emplace(client_id);
else
return playersao;
}
-bool Server::registerModStorage(ModMetadata *storage)
-{
- if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
- errorstream << "Unable to register same mod storage twice. Storage name: "
- << storage->getModName() << std::endl;
- return false;
- }
-
- m_mod_storages[storage->getModName()] = storage;
- return true;
-}
-
-void Server::unregisterModStorage(const std::string &name)
-{
- std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
- if (it != m_mod_storages.end())
- m_mod_storages.erase(name);
-}
-
void dedicated_server_loop(Server &server, bool &kill)
{
verbosestream<<"dedicated_server_loop()"<<std::endl;
return translations;
}
-ModMetadataDatabase *Server::openModStorageDatabase(const std::string &world_path)
+ModStorageDatabase *Server::openModStorageDatabase(const std::string &world_path)
{
std::string world_mt_path = world_path + DIR_DELIM + "world.mt";
Settings world_mt;
return openModStorageDatabase(backend, world_path, world_mt);
}
-ModMetadataDatabase *Server::openModStorageDatabase(const std::string &backend,
+ModStorageDatabase *Server::openModStorageDatabase(const std::string &backend,
const std::string &world_path, const Settings &world_mt)
{
if (backend == "sqlite3")
- return new ModMetadataDatabaseSQLite3(world_path);
+ return new ModStorageDatabaseSQLite3(world_path);
+
+#if USE_POSTGRESQL
+ if (backend == "postgresql") {
+ std::string connect_string;
+ world_mt.getNoEx("pgsql_mod_storage_connection", connect_string);
+ return new ModStorageDatabasePostgreSQL(connect_string);
+ }
+#endif // USE_POSTGRESQL
if (backend == "files")
- return new ModMetadataDatabaseFiles(world_path);
+ return new ModStorageDatabaseFiles(world_path);
if (backend == "dummy")
return new Database_Dummy();
return false;
}
- ModMetadataDatabase *srcdb = nullptr;
- ModMetadataDatabase *dstdb = nullptr;
+ ModStorageDatabase *srcdb = nullptr;
+ ModStorageDatabase *dstdb = nullptr;
bool succeeded = false;