2010-11-29 19:13:04 +01:00
|
|
|
/*
|
2013-02-24 18:40:43 +01:00
|
|
|
Minetest
|
2013-02-24 19:38:45 +01:00
|
|
|
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
|
2010-11-29 19:13:04 +01:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
2012-06-05 16:56:56 +02:00
|
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
2010-11-29 19:13:04 +01:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2012-06-05 16:56:56 +02:00
|
|
|
GNU Lesser General Public License for more details.
|
2010-11-29 19:13:04 +01:00
|
|
|
|
2012-06-05 16:56:56 +02:00
|
|
|
You should have received a copy of the GNU Lesser General Public License along
|
2010-11-29 19:13:04 +01:00
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2010-11-27 00:02:21 +01:00
|
|
|
#include "server.h"
|
|
|
|
#include <iostream>
|
2011-11-27 10:44:05 +01:00
|
|
|
#include <queue>
|
2013-01-23 18:32:02 +01:00
|
|
|
#include <algorithm>
|
2017-08-24 08:28:54 +02:00
|
|
|
#include "network/connection.h"
|
2015-01-12 17:01:41 +01:00
|
|
|
#include "network/networkprotocol.h"
|
|
|
|
#include "network/serveropcodes.h"
|
2024-01-24 19:13:03 +01:00
|
|
|
#include "server/ban.h"
|
2013-08-11 04:09:45 +02:00
|
|
|
#include "environment.h"
|
2024-03-06 21:04:57 +01:00
|
|
|
#include "servermap.h"
|
2015-04-07 12:13:12 +02:00
|
|
|
#include "threading/mutex_auto_lock.h"
|
2010-11-27 00:02:21 +01:00
|
|
|
#include "constants.h"
|
2010-12-11 17:11:03 +01:00
|
|
|
#include "voxel.h"
|
2011-04-24 23:31:22 +02:00
|
|
|
#include "config.h"
|
2013-09-25 04:29:07 +02:00
|
|
|
#include "version.h"
|
2011-05-22 16:00:09 +02:00
|
|
|
#include "filesys.h"
|
2011-06-26 01:34:36 +02:00
|
|
|
#include "mapblock.h"
|
2020-04-10 21:25:42 +02:00
|
|
|
#include "server/serveractiveobject.h"
|
2011-10-12 12:53:38 +02:00
|
|
|
#include "settings.h"
|
|
|
|
#include "profiler.h"
|
2011-10-16 13:57:53 +02:00
|
|
|
#include "log.h"
|
2017-04-25 19:38:08 +02:00
|
|
|
#include "scripting_server.h"
|
2011-11-14 20:41:30 +01:00
|
|
|
#include "nodedef.h"
|
2012-01-12 06:10:39 +01:00
|
|
|
#include "itemdef.h"
|
2011-11-17 01:28:46 +01:00
|
|
|
#include "craftdef.h"
|
2013-02-14 04:43:15 +01:00
|
|
|
#include "emerge.h"
|
2017-11-08 23:56:20 +01:00
|
|
|
#include "mapgen/mapgen.h"
|
|
|
|
#include "mapgen/mg_biome.h"
|
2017-06-06 16:19:04 +02:00
|
|
|
#include "content_mapnode.h"
|
2012-03-19 03:04:16 +01:00
|
|
|
#include "content_nodemeta.h"
|
2018-04-17 15:54:50 +02:00
|
|
|
#include "content/mods.h"
|
2017-09-26 00:11:20 +02:00
|
|
|
#include "modchannels.h"
|
2024-01-24 19:13:03 +01:00
|
|
|
#include "server/serverlist.h"
|
2012-06-17 01:40:36 +02:00
|
|
|
#include "util/string.h"
|
2024-01-24 19:13:03 +01:00
|
|
|
#include "server/rollback.h"
|
2012-11-26 10:18:34 +01:00
|
|
|
#include "util/serialize.h"
|
2013-08-11 04:09:45 +02:00
|
|
|
#include "util/thread.h"
|
2013-03-21 20:42:23 +01:00
|
|
|
#include "defaultsettings.h"
|
2018-03-16 08:41:33 +01:00
|
|
|
#include "server/mods.h"
|
2015-02-21 14:17:36 +01:00
|
|
|
#include "util/base64.h"
|
|
|
|
#include "util/sha1.h"
|
|
|
|
#include "util/hex.h"
|
2017-11-08 23:56:20 +01:00
|
|
|
#include "database/database.h"
|
2017-07-16 10:47:31 +02:00
|
|
|
#include "chatmessage.h"
|
2017-08-16 22:11:45 +02:00
|
|
|
#include "chat_interface.h"
|
2017-08-18 19:25:07 +02:00
|
|
|
#include "remoteplayer.h"
|
2020-04-11 09:59:09 +02:00
|
|
|
#include "server/player_sao.h"
|
2020-05-07 22:38:41 +02:00
|
|
|
#include "server/serverinventorymgr.h"
|
2020-04-25 07:20:00 +02:00
|
|
|
#include "translation.h"
|
2022-01-07 19:28:49 +01:00
|
|
|
#include "database/database-sqlite3.h"
|
2022-10-19 20:16:57 +02:00
|
|
|
#if USE_POSTGRESQL
|
|
|
|
#include "database/database-postgresql.h"
|
|
|
|
#endif
|
2022-01-07 19:28:49 +01:00
|
|
|
#include "database/database-files.h"
|
|
|
|
#include "database/database-dummy.h"
|
|
|
|
#include "gameparams.h"
|
2023-03-08 22:58:47 +01:00
|
|
|
#include "particles.h"
|
2023-07-03 20:34:02 +02:00
|
|
|
#include "gettext.h"
|
2011-10-16 13:57:53 +02:00
|
|
|
|
2013-08-04 07:17:07 +02:00
|
|
|
class ClientNotFoundException : public BaseException
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ClientNotFoundException(const char *s):
|
|
|
|
BaseException(s)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2015-04-07 12:13:12 +02:00
|
|
|
class ServerThread : public Thread
|
2013-08-11 04:09:45 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
ServerThread(Server *server):
|
2015-04-07 12:13:12 +02:00
|
|
|
Thread("Server"),
|
2013-08-11 04:09:45 +02:00
|
|
|
m_server(server)
|
2015-04-07 12:13:12 +02:00
|
|
|
{}
|
2013-08-11 04:09:45 +02:00
|
|
|
|
2015-04-07 12:13:12 +02:00
|
|
|
void *run();
|
|
|
|
|
|
|
|
private:
|
|
|
|
Server *m_server;
|
2013-08-11 04:09:45 +02:00
|
|
|
};
|
|
|
|
|
2015-04-07 12:13:12 +02:00
|
|
|
void *ServerThread::run()
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2010-12-27 13:34:17 +01:00
|
|
|
BEGIN_DEBUG_EXCEPTION_HANDLER
|
|
|
|
|
2019-11-14 17:38:15 +01:00
|
|
|
/*
|
|
|
|
* The real business of the server happens on the ServerThread.
|
|
|
|
* How this works:
|
2023-03-29 11:42:50 +02:00
|
|
|
* AsyncRunStep() (which runs the actual server step) is called at the
|
|
|
|
* server-step frequency. Receive() is used for waiting between the steps.
|
2019-11-14 17:38:15 +01:00
|
|
|
*/
|
|
|
|
|
2021-09-10 23:16:46 +02:00
|
|
|
try {
|
2023-03-29 11:42:50 +02:00
|
|
|
m_server->AsyncRunStep(0.0f, true);
|
2021-09-10 23:16:46 +02:00
|
|
|
} catch (con::ConnectionBindFailed &e) {
|
|
|
|
m_server->setAsyncFatalError(e.what());
|
|
|
|
} catch (LuaError &e) {
|
|
|
|
m_server->setAsyncFatalError(e);
|
|
|
|
}
|
2014-01-06 20:05:28 +01:00
|
|
|
|
2023-03-29 11:42:50 +02:00
|
|
|
float dtime = 0.0f;
|
|
|
|
|
2015-04-07 12:13:12 +02:00
|
|
|
while (!stopRequested()) {
|
2023-04-09 19:48:00 +02:00
|
|
|
ScopeProfiler spm(g_profiler, "Server::RunStep() (max)", SPT_MAX);
|
2023-03-29 11:42:50 +02:00
|
|
|
|
|
|
|
u64 t0 = porting::getTimeUs();
|
|
|
|
|
|
|
|
const Server::StepSettings step_settings = m_server->getStepSettings();
|
|
|
|
|
2015-08-01 22:52:28 +02:00
|
|
|
try {
|
2023-03-29 11:42:50 +02:00
|
|
|
m_server->AsyncRunStep(step_settings.pause ? 0.0f : dtime);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2023-03-29 11:42:50 +02:00
|
|
|
const float remaining_time = step_settings.steplen
|
|
|
|
- 1e-6f * (porting::getTimeUs() - t0);
|
|
|
|
m_server->Receive(remaining_time);
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2015-08-01 22:52:28 +02:00
|
|
|
} catch (con::PeerNotFoundException &e) {
|
2011-10-16 13:57:53 +02:00
|
|
|
infostream<<"Server: PeerNotFoundException"<<std::endl;
|
2015-08-01 22:52:28 +02:00
|
|
|
} catch (ClientNotFoundException &e) {
|
2024-01-19 20:08:55 +01:00
|
|
|
infostream<<"Server: ClientNotFoundException"<<std::endl;
|
2015-08-01 22:52:28 +02:00
|
|
|
} catch (con::ConnectionBindFailed &e) {
|
2012-03-30 17:42:18 +02:00
|
|
|
m_server->setAsyncFatalError(e.what());
|
2015-08-01 22:52:28 +02:00
|
|
|
} catch (LuaError &e) {
|
2021-09-10 23:16:46 +02:00
|
|
|
m_server->setAsyncFatalError(e);
|
2012-03-30 17:42:18 +02:00
|
|
|
}
|
2023-03-29 11:42:50 +02:00
|
|
|
|
|
|
|
dtime = 1e-6f * (porting::getTimeUs() - t0);
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2015-10-14 08:33:04 +02:00
|
|
|
END_DEBUG_EXCEPTION_HANDLER
|
2010-11-27 00:02:21 +01:00
|
|
|
|
2017-08-15 09:30:31 +02:00
|
|
|
return nullptr;
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
v3f ServerPlayingSound::getPos(ServerEnvironment *env, bool *pos_exists) const
|
2012-03-19 03:04:16 +01:00
|
|
|
{
|
2022-07-09 22:32:24 +02:00
|
|
|
if (pos_exists)
|
|
|
|
*pos_exists = false;
|
|
|
|
|
|
|
|
switch (type ){
|
|
|
|
case SoundLocation::Local:
|
2012-03-19 03:04:16 +01:00
|
|
|
return v3f(0,0,0);
|
2022-07-09 22:32:24 +02:00
|
|
|
case SoundLocation::Position:
|
|
|
|
if (pos_exists)
|
|
|
|
*pos_exists = true;
|
2012-03-19 03:04:16 +01:00
|
|
|
return pos;
|
2022-07-09 22:32:24 +02:00
|
|
|
case SoundLocation::Object:
|
|
|
|
{
|
|
|
|
if (object == 0)
|
|
|
|
return v3f(0,0,0);
|
|
|
|
ServerActiveObject *sao = env->getActiveObject(object);
|
|
|
|
if (!sao)
|
|
|
|
return v3f(0,0,0);
|
|
|
|
if (pos_exists)
|
|
|
|
*pos_exists = true;
|
|
|
|
return sao->getBasePosition();
|
|
|
|
}
|
2012-03-19 03:04:16 +01:00
|
|
|
}
|
2022-07-13 11:57:12 +02:00
|
|
|
|
2012-03-19 03:04:16 +01:00
|
|
|
return v3f(0,0,0);
|
|
|
|
}
|
|
|
|
|
2018-06-13 21:58:34 +02:00
|
|
|
void Server::ShutdownState::reset()
|
|
|
|
{
|
|
|
|
m_timer = 0.0f;
|
|
|
|
message.clear();
|
|
|
|
should_reconnect = false;
|
|
|
|
is_requested = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Server::ShutdownState::trigger(float delay, const std::string &msg, bool reconnect)
|
|
|
|
{
|
|
|
|
m_timer = delay;
|
|
|
|
message = msg;
|
|
|
|
should_reconnect = reconnect;
|
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2018-06-13 21:58:34 +02:00
|
|
|
void Server::ShutdownState::tick(float dtime, Server *server)
|
|
|
|
{
|
|
|
|
if (m_timer <= 0.0f)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Timed shutdown
|
|
|
|
static const float shutdown_msg_times[] =
|
|
|
|
{
|
|
|
|
1, 2, 3, 4, 5, 10, 20, 40, 60, 120, 180, 300, 600, 1200, 1800, 3600
|
|
|
|
};
|
|
|
|
|
|
|
|
// Automated messages
|
|
|
|
if (m_timer < shutdown_msg_times[ARRLEN(shutdown_msg_times) - 1]) {
|
|
|
|
for (float t : shutdown_msg_times) {
|
|
|
|
// If shutdown timer matches an automessage, shot it
|
|
|
|
if (m_timer > t && m_timer - dtime < t) {
|
|
|
|
std::wstring periodicMsg = getShutdownTimerMessage();
|
|
|
|
|
|
|
|
infostream << wide_to_utf8(periodicMsg).c_str() << std::endl;
|
|
|
|
server->SendChatMessage(PEER_ID_INEXISTENT, periodicMsg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_timer -= dtime;
|
|
|
|
if (m_timer < 0.0f) {
|
|
|
|
m_timer = 0.0f;
|
|
|
|
is_requested = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring Server::ShutdownState::getShutdownTimerMessage() const
|
|
|
|
{
|
|
|
|
std::wstringstream ws;
|
|
|
|
ws << L"*** Server shutting down in "
|
|
|
|
<< duration_to_string(myround(m_timer)).c_str() << ".";
|
|
|
|
return ws.str();
|
|
|
|
}
|
2010-11-27 00:02:21 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Server
|
|
|
|
*/
|
|
|
|
|
|
|
|
Server::Server(
|
2012-03-11 13:54:23 +01:00
|
|
|
const std::string &path_world,
|
2012-03-15 14:20:20 +01:00
|
|
|
const SubgameSpec &gamespec,
|
2014-03-07 01:00:03 +01:00
|
|
|
bool simple_singleplayer_mode,
|
2017-09-28 13:47:30 +02:00
|
|
|
Address bind_addr,
|
2015-10-15 19:04:15 +02:00
|
|
|
bool dedicated,
|
2020-08-23 19:44:25 +02:00
|
|
|
ChatInterface *iface,
|
2023-07-03 20:34:02 +02:00
|
|
|
std::string *shutdown_errmsg
|
2010-11-27 00:02:21 +01:00
|
|
|
):
|
2017-09-28 13:47:30 +02:00
|
|
|
m_bind_addr(bind_addr),
|
2012-03-10 14:56:24 +01:00
|
|
|
m_path_world(path_world),
|
2012-03-11 13:54:23 +01:00
|
|
|
m_gamespec(gamespec),
|
2012-03-15 14:20:20 +01:00
|
|
|
m_simple_singleplayer_mode(simple_singleplayer_mode),
|
2015-10-15 19:04:15 +02:00
|
|
|
m_dedicated(dedicated),
|
2012-03-11 19:45:43 +01:00
|
|
|
m_async_fatal_error(""),
|
2017-08-24 08:28:54 +02:00
|
|
|
m_con(std::make_shared<con::Connection>(PROTOCOL_ID,
|
2014-01-31 00:24:00 +01:00
|
|
|
512,
|
|
|
|
CONNECTION_TIMEOUT,
|
2017-09-28 13:47:30 +02:00
|
|
|
m_bind_addr.isIPv6(),
|
2017-08-24 08:28:54 +02:00
|
|
|
this)),
|
2012-01-12 06:10:39 +01:00
|
|
|
m_itemdef(createItemDefManager()),
|
2011-11-16 13:08:31 +01:00
|
|
|
m_nodedef(createNodeDefManager()),
|
2011-11-17 01:28:46 +01:00
|
|
|
m_craftdef(createCraftDefManager()),
|
2019-03-25 16:54:27 +01:00
|
|
|
m_thread(new ServerThread(this)),
|
2017-08-24 08:28:54 +02:00
|
|
|
m_clients(m_con),
|
2017-09-26 00:11:20 +02:00
|
|
|
m_admin_chat(iface),
|
2023-07-03 20:34:02 +02:00
|
|
|
m_shutdown_errmsg(shutdown_errmsg),
|
2017-09-26 00:11:20 +02:00
|
|
|
m_modchannel_mgr(new ModChannelMgr())
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2018-06-13 21:58:34 +02:00
|
|
|
if (m_path_world.empty())
|
2012-03-11 19:45:43 +01:00
|
|
|
throw ServerError("Supplied empty world path");
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2018-06-13 21:58:34 +02:00
|
|
|
if (!gamespec.isValid())
|
2012-03-11 13:54:23 +01:00
|
|
|
throw ServerError("Supplied invalid gamespec");
|
2020-04-27 08:31:37 +02:00
|
|
|
|
|
|
|
#if USE_PROMETHEUS
|
2023-01-14 13:11:15 +01:00
|
|
|
if (!simple_singleplayer_mode)
|
|
|
|
m_metrics_backend = std::unique_ptr<MetricsBackend>(createPrometheusMetricsBackend());
|
|
|
|
else
|
2020-04-27 08:31:37 +02:00
|
|
|
#else
|
2023-01-14 13:11:15 +01:00
|
|
|
if (true)
|
2020-04-27 08:31:37 +02:00
|
|
|
#endif
|
2023-01-14 13:11:15 +01:00
|
|
|
m_metrics_backend = std::make_unique<MetricsBackend>();
|
2020-04-27 08:31:37 +02:00
|
|
|
|
|
|
|
m_uptime_counter = m_metrics_backend->addCounter("minetest_core_server_uptime", "Server uptime (in seconds)");
|
|
|
|
m_player_gauge = m_metrics_backend->addGauge("minetest_core_player_number", "Number of connected players");
|
|
|
|
|
|
|
|
m_timeofday_gauge = m_metrics_backend->addGauge(
|
|
|
|
"minetest_core_timeofday",
|
|
|
|
"Time of day value");
|
|
|
|
|
|
|
|
m_lag_gauge = m_metrics_backend->addGauge(
|
|
|
|
"minetest_core_latency",
|
|
|
|
"Latency value (in seconds)");
|
|
|
|
|
2022-05-09 21:20:58 +02:00
|
|
|
|
|
|
|
const std::string aom_types[] = {"reliable", "unreliable"};
|
|
|
|
for (u32 i = 0; i < ARRLEN(aom_types); i++) {
|
|
|
|
std::string help_str("Number of active object messages generated (");
|
|
|
|
help_str.append(aom_types[i]).append(")");
|
|
|
|
m_aom_buffer_counter[i] = m_metrics_backend->addCounter(
|
|
|
|
"minetest_core_aom_generated_count", help_str,
|
|
|
|
{{"type", aom_types[i]}});
|
|
|
|
}
|
2020-04-27 08:31:37 +02:00
|
|
|
|
|
|
|
m_packet_recv_counter = m_metrics_backend->addCounter(
|
|
|
|
"minetest_core_server_packet_recv",
|
|
|
|
"Processable packets received");
|
|
|
|
|
|
|
|
m_packet_recv_processed_counter = m_metrics_backend->addCounter(
|
|
|
|
"minetest_core_server_packet_recv_processed",
|
|
|
|
"Valid received packets processed");
|
|
|
|
|
2022-05-09 21:20:58 +02:00
|
|
|
m_map_edit_event_counter = m_metrics_backend->addCounter(
|
|
|
|
"minetest_core_map_edit_events",
|
|
|
|
"Number of map edit events");
|
|
|
|
|
2020-04-27 08:31:37 +02:00
|
|
|
m_lag_gauge->set(g_settings->getFloat("dedicated_server_step"));
|
2024-03-24 18:18:58 +01:00
|
|
|
|
|
|
|
m_path_mod_data = porting::path_user + DIR_DELIM "mod_data";
|
|
|
|
if (!fs::CreateDir(m_path_mod_data))
|
|
|
|
throw ServerError("Failed to create mod data dir");
|
2018-06-13 21:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Server::~Server()
|
|
|
|
{
|
|
|
|
// Send shutdown message
|
|
|
|
SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE,
|
|
|
|
L"*** Server shutting down"));
|
|
|
|
|
2018-07-28 12:58:02 +02:00
|
|
|
actionstream << "Server: Shutting down" << std::endl;
|
2018-06-13 21:58:34 +02:00
|
|
|
|
2024-03-01 20:02:58 +01:00
|
|
|
// Stop server step from happening
|
|
|
|
if (m_thread) {
|
|
|
|
stop();
|
|
|
|
delete m_thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop all emerge activity and finish off mapgen callbacks. Do this before
|
|
|
|
// shutdown callbacks since there may be state that is finalized in a
|
2018-06-13 21:58:34 +02:00
|
|
|
// callback.
|
2024-03-01 20:02:58 +01:00
|
|
|
// Note: The emerge manager is not deleted yet because further code can
|
|
|
|
// still interact with map loading.
|
2018-06-13 21:58:34 +02:00
|
|
|
if (m_emerge)
|
|
|
|
m_emerge->stopThreads();
|
|
|
|
|
|
|
|
if (m_env) {
|
|
|
|
MutexAutoLock envlock(m_env_mutex);
|
|
|
|
|
2024-06-15 16:00:33 +02:00
|
|
|
infostream << "Server: Executing shutdown hooks" << std::endl;
|
2024-03-01 20:02:58 +01:00
|
|
|
try {
|
2024-06-15 16:00:33 +02:00
|
|
|
m_script->on_shutdown();
|
2024-03-01 20:02:58 +01:00
|
|
|
} catch (ModError &e) {
|
|
|
|
addShutdownError(e);
|
|
|
|
}
|
|
|
|
|
2024-06-15 16:00:33 +02:00
|
|
|
infostream << "Server: Saving players" << std::endl;
|
|
|
|
m_env->saveLoadedPlayers();
|
|
|
|
|
|
|
|
infostream << "Server: Kicking players" << std::endl;
|
|
|
|
std::string kick_msg;
|
|
|
|
bool reconnect = false;
|
|
|
|
if (isShutdownRequested()) {
|
|
|
|
reconnect = m_shutdown_state.should_reconnect;
|
|
|
|
kick_msg = m_shutdown_state.message;
|
|
|
|
}
|
|
|
|
if (kick_msg.empty()) {
|
|
|
|
kick_msg = g_settings->get("kick_msg_shutdown");
|
|
|
|
}
|
|
|
|
m_env->saveLoadedPlayers(true);
|
|
|
|
kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
|
|
|
|
kick_msg, reconnect);
|
|
|
|
|
2020-08-23 19:44:25 +02:00
|
|
|
try {
|
2024-06-15 16:00:33 +02:00
|
|
|
// Empty out the environment, this can also invoke callbacks.
|
|
|
|
m_env->deactivateBlocksAndObjects();
|
2020-08-23 19:44:25 +02:00
|
|
|
} catch (ModError &e) {
|
2023-07-03 20:34:02 +02:00
|
|
|
addShutdownError(e);
|
2020-08-23 19:44:25 +02:00
|
|
|
}
|
2018-06-13 21:58:34 +02:00
|
|
|
|
|
|
|
infostream << "Server: Saving environment metadata" << std::endl;
|
|
|
|
m_env->saveMeta();
|
|
|
|
|
2024-03-01 20:02:58 +01:00
|
|
|
// Note that this also deletes and saves the map.
|
|
|
|
delete m_env;
|
|
|
|
m_env = nullptr;
|
2018-06-13 21:58:34 +02:00
|
|
|
}
|
|
|
|
|
2022-01-07 19:28:49 +01:00
|
|
|
// Write any changes before deletion.
|
|
|
|
if (m_mod_storage_database)
|
|
|
|
m_mod_storage_database->endSave();
|
|
|
|
|
2024-01-23 21:15:09 +01:00
|
|
|
// Clean up files
|
|
|
|
for (auto &it : m_media) {
|
|
|
|
if (it.second.delete_at_shutdown) {
|
|
|
|
fs::DeleteSingleFileOrEmptyDirectory(it.second.path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-01 20:02:58 +01:00
|
|
|
// Delete the rest in the reverse order of creation
|
|
|
|
delete m_game_settings;
|
2018-06-13 21:58:34 +02:00
|
|
|
delete m_banmanager;
|
2024-03-01 20:02:58 +01:00
|
|
|
delete m_mod_storage_database;
|
|
|
|
delete m_rollback;
|
2018-06-13 21:58:34 +02:00
|
|
|
delete m_itemdef;
|
|
|
|
delete m_nodedef;
|
|
|
|
delete m_craftdef;
|
|
|
|
|
2019-09-24 19:05:28 +02:00
|
|
|
while (!m_unsent_map_edit_queue.empty()) {
|
|
|
|
delete m_unsent_map_edit_queue.front();
|
|
|
|
m_unsent_map_edit_queue.pop();
|
|
|
|
}
|
2018-06-13 21:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Server::init()
|
|
|
|
{
|
|
|
|
infostream << "Server created for gameid \"" << m_gamespec.id << "\"";
|
|
|
|
if (m_simple_singleplayer_mode)
|
|
|
|
infostream << " in simple singleplayer mode" << std::endl;
|
2012-03-15 14:20:20 +01:00
|
|
|
else
|
2018-06-13 21:58:34 +02:00
|
|
|
infostream << std::endl;
|
|
|
|
infostream << "- world: " << m_path_world << std::endl;
|
|
|
|
infostream << "- game: " << m_gamespec.path << std::endl;
|
2012-03-11 03:15:45 +01:00
|
|
|
|
2020-11-22 17:49:30 +01:00
|
|
|
m_game_settings = Settings::createLayer(SL_GAME);
|
|
|
|
|
2015-01-26 12:44:49 +01:00
|
|
|
// Create world if it doesn't exist
|
2020-07-28 19:16:57 +02:00
|
|
|
try {
|
|
|
|
loadGameConfAndInitWorld(m_path_world,
|
|
|
|
fs::GetFilenameFromPath(m_path_world.c_str()),
|
|
|
|
m_gamespec, false);
|
|
|
|
} catch (const BaseException &e) {
|
|
|
|
throw ServerError(std::string("Failed to initialize world: ") + e.what());
|
|
|
|
}
|
2013-08-11 04:09:45 +02:00
|
|
|
|
2013-03-24 06:43:38 +01:00
|
|
|
// Create emerge manager
|
2024-03-12 14:13:24 +01:00
|
|
|
m_emerge = std::make_unique<EmergeManager>(this, m_metrics_backend.get());
|
2013-08-11 04:09:45 +02:00
|
|
|
|
|
|
|
// Create ban manager
|
2014-06-26 02:28:41 +02:00
|
|
|
std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
|
2013-08-11 04:09:45 +02:00
|
|
|
m_banmanager = new BanManager(ban_path);
|
|
|
|
|
2022-01-07 19:28:49 +01:00
|
|
|
// Create mod storage database and begin a save for later
|
|
|
|
m_mod_storage_database = openModStorageDatabase(m_path_world);
|
|
|
|
m_mod_storage_database->beginSave();
|
|
|
|
|
2022-02-23 20:02:58 +01:00
|
|
|
m_modmgr = std::make_unique<ServerModManager>(m_path_world);
|
2022-09-06 12:21:09 +02:00
|
|
|
|
2012-12-08 18:10:54 +01:00
|
|
|
// complain about mods with unsatisfied dependencies
|
2018-03-16 08:41:33 +01:00
|
|
|
if (!m_modmgr->isConsistent()) {
|
2022-08-19 13:31:36 +02:00
|
|
|
std::string error = m_modmgr->getUnsatisfiedModsError();
|
|
|
|
throw ServerError(error);
|
2012-12-08 18:10:54 +01:00
|
|
|
}
|
|
|
|
|
2015-04-07 12:13:12 +02:00
|
|
|
//lock environment
|
|
|
|
MutexAutoLock envlock(m_env_mutex);
|
2012-03-10 14:56:24 +01:00
|
|
|
|
2014-12-30 18:30:14 +01:00
|
|
|
// Create the Map (loads map_meta.txt, overriding configured mapgen params)
|
2024-03-12 14:13:24 +01:00
|
|
|
auto startup_server_map = std::make_unique<ServerMap>(m_path_world, this,
|
|
|
|
m_emerge.get(), m_metrics_backend.get());
|
2014-12-30 18:30:14 +01:00
|
|
|
|
2011-11-11 18:33:17 +01:00
|
|
|
// Initialize scripting
|
2018-06-13 21:58:34 +02:00
|
|
|
infostream << "Server: Initializing Lua" << std::endl;
|
2013-05-25 00:51:02 +02:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
m_script = std::make_unique<ServerScripting>(this);
|
2013-05-25 00:51:02 +02:00
|
|
|
|
2020-05-07 22:38:41 +02:00
|
|
|
// Must be created before mod loading because we have some inventory creation
|
2022-02-23 20:02:58 +01:00
|
|
|
m_inventory_mgr = std::make_unique<ServerInventoryManager>();
|
2020-05-07 22:38:41 +02:00
|
|
|
|
2024-03-03 19:51:49 +01:00
|
|
|
m_script->loadBuiltin();
|
2014-04-27 23:55:49 +02:00
|
|
|
|
2022-05-21 17:23:30 +02:00
|
|
|
m_gamespec.checkAndLog();
|
2024-03-12 14:13:24 +01:00
|
|
|
m_modmgr->loadMods(*m_script);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2022-12-30 15:04:46 +01:00
|
|
|
m_script->saveGlobals();
|
|
|
|
|
2012-01-02 12:31:50 +01:00
|
|
|
// Read Textures and calculate sha1 sums
|
2012-03-25 10:50:29 +02:00
|
|
|
fillMediaCache();
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2012-01-12 06:10:39 +01:00
|
|
|
// Apply item aliases in the node definition manager
|
|
|
|
m_nodedef->updateAliases(m_itemdef);
|
|
|
|
|
2015-03-30 12:55:29 +02:00
|
|
|
// Apply texture overrides from texturepack/override.txt
|
2017-06-23 02:51:57 +02:00
|
|
|
std::vector<std::string> paths;
|
|
|
|
fs::GetRecursiveDirs(paths, g_settings->get("texture_path"));
|
|
|
|
fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
|
2020-04-14 20:41:29 +02:00
|
|
|
for (const std::string &path : paths) {
|
|
|
|
TextureOverrideSource override_source(path + DIR_DELIM + "override.txt");
|
|
|
|
m_nodedef->applyTextureOverrides(override_source.getNodeTileOverrides());
|
|
|
|
m_itemdef->applyTextureOverrides(override_source.getItemTextureOverrides());
|
|
|
|
}
|
2015-03-30 12:55:29 +02:00
|
|
|
|
2015-01-04 22:32:31 +01:00
|
|
|
m_nodedef->setNodeRegistrationStatus(true);
|
|
|
|
|
2014-10-08 21:28:14 +02:00
|
|
|
// Perform pending node name resolutions
|
2015-04-16 10:12:26 +02:00
|
|
|
m_nodedef->runNodeResolveCallbacks();
|
2014-10-08 21:28:14 +02:00
|
|
|
|
2020-05-20 23:52:10 +02:00
|
|
|
// unmap node names in cross-references
|
|
|
|
m_nodedef->resolveCrossrefs();
|
Nodebox: Allow nodeboxes to "connect"
We introduce a new nodebox type "connected", and allow these nodes to
have optional nodeboxes that connect it to other connecting nodeboxes.
This is all done at scenedraw time in the client. The client will
inspect the surrounding nodes and if they are to be connected to,
it will draw the appropriate connecting nodeboxes to make those
connections.
In the node_box definition, we have to specify separate nodeboxes for
each valid connection. This allows us to make nodes that connect only
horizontally (the common case) by providing optional nodeboxes for +x,
-x, +z, -z directions. Or this allows us to make wires that can connect
up and down, by providing nodeboxes that connect it up and down (+y,
-y) as well.
The optional nodeboxes can be arrays. They are named "connect_top,
"connect_bottom", "connect_front", "connect_left", "connect_back" and
"connect_right". Here, "front" means the south facing side of the node
that has facedir = 0.
Additionally, a "fixed" nodebox list present will always be drawn,
so one can make a central post, for instance. This "fixed" nodebox
can be omitted, or it can be an array of nodeboxes.
Collision boxes are also updated in exactly the same fashion, which
allows you to walk over the upper extremities of the individual
node boxes, or stand really close to them. You can also walk up
node noxes that are small in height, all as expected, and unlike the
NDT_FENCELIKE nodes.
I've posted a screenshot demonstrating the flexibility at
http://i.imgur.com/zaJq8jo.png
In the screenshot, all connecting nodes are of this new subtype.
Transparent textures render incorrectly, Which I don't think is
related to this text, as other nodeboxes also have issues with this.
A protocol bump is performed in order to be able to send older clients
a nodeblock that is usable for them. In order to avoid abuse of users
we send older clients a "full-size" node, so that it's impossible for
them to try and walk through a fence or wall that's created in this
fashion. This was tested with a pre-bump client connected against a
server running the new protocol.
These nodes connect to other nodes, and you can select which ones
those are by specifying node names (or group names) in the
connects_to string array:
connects_to = { "group:fence", "default:wood" }
By default, nodes do not connect to anything, allowing you to create
nodes that always have to be paired in order to connect. lua_api.txt
is updated to reflect the extension to the node_box API.
Example lua code needed to generate these nodes can be found here:
https://gist.github.com/sofar/b381c8c192c8e53e6062
2016-02-25 09:16:31 +01:00
|
|
|
|
2015-04-04 01:33:34 +02:00
|
|
|
// init the recipe hashes to speed up crafting
|
|
|
|
m_craftdef->initHashes(this);
|
|
|
|
|
2013-01-23 04:32:30 +01:00
|
|
|
// Initialize Environment
|
2024-03-12 14:13:24 +01:00
|
|
|
m_env = new ServerEnvironment(std::move(startup_server_map),
|
|
|
|
this, m_metrics_backend.get());
|
2022-09-27 22:22:11 +02:00
|
|
|
m_env->init();
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2020-05-07 22:38:41 +02:00
|
|
|
m_inventory_mgr->setEnv(m_env);
|
2014-01-31 00:24:00 +01:00
|
|
|
m_clients.setEnv(m_env);
|
|
|
|
|
2013-06-27 23:06:52 +02:00
|
|
|
// Initialize mapgens
|
2024-03-12 14:13:24 +01:00
|
|
|
auto &servermap = m_env->getServerMap();
|
|
|
|
if (!servermap.settings_mgr.makeMapgenParams())
|
|
|
|
FATAL_ERROR("Couldn't create any mapgen type");
|
|
|
|
m_emerge->initMapgens(servermap.getMapgenParams());
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2018-03-16 09:12:39 +01:00
|
|
|
if (g_settings->getBool("enable_rollback_recording")) {
|
2015-02-17 20:09:36 +01:00
|
|
|
// Create rollback manager
|
|
|
|
m_rollback = new RollbackManager(m_path_world, this);
|
|
|
|
}
|
|
|
|
|
2011-11-12 01:25:30 +01:00
|
|
|
// Give environment reference to scripting api
|
2013-05-25 00:51:02 +02:00
|
|
|
m_script->initializeEnvironment(m_env);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2022-05-02 20:55:04 +02:00
|
|
|
// Do this after regular script init is done
|
|
|
|
m_script->initAsync();
|
|
|
|
|
2011-05-22 16:00:09 +02:00
|
|
|
// Register us to receive map edit events
|
2024-03-12 14:13:24 +01:00
|
|
|
servermap.addEventReceiver(this);
|
2011-02-23 01:49:57 +01:00
|
|
|
|
2018-03-16 08:52:42 +01:00
|
|
|
m_env->loadMeta();
|
2011-05-22 16:00:09 +02:00
|
|
|
|
2020-05-07 22:38:41 +02:00
|
|
|
// Those settings can be overwritten in world.mt, they are
|
|
|
|
// intended to be cached after environment loading.
|
2013-02-24 15:39:07 +01:00
|
|
|
m_liquid_transform_every = g_settings->getFloat("liquid_update");
|
2016-10-04 18:17:12 +02:00
|
|
|
m_max_chatmessage_length = g_settings->getU16("chat_message_max_size");
|
2018-06-20 22:36:08 +02:00
|
|
|
m_csm_restriction_flags = g_settings->getU64("csm_restriction_flags");
|
|
|
|
m_csm_restriction_noderange = g_settings->getU32("csm_restriction_noderange");
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2017-09-28 13:47:30 +02:00
|
|
|
void Server::start()
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2020-05-07 22:38:41 +02:00
|
|
|
init();
|
|
|
|
|
2017-09-28 13:47:30 +02:00
|
|
|
infostream << "Starting server on " << m_bind_addr.serializeString()
|
|
|
|
<< "..." << std::endl;
|
2012-03-11 19:45:43 +01:00
|
|
|
|
2010-11-27 00:02:21 +01:00
|
|
|
// Stop thread if already running
|
2015-04-07 12:13:12 +02:00
|
|
|
m_thread->stop();
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2010-11-27 00:02:21 +01:00
|
|
|
// Initialize connection
|
2017-08-24 08:28:54 +02:00
|
|
|
m_con->SetTimeoutMs(30);
|
2017-09-28 13:47:30 +02:00
|
|
|
m_con->Serve(m_bind_addr);
|
2010-11-27 00:02:21 +01:00
|
|
|
|
|
|
|
// Start thread
|
2015-04-07 12:13:12 +02:00
|
|
|
m_thread->start();
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2012-03-11 03:15:45 +01:00
|
|
|
// ASCII art for the win!
|
2023-10-08 23:00:49 +02:00
|
|
|
const char *art[] = {
|
|
|
|
" __. __. __. ",
|
|
|
|
" _____ |__| ____ _____ / |_ _____ _____ / |_ ",
|
|
|
|
" / \\| |/ \\ / __ \\ _\\/ __ \\/ __> _\\",
|
|
|
|
"| Y Y \\ | | \\ ___/| | | ___/\\___ \\| | ",
|
|
|
|
"|__|_| / |___| /\\______> | \\______>_____/| | ",
|
|
|
|
" \\/ \\/ \\/ \\/ \\/ "
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!m_admin_chat) {
|
|
|
|
// we're not printing to rawstream to avoid it showing up in the logs.
|
|
|
|
// however it would then mess up the ncurses terminal (m_admin_chat),
|
|
|
|
// so we skip it in that case.
|
|
|
|
for (auto line : art)
|
|
|
|
std::cerr << line << std::endl;
|
|
|
|
}
|
2017-09-28 13:47:30 +02:00
|
|
|
actionstream << "World at [" << m_path_world << "]" << std::endl;
|
|
|
|
actionstream << "Server for gameid=\"" << m_gamespec.id
|
2021-12-29 23:01:26 +01:00
|
|
|
<< "\" listening on ";
|
2022-05-04 20:55:01 +02:00
|
|
|
m_bind_addr.print(actionstream);
|
2021-12-29 23:01:26 +01:00
|
|
|
actionstream << "." << std::endl;
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Server::stop()
|
|
|
|
{
|
2024-03-01 20:02:58 +01:00
|
|
|
infostream<<"Server: Stopping and waiting for threads"<<std::endl;
|
2011-02-21 15:10:36 +01:00
|
|
|
|
2010-11-27 00:02:21 +01:00
|
|
|
// Stop threads (set run=false first so both start stopping)
|
2015-04-07 12:13:12 +02:00
|
|
|
m_thread->stop();
|
|
|
|
m_thread->wait();
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2011-10-16 13:57:53 +02:00
|
|
|
infostream<<"Server: Threads stopped"<<std::endl;
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2023-03-29 11:42:50 +02:00
|
|
|
void Server::step()
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2015-03-17 02:17:27 +01:00
|
|
|
// Throw if fatal error occurred in thread
|
2012-03-11 19:45:43 +01:00
|
|
|
std::string async_err = m_async_fatal_error.get();
|
2015-10-29 19:48:10 +01:00
|
|
|
if (!async_err.empty()) {
|
|
|
|
if (!m_simple_singleplayer_mode) {
|
2024-02-02 22:13:24 +01:00
|
|
|
kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
|
2015-07-17 16:40:41 +02:00
|
|
|
g_settings->get("kick_msg_crash"),
|
|
|
|
g_settings->getBool("ask_reconnect_on_crash"));
|
2015-03-17 09:13:12 +01:00
|
|
|
}
|
2017-01-15 13:36:53 +01:00
|
|
|
throw ServerError("AsyncErr: " + async_err);
|
2012-03-11 19:45:43 +01:00
|
|
|
}
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2023-03-29 11:42:50 +02:00
|
|
|
void Server::AsyncRunStep(float dtime, bool initial_step)
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2011-05-30 23:15:43 +02:00
|
|
|
{
|
|
|
|
// Send blocks to clients
|
|
|
|
SendBlocks(dtime);
|
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2023-12-29 15:08:22 +01:00
|
|
|
// If paused, this function is called with a 0.0f literal
|
|
|
|
if ((dtime == 0.0f) && !initial_step)
|
2010-12-13 20:32:35 +01:00
|
|
|
return;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2019-08-13 19:56:55 +02:00
|
|
|
ScopeProfiler sp(g_profiler, "Server::AsyncRunStep()", SPT_AVG);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2010-12-24 16:08:50 +01:00
|
|
|
/*
|
|
|
|
Update uptime
|
|
|
|
*/
|
2020-04-27 08:31:37 +02:00
|
|
|
m_uptime_counter->increment(dtime);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2014-01-31 00:24:00 +01:00
|
|
|
handlePeerChanges();
|
2011-08-22 20:27:11 +02:00
|
|
|
|
2010-12-20 13:04:31 +01:00
|
|
|
/*
|
2012-03-16 15:34:30 +01:00
|
|
|
Update time of day and overall game time
|
2010-12-20 13:04:31 +01:00
|
|
|
*/
|
2015-03-04 11:46:31 +01:00
|
|
|
m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
|
2011-05-22 16:00:09 +02:00
|
|
|
|
2015-03-04 11:46:31 +01:00
|
|
|
/*
|
|
|
|
Send to clients at constant intervals
|
|
|
|
*/
|
2010-12-20 13:04:31 +01:00
|
|
|
|
2015-03-04 11:46:31 +01:00
|
|
|
m_time_of_day_send_timer -= dtime;
|
2020-04-27 08:31:37 +02:00
|
|
|
if (m_time_of_day_send_timer < 0.0) {
|
2015-03-04 11:46:31 +01:00
|
|
|
m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
|
|
|
|
u16 time = m_env->getTimeOfDay();
|
|
|
|
float time_speed = g_settings->getFloat("time_speed");
|
|
|
|
SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
|
2020-04-27 08:31:37 +02:00
|
|
|
|
|
|
|
m_timeofday_gauge->set(time);
|
2010-12-20 13:04:31 +01:00
|
|
|
}
|
2010-12-13 20:32:35 +01:00
|
|
|
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock lock(m_env_mutex);
|
2013-08-03 22:16:37 +02:00
|
|
|
float max_lag = m_env->getMaxLagEstimate();
|
2024-02-26 20:46:57 +01:00
|
|
|
constexpr float lag_warn_threshold = 2.0f;
|
|
|
|
|
|
|
|
// Decrease value gradually, halve it every minute.
|
|
|
|
if (m_max_lag_decrease.step(dtime, 0.5f)) {
|
|
|
|
// To reproduce this number enter "solve (x)**(60/0.5) = 0.5"
|
|
|
|
// into Wolfram Alpha.
|
|
|
|
max_lag *= 0.99425f;
|
2013-08-03 22:16:37 +02:00
|
|
|
}
|
2024-02-26 20:46:57 +01:00
|
|
|
|
|
|
|
// Report a 20% change to the log but only if we're >10% off target
|
|
|
|
// also report if we crossed into the warning boundary
|
|
|
|
if (dtime >= max_lag * 1.2f ||
|
|
|
|
(max_lag < lag_warn_threshold && dtime >= lag_warn_threshold)) {
|
|
|
|
const float steplen = getStepSettings().steplen;
|
|
|
|
if (dtime > steplen * 1.1f) {
|
|
|
|
auto &to = dtime >= lag_warn_threshold ? warningstream : infostream;
|
|
|
|
to << "Server: Maximum lag peaked at " << dtime
|
|
|
|
<< " (steplen=" << steplen << ")" << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
max_lag = std::max(max_lag, dtime),
|
|
|
|
|
2013-08-03 22:16:37 +02:00
|
|
|
m_env->reportMaxLagEstimate(max_lag);
|
2022-05-09 21:20:58 +02:00
|
|
|
|
2011-06-26 23:27:17 +02:00
|
|
|
// Step environment
|
2011-11-11 18:33:17 +01:00
|
|
|
m_env->step(dtime);
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2014-12-12 09:06:36 +01:00
|
|
|
static const float map_timer_and_unload_dtime = 2.92;
|
2011-06-26 23:27:17 +02:00
|
|
|
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
|
|
|
{
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock lock(m_env_mutex);
|
2011-06-26 23:27:17 +02:00
|
|
|
// Run Map's timers and unload unused data
|
2011-10-12 12:53:38 +02:00
|
|
|
ScopeProfiler sp(g_profiler, "Server: map timer and unload");
|
2011-11-11 18:33:17 +01:00
|
|
|
m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
|
2022-07-09 22:32:08 +02:00
|
|
|
std::max(g_settings->getFloat("server_unload_unused_data_timeout"), 0.0f),
|
|
|
|
-1);
|
2011-06-26 23:27:17 +02:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2023-03-24 12:34:44 +01:00
|
|
|
/*
|
|
|
|
Note: Orphan MapBlock ptrs become dangling after this call.
|
|
|
|
*/
|
|
|
|
m_env->getServerMap().step();
|
|
|
|
|
2015-07-25 07:43:32 +02:00
|
|
|
/*
|
|
|
|
Listen to the admin chat, if available
|
|
|
|
*/
|
|
|
|
if (m_admin_chat) {
|
|
|
|
if (!m_admin_chat->command_queue.empty()) {
|
|
|
|
MutexAutoLock lock(m_env_mutex);
|
|
|
|
while (!m_admin_chat->command_queue.empty()) {
|
|
|
|
ChatEvent *evt = m_admin_chat->command_queue.pop_frontNoEx();
|
2015-11-09 06:04:24 +01:00
|
|
|
handleChatInterfaceEvent(evt);
|
2015-07-25 07:43:32 +02:00
|
|
|
delete evt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_admin_chat->outgoing_queue.push_back(
|
|
|
|
new ChatEventTimeInfo(m_env->getGameTime(), m_env->getTimeOfDay()));
|
|
|
|
}
|
|
|
|
|
2010-11-27 00:02:21 +01:00
|
|
|
/*
|
|
|
|
Do background stuff
|
|
|
|
*/
|
2011-11-26 13:03:56 +01:00
|
|
|
|
|
|
|
/* Transform liquids */
|
2011-01-17 20:15:31 +01:00
|
|
|
m_liquid_transform_timer += dtime;
|
2013-02-24 15:39:07 +01:00
|
|
|
if(m_liquid_transform_timer >= m_liquid_transform_every)
|
2011-01-17 13:57:37 +01:00
|
|
|
{
|
2013-02-24 15:39:07 +01:00
|
|
|
m_liquid_transform_timer -= m_liquid_transform_every;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock lock(m_env_mutex);
|
2011-05-30 23:15:43 +02:00
|
|
|
|
2011-10-12 12:53:38 +02:00
|
|
|
ScopeProfiler sp(g_profiler, "Server: liquid transform");
|
2011-05-30 23:15:43 +02:00
|
|
|
|
2012-12-20 18:19:49 +01:00
|
|
|
std::map<v3s16, MapBlock*> modified_blocks;
|
2022-04-07 21:58:04 +02:00
|
|
|
m_env->getServerMap().transformLiquids(modified_blocks, m_env);
|
2017-08-14 01:06:12 +02:00
|
|
|
|
2018-03-08 22:58:43 +01:00
|
|
|
if (!modified_blocks.empty()) {
|
2022-10-08 16:25:22 +02:00
|
|
|
MapEditEvent event;
|
|
|
|
event.type = MEET_OTHER;
|
2022-12-24 18:21:59 +01:00
|
|
|
event.setModifiedBlocks(modified_blocks);
|
2022-10-08 16:25:22 +02:00
|
|
|
m_env->getMap().dispatchEvent(event);
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
}
|
2014-01-31 00:24:00 +01:00
|
|
|
m_clients.step(dtime);
|
2013-02-21 23:00:44 +01:00
|
|
|
|
2020-09-25 18:52:42 +02:00
|
|
|
// increase/decrease lag gauge gradually
|
|
|
|
if (m_lag_gauge->get() > dtime) {
|
|
|
|
m_lag_gauge->decrement(dtime/100);
|
|
|
|
} else {
|
|
|
|
m_lag_gauge->increment(dtime/100);
|
|
|
|
}
|
2021-09-09 16:51:35 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
float &counter = m_step_pending_dyn_media_timer;
|
|
|
|
counter += dtime;
|
|
|
|
if (counter >= 5.0f) {
|
|
|
|
stepPendingDynMediaCallbacks(counter);
|
|
|
|
counter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-21 23:00:44 +01:00
|
|
|
#if USE_CURL
|
|
|
|
// send masterserver announce
|
|
|
|
{
|
|
|
|
float &counter = m_masterserver_timer;
|
2015-10-15 19:04:15 +02:00
|
|
|
if (!isSingleplayer() && (!counter || counter >= 300.0) &&
|
|
|
|
g_settings->getBool("server_announce")) {
|
|
|
|
ServerList::sendAnnounce(counter ? ServerList::AA_UPDATE :
|
|
|
|
ServerList::AA_START,
|
2015-01-21 20:32:12 +01:00
|
|
|
m_bind_addr.getPort(),
|
2014-06-20 06:59:39 +02:00
|
|
|
m_clients.getPlayerNames(),
|
2020-04-27 08:31:37 +02:00
|
|
|
m_uptime_counter->get(),
|
2014-06-20 06:59:39 +02:00
|
|
|
m_env->getGameTime(),
|
2020-04-27 08:31:37 +02:00
|
|
|
m_lag_gauge->get(),
|
2014-06-20 06:59:39 +02:00
|
|
|
m_gamespec.id,
|
2016-06-25 00:15:56 +02:00
|
|
|
Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
|
2018-03-16 08:41:33 +01:00
|
|
|
m_modmgr->getMods(),
|
2015-10-15 19:04:15 +02:00
|
|
|
m_dedicated);
|
2013-02-21 23:00:44 +01:00
|
|
|
counter = 0.01;
|
|
|
|
}
|
|
|
|
counter += dtime;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-12-18 12:10:37 +01:00
|
|
|
/*
|
2011-02-20 23:45:14 +01:00
|
|
|
Check added and deleted active objects
|
2010-12-18 12:10:37 +01:00
|
|
|
*/
|
|
|
|
{
|
2011-10-16 13:57:53 +02:00
|
|
|
//infostream<<"Server: Checking added and deleted active objects"<<std::endl;
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock envlock(m_env_mutex);
|
2011-05-30 23:15:43 +02:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
{
|
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
|
|
|
const RemoteClientMap &clients = m_clients.getClientList();
|
|
|
|
ScopeProfiler sp(g_profiler, "Server: update objects within range");
|
2014-11-08 14:35:55 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
m_player_gauge->set(clients.size());
|
|
|
|
for (const auto &client_it : clients) {
|
|
|
|
RemoteClient *client = client_it.second;
|
2011-12-02 00:18:25 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
if (client->getState() < CS_DefinitionsSent)
|
|
|
|
continue;
|
2011-12-02 00:18:25 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
// This can happen if the client times out somehow
|
|
|
|
if (!m_env->getPlayer(client->peer_id))
|
|
|
|
continue;
|
2011-02-20 23:45:14 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
PlayerSAO *playersao = getPlayerSAO(client->peer_id);
|
|
|
|
if (!playersao)
|
|
|
|
continue;
|
2016-10-30 14:53:26 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
SendActiveObjectRemoveAdd(client, playersao);
|
|
|
|
}
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
}
|
2017-02-08 00:15:55 +01:00
|
|
|
|
2022-01-07 19:28:49 +01:00
|
|
|
// Write changes to the mod storage
|
2017-02-08 00:15:55 +01:00
|
|
|
m_mod_storage_save_timer -= dtime;
|
|
|
|
if (m_mod_storage_save_timer <= 0.0f) {
|
|
|
|
m_mod_storage_save_timer = g_settings->getFloat("server_map_save_interval");
|
2022-01-07 19:28:49 +01:00
|
|
|
m_mod_storage_database->endSave();
|
|
|
|
m_mod_storage_database->beginSave();
|
2017-02-08 00:15:55 +01:00
|
|
|
}
|
2011-02-20 23:45:14 +01:00
|
|
|
}
|
2010-12-18 12:10:37 +01:00
|
|
|
|
2011-02-20 23:45:14 +01:00
|
|
|
/*
|
|
|
|
Send object messages
|
|
|
|
*/
|
|
|
|
{
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock envlock(m_env_mutex);
|
2019-08-13 19:56:55 +02:00
|
|
|
ScopeProfiler sp(g_profiler, "Server: send SAO messages");
|
2011-05-30 23:15:43 +02:00
|
|
|
|
2011-02-20 23:45:14 +01:00
|
|
|
// Key = object id
|
|
|
|
// Value = data sent by object
|
2017-06-04 21:00:04 +02:00
|
|
|
std::unordered_map<u16, std::vector<ActiveObjectMessage>*> buffered_messages;
|
2011-02-20 23:45:14 +01:00
|
|
|
|
|
|
|
// Get active object messages from environment
|
2020-05-26 17:38:31 +02:00
|
|
|
ActiveObjectMessage aom(0);
|
2022-05-09 21:20:58 +02:00
|
|
|
u32 count_reliable = 0, count_unreliable = 0;
|
2015-03-05 11:18:17 +01:00
|
|
|
for(;;) {
|
2020-05-26 17:38:31 +02:00
|
|
|
if (!m_env->getActiveObjectMessage(&aom))
|
2011-02-20 23:45:14 +01:00
|
|
|
break;
|
2022-05-09 21:20:58 +02:00
|
|
|
if (aom.reliable)
|
|
|
|
count_reliable++;
|
|
|
|
else
|
|
|
|
count_unreliable++;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2017-08-14 00:44:45 +02:00
|
|
|
std::vector<ActiveObjectMessage>* message_list = nullptr;
|
2020-05-26 17:38:31 +02:00
|
|
|
auto n = buffered_messages.find(aom.id);
|
2015-03-05 11:18:17 +01:00
|
|
|
if (n == buffered_messages.end()) {
|
|
|
|
message_list = new std::vector<ActiveObjectMessage>;
|
2012-12-20 18:19:49 +01:00
|
|
|
buffered_messages[aom.id] = message_list;
|
2020-05-26 17:38:31 +02:00
|
|
|
} else {
|
2012-12-20 18:19:49 +01:00
|
|
|
message_list = n->second;
|
2010-12-18 12:10:37 +01:00
|
|
|
}
|
2020-05-26 17:38:31 +02:00
|
|
|
message_list->push_back(std::move(aom));
|
2011-02-20 23:45:14 +01:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2022-05-09 21:20:58 +02:00
|
|
|
m_aom_buffer_counter[0]->increment(count_reliable);
|
|
|
|
m_aom_buffer_counter[1]->increment(count_unreliable);
|
2020-04-27 08:31:37 +02:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
{
|
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
|
|
|
const RemoteClientMap &clients = m_clients.getClientList();
|
|
|
|
// Route data to every client
|
|
|
|
std::string reliable_data, unreliable_data;
|
|
|
|
for (const auto &client_it : clients) {
|
|
|
|
reliable_data.clear();
|
|
|
|
unreliable_data.clear();
|
|
|
|
RemoteClient *client = client_it.second;
|
|
|
|
PlayerSAO *player = getPlayerSAO(client->peer_id);
|
|
|
|
// Go through all objects in message buffer
|
|
|
|
for (const auto &buffered_message : buffered_messages) {
|
|
|
|
// If object does not exist or is not known by client, skip it
|
|
|
|
u16 id = buffered_message.first;
|
|
|
|
ServerActiveObject *sao = m_env->getActiveObject(id);
|
|
|
|
if (!sao || client->m_known_objects.find(id) == client->m_known_objects.end())
|
|
|
|
continue;
|
2015-03-05 11:18:17 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
// Get message list of object
|
|
|
|
std::vector<ActiveObjectMessage>* list = buffered_message.second;
|
|
|
|
// Go through every message
|
|
|
|
for (const ActiveObjectMessage &aom : *list) {
|
|
|
|
// Send position updates to players who do not see the attachment
|
|
|
|
if (aom.datastring[0] == AO_CMD_UPDATE_POSITION) {
|
|
|
|
if (sao->getId() == player->getId())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Do not send position updates for attached players
|
|
|
|
// as long the parent is known to the client
|
|
|
|
ServerActiveObject *parent = sao->getParent();
|
|
|
|
if (parent && client->m_known_objects.find(parent->getId()) !=
|
|
|
|
client->m_known_objects.end())
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add full new data to appropriate buffer
|
|
|
|
std::string &buffer = aom.reliable ? reliable_data : unreliable_data;
|
|
|
|
char idbuf[2];
|
|
|
|
writeU16((u8*) idbuf, aom.id);
|
|
|
|
// u16 id
|
|
|
|
// std::string data
|
|
|
|
buffer.append(idbuf, sizeof(idbuf));
|
|
|
|
buffer.append(serializeString16(aom.datastring));
|
2019-10-02 19:11:27 +02:00
|
|
|
}
|
2011-02-20 23:45:14 +01:00
|
|
|
}
|
2022-02-02 02:49:19 +01:00
|
|
|
/*
|
|
|
|
reliable_data and unreliable_data are now ready.
|
|
|
|
Send them.
|
|
|
|
*/
|
|
|
|
if (!reliable_data.empty()) {
|
|
|
|
SendActiveObjectMessages(client->peer_id, reliable_data);
|
|
|
|
}
|
2011-02-21 15:10:36 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
if (!unreliable_data.empty()) {
|
|
|
|
SendActiveObjectMessages(client->peer_id, unreliable_data, false);
|
|
|
|
}
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
}
|
2011-02-20 23:45:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clear buffered_messages
|
2017-08-14 00:44:45 +02:00
|
|
|
for (auto &buffered_message : buffered_messages) {
|
|
|
|
delete buffered_message.second;
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
2010-12-18 12:10:37 +01:00
|
|
|
}
|
2010-11-27 00:02:21 +01:00
|
|
|
|
2011-02-23 01:49:57 +01:00
|
|
|
/*
|
|
|
|
Send queued-for-sending map edit events.
|
|
|
|
*/
|
|
|
|
{
|
2014-01-31 00:24:00 +01:00
|
|
|
// We will be accessing the environment
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock lock(m_env_mutex);
|
2012-03-28 11:51:47 +02:00
|
|
|
|
2022-05-09 21:20:58 +02:00
|
|
|
// Single change sending is disabled if queue size is big
|
2011-06-26 02:14:52 +02:00
|
|
|
bool disable_single_change_sending = false;
|
|
|
|
if(m_unsent_map_edit_queue.size() >= 4)
|
|
|
|
disable_single_change_sending = true;
|
|
|
|
|
2022-05-09 21:20:58 +02:00
|
|
|
const auto event_count = m_unsent_map_edit_queue.size();
|
|
|
|
m_map_edit_event_counter->increment(event_count);
|
2011-06-26 23:27:17 +02:00
|
|
|
|
|
|
|
// We'll log the amount of each
|
|
|
|
Profiler prof;
|
|
|
|
|
2022-05-26 14:40:00 +02:00
|
|
|
std::unordered_set<v3s16> node_meta_updates;
|
2018-12-04 20:37:48 +01:00
|
|
|
|
2017-08-14 00:44:45 +02:00
|
|
|
while (!m_unsent_map_edit_queue.empty()) {
|
2015-03-04 17:48:07 +01:00
|
|
|
MapEditEvent* event = m_unsent_map_edit_queue.front();
|
|
|
|
m_unsent_map_edit_queue.pop();
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2011-06-25 03:25:14 +02:00
|
|
|
// Players far away from the change are stored here.
|
|
|
|
// Instead of sending the changes, MapBlocks are set not sent
|
|
|
|
// for them.
|
2018-08-16 20:10:34 +02:00
|
|
|
std::unordered_set<u16> far_players;
|
2011-02-23 01:49:57 +01:00
|
|
|
|
2015-03-05 11:18:17 +01:00
|
|
|
switch (event->type) {
|
|
|
|
case MEET_ADDNODE:
|
|
|
|
case MEET_SWAPNODE:
|
2011-06-26 23:27:17 +02:00
|
|
|
prof.add("MEET_ADDNODE", 1);
|
2018-08-16 20:10:34 +02:00
|
|
|
sendAddNode(event->p, event->n, &far_players,
|
|
|
|
disable_single_change_sending ? 5 : 30,
|
2015-03-05 11:18:17 +01:00
|
|
|
event->type == MEET_ADDNODE);
|
|
|
|
break;
|
|
|
|
case MEET_REMOVENODE:
|
2011-06-26 23:27:17 +02:00
|
|
|
prof.add("MEET_REMOVENODE", 1);
|
2018-08-16 20:10:34 +02:00
|
|
|
sendRemoveNode(event->p, &far_players,
|
|
|
|
disable_single_change_sending ? 5 : 30);
|
2015-03-05 11:18:17 +01:00
|
|
|
break;
|
2018-12-04 20:37:48 +01:00
|
|
|
case MEET_BLOCK_NODE_METADATA_CHANGED: {
|
|
|
|
prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
|
|
|
|
if (!event->is_private_change) {
|
2022-05-26 14:40:00 +02:00
|
|
|
node_meta_updates.emplace(event->p);
|
2018-12-04 20:37:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(
|
|
|
|
getNodeBlockPos(event->p))) {
|
|
|
|
block->raiseModified(MOD_STATE_WRITE_NEEDED,
|
|
|
|
MOD_REASON_REPORT_META_CHANGE);
|
|
|
|
}
|
2015-03-05 11:18:17 +01:00
|
|
|
break;
|
2018-12-04 20:37:48 +01:00
|
|
|
}
|
2015-03-05 11:18:17 +01:00
|
|
|
case MEET_OTHER:
|
2011-06-26 23:27:17 +02:00
|
|
|
prof.add("MEET_OTHER", 1);
|
2024-01-23 21:32:36 +01:00
|
|
|
m_clients.markBlocksNotSent(event->modified_blocks);
|
2015-03-05 11:18:17 +01:00
|
|
|
break;
|
|
|
|
default:
|
2011-06-26 23:27:17 +02:00
|
|
|
prof.add("unknown", 1);
|
2015-10-14 07:26:03 +02:00
|
|
|
warningstream << "Server: Unknown MapEditEvent "
|
2015-03-05 11:18:17 +01:00
|
|
|
<< ((u32)event->type) << std::endl;
|
|
|
|
break;
|
2011-02-23 01:49:57 +01:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2011-06-25 03:25:14 +02:00
|
|
|
/*
|
|
|
|
Set blocks not sent to far players
|
|
|
|
*/
|
2024-01-23 21:32:36 +01:00
|
|
|
for (const u16 far_player : far_players) {
|
|
|
|
if (RemoteClient *client = getClient(far_player))
|
|
|
|
client->SetBlocksNotSent(event->modified_blocks);
|
2011-06-25 03:25:14 +02:00
|
|
|
}
|
2011-02-23 01:49:57 +01:00
|
|
|
|
|
|
|
delete event;
|
|
|
|
}
|
2011-06-26 23:27:17 +02:00
|
|
|
|
2017-08-14 00:44:45 +02:00
|
|
|
if (event_count >= 5) {
|
|
|
|
infostream << "Server: MapEditEvents:" << std::endl;
|
2011-10-16 13:57:53 +02:00
|
|
|
prof.print(infostream);
|
2017-08-14 00:44:45 +02:00
|
|
|
} else if (event_count != 0) {
|
|
|
|
verbosestream << "Server: MapEditEvents:" << std::endl;
|
2012-03-11 03:15:45 +01:00
|
|
|
prof.print(verbosestream);
|
2011-06-26 23:27:17 +02:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2018-12-04 20:37:48 +01:00
|
|
|
// Send all metadata updates
|
2022-05-26 14:40:00 +02:00
|
|
|
if (!node_meta_updates.empty())
|
2018-12-04 20:37:48 +01:00
|
|
|
sendMetadataChanged(node_meta_updates);
|
2011-02-23 01:49:57 +01:00
|
|
|
}
|
|
|
|
|
2011-02-05 13:55:16 +01:00
|
|
|
/*
|
2021-12-05 14:40:30 +01:00
|
|
|
Trigger emerge thread
|
|
|
|
Doing this every 2s is left over from old code, unclear if this is still needed.
|
2011-02-05 13:55:16 +01:00
|
|
|
*/
|
2010-11-29 09:52:07 +01:00
|
|
|
{
|
2010-12-19 15:51:45 +01:00
|
|
|
float &counter = m_emergethread_trigger_timer;
|
2021-12-05 14:40:30 +01:00
|
|
|
counter -= dtime;
|
|
|
|
if (counter <= 0.0f) {
|
|
|
|
counter = 2.0f;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2014-01-26 07:12:18 +01:00
|
|
|
m_emerge->startThreads();
|
2010-11-29 09:52:07 +01:00
|
|
|
}
|
|
|
|
}
|
2010-11-27 00:02:21 +01:00
|
|
|
|
2011-05-29 20:11:16 +02:00
|
|
|
// Save map, players and auth stuff
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2010-12-19 15:51:45 +01:00
|
|
|
float &counter = m_savemap_timer;
|
2010-11-27 00:02:21 +01:00
|
|
|
counter += dtime;
|
2017-06-11 13:58:43 +02:00
|
|
|
static thread_local const float save_interval =
|
2015-09-02 21:21:55 +02:00
|
|
|
g_settings->getFloat("server_map_save_interval");
|
|
|
|
if (counter >= save_interval) {
|
2010-11-27 00:02:21 +01:00
|
|
|
counter = 0.0;
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock lock(m_env_mutex);
|
2010-11-27 00:02:21 +01:00
|
|
|
|
2019-08-13 19:56:55 +02:00
|
|
|
ScopeProfiler sp(g_profiler, "Server: map saving (sum)");
|
2011-05-30 23:15:43 +02:00
|
|
|
|
2014-05-30 22:04:07 +02:00
|
|
|
// Save ban file
|
|
|
|
if (m_banmanager->isModified()) {
|
2013-08-11 04:09:45 +02:00
|
|
|
m_banmanager->save();
|
2014-05-30 22:04:07 +02:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2011-11-27 23:45:34 +01:00
|
|
|
// Save changed parts of map
|
|
|
|
m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
|
2011-06-26 23:27:17 +02:00
|
|
|
|
|
|
|
// Save players
|
2014-05-30 22:04:07 +02:00
|
|
|
m_env->saveLoadedPlayers();
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2011-06-26 23:27:17 +02:00
|
|
|
// Save environment metadata
|
2014-05-30 22:04:07 +02:00
|
|
|
m_env->saveMeta();
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
}
|
2017-04-15 23:19:18 +02:00
|
|
|
|
2018-06-13 21:58:34 +02:00
|
|
|
m_shutdown_state.tick(dtime, this);
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2023-03-29 11:42:50 +02:00
|
|
|
void Server::Receive(float timeout)
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2023-03-29 11:42:50 +02:00
|
|
|
const u64 t0 = porting::getTimeUs();
|
|
|
|
const float timeout_us = timeout * 1e6f;
|
|
|
|
auto remaining_time_us = [&]() -> float {
|
|
|
|
return std::max(0.0f, timeout_us - (porting::getTimeUs() - t0));
|
|
|
|
};
|
|
|
|
|
2019-11-14 17:38:15 +01:00
|
|
|
NetworkPacket pkt;
|
|
|
|
session_t peer_id;
|
|
|
|
for (;;) {
|
|
|
|
pkt.clear();
|
|
|
|
peer_id = 0;
|
|
|
|
try {
|
2023-03-29 11:42:50 +02:00
|
|
|
if (!m_con->ReceiveTimeoutMs(&pkt,
|
|
|
|
(u32)remaining_time_us() / 1000)) {
|
|
|
|
// No incoming data.
|
|
|
|
// Already break if there's 1ms left, as ReceiveTimeoutMs is too coarse
|
|
|
|
// and a faster server-step is better than busy waiting.
|
|
|
|
if (remaining_time_us() < 1000.0f)
|
|
|
|
break;
|
2019-11-14 17:38:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
peer_id = pkt.getPeerId();
|
2020-04-27 08:31:37 +02:00
|
|
|
m_packet_recv_counter->increment();
|
2019-11-14 17:38:15 +01:00
|
|
|
ProcessData(&pkt);
|
2020-04-27 08:31:37 +02:00
|
|
|
m_packet_recv_processed_counter->increment();
|
2019-11-14 17:38:15 +01:00
|
|
|
} catch (const con::InvalidIncomingDataException &e) {
|
|
|
|
infostream << "Server::Receive(): InvalidIncomingDataException: what()="
|
|
|
|
<< e.what() << std::endl;
|
|
|
|
} catch (const SerializationError &e) {
|
|
|
|
infostream << "Server::Receive(): SerializationError: what()="
|
|
|
|
<< e.what() << std::endl;
|
|
|
|
} catch (const ClientStateError &e) {
|
2024-01-24 18:23:11 +01:00
|
|
|
errorstream << "ClientStateError: peer=" << peer_id << " what()="
|
2019-11-14 17:38:15 +01:00
|
|
|
<< e.what() << std::endl;
|
2022-04-27 19:55:13 +02:00
|
|
|
DenyAccess(peer_id, SERVER_ACCESSDENIED_UNEXPECTED_DATA);
|
2024-01-24 18:23:11 +01:00
|
|
|
} catch (con::PeerNotFoundException &e) {
|
|
|
|
infostream << "Server: PeerNotFoundException" << std::endl;
|
|
|
|
} catch (ClientNotFoundException &e) {
|
|
|
|
infostream << "Server: ClientNotFoundException" << std::endl;
|
2019-11-14 17:38:15 +01:00
|
|
|
}
|
2015-01-12 17:01:41 +01:00
|
|
|
}
|
|
|
|
}
|
2011-11-29 16:15:18 +01:00
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
|
2015-01-12 17:01:41 +01:00
|
|
|
{
|
2017-08-14 01:06:12 +02:00
|
|
|
std::string playername;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
PlayerSAO *playersao = NULL;
|
2022-02-02 02:49:19 +01:00
|
|
|
{
|
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
|
2017-08-15 09:30:31 +02:00
|
|
|
if (client) {
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
playername = client->getName();
|
2015-07-17 16:40:41 +02:00
|
|
|
playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
}
|
|
|
|
}
|
2012-01-21 00:11:44 +01:00
|
|
|
|
2024-03-10 13:24:35 +01:00
|
|
|
RemotePlayer *player = m_env->getPlayer(playername.c_str(), true);
|
2011-11-29 16:15:18 +01:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
// If failed, cancel
|
2017-08-15 09:30:31 +02:00
|
|
|
if (!playersao || !player) {
|
2017-09-30 12:00:05 +02:00
|
|
|
if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
|
2015-05-19 00:55:58 +02:00
|
|
|
actionstream << "Server: Failed to emerge player \"" << playername
|
2022-11-09 17:57:19 +01:00
|
|
|
<< "\" (player allocated to another client)" << std::endl;
|
2022-04-27 19:55:13 +02:00
|
|
|
DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
} else {
|
2015-05-19 00:55:58 +02:00
|
|
|
errorstream << "Server: " << playername << ": Failed to emerge player"
|
|
|
|
<< std::endl;
|
2022-04-27 19:55:13 +02:00
|
|
|
DenyAccess(peer_id, SERVER_ACCESSDENIED_SERVER_FAIL);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
}
|
2022-04-27 19:55:13 +02:00
|
|
|
return nullptr;
|
2015-01-12 17:01:41 +01:00
|
|
|
}
|
2011-11-29 16:15:18 +01:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
/*
|
|
|
|
Send complete position information
|
|
|
|
*/
|
2024-02-02 22:13:24 +01:00
|
|
|
SendMovePlayer(playersao);
|
2011-11-29 16:15:18 +01:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
// Send privileges
|
|
|
|
SendPlayerPrivileges(peer_id);
|
2011-05-23 21:40:25 +02:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
// Send inventory formspec
|
|
|
|
SendPlayerInventoryFormspec(peer_id);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
// Send inventory
|
2024-02-02 22:13:24 +01:00
|
|
|
SendInventory(player, false);
|
2011-11-29 16:15:18 +01:00
|
|
|
|
2022-01-15 17:44:55 +01:00
|
|
|
// Send HP
|
2022-06-11 20:00:40 +02:00
|
|
|
SendPlayerHP(playersao, false);
|
2022-01-15 17:44:55 +01:00
|
|
|
|
|
|
|
// Send death screen
|
2017-04-07 05:32:50 +02:00
|
|
|
if (playersao->isDead())
|
|
|
|
SendDeathscreen(peer_id, false, v3f(0,0,0));
|
2012-01-12 06:10:39 +01:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
// Send Breath
|
2017-01-01 16:13:01 +01:00
|
|
|
SendPlayerBreath(playersao);
|
2011-05-29 20:11:16 +02:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
/*
|
2022-02-14 21:01:42 +01:00
|
|
|
Update player list and print action
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
*/
|
|
|
|
{
|
2022-02-14 21:01:42 +01:00
|
|
|
NetworkPacket notice_pkt(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
|
|
|
|
notice_pkt << (u8) PLAYER_LIST_ADD << (u16) 1 << std::string(player->getName());
|
|
|
|
m_clients.sendToAll(¬ice_pkt);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::string ip_str = getPeerAddress(player->getPeerId()).serializeString();
|
|
|
|
const auto &names = m_clients.getPlayerNames();
|
2015-01-12 17:01:41 +01:00
|
|
|
|
2020-03-08 18:24:32 +01:00
|
|
|
actionstream << player->getName() << " [" << ip_str << "] joins game. List of players: ";
|
2022-02-14 21:01:42 +01:00
|
|
|
for (const std::string &name : names)
|
2017-08-14 01:06:12 +02:00
|
|
|
actionstream << name << " ";
|
2022-02-14 21:01:42 +01:00
|
|
|
actionstream << player->getName() << std::endl;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
}
|
|
|
|
return playersao;
|
2015-01-12 17:01:41 +01:00
|
|
|
}
|
|
|
|
|
2019-08-25 02:54:21 +02:00
|
|
|
inline void Server::handleCommand(NetworkPacket *pkt)
|
2015-01-12 17:01:41 +01:00
|
|
|
{
|
2019-08-25 02:54:21 +02:00
|
|
|
const ToServerCommandHandler &opHandle = toServerCommandTable[pkt->getCommand()];
|
2015-01-12 17:01:41 +01:00
|
|
|
(this->*opHandle.handler)(pkt);
|
|
|
|
}
|
|
|
|
|
2015-03-31 10:35:51 +02:00
|
|
|
void Server::ProcessData(NetworkPacket *pkt)
|
2015-01-12 17:01:41 +01:00
|
|
|
{
|
|
|
|
// Environment is locked first.
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock envlock(m_env_mutex);
|
2015-01-12 17:01:41 +01:00
|
|
|
|
2019-08-13 19:56:55 +02:00
|
|
|
ScopeProfiler sp(g_profiler, "Server: Process network packet (sum)");
|
2015-03-31 10:35:51 +02:00
|
|
|
u32 peer_id = pkt->getPeerId();
|
2015-01-12 17:01:41 +01:00
|
|
|
|
|
|
|
try {
|
2015-03-31 10:35:51 +02:00
|
|
|
ToServerCommand command = (ToServerCommand) pkt->getCommand();
|
2015-01-12 17:01:41 +01:00
|
|
|
|
|
|
|
// Command must be handled into ToServerCommandHandler
|
|
|
|
if (command >= TOSERVER_NUM_MSG_TYPES) {
|
|
|
|
infostream << "Server: Ignoring unknown command "
|
2024-01-24 18:23:11 +01:00
|
|
|
<< static_cast<unsigned>(command) << std::endl;
|
2015-06-24 22:45:52 +02:00
|
|
|
return;
|
2012-06-01 19:51:15 +02:00
|
|
|
}
|
|
|
|
|
2015-01-12 17:01:41 +01:00
|
|
|
if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
|
2015-03-31 10:35:51 +02:00
|
|
|
handleCommand(pkt);
|
2015-01-12 17:01:41 +01:00
|
|
|
return;
|
|
|
|
}
|
2012-07-26 21:06:45 +02:00
|
|
|
|
2015-01-12 17:01:41 +01:00
|
|
|
u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
|
2012-07-26 21:06:45 +02:00
|
|
|
|
2015-01-12 17:01:41 +01:00
|
|
|
if(peer_ser_ver == SER_FMT_VER_INVALID) {
|
2024-01-24 18:23:11 +01:00
|
|
|
errorstream << "Server: Peer serialization format invalid. "
|
|
|
|
"Skipping incoming command "
|
|
|
|
<< static_cast<unsigned>(command) << std::endl;
|
2015-01-12 17:01:41 +01:00
|
|
|
return;
|
2012-07-26 21:06:45 +02:00
|
|
|
}
|
2015-01-12 17:01:41 +01:00
|
|
|
|
|
|
|
/* Handle commands related to client startup */
|
|
|
|
if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
|
2015-03-31 10:35:51 +02:00
|
|
|
handleCommand(pkt);
|
2015-01-12 17:01:41 +01:00
|
|
|
return;
|
2012-07-22 16:10:58 +02:00
|
|
|
}
|
|
|
|
|
2015-01-12 17:01:41 +01:00
|
|
|
if (m_clients.getClientState(peer_id) < CS_Active) {
|
|
|
|
if (command == TOSERVER_PLAYERPOS) return;
|
|
|
|
|
2024-01-24 18:23:11 +01:00
|
|
|
errorstream << "Server: Got packet command "
|
|
|
|
<< static_cast<unsigned>(command)
|
|
|
|
<< " for peer id " << peer_id
|
|
|
|
<< " but client isn't active yet. Dropping packet." << std::endl;
|
2015-01-12 17:01:41 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-31 10:35:51 +02:00
|
|
|
handleCommand(pkt);
|
2015-05-08 06:51:03 +02:00
|
|
|
} catch (SendFailedException &e) {
|
2015-01-12 17:01:41 +01:00
|
|
|
errorstream << "Server::ProcessData(): SendFailedException: "
|
|
|
|
<< "what=" << e.what()
|
|
|
|
<< std::endl;
|
2015-05-08 06:51:03 +02:00
|
|
|
} catch (PacketError &e) {
|
|
|
|
actionstream << "Server::ProcessData(): PacketError: "
|
|
|
|
<< "what=" << e.what()
|
|
|
|
<< std::endl;
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-11 04:09:45 +02:00
|
|
|
void Server::setTimeOfDay(u32 time)
|
|
|
|
{
|
|
|
|
m_env->setTimeOfDay(time);
|
|
|
|
m_time_of_day_send_timer = 0;
|
|
|
|
}
|
|
|
|
|
2019-09-24 19:05:28 +02:00
|
|
|
void Server::onMapEditEvent(const MapEditEvent &event)
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2019-09-24 19:05:28 +02:00
|
|
|
if (m_ignore_map_edit_events_area.contains(event.getArea()))
|
2012-03-29 00:22:08 +02:00
|
|
|
return;
|
2019-09-24 19:05:28 +02:00
|
|
|
|
|
|
|
m_unsent_map_edit_queue.push(new MapEditEvent(event));
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Server::peerAdded(con::Peer *peer)
|
|
|
|
{
|
2012-03-11 03:15:45 +01:00
|
|
|
verbosestream<<"Server::peerAdded(): peer->id="
|
2010-11-27 00:02:21 +01:00
|
|
|
<<peer->id<<std::endl;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2017-08-15 09:30:31 +02:00
|
|
|
m_peer_change_queue.push(con::PeerChange(con::PEER_ADDED, peer->id, false));
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Server::deletingPeer(con::Peer *peer, bool timeout)
|
|
|
|
{
|
2012-03-11 03:15:45 +01:00
|
|
|
verbosestream<<"Server::deletingPeer(): peer->id="
|
2010-11-27 00:02:21 +01:00
|
|
|
<<peer->id<<", timeout="<<timeout<<std::endl;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2014-06-28 08:02:38 +02:00
|
|
|
m_clients.event(peer->id, CSE_Disconnect);
|
2017-08-15 09:30:31 +02:00
|
|
|
m_peer_change_queue.push(con::PeerChange(con::PEER_REMOVED, peer->id, timeout));
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
bool Server::getClientConInfo(session_t peer_id, con::rtt_stat_type type, float* retval)
|
2014-02-13 20:17:42 +01:00
|
|
|
{
|
2017-08-24 08:28:54 +02:00
|
|
|
*retval = m_con->getPeerStat(peer_id,type);
|
2017-08-14 01:06:12 +02:00
|
|
|
return *retval != -1;
|
2014-02-13 20:17:42 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 20:36:47 +01:00
|
|
|
bool Server::getClientInfo(session_t peer_id, ClientInfo &ret)
|
|
|
|
{
|
2022-02-02 02:49:19 +01:00
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
2014-06-28 08:02:38 +02:00
|
|
|
RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
|
2014-02-13 20:17:42 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
if (!client)
|
2014-02-13 20:17:42 +01:00
|
|
|
return false;
|
|
|
|
|
2021-01-31 20:36:47 +01:00
|
|
|
ret.state = client->getState();
|
|
|
|
ret.addr = client->getAddress();
|
|
|
|
ret.uptime = client->uptime();
|
|
|
|
ret.ser_vers = client->serialization_version;
|
|
|
|
ret.prot_vers = client->net_proto_version;
|
|
|
|
|
|
|
|
ret.major = client->getMajor();
|
|
|
|
ret.minor = client->getMinor();
|
|
|
|
ret.patch = client->getPatch();
|
|
|
|
ret.vers_string = client->getFullVer();
|
2014-02-13 20:17:42 +01:00
|
|
|
|
2021-01-31 20:36:47 +01:00
|
|
|
ret.lang_code = client->getLangCode();
|
2014-02-13 20:17:42 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-02-27 23:58:41 +01:00
|
|
|
const ClientDynamicInfo *Server::getClientDynamicInfo(session_t peer_id)
|
|
|
|
{
|
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
|
|
|
RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
|
|
|
|
|
|
|
|
if (!client)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return &client->getDynamicInfo();
|
|
|
|
}
|
|
|
|
|
2014-01-31 00:24:00 +01:00
|
|
|
void Server::handlePeerChanges()
|
|
|
|
{
|
2017-08-14 01:06:12 +02:00
|
|
|
while(!m_peer_change_queue.empty())
|
2014-01-31 00:24:00 +01:00
|
|
|
{
|
2015-03-04 17:48:07 +01:00
|
|
|
con::PeerChange c = m_peer_change_queue.front();
|
|
|
|
m_peer_change_queue.pop();
|
2014-01-31 00:24:00 +01:00
|
|
|
|
|
|
|
verbosestream<<"Server: Handling peer change: "
|
|
|
|
<<"id="<<c.peer_id<<", timeout="<<c.timeout
|
|
|
|
<<std::endl;
|
|
|
|
|
|
|
|
switch(c.type)
|
|
|
|
{
|
|
|
|
case con::PEER_ADDED:
|
|
|
|
m_clients.CreateClient(c.peer_id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case con::PEER_REMOVED:
|
|
|
|
DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2015-03-06 11:21:51 +01:00
|
|
|
FATAL_ERROR("Invalid peer change event received!");
|
2014-01-31 00:24:00 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2015-07-25 07:43:32 +02:00
|
|
|
void Server::printToConsoleOnly(const std::string &text)
|
|
|
|
{
|
|
|
|
if (m_admin_chat) {
|
|
|
|
m_admin_chat->outgoing_queue.push_back(
|
|
|
|
new ChatEventChat("", utf8_to_wide(text)));
|
|
|
|
} else {
|
2015-11-08 22:23:16 +01:00
|
|
|
std::cout << text << std::endl;
|
2015-07-25 07:43:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-26 00:11:20 +02:00
|
|
|
void Server::Send(NetworkPacket *pkt)
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
{
|
2024-01-24 18:23:11 +01:00
|
|
|
FATAL_ERROR_IF(pkt->getPeerId() == 0, "Server::Send() missing peer ID");
|
2017-09-26 00:11:20 +02:00
|
|
|
Send(pkt->getPeerId(), pkt);
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::Send(session_t peer_id, NetworkPacket *pkt)
|
2017-09-26 00:11:20 +02:00
|
|
|
{
|
2024-01-24 18:23:11 +01:00
|
|
|
m_clients.send(peer_id, pkt);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendMovement(session_t peer_id)
|
2013-02-08 21:54:01 +01:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
|
|
|
|
|
|
|
|
pkt << g_settings->getFloat("movement_acceleration_default");
|
|
|
|
pkt << g_settings->getFloat("movement_acceleration_air");
|
|
|
|
pkt << g_settings->getFloat("movement_acceleration_fast");
|
|
|
|
pkt << g_settings->getFloat("movement_speed_walk");
|
|
|
|
pkt << g_settings->getFloat("movement_speed_crouch");
|
|
|
|
pkt << g_settings->getFloat("movement_speed_fast");
|
|
|
|
pkt << g_settings->getFloat("movement_speed_climb");
|
|
|
|
pkt << g_settings->getFloat("movement_speed_jump");
|
|
|
|
pkt << g_settings->getFloat("movement_liquid_fluidity");
|
|
|
|
pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
|
|
|
|
pkt << g_settings->getFloat("movement_liquid_sink");
|
|
|
|
pkt << g_settings->getFloat("movement_gravity");
|
2013-02-08 21:54:01 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2013-02-08 21:54:01 +01:00
|
|
|
}
|
|
|
|
|
2022-01-15 17:44:55 +01:00
|
|
|
void Server::HandlePlayerHPChange(PlayerSAO *playersao, const PlayerHPChangeReason &reason)
|
2015-07-10 21:58:32 +02:00
|
|
|
{
|
2022-01-15 17:44:55 +01:00
|
|
|
m_script->player_event(playersao, "health_changed");
|
2022-06-11 20:00:40 +02:00
|
|
|
SendPlayerHP(playersao, reason.type != PlayerHPChangeReason::SET_HP_MAX);
|
2015-07-10 21:58:32 +02:00
|
|
|
|
2022-01-15 17:44:55 +01:00
|
|
|
// Send to other clients
|
|
|
|
playersao->sendPunchCommand();
|
2015-07-10 21:58:32 +02:00
|
|
|
|
2022-01-15 17:44:55 +01:00
|
|
|
if (playersao->isDead())
|
|
|
|
HandlePlayerDeath(playersao, reason);
|
|
|
|
}
|
|
|
|
|
2022-06-11 20:00:40 +02:00
|
|
|
void Server::SendPlayerHP(PlayerSAO *playersao, bool effect)
|
2022-01-15 17:44:55 +01:00
|
|
|
{
|
2022-06-11 20:00:40 +02:00
|
|
|
SendHP(playersao->getPeerID(), playersao->getHP(), effect);
|
2015-07-10 21:58:32 +02:00
|
|
|
}
|
|
|
|
|
2022-06-11 20:00:40 +02:00
|
|
|
void Server::SendHP(session_t peer_id, u16 hp, bool effect)
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2022-06-11 20:00:40 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_HP, 3, peer_id);
|
|
|
|
pkt << hp << effect;
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendBreath(session_t peer_id, u16 breath)
|
2013-07-19 19:50:33 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
|
|
|
|
pkt << (u16) breath;
|
|
|
|
Send(&pkt);
|
2013-07-19 19:50:33 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
|
2015-07-17 16:40:41 +02:00
|
|
|
const std::string &custom_reason, bool reconnect)
|
2015-03-13 16:35:21 +01:00
|
|
|
{
|
2015-07-17 16:40:41 +02:00
|
|
|
assert(reason < SERVER_ACCESSDENIED_MAX);
|
2015-03-13 16:35:21 +01:00
|
|
|
|
|
|
|
NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
|
2015-07-17 16:40:41 +02:00
|
|
|
pkt << (u8)reason;
|
|
|
|
if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
|
2015-03-13 16:35:21 +01:00
|
|
|
pkt << custom_reason;
|
2015-07-17 16:40:41 +02:00
|
|
|
else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
|
|
|
|
reason == SERVER_ACCESSDENIED_CRASH)
|
|
|
|
pkt << custom_reason << (u8)reconnect;
|
2015-03-13 16:35:21 +01:00
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
|
2014-01-31 00:24:00 +01:00
|
|
|
v3f camera_point_target)
|
2011-10-15 13:46:59 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
|
|
|
|
pkt << set_camera_point_target << camera_point_target;
|
|
|
|
Send(&pkt);
|
2011-10-15 13:46:59 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendItemDef(session_t peer_id,
|
2013-03-28 21:40:44 +01:00
|
|
|
IItemDefManager *itemdef, u16 protocol_version)
|
2011-11-15 00:00:16 +01:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
|
2011-11-15 00:00:16 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
u16 command
|
|
|
|
u32 length of the next item
|
2012-01-12 06:10:39 +01:00
|
|
|
zlib-compressed serialized ItemDefManager
|
2011-11-15 00:00:16 +01:00
|
|
|
*/
|
|
|
|
std::ostringstream tmp_os(std::ios::binary);
|
2013-03-28 21:40:44 +01:00
|
|
|
itemdef->serialize(tmp_os, protocol_version);
|
2012-01-12 06:10:39 +01:00
|
|
|
std::ostringstream tmp_os2(std::ios::binary);
|
|
|
|
compressZlib(tmp_os.str(), tmp_os2);
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt.putLongString(tmp_os2.str());
|
2011-11-15 00:00:16 +01:00
|
|
|
|
|
|
|
// Make data buffer
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
verbosestream << "Server: Sending item definitions to id(" << peer_id
|
2015-03-13 22:01:49 +01:00
|
|
|
<< "): size=" << pkt.getSize() << std::endl;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2011-11-15 19:32:56 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendNodeDef(session_t peer_id,
|
2018-02-10 21:04:16 +01:00
|
|
|
const NodeDefManager *nodedef, u16 protocol_version)
|
2011-11-15 19:32:56 +01:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
|
2011-11-15 19:32:56 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
u16 command
|
|
|
|
u32 length of the next item
|
2012-01-12 06:10:39 +01:00
|
|
|
zlib-compressed serialized NodeDefManager
|
2011-11-15 19:32:56 +01:00
|
|
|
*/
|
|
|
|
std::ostringstream tmp_os(std::ios::binary);
|
2012-11-26 22:59:03 +01:00
|
|
|
nodedef->serialize(tmp_os, protocol_version);
|
2012-01-12 06:10:39 +01:00
|
|
|
std::ostringstream tmp_os2(std::ios::binary);
|
|
|
|
compressZlib(tmp_os.str(), tmp_os2);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt.putLongString(tmp_os2.str());
|
2011-11-15 19:32:56 +01:00
|
|
|
|
|
|
|
// Make data buffer
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
verbosestream << "Server: Sending node definitions to id(" << peer_id
|
2015-03-13 22:01:49 +01:00
|
|
|
<< "): size=" << pkt.getSize() << std::endl;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2011-11-15 00:00:16 +01:00
|
|
|
}
|
|
|
|
|
2011-04-21 18:35:17 +02:00
|
|
|
/*
|
|
|
|
Non-static send methods
|
|
|
|
*/
|
|
|
|
|
2024-02-02 22:13:24 +01:00
|
|
|
void Server::SendInventory(RemotePlayer *player, bool incremental)
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2019-08-24 19:07:38 +02:00
|
|
|
// Do not send new format to old clients
|
|
|
|
incremental &= player->protocol_version >= 38;
|
|
|
|
|
|
|
|
UpdateCrafting(player);
|
2011-11-29 22:18:20 +01:00
|
|
|
|
2010-12-22 15:30:23 +01:00
|
|
|
/*
|
2011-04-21 18:35:17 +02:00
|
|
|
Serialize it
|
2010-12-22 15:30:23 +01:00
|
|
|
*/
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2024-02-02 22:13:24 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_INVENTORY, 0, player->getPeerId());
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2019-08-24 19:07:38 +02:00
|
|
|
std::ostringstream os(std::ios::binary);
|
2024-02-02 22:13:24 +01:00
|
|
|
player->inventory.serialize(os, incremental);
|
|
|
|
player->inventory.setModified(false);
|
2019-08-24 19:07:38 +02:00
|
|
|
player->setModified(true);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
pkt.putRawString(os.str());
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2017-07-16 10:47:31 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
|
|
|
|
u8 version = 1;
|
|
|
|
u8 type = message.type;
|
2021-01-29 15:24:07 +01:00
|
|
|
pkt << version << type << message.sender << message.message
|
|
|
|
<< static_cast<u64>(message.timestamp);
|
2017-07-16 10:47:31 +02:00
|
|
|
|
2017-06-09 21:39:25 +02:00
|
|
|
if (peer_id != PEER_ID_INEXISTENT) {
|
2017-07-16 10:47:31 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
|
|
|
if (!player)
|
|
|
|
return;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2017-09-12 19:48:09 +02:00
|
|
|
Send(&pkt);
|
2017-06-09 21:39:25 +02:00
|
|
|
} else {
|
2017-09-12 19:48:09 +02:00
|
|
|
m_clients.sendToAll(&pkt);
|
2014-01-31 00:24:00 +01:00
|
|
|
}
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
2013-04-14 00:20:22 +02:00
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
|
2019-08-08 18:04:46 +02:00
|
|
|
const std::string &formname)
|
2013-01-02 20:45:04 +01:00
|
|
|
{
|
2019-09-10 21:18:42 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0, peer_id);
|
2017-08-14 01:06:12 +02:00
|
|
|
if (formspec.empty()){
|
2023-03-19 20:23:11 +01:00
|
|
|
// The client should close the formspec
|
|
|
|
// But make sure there wasn't another one open in meantime
|
|
|
|
// If the formname is empty, any open formspec will be closed so the
|
|
|
|
// form name should always be erased from the state.
|
2019-01-21 09:53:09 +01:00
|
|
|
const auto it = m_formspec_state_data.find(peer_id);
|
2023-03-19 20:23:11 +01:00
|
|
|
if (it != m_formspec_state_data.end() &&
|
|
|
|
(it->second == formname || formname.empty())) {
|
2019-01-21 09:53:09 +01:00
|
|
|
m_formspec_state_data.erase(peer_id);
|
|
|
|
}
|
2016-11-22 17:15:22 +01:00
|
|
|
pkt.putLongString("");
|
|
|
|
} else {
|
2018-02-18 22:33:42 +01:00
|
|
|
m_formspec_state_data[peer_id] = formname;
|
2019-09-10 21:18:42 +02:00
|
|
|
pkt.putLongString(formspec);
|
2016-11-22 17:15:22 +01:00
|
|
|
}
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << formname;
|
2013-01-02 20:45:04 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2013-01-02 20:45:04 +01:00
|
|
|
}
|
2011-04-11 20:28:04 +02:00
|
|
|
|
2013-01-23 18:32:02 +01:00
|
|
|
// Spawns a particle on peer with peer_id
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
|
2020-05-22 13:23:25 +02:00
|
|
|
const ParticleParameters &p)
|
2013-01-23 18:32:02 +01:00
|
|
|
{
|
2017-06-11 13:58:43 +02:00
|
|
|
static thread_local const float radius =
|
2017-05-17 10:37:28 +02:00
|
|
|
g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
|
|
|
|
|
2017-01-14 16:48:49 +01:00
|
|
|
if (peer_id == PEER_ID_INEXISTENT) {
|
2017-09-27 23:48:06 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
2020-05-22 13:23:25 +02:00
|
|
|
const v3f pos = p.pos * BS;
|
|
|
|
const float radius_sq = radius * radius;
|
2017-05-17 10:37:28 +02:00
|
|
|
|
2017-09-27 23:48:06 +02:00
|
|
|
for (const session_t client_id : clients) {
|
2017-08-14 01:06:12 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(client_id);
|
2017-01-14 16:48:49 +01:00
|
|
|
if (!player)
|
|
|
|
continue;
|
2017-05-17 10:37:28 +02:00
|
|
|
|
|
|
|
PlayerSAO *sao = player->getPlayerSAO();
|
|
|
|
if (!sao)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Do not send to distant clients
|
2020-05-22 13:23:25 +02:00
|
|
|
if (sao->getBasePosition().getDistanceFromSQ(pos) > radius_sq)
|
2017-05-17 10:37:28 +02:00
|
|
|
continue;
|
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
SendSpawnParticle(client_id, player->protocol_version, p);
|
2017-01-14 16:48:49 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2020-05-22 13:23:25 +02:00
|
|
|
assert(protocol_version != 0);
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
{
|
|
|
|
// NetworkPacket and iostreams are incompatible...
|
|
|
|
std::ostringstream oss(std::ios_base::binary);
|
|
|
|
p.serialize(oss, protocol_version);
|
|
|
|
pkt.putRawString(oss.str());
|
|
|
|
}
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2017-01-14 16:48:49 +01:00
|
|
|
Send(&pkt);
|
2013-01-23 18:32:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Adds a ParticleSpawner on peer with peer_id
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
|
2020-05-22 13:23:25 +02:00
|
|
|
const ParticleSpawnerParameters &p, u16 attached_id, u32 id)
|
2013-01-23 18:32:02 +01:00
|
|
|
{
|
2020-05-22 15:25:47 +02:00
|
|
|
static thread_local const float radius =
|
|
|
|
g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
|
|
|
|
|
2017-01-14 16:48:49 +01:00
|
|
|
if (peer_id == PEER_ID_INEXISTENT) {
|
2017-09-27 23:48:06 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
2022-07-13 11:57:12 +02:00
|
|
|
const v3f pos = (
|
|
|
|
p.pos.start.min.val +
|
|
|
|
p.pos.start.max.val +
|
|
|
|
p.pos.end.min.val +
|
|
|
|
p.pos.end.max.val
|
|
|
|
) / 4.0f * BS;
|
2020-05-22 15:25:47 +02:00
|
|
|
const float radius_sq = radius * radius;
|
|
|
|
/* Don't send short-lived spawners to distant players.
|
2023-09-02 22:58:11 +02:00
|
|
|
* This could be replaced with proper tracking at some point.
|
|
|
|
* A lifetime of 0 means that the spawner exists forever.*/
|
|
|
|
const bool distance_check = !attached_id && p.time <= 1.0f && p.time != 0.0f;
|
2020-05-22 15:25:47 +02:00
|
|
|
|
2017-09-27 23:48:06 +02:00
|
|
|
for (const session_t client_id : clients) {
|
2017-08-14 01:06:12 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(client_id);
|
2017-01-14 16:48:49 +01:00
|
|
|
if (!player)
|
|
|
|
continue;
|
2020-05-22 15:25:47 +02:00
|
|
|
|
|
|
|
if (distance_check) {
|
|
|
|
PlayerSAO *sao = player->getPlayerSAO();
|
|
|
|
if (!sao)
|
|
|
|
continue;
|
|
|
|
if (sao->getBasePosition().getDistanceFromSQ(pos) > radius_sq)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-08-14 01:06:12 +02:00
|
|
|
SendAddParticleSpawner(client_id, player->protocol_version,
|
2020-05-22 13:23:25 +02:00
|
|
|
p, attached_id, id);
|
2017-01-14 16:48:49 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2020-05-22 13:23:25 +02:00
|
|
|
assert(protocol_version != 0);
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 100, peer_id);
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2022-07-13 11:57:12 +02:00
|
|
|
pkt << p.amount << p.time;
|
2023-04-05 20:23:16 +02:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
std::ostringstream os(std::ios_base::binary);
|
2023-04-05 20:23:16 +02:00
|
|
|
if (protocol_version >= 42) {
|
|
|
|
// Serialize entire thing
|
|
|
|
p.pos.serialize(os);
|
|
|
|
p.vel.serialize(os);
|
|
|
|
p.acc.serialize(os);
|
|
|
|
p.exptime.serialize(os);
|
|
|
|
p.size.serialize(os);
|
|
|
|
} else {
|
|
|
|
// serialize legacy fields only (compatibility)
|
2022-07-13 11:57:12 +02:00
|
|
|
p.pos.start.legacySerialize(os);
|
|
|
|
p.vel.start.legacySerialize(os);
|
|
|
|
p.acc.start.legacySerialize(os);
|
|
|
|
p.exptime.start.legacySerialize(os);
|
|
|
|
p.size.start.legacySerialize(os);
|
|
|
|
}
|
2024-03-12 14:13:24 +01:00
|
|
|
pkt.putRawString(os.str());
|
2022-07-13 11:57:12 +02:00
|
|
|
pkt << p.collisiondetection;
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2022-07-13 11:57:12 +02:00
|
|
|
pkt.putLongString(p.texture.string);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
pkt << id << p.vertical << p.collision_removal << attached_id;
|
|
|
|
{
|
2024-03-12 14:13:24 +01:00
|
|
|
os.str("");
|
2020-05-22 13:23:25 +02:00
|
|
|
p.animation.serialize(os, protocol_version);
|
|
|
|
pkt.putRawString(os.str());
|
|
|
|
}
|
|
|
|
pkt << p.glow << p.object_collision;
|
2020-05-22 14:17:03 +02:00
|
|
|
pkt << p.node.param0 << p.node.param2 << p.node_tile;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2022-07-13 11:57:12 +02:00
|
|
|
{ // serialize new fields
|
2024-03-12 14:13:24 +01:00
|
|
|
os.str("");
|
2023-04-05 20:23:16 +02:00
|
|
|
if (protocol_version < 42) {
|
|
|
|
// initial bias for older properties
|
|
|
|
pkt << p.pos.start.bias
|
|
|
|
<< p.vel.start.bias
|
|
|
|
<< p.acc.start.bias
|
|
|
|
<< p.exptime.start.bias
|
|
|
|
<< p.size.start.bias;
|
|
|
|
|
|
|
|
// final tween frames of older properties
|
|
|
|
p.pos.end.serialize(os);
|
|
|
|
p.vel.end.serialize(os);
|
|
|
|
p.acc.end.serialize(os);
|
|
|
|
p.exptime.end.serialize(os);
|
|
|
|
p.size.end.serialize(os);
|
|
|
|
}
|
|
|
|
// else: fields are already written by serialize() very early
|
2022-07-13 11:57:12 +02:00
|
|
|
|
|
|
|
// properties for legacy texture field
|
|
|
|
p.texture.serialize(os, protocol_version, true);
|
|
|
|
|
|
|
|
// new properties
|
|
|
|
p.drag.serialize(os);
|
|
|
|
p.jitter.serialize(os);
|
|
|
|
p.bounce.serialize(os);
|
|
|
|
ParticleParamTypes::serializeParameterValue(os, p.attractor_kind);
|
|
|
|
if (p.attractor_kind != ParticleParamTypes::AttractorKind::none) {
|
|
|
|
p.attract.serialize(os);
|
|
|
|
p.attractor_origin.serialize(os);
|
|
|
|
writeU16(os, p.attractor_attachment); /* object ID */
|
|
|
|
writeU8(os, p.attractor_kill);
|
|
|
|
if (p.attractor_kind != ParticleParamTypes::AttractorKind::point) {
|
|
|
|
p.attractor_direction.serialize(os);
|
|
|
|
writeU16(os, p.attractor_direction_attachment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.radius.serialize(os);
|
|
|
|
|
|
|
|
ParticleParamTypes::serializeParameterValue(os, (u16)p.texpool.size());
|
|
|
|
for (const auto& tex : p.texpool) {
|
|
|
|
tex.serialize(os, protocol_version);
|
|
|
|
}
|
|
|
|
|
|
|
|
pkt.putRawString(os.str());
|
|
|
|
}
|
|
|
|
|
2017-01-14 16:48:49 +01:00
|
|
|
Send(&pkt);
|
2013-01-23 18:32:02 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
|
2013-01-23 18:32:02 +01:00
|
|
|
{
|
2017-09-12 19:48:09 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER, 4, peer_id);
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2017-09-12 19:48:09 +02:00
|
|
|
pkt << id;
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2017-09-12 19:48:09 +02:00
|
|
|
if (peer_id != PEER_ID_INEXISTENT)
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2017-09-12 19:48:09 +02:00
|
|
|
else
|
2017-04-14 15:34:01 +02:00
|
|
|
m_clients.sendToAll(&pkt);
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2013-01-23 18:32:02 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
|
2013-04-11 20:23:38 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
|
2013-04-11 20:23:38 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << id << (u8) form->type << form->pos << form->name << form->scale
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
<< form->text << form->number << form->item << form->dir
|
2019-11-04 09:30:02 +01:00
|
|
|
<< form->align << form->offset << form->world_pos << form->size
|
2021-07-27 19:11:46 +02:00
|
|
|
<< form->z_index << form->text2 << form->style;
|
2013-04-11 20:23:38 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2013-04-11 20:23:38 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendHUDRemove(session_t peer_id, u32 id)
|
2013-04-11 20:23:38 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
|
|
|
|
pkt << id;
|
|
|
|
Send(&pkt);
|
2013-04-11 20:23:38 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value)
|
2013-04-11 20:23:38 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
|
|
|
|
pkt << id << (u8) stat;
|
2013-04-11 20:23:38 +02:00
|
|
|
|
2013-04-14 00:20:22 +02:00
|
|
|
switch (stat) {
|
|
|
|
case HUD_STAT_POS:
|
|
|
|
case HUD_STAT_SCALE:
|
2013-04-22 11:53:55 +02:00
|
|
|
case HUD_STAT_ALIGN:
|
2013-04-23 01:47:59 +02:00
|
|
|
case HUD_STAT_OFFSET:
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << *(v2f *) value;
|
2013-04-14 00:20:22 +02:00
|
|
|
break;
|
|
|
|
case HUD_STAT_NAME:
|
|
|
|
case HUD_STAT_TEXT:
|
2020-05-11 21:40:45 +02:00
|
|
|
case HUD_STAT_TEXT2:
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << *(std::string *) value;
|
2013-04-14 00:20:22 +02:00
|
|
|
break;
|
2014-01-26 21:31:59 +01:00
|
|
|
case HUD_STAT_WORLD_POS:
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << *(v3f *) value;
|
2014-01-26 21:31:59 +01:00
|
|
|
break;
|
2014-04-28 23:41:27 +02:00
|
|
|
case HUD_STAT_SIZE:
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << *(v2s32 *) value;
|
2014-04-28 23:41:27 +02:00
|
|
|
break;
|
2021-07-27 19:11:46 +02:00
|
|
|
default: // all other types
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << *(u32 *) value;
|
2013-04-14 00:20:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2013-04-11 20:23:38 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2013-04-11 20:23:38 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask)
|
2013-04-24 12:52:46 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
|
2013-04-24 12:52:46 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << flags << mask;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2013-04-24 12:52:46 +02:00
|
|
|
}
|
|
|
|
|
2024-02-29 14:56:13 +01:00
|
|
|
void Server::SendHUDSetParam(session_t peer_id, u16 param, std::string_view value)
|
2013-05-04 02:08:52 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
|
|
|
|
pkt << param << value;
|
|
|
|
Send(&pkt);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
2010-12-25 00:54:39 +01:00
|
|
|
|
2019-08-21 22:47:45 +02:00
|
|
|
void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms)
|
2013-05-02 22:52:50 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
|
2013-05-02 22:52:50 +02:00
|
|
|
|
2019-08-21 22:47:45 +02:00
|
|
|
// Handle prior clients here
|
|
|
|
if (m_clients.getProtocolVersion(peer_id) < 39) {
|
|
|
|
pkt << params.bgcolor << params.type << (u16) params.textures.size();
|
|
|
|
|
|
|
|
for (const std::string& texture : params.textures)
|
|
|
|
pkt << texture;
|
|
|
|
|
|
|
|
pkt << params.clouds;
|
|
|
|
} else { // Handle current clients and future clients
|
|
|
|
pkt << params.bgcolor << params.type
|
2024-01-23 22:33:33 +01:00
|
|
|
<< params.clouds << params.fog_sun_tint
|
|
|
|
<< params.fog_moon_tint << params.fog_tint_type;
|
2019-08-21 22:47:45 +02:00
|
|
|
|
|
|
|
if (params.type == "skybox") {
|
|
|
|
pkt << (u16) params.textures.size();
|
|
|
|
for (const std::string &texture : params.textures)
|
|
|
|
pkt << texture;
|
|
|
|
} else if (params.type == "regular") {
|
2024-01-23 22:33:33 +01:00
|
|
|
auto &c = params.sky_color;
|
|
|
|
pkt << c.day_sky << c.day_horizon << c.dawn_sky << c.dawn_horizon
|
|
|
|
<< c.night_sky << c.night_horizon << c.indoors;
|
2019-08-21 22:47:45 +02:00
|
|
|
}
|
2023-02-26 01:08:33 +01:00
|
|
|
|
2024-01-23 22:33:33 +01:00
|
|
|
pkt << params.body_orbit_tilt << params.fog_distance << params.fog_start
|
|
|
|
<< params.fog_color;
|
2019-08-21 22:47:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Server::SendSetSun(session_t peer_id, const SunParams ¶ms)
|
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_SET_SUN, 0, peer_id);
|
|
|
|
pkt << params.visible << params.texture
|
|
|
|
<< params.tonemap << params.sunrise
|
|
|
|
<< params.sunrise_visible << params.scale;
|
|
|
|
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
void Server::SendSetMoon(session_t peer_id, const MoonParams ¶ms)
|
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_SET_MOON, 0, peer_id);
|
|
|
|
|
|
|
|
pkt << params.visible << params.texture
|
|
|
|
<< params.tonemap << params.scale;
|
|
|
|
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
void Server::SendSetStars(session_t peer_id, const StarParams ¶ms)
|
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_SET_STARS, 0, peer_id);
|
2013-05-02 22:52:50 +02:00
|
|
|
|
2019-08-21 22:47:45 +02:00
|
|
|
pkt << params.visible << params.count
|
2022-07-02 20:57:48 +02:00
|
|
|
<< params.starcolor << params.scale
|
|
|
|
<< params.day_opacity;
|
2017-04-28 04:06:49 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2013-05-02 22:52:50 +02:00
|
|
|
}
|
|
|
|
|
2018-03-08 22:19:25 +01:00
|
|
|
void Server::SendCloudParams(session_t peer_id, const CloudParams ¶ms)
|
2017-03-17 10:39:47 +01:00
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
|
2018-03-08 22:19:25 +01:00
|
|
|
pkt << params.density << params.color_bright << params.color_ambient
|
|
|
|
<< params.height << params.thickness << params.speed;
|
2017-03-17 10:39:47 +01:00
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
|
2013-10-18 10:53:19 +02:00
|
|
|
float ratio)
|
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
1 + 2, peer_id);
|
2013-10-18 10:53:19 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << do_override << (u16) (ratio * 65535);
|
2013-10-18 10:53:19 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2013-10-18 10:53:19 +02:00
|
|
|
}
|
|
|
|
|
2022-03-26 16:58:26 +01:00
|
|
|
void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
|
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_SET_LIGHTING,
|
|
|
|
4, peer_id);
|
2022-11-03 17:35:31 +01:00
|
|
|
|
2022-03-26 16:58:26 +01:00
|
|
|
pkt << lighting.shadow_intensity;
|
2022-12-26 01:15:32 +01:00
|
|
|
pkt << lighting.saturation;
|
2022-03-26 16:58:26 +01:00
|
|
|
|
2023-01-06 22:33:25 +01:00
|
|
|
pkt << lighting.exposure.luminance_min
|
|
|
|
<< lighting.exposure.luminance_max
|
|
|
|
<< lighting.exposure.exposure_correction
|
|
|
|
<< lighting.exposure.speed_dark_bright
|
|
|
|
<< lighting.exposure.speed_bright_dark
|
|
|
|
<< lighting.exposure.center_weight_power;
|
|
|
|
|
2023-10-24 02:05:31 +02:00
|
|
|
pkt << lighting.volumetric_light_strength;
|
|
|
|
|
2022-03-26 16:58:26 +01:00
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
|
2013-08-11 04:09:45 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
|
|
|
|
pkt << time << time_speed;
|
2013-08-11 04:09:45 +02:00
|
|
|
|
2014-01-31 00:24:00 +01:00
|
|
|
if (peer_id == PEER_ID_INEXISTENT) {
|
2017-04-14 15:34:01 +02:00
|
|
|
m_clients.sendToAll(&pkt);
|
2014-01-31 00:24:00 +01:00
|
|
|
}
|
|
|
|
else {
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2014-01-31 00:24:00 +01:00
|
|
|
}
|
2013-08-11 04:09:45 +02:00
|
|
|
}
|
|
|
|
|
2017-01-01 16:13:01 +01:00
|
|
|
void Server::SendPlayerBreath(PlayerSAO *sao)
|
2013-07-19 19:50:33 +02:00
|
|
|
{
|
2017-01-01 16:13:01 +01:00
|
|
|
assert(sao);
|
2015-03-03 16:23:47 +01:00
|
|
|
|
2017-01-01 16:13:01 +01:00
|
|
|
m_script->player_event(sao, "breath_changed");
|
|
|
|
SendBreath(sao->getPeerID(), sao->getBreath());
|
2013-07-19 19:50:33 +02:00
|
|
|
}
|
|
|
|
|
2024-02-02 22:13:24 +01:00
|
|
|
void Server::SendMovePlayer(PlayerSAO *sao)
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2021-02-12 20:54:06 +01:00
|
|
|
// Send attachment updates instantly to the client prior updating position
|
|
|
|
sao->sendOutdatedData();
|
|
|
|
|
2024-02-02 22:13:24 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, sao->getPeerID());
|
2018-11-28 09:38:50 +01:00
|
|
|
pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2016-10-30 14:53:26 +01:00
|
|
|
v3f pos = sao->getBasePosition();
|
2015-03-13 22:01:49 +01:00
|
|
|
verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
|
|
|
|
<< " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
|
2018-11-28 09:38:50 +01:00
|
|
|
<< " pitch=" << sao->getLookPitch()
|
|
|
|
<< " yaw=" << sao->getRotation().Y
|
2015-03-13 22:01:49 +01:00
|
|
|
<< std::endl;
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
2024-01-01 22:48:56 +01:00
|
|
|
void Server::SendMovePlayerRel(session_t peer_id, const v3f &added_pos)
|
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_MOVE_PLAYER_REL, 0, peer_id);
|
|
|
|
pkt << added_pos;
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2018-07-15 02:26:30 +02:00
|
|
|
void Server::SendPlayerFov(session_t peer_id)
|
|
|
|
{
|
2024-03-10 13:24:35 +01:00
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
|
|
|
if (!player)
|
|
|
|
return;
|
|
|
|
|
2020-05-02 12:52:11 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_FOV, 4 + 1 + 4, peer_id);
|
2018-07-15 02:26:30 +02:00
|
|
|
|
2024-03-10 13:24:35 +01:00
|
|
|
PlayerFovSpec fov_spec = player->getFov();
|
2020-05-02 12:52:11 +02:00
|
|
|
pkt << fov_spec.fov << fov_spec.is_multiplier << fov_spec.transition_time;
|
2018-07-15 02:26:30 +02:00
|
|
|
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
|
|
|
|
f32 animation_speed)
|
2014-01-08 13:47:53 +01:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
peer_id);
|
2014-01-08 13:47:53 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
<< animation_frames[3] << animation_speed;
|
2014-01-08 13:47:53 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2014-01-08 13:47:53 +01:00
|
|
|
}
|
|
|
|
|
2023-10-02 13:44:03 +02:00
|
|
|
void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third, v3f third_front)
|
2014-04-11 15:32:46 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
|
2023-10-02 13:44:03 +02:00
|
|
|
pkt << first << third << third_front;
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2014-04-11 15:32:46 +02:00
|
|
|
}
|
2017-09-27 19:47:36 +02:00
|
|
|
|
|
|
|
void Server::SendPlayerPrivileges(session_t peer_id)
|
2012-03-31 15:23:26 +02:00
|
|
|
{
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
2024-03-10 13:24:35 +01:00
|
|
|
if (!player)
|
2012-07-19 13:09:16 +02:00
|
|
|
return;
|
|
|
|
|
2012-03-31 15:23:26 +02:00
|
|
|
std::set<std::string> privs;
|
2013-05-25 00:51:02 +02:00
|
|
|
m_script->getAuth(player->getName(), NULL, &privs);
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
|
|
|
|
pkt << (u16) privs.size();
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2017-08-14 01:06:12 +02:00
|
|
|
for (const std::string &priv : privs) {
|
|
|
|
pkt << priv;
|
2012-03-31 15:23:26 +02:00
|
|
|
}
|
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2012-03-31 15:23:26 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendPlayerInventoryFormspec(session_t peer_id)
|
2012-07-19 13:09:16 +02:00
|
|
|
{
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
2024-03-10 13:24:35 +01:00
|
|
|
if (!player)
|
2012-07-19 13:09:16 +02:00
|
|
|
return;
|
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
|
2019-09-10 21:18:42 +02:00
|
|
|
pkt.putLongString(player->inventory_formspec);
|
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2012-07-19 13:09:16 +02:00
|
|
|
}
|
|
|
|
|
2018-03-28 17:04:41 +02:00
|
|
|
void Server::SendPlayerFormspecPrepend(session_t peer_id)
|
|
|
|
{
|
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
2024-03-10 13:24:35 +01:00
|
|
|
if (!player)
|
2018-03-28 17:04:41 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
|
2019-09-10 21:18:42 +02:00
|
|
|
pkt << player->formspec_prepend;
|
2018-03-28 17:04:41 +02:00
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2019-08-25 02:54:21 +02:00
|
|
|
void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao)
|
2015-03-16 12:01:40 +01:00
|
|
|
{
|
2019-08-25 02:54:21 +02:00
|
|
|
// Radius inside which objects are active
|
|
|
|
static thread_local const s16 radius =
|
|
|
|
g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
|
|
|
|
|
|
|
|
// Radius inside which players are active
|
|
|
|
static thread_local const bool is_transfer_limited =
|
|
|
|
g_settings->exists("unlimited_player_transfer_distance") &&
|
|
|
|
!g_settings->getBool("unlimited_player_transfer_distance");
|
|
|
|
|
|
|
|
static thread_local const s16 player_transfer_dist =
|
|
|
|
g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
|
|
|
|
|
|
|
|
s16 player_radius = player_transfer_dist == 0 && is_transfer_limited ?
|
|
|
|
radius : player_transfer_dist;
|
|
|
|
|
|
|
|
s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
|
|
|
|
if (my_radius <= 0)
|
|
|
|
my_radius = radius;
|
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
std::vector<std::pair<bool, u16>> removed_objects;
|
|
|
|
std::vector<u16> added_objects;
|
2019-08-25 02:54:21 +02:00
|
|
|
m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
|
|
|
|
client->m_known_objects, removed_objects);
|
|
|
|
m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
|
|
|
|
client->m_known_objects, added_objects);
|
|
|
|
|
|
|
|
if (removed_objects.empty() && added_objects.empty())
|
|
|
|
return;
|
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD,
|
|
|
|
2 * removed_objects.size() + 32 * added_objects.size(), client->peer_id);
|
|
|
|
|
|
|
|
// Removed objects
|
|
|
|
pkt << static_cast<u16>(removed_objects.size());
|
2019-08-25 02:54:21 +02:00
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
std::vector<u16> sounds_to_stop;
|
2024-03-06 20:36:02 +01:00
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
for (auto &it : removed_objects) {
|
|
|
|
const auto [gone, id] = it;
|
|
|
|
ServerActiveObject *obj = m_env->getActiveObject(id);
|
2019-08-25 02:54:21 +02:00
|
|
|
|
2024-03-06 20:36:02 +01:00
|
|
|
// Stop sounds if objects go out of range.
|
|
|
|
// This fixes https://github.com/minetest/minetest/issues/8094.
|
|
|
|
// We may not remove sounds if an entity was removed on the server.
|
|
|
|
// See https://github.com/minetest/minetest/issues/14422.
|
|
|
|
if (!gone) // just out of range for client, not gone on server?
|
2024-03-06 18:57:01 +01:00
|
|
|
sounds_to_stop.push_back(id);
|
2024-03-06 20:36:02 +01:00
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
pkt << id;
|
2019-08-25 02:54:21 +02:00
|
|
|
|
|
|
|
// Remove from known objects
|
|
|
|
client->m_known_objects.erase(id);
|
|
|
|
if (obj && obj->m_known_by_count > 0)
|
|
|
|
obj->m_known_by_count--;
|
|
|
|
}
|
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
if (!sounds_to_stop.empty())
|
|
|
|
stopAttachedSounds(client->peer_id, sounds_to_stop);
|
|
|
|
|
|
|
|
// Added objects
|
|
|
|
pkt << static_cast<u16>(added_objects.size());
|
2019-10-02 19:11:27 +02:00
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
for (u16 id : added_objects) {
|
|
|
|
ServerActiveObject *obj = m_env->getActiveObject(id);
|
2019-10-02 19:11:27 +02:00
|
|
|
if (!obj) {
|
2024-03-06 18:57:01 +01:00
|
|
|
warningstream << FUNCTION_NAME << ": found NULL object id="
|
2019-10-02 19:11:27 +02:00
|
|
|
<< (int)id << std::endl;
|
|
|
|
continue;
|
|
|
|
}
|
2019-08-25 02:54:21 +02:00
|
|
|
|
2019-10-02 19:11:27 +02:00
|
|
|
u8 type = obj->getSendType();
|
2019-08-25 02:54:21 +02:00
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
pkt << id << type;
|
|
|
|
pkt.putLongString(obj->getClientInitializationData(client->net_proto_version));
|
2019-08-25 02:54:21 +02:00
|
|
|
|
|
|
|
// Add to known objects
|
|
|
|
client->m_known_objects.insert(id);
|
2019-10-02 19:11:27 +02:00
|
|
|
obj->m_known_by_count++;
|
2019-08-25 02:54:21 +02:00
|
|
|
}
|
|
|
|
|
2015-03-16 12:01:40 +01:00
|
|
|
Send(&pkt);
|
2019-08-25 02:54:21 +02:00
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
verbosestream << "Server::SendActiveObjectRemoveAdd(): "
|
|
|
|
<< removed_objects.size() << " removed, " << added_objects.size()
|
|
|
|
<< " added, packet size is " << pkt.getSize() << std::endl;
|
2015-03-16 12:01:40 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
|
|
|
|
bool reliable)
|
2015-03-16 12:01:40 +01:00
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
|
2015-04-05 11:37:53 +02:00
|
|
|
datas.size(), peer_id);
|
2015-03-16 12:01:40 +01:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
pkt.putRawString(datas);
|
2015-03-17 09:16:39 +01:00
|
|
|
|
2024-01-24 18:23:11 +01:00
|
|
|
auto &ccf = clientCommandFactoryTable[pkt.getCommand()];
|
|
|
|
m_clients.sendCustom(pkt.getPeerId(), reliable ? ccf.channel : 1, &pkt, reliable);
|
2017-07-18 21:39:55 +02:00
|
|
|
}
|
2015-03-17 09:16:39 +01:00
|
|
|
|
2018-06-20 22:36:08 +02:00
|
|
|
void Server::SendCSMRestrictionFlags(session_t peer_id)
|
2017-07-18 21:39:55 +02:00
|
|
|
{
|
2018-06-20 22:36:08 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
|
|
|
|
sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
|
|
|
|
pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
|
2017-07-18 21:39:55 +02:00
|
|
|
Send(&pkt);
|
2015-03-16 12:01:40 +01:00
|
|
|
}
|
|
|
|
|
2019-07-16 14:00:42 +02:00
|
|
|
void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
|
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_PLAYER_SPEED, 0, peer_id);
|
|
|
|
pkt << added_vel;
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2020-01-25 21:19:29 +01:00
|
|
|
inline s32 Server::nextSoundId()
|
|
|
|
{
|
2023-11-29 21:10:19 +01:00
|
|
|
s32 free_id = m_playing_sounds_id_last_used;
|
2023-12-01 00:09:53 +01:00
|
|
|
do {
|
2023-11-29 21:10:19 +01:00
|
|
|
if (free_id == INT32_MAX)
|
|
|
|
free_id = 0; // signed overflow is undefined
|
|
|
|
else
|
|
|
|
free_id++;
|
|
|
|
|
|
|
|
if (free_id == m_playing_sounds_id_last_used)
|
|
|
|
return 0;
|
2023-12-01 00:09:53 +01:00
|
|
|
} while (free_id == 0 || m_playing_sounds.find(free_id) != m_playing_sounds.end());
|
|
|
|
|
2023-11-29 21:10:19 +01:00
|
|
|
m_playing_sounds_id_last_used = free_id;
|
|
|
|
return free_id;
|
2020-01-25 21:19:29 +01:00
|
|
|
}
|
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
s32 Server::playSound(ServerPlayingSound ¶ms, bool ephemeral)
|
2012-03-24 18:01:26 +01:00
|
|
|
{
|
|
|
|
// Find out initial position of sound
|
|
|
|
bool pos_exists = false;
|
2022-07-09 22:32:24 +02:00
|
|
|
const v3f pos = params.getPos(m_env, &pos_exists);
|
2012-03-24 18:01:26 +01:00
|
|
|
// If position is not found while it should be, cancel sound
|
2022-07-09 22:32:24 +02:00
|
|
|
if(pos_exists != (params.type != SoundLocation::Local))
|
2012-03-24 18:01:26 +01:00
|
|
|
return -1;
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2012-03-24 18:01:26 +01:00
|
|
|
// Filter destination clients
|
2017-09-27 23:48:06 +02:00
|
|
|
std::vector<session_t> dst_clients;
|
2020-01-25 21:19:29 +01:00
|
|
|
if (!params.to_player.empty()) {
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
|
2012-03-24 18:01:26 +01:00
|
|
|
if(!player){
|
|
|
|
infostream<<"Server::playSound: Player \""<<params.to_player
|
|
|
|
<<"\" not found"<<std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
2017-09-30 12:00:05 +02:00
|
|
|
dst_clients.push_back(player->getPeerId());
|
2017-08-14 01:06:12 +02:00
|
|
|
} else {
|
2017-09-27 23:48:06 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2017-09-27 23:48:06 +02:00
|
|
|
for (const session_t client_id : clients) {
|
2017-08-14 01:06:12 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(client_id);
|
2016-10-08 16:31:22 +02:00
|
|
|
if (!player)
|
2012-03-24 18:01:26 +01:00
|
|
|
continue;
|
2020-01-25 21:19:29 +01:00
|
|
|
if (!params.exclude_player.empty() &&
|
|
|
|
params.exclude_player == player->getName())
|
|
|
|
continue;
|
2015-03-04 16:30:24 +01:00
|
|
|
|
2016-10-30 14:53:26 +01:00
|
|
|
PlayerSAO *sao = player->getPlayerSAO();
|
|
|
|
if (!sao)
|
|
|
|
continue;
|
|
|
|
|
2016-10-08 16:31:22 +02:00
|
|
|
if (pos_exists) {
|
2016-10-30 14:53:26 +01:00
|
|
|
if(sao->getBasePosition().getDistanceFrom(pos) >
|
2012-03-24 18:01:26 +01:00
|
|
|
params.max_hear_distance)
|
|
|
|
continue;
|
|
|
|
}
|
2017-08-14 01:06:12 +02:00
|
|
|
dst_clients.push_back(client_id);
|
2012-03-24 18:01:26 +01:00
|
|
|
}
|
|
|
|
}
|
2015-03-04 16:30:24 +01:00
|
|
|
|
2014-12-12 15:55:40 +01:00
|
|
|
if(dst_clients.empty())
|
2012-03-24 18:01:26 +01:00
|
|
|
return -1;
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
// old clients will still use this, so pick a reserved ID (-1)
|
|
|
|
const s32 id = ephemeral ? -1 : nextSoundId();
|
2023-11-29 21:10:19 +01:00
|
|
|
if (id == 0)
|
|
|
|
return 0;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
float gain = params.gain * params.spec.gain;
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
|
2022-06-20 21:56:12 +02:00
|
|
|
pkt << id << params.spec.name << gain
|
2016-07-10 07:08:26 +02:00
|
|
|
<< (u8) params.type << pos << params.object
|
2022-06-20 21:56:12 +02:00
|
|
|
<< params.spec.loop << params.spec.fade << params.spec.pitch
|
2023-06-16 20:15:21 +02:00
|
|
|
<< ephemeral << params.spec.start_time;
|
2015-03-05 11:39:05 +01:00
|
|
|
|
2024-01-24 18:23:11 +01:00
|
|
|
const bool as_reliable = !ephemeral;
|
2016-07-10 07:08:26 +02:00
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
for (const session_t peer_id : dst_clients) {
|
|
|
|
if (!ephemeral)
|
|
|
|
params.clients.insert(peer_id);
|
2024-01-24 18:23:11 +01:00
|
|
|
m_clients.sendCustom(peer_id, 0, &pkt, as_reliable);
|
2012-03-24 18:01:26 +01:00
|
|
|
}
|
2022-06-20 21:56:12 +02:00
|
|
|
|
|
|
|
if (!ephemeral)
|
|
|
|
m_playing_sounds[id] = std::move(params);
|
2012-03-24 18:01:26 +01:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
void Server::stopSound(s32 handle)
|
|
|
|
{
|
2022-06-20 21:56:12 +02:00
|
|
|
auto it = m_playing_sounds.find(handle);
|
|
|
|
if (it == m_playing_sounds.end())
|
2012-03-24 18:01:26 +01:00
|
|
|
return;
|
2022-06-20 21:56:12 +02:00
|
|
|
|
|
|
|
ServerPlayingSound &psound = it->second;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
|
|
|
|
pkt << handle;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
for (session_t peer_id : psound.clients) {
|
2024-01-24 18:23:11 +01:00
|
|
|
Send(peer_id, &pkt);
|
2012-03-24 18:01:26 +01:00
|
|
|
}
|
2022-06-20 21:56:12 +02:00
|
|
|
|
2012-03-24 18:01:26 +01:00
|
|
|
// Remove sound reference
|
2022-06-20 21:56:12 +02:00
|
|
|
m_playing_sounds.erase(it);
|
2012-03-24 18:01:26 +01:00
|
|
|
}
|
|
|
|
|
2016-07-10 07:08:26 +02:00
|
|
|
void Server::fadeSound(s32 handle, float step, float gain)
|
|
|
|
{
|
2022-06-20 21:56:12 +02:00
|
|
|
auto it = m_playing_sounds.find(handle);
|
|
|
|
if (it == m_playing_sounds.end())
|
2016-07-10 07:08:26 +02:00
|
|
|
return;
|
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
ServerPlayingSound &psound = it->second;
|
|
|
|
psound.gain = gain; // destination gain
|
2016-07-10 07:08:26 +02:00
|
|
|
|
|
|
|
NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
|
|
|
|
pkt << handle << step << gain;
|
|
|
|
|
2022-06-20 21:56:12 +02:00
|
|
|
for (session_t peer_id : psound.clients) {
|
2024-01-24 18:23:11 +01:00
|
|
|
Send(peer_id, &pkt);
|
2016-07-10 07:08:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove sound reference
|
2022-06-20 21:56:12 +02:00
|
|
|
if (gain <= 0 || psound.clients.empty())
|
|
|
|
m_playing_sounds.erase(it);
|
2016-07-10 07:08:26 +02:00
|
|
|
}
|
|
|
|
|
2024-03-06 18:57:01 +01:00
|
|
|
void Server::stopAttachedSounds(session_t peer_id,
|
|
|
|
const std::vector<u16> &object_ids)
|
2024-02-25 23:10:39 +01:00
|
|
|
{
|
2024-03-06 20:36:02 +01:00
|
|
|
assert(peer_id != PEER_ID_INEXISTENT);
|
2024-03-06 18:57:01 +01:00
|
|
|
assert(!object_ids.empty());
|
2024-02-25 23:10:39 +01:00
|
|
|
|
2024-03-13 21:24:35 +01:00
|
|
|
auto cb = [&] (const s32 id, ServerPlayingSound &sound) -> bool {
|
2024-03-06 18:57:01 +01:00
|
|
|
if (!CONTAINS(object_ids, sound.object))
|
2024-03-13 21:24:35 +01:00
|
|
|
return false;
|
2024-03-06 20:36:02 +01:00
|
|
|
|
|
|
|
auto clients_it = sound.clients.find(peer_id);
|
|
|
|
if (clients_it == sound.clients.end())
|
2024-03-13 21:24:35 +01:00
|
|
|
return false;
|
2024-03-06 20:36:02 +01:00
|
|
|
|
|
|
|
NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
|
2024-03-13 21:24:35 +01:00
|
|
|
pkt << id;
|
2024-03-06 20:36:02 +01:00
|
|
|
Send(peer_id, &pkt);
|
|
|
|
|
|
|
|
sound.clients.erase(clients_it);
|
2024-03-13 21:24:35 +01:00
|
|
|
// delete if client list empty
|
|
|
|
return sound.clients.empty();
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto it = m_playing_sounds.begin(); it != m_playing_sounds.end(); ) {
|
|
|
|
if (cb(it->first, it->second))
|
2024-02-25 23:10:39 +01:00
|
|
|
it = m_playing_sounds.erase(it);
|
|
|
|
else
|
2024-03-06 20:36:02 +01:00
|
|
|
++it;
|
2024-02-25 23:10:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-16 20:10:34 +02:00
|
|
|
void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
|
|
|
|
float far_d_nodes)
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
|
|
|
v3f p_f = intToFloat(p, BS);
|
2018-08-16 20:10:34 +02:00
|
|
|
v3s16 block_pos = getNodeBlockPos(p);
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
|
|
|
|
pkt << p;
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2022-11-03 17:35:31 +01:00
|
|
|
sendNodeChangePkt(pkt, block_pos, p_f, far_d_nodes, far_players);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
2018-08-16 20:10:34 +02:00
|
|
|
void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
|
|
|
|
float far_d_nodes, bool remove_metadata)
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
|
|
|
v3f p_f = intToFloat(p, BS);
|
2018-08-16 20:10:34 +02:00
|
|
|
v3s16 block_pos = getNodeBlockPos(p);
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2018-08-16 20:10:34 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
|
|
|
|
pkt << p << n.param0 << n.param1 << n.param2
|
|
|
|
<< (u8) (remove_metadata ? 0 : 1);
|
2022-11-03 17:35:31 +01:00
|
|
|
sendNodeChangePkt(pkt, block_pos, p_f, far_d_nodes, far_players);
|
|
|
|
}
|
2016-10-30 14:53:26 +01:00
|
|
|
|
2022-11-03 17:35:31 +01:00
|
|
|
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;
|
2018-08-16 20:10:34 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
2022-02-02 02:49:19 +01:00
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2018-08-16 20:10:34 +02:00
|
|
|
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 &&
|
2022-11-03 17:35:31 +01:00
|
|
|
sao->getBasePosition().getDistanceFrom(p) > maxd)) {
|
2018-08-16 20:10:34 +02:00
|
|
|
if (far_players)
|
|
|
|
far_players->emplace(client_id);
|
|
|
|
else
|
|
|
|
client->SetBlockNotSent(block_pos);
|
|
|
|
continue;
|
2013-11-23 15:35:49 +01:00
|
|
|
}
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2024-01-24 18:23:11 +01:00
|
|
|
Send(client_id, &pkt);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-26 14:40:00 +02:00
|
|
|
void Server::sendMetadataChanged(const std::unordered_set<v3s16> &positions, float far_d_nodes)
|
2018-12-04 20:37:48 +01:00
|
|
|
{
|
|
|
|
NodeMetadataList meta_updates_list(false);
|
2022-05-26 14:40:00 +02:00
|
|
|
std::ostringstream os(std::ios::binary);
|
2018-12-04 20:37:48 +01:00
|
|
|
|
2022-05-26 14:40:00 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
2022-02-02 02:49:19 +01:00
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
2018-12-04 20:37:48 +01:00
|
|
|
|
|
|
|
for (session_t i : clients) {
|
|
|
|
RemoteClient *client = m_clients.lockedGetClientNoEx(i);
|
|
|
|
if (!client)
|
|
|
|
continue;
|
|
|
|
|
2022-05-26 14:40:00 +02:00
|
|
|
ServerActiveObject *player = getPlayerSAO(i);
|
|
|
|
v3s16 player_pos;
|
|
|
|
if (player)
|
|
|
|
player_pos = floatToInt(player->getBasePosition(), BS);
|
2018-12-04 20:37:48 +01:00
|
|
|
|
2022-05-26 14:40:00 +02:00
|
|
|
for (const v3s16 pos : positions) {
|
2018-12-04 20:37:48 +01:00
|
|
|
NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos);
|
|
|
|
|
|
|
|
if (!meta)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
v3s16 block_pos = getNodeBlockPos(pos);
|
2022-05-26 14:40:00 +02:00
|
|
|
if (!client->isBlockSent(block_pos) ||
|
|
|
|
player_pos.getDistanceFrom(pos) > far_d_nodes) {
|
2018-12-04 20:37:48 +01:00
|
|
|
client->SetBlockNotSent(block_pos);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the change to send list
|
|
|
|
meta_updates_list.set(pos, meta);
|
|
|
|
}
|
|
|
|
if (meta_updates_list.size() == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Send the meta changes
|
2022-05-26 14:40:00 +02:00
|
|
|
os.str("");
|
2021-09-10 23:16:34 +02:00
|
|
|
meta_updates_list.serialize(os, client->serialization_version, false, true, true);
|
2022-05-26 14:40:00 +02:00
|
|
|
std::string raw = os.str();
|
|
|
|
os.str("");
|
|
|
|
compressZlib(raw, os);
|
2018-12-04 20:37:48 +01:00
|
|
|
|
2022-05-26 14:40:00 +02:00
|
|
|
NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0, i);
|
|
|
|
pkt.putLongString(os.str());
|
|
|
|
Send(&pkt);
|
2018-12-04 20:37:48 +01:00
|
|
|
|
|
|
|
meta_updates_list.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
|
2022-05-05 22:03:49 +02:00
|
|
|
u16 net_proto_version, SerializedBlockCache *cache)
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2020-12-09 23:30:37 +01:00
|
|
|
thread_local const int net_compression_level = rangelim(g_settings->getS16("map_compression_level_net"), -1, 9);
|
2022-05-05 22:03:49 +02:00
|
|
|
std::string s, *sptr = nullptr;
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2022-05-05 22:03:49 +02:00
|
|
|
if (cache) {
|
|
|
|
auto it = cache->find({block->getPos(), ver});
|
|
|
|
if (it != cache->end())
|
|
|
|
sptr = &it->second;
|
|
|
|
}
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2022-05-05 22:03:49 +02:00
|
|
|
// Serialize the block in the right format
|
|
|
|
if (!sptr) {
|
|
|
|
std::ostringstream os(std::ios_base::binary);
|
|
|
|
block->serialize(os, ver, false, net_compression_level);
|
|
|
|
block->serializeNetworkSpecific(os);
|
|
|
|
s = os.str();
|
|
|
|
sptr = &s;
|
|
|
|
}
|
|
|
|
|
|
|
|
NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + sptr->size(), peer_id);
|
2018-03-08 22:58:43 +01:00
|
|
|
pkt << block->getPos();
|
2022-05-05 22:03:49 +02:00
|
|
|
pkt.putRawString(*sptr);
|
2015-03-13 22:01:49 +01:00
|
|
|
Send(&pkt);
|
2022-05-05 22:03:49 +02:00
|
|
|
|
|
|
|
// Store away in cache
|
|
|
|
if (cache && sptr == &s)
|
|
|
|
(*cache)[{block->getPos(), ver}] = std::move(s);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Server::SendBlocks(float dtime)
|
|
|
|
{
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock envlock(m_env_mutex);
|
2014-01-31 00:24:00 +01:00
|
|
|
//TODO check if one big lock could be faster then multiple small ones
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2012-12-20 18:19:49 +01:00
|
|
|
std::vector<PrioritySortedBlockTransfer> queue;
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2022-05-05 22:03:49 +02:00
|
|
|
u32 total_sending = 0, unique_clients = 0;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2019-08-13 19:56:55 +02:00
|
|
|
ScopeProfiler sp2(g_profiler, "Server::SendBlocks(): Collect list");
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2017-09-27 23:48:06 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
2017-09-27 23:48:06 +02:00
|
|
|
for (const session_t client_id : clients) {
|
2017-08-14 00:44:45 +02:00
|
|
|
RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
|
2011-05-30 23:15:43 +02:00
|
|
|
|
2017-08-14 00:44:45 +02:00
|
|
|
if (!client)
|
2014-09-12 02:12:52 +02:00
|
|
|
continue;
|
2011-12-02 00:18:25 +01:00
|
|
|
|
2017-09-09 00:36:48 +02:00
|
|
|
total_sending += client->getSendingCount();
|
2022-05-05 22:03:49 +02:00
|
|
|
const auto old_count = queue.size();
|
2024-03-12 14:13:24 +01:00
|
|
|
client->GetNextBlocks(m_env, m_emerge.get(), dtime, queue);
|
2022-05-05 22:03:49 +02:00
|
|
|
unique_clients += queue.size() > old_count ? 1 : 0;
|
2011-05-30 23:15:43 +02:00
|
|
|
}
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sort.
|
|
|
|
// Lowest priority number comes first.
|
|
|
|
// Lowest is most important.
|
2012-12-20 18:19:49 +01:00
|
|
|
std::sort(queue.begin(), queue.end());
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
2017-09-09 00:36:48 +02:00
|
|
|
|
|
|
|
// Maximal total count calculation
|
|
|
|
// The per-client block sends is halved with the maximal online users
|
|
|
|
u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
|
|
|
|
g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
|
2017-08-18 12:17:30 +02:00
|
|
|
|
2019-08-13 19:56:55 +02:00
|
|
|
ScopeProfiler sp(g_profiler, "Server::SendBlocks(): Send to clients");
|
2019-08-13 20:02:50 +02:00
|
|
|
Map &map = m_env->getMap();
|
|
|
|
|
2022-05-05 22:03:49 +02:00
|
|
|
SerializedBlockCache cache, *cache_ptr = nullptr;
|
|
|
|
if (unique_clients > 1) {
|
|
|
|
// caching is pointless with a single client
|
|
|
|
cache_ptr = &cache;
|
|
|
|
}
|
|
|
|
|
2017-08-18 12:17:30 +02:00
|
|
|
for (const PrioritySortedBlockTransfer &block_to_send : queue) {
|
|
|
|
if (total_sending >= max_blocks_to_send)
|
2011-04-21 18:35:17 +02:00
|
|
|
break;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2019-08-13 20:02:50 +02:00
|
|
|
MapBlock *block = map.getBlockNoCreateNoEx(block_to_send.pos);
|
|
|
|
if (!block)
|
2011-04-21 18:35:17 +02:00
|
|
|
continue;
|
|
|
|
|
2017-08-18 12:17:30 +02:00
|
|
|
RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
|
|
|
|
CS_Active);
|
2017-08-15 09:30:31 +02:00
|
|
|
if (!client)
|
2013-08-04 07:17:07 +02:00
|
|
|
continue;
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2017-08-18 12:17:30 +02:00
|
|
|
SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
|
2022-05-05 22:03:49 +02:00
|
|
|
client->net_proto_version, cache_ptr);
|
2011-04-21 18:35:17 +02:00
|
|
|
|
2017-08-18 12:17:30 +02:00
|
|
|
client->SentBlock(block_to_send.pos);
|
2011-04-21 18:35:17 +02:00
|
|
|
total_sending++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Force send a mapblock to a player (#8140)
* Force send a mapblock to a player.
Send a single mapblock to a specific remote player.
This is badly needed for mods and games where players are teleported
into terrain which may be not generated, loaded, or modified
significantly since the last player visit.
In all these cases, the player currently ends up in void, air, or
inside blocks which not only looks bad, but has the effect that the
player might end up falling and then the server needs to correct for
the player position again later, which is a hack.
The best solution is to send at least the single mapblock that the
player will be teleported to. I've tested this with ITB which does this
all the time, and I can see it functioning as expected (it even shows
a half loaded entry hallway, as the further blocks aren't loaded yet).
The parameter is a blockpos (table of x, y, z), not a regular pos.
The function may return false if the call failed. This is most likely
due to the target position not being generated or emerged yet, or
another internal failure, such as the player not being initialized.
* Always send mapblock on teleport or respawn.
This avoids the need for mods to send a mapblock on teleport or
respawn, since any call to `player:set_pos()` will pass this code.
2019-04-28 01:42:13 +02:00
|
|
|
bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos)
|
|
|
|
{
|
2019-08-13 20:02:50 +02:00
|
|
|
MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
|
Force send a mapblock to a player (#8140)
* Force send a mapblock to a player.
Send a single mapblock to a specific remote player.
This is badly needed for mods and games where players are teleported
into terrain which may be not generated, loaded, or modified
significantly since the last player visit.
In all these cases, the player currently ends up in void, air, or
inside blocks which not only looks bad, but has the effect that the
player might end up falling and then the server needs to correct for
the player position again later, which is a hack.
The best solution is to send at least the single mapblock that the
player will be teleported to. I've tested this with ITB which does this
all the time, and I can see it functioning as expected (it even shows
a half loaded entry hallway, as the further blocks aren't loaded yet).
The parameter is a blockpos (table of x, y, z), not a regular pos.
The function may return false if the call failed. This is most likely
due to the target position not being generated or emerged yet, or
another internal failure, such as the player not being initialized.
* Always send mapblock on teleport or respawn.
This avoids the need for mods to send a mapblock on teleport or
respawn, since any call to `player:set_pos()` will pass this code.
2019-04-28 01:42:13 +02:00
|
|
|
if (!block)
|
|
|
|
return false;
|
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
Force send a mapblock to a player (#8140)
* Force send a mapblock to a player.
Send a single mapblock to a specific remote player.
This is badly needed for mods and games where players are teleported
into terrain which may be not generated, loaded, or modified
significantly since the last player visit.
In all these cases, the player currently ends up in void, air, or
inside blocks which not only looks bad, but has the effect that the
player might end up falling and then the server needs to correct for
the player position again later, which is a hack.
The best solution is to send at least the single mapblock that the
player will be teleported to. I've tested this with ITB which does this
all the time, and I can see it functioning as expected (it even shows
a half loaded entry hallway, as the further blocks aren't loaded yet).
The parameter is a blockpos (table of x, y, z), not a regular pos.
The function may return false if the call failed. This is most likely
due to the target position not being generated or emerged yet, or
another internal failure, such as the player not being initialized.
* Always send mapblock on teleport or respawn.
This avoids the need for mods to send a mapblock on teleport or
respawn, since any call to `player:set_pos()` will pass this code.
2019-04-28 01:42:13 +02:00
|
|
|
RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Active);
|
2022-02-02 02:49:19 +01:00
|
|
|
if (!client || client->isBlockSent(blockpos))
|
Force send a mapblock to a player (#8140)
* Force send a mapblock to a player.
Send a single mapblock to a specific remote player.
This is badly needed for mods and games where players are teleported
into terrain which may be not generated, loaded, or modified
significantly since the last player visit.
In all these cases, the player currently ends up in void, air, or
inside blocks which not only looks bad, but has the effect that the
player might end up falling and then the server needs to correct for
the player position again later, which is a hack.
The best solution is to send at least the single mapblock that the
player will be teleported to. I've tested this with ITB which does this
all the time, and I can see it functioning as expected (it even shows
a half loaded entry hallway, as the further blocks aren't loaded yet).
The parameter is a blockpos (table of x, y, z), not a regular pos.
The function may return false if the call failed. This is most likely
due to the target position not being generated or emerged yet, or
another internal failure, such as the player not being initialized.
* Always send mapblock on teleport or respawn.
This avoids the need for mods to send a mapblock on teleport or
respawn, since any call to `player:set_pos()` will pass this code.
2019-04-28 01:42:13 +02:00
|
|
|
return false;
|
|
|
|
SendBlockNoLock(peer_id, block, client->serialization_version,
|
|
|
|
client->net_proto_version);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-13 19:03:26 +02:00
|
|
|
bool Server::addMediaFile(const std::string &filename,
|
|
|
|
const std::string &filepath, std::string *filedata_to,
|
|
|
|
std::string *digest_to)
|
|
|
|
{
|
|
|
|
// If name contains illegal characters, ignore the file
|
|
|
|
if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
|
2023-08-06 14:16:00 +02:00
|
|
|
warningstream << "Server: ignoring file as it has disallowed characters: \""
|
2020-06-13 19:03:26 +02:00
|
|
|
<< filename << "\"" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// If name is not in a supported format, ignore it
|
|
|
|
const char *supported_ext[] = {
|
2021-09-15 12:12:24 +02:00
|
|
|
".png", ".jpg", ".bmp", ".tga",
|
2020-06-13 19:03:26 +02:00
|
|
|
".ogg",
|
2021-07-29 22:36:25 +02:00
|
|
|
".x", ".b3d", ".obj",
|
2020-06-13 19:03:26 +02:00
|
|
|
// Custom translation file format
|
|
|
|
".tr",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
if (removeStringEnd(filename, supported_ext).empty()) {
|
|
|
|
infostream << "Server: ignoring unsupported file extension: \""
|
|
|
|
<< filename << "\"" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Ok, attempt to load the file and add to cache
|
|
|
|
|
|
|
|
// Read data
|
|
|
|
std::string filedata;
|
2024-05-08 20:37:10 +02:00
|
|
|
if (!fs::ReadFile(filepath, filedata, true)) {
|
2020-06-13 19:03:26 +02:00
|
|
|
return false;
|
2020-09-16 15:51:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (filedata.empty()) {
|
2020-06-13 19:03:26 +02:00
|
|
|
errorstream << "Server::addMediaFile(): Empty file \""
|
|
|
|
<< filepath << "\"" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-10-25 17:18:34 +02:00
|
|
|
const char *deprecated_ext[] = { ".bmp", nullptr };
|
|
|
|
if (!removeStringEnd(filename, deprecated_ext).empty())
|
|
|
|
{
|
|
|
|
warningstream << "Media file \"" << filename << "\" is using a"
|
|
|
|
" deprecated format and will stop working in the future." << std::endl;
|
|
|
|
}
|
|
|
|
|
2020-06-13 19:03:26 +02:00
|
|
|
SHA1 sha1;
|
2024-02-17 15:35:33 +01:00
|
|
|
sha1.addBytes(filedata);
|
2020-06-13 19:03:26 +02:00
|
|
|
|
2024-02-17 15:35:33 +01:00
|
|
|
std::string digest = sha1.getDigest();
|
|
|
|
std::string sha1_base64 = base64_encode(digest);
|
|
|
|
std::string sha1_hex = hex_encode(digest);
|
2020-06-13 19:03:26 +02:00
|
|
|
if (digest_to)
|
2024-02-17 15:35:33 +01:00
|
|
|
*digest_to = digest;
|
2020-06-13 19:03:26 +02:00
|
|
|
|
|
|
|
// Put in list
|
|
|
|
m_media[filename] = MediaInfo(filepath, sha1_base64);
|
|
|
|
verbosestream << "Server: " << sha1_hex << " is " << filename
|
|
|
|
<< std::endl;
|
|
|
|
|
|
|
|
if (filedata_to)
|
|
|
|
*filedata_to = std::move(filedata);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-25 10:50:29 +02:00
|
|
|
void Server::fillMediaCache()
|
2012-03-11 03:15:45 +01:00
|
|
|
{
|
2020-06-13 19:03:26 +02:00
|
|
|
infostream << "Server: Calculating media file checksums" << std::endl;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2012-03-25 11:10:58 +02:00
|
|
|
// Collect all media file paths
|
2015-03-05 11:39:05 +01:00
|
|
|
std::vector<std::string> paths;
|
2021-03-05 16:27:33 +01:00
|
|
|
|
|
|
|
// ordered in descending priority
|
|
|
|
paths.push_back(getBuiltinLuaPath() + DIR_DELIM + "locale");
|
2017-06-23 02:51:57 +02:00
|
|
|
fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
|
2020-08-20 22:25:29 +02:00
|
|
|
fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
|
|
|
|
m_modmgr->getModsMediaPaths(paths);
|
2017-06-23 02:51:57 +02:00
|
|
|
|
2012-03-25 11:10:58 +02:00
|
|
|
// Collect media file information from paths into cache
|
2017-08-19 14:25:35 +02:00
|
|
|
for (const std::string &mediapath : paths) {
|
2012-03-25 11:10:58 +02:00
|
|
|
std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
|
2017-08-19 14:25:35 +02:00
|
|
|
for (const fs::DirListNode &dln : dirlist) {
|
2020-08-20 22:25:29 +02:00
|
|
|
if (dln.dir) // Ignore dirs (already in paths)
|
2012-03-11 03:15:45 +01:00
|
|
|
continue;
|
2020-08-20 22:25:29 +02:00
|
|
|
|
|
|
|
const std::string &filename = dln.name;
|
|
|
|
if (m_media.find(filename) != m_media.end()) // Do not override
|
|
|
|
continue;
|
|
|
|
|
2020-06-13 19:03:26 +02:00
|
|
|
std::string filepath = mediapath;
|
2020-08-20 22:25:29 +02:00
|
|
|
filepath.append(DIR_DELIM).append(filename);
|
|
|
|
addMediaFile(filename, filepath);
|
2012-03-11 03:15:45 +01:00
|
|
|
}
|
2012-01-02 12:31:50 +01:00
|
|
|
}
|
2020-06-13 19:03:26 +02:00
|
|
|
|
|
|
|
infostream << "Server: " << m_media.size() << " media files collected" << std::endl;
|
2012-01-02 12:31:50 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
|
2012-03-25 10:50:29 +02:00
|
|
|
{
|
2024-01-20 13:24:54 +01:00
|
|
|
std::string lang_suffix = ".";
|
|
|
|
lang_suffix.append(lang_code).append(".tr");
|
|
|
|
|
|
|
|
auto include = [&] (const std::string &name, const MediaInfo &info) -> bool {
|
|
|
|
if (info.no_announce)
|
|
|
|
return false;
|
|
|
|
if (str_ends_with(name, ".tr") && !str_ends_with(name, lang_suffix))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2012-03-25 10:50:29 +02:00
|
|
|
// Make packet
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
|
2017-01-31 18:05:03 +01:00
|
|
|
|
|
|
|
u16 media_sent = 0;
|
|
|
|
for (const auto &i : m_media) {
|
2024-01-20 13:24:54 +01:00
|
|
|
if (include(i.first, i.second))
|
|
|
|
media_sent++;
|
2017-01-31 18:05:03 +01:00
|
|
|
}
|
|
|
|
pkt << media_sent;
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2017-08-14 01:06:12 +02:00
|
|
|
for (const auto &i : m_media) {
|
2024-01-20 13:24:54 +01:00
|
|
|
if (include(i.first, i.second))
|
|
|
|
pkt << i.first << i.second.sha1_digest;
|
2012-01-02 12:31:50 +01:00
|
|
|
}
|
|
|
|
|
2015-03-13 22:01:49 +01:00
|
|
|
pkt << g_settings->get("remote_media");
|
|
|
|
Send(&pkt);
|
2020-04-08 20:13:23 +02:00
|
|
|
|
|
|
|
verbosestream << "Server: Announcing files to id(" << peer_id
|
|
|
|
<< "): count=" << media_sent << " size=" << pkt.getSize() << std::endl;
|
2012-01-02 12:31:50 +01:00
|
|
|
}
|
|
|
|
|
2024-01-20 13:24:54 +01:00
|
|
|
namespace {
|
|
|
|
|
2012-03-25 10:50:29 +02:00
|
|
|
struct SendableMedia
|
2011-11-15 10:02:47 +01:00
|
|
|
{
|
2024-01-20 13:24:54 +01:00
|
|
|
const std::string &name;
|
|
|
|
const std::string &path;
|
2011-11-15 10:02:47 +01:00
|
|
|
std::string data;
|
|
|
|
|
2021-09-09 16:51:35 +02:00
|
|
|
SendableMedia(const std::string &name, const std::string &path,
|
|
|
|
std::string &&data):
|
|
|
|
name(name), path(path), data(std::move(data))
|
2011-11-15 10:02:47 +01:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2024-01-20 13:24:54 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::sendRequestedMedia(session_t peer_id,
|
2024-01-19 20:08:55 +01:00
|
|
|
const std::unordered_set<std::string> &tosend)
|
2012-03-25 10:50:29 +02:00
|
|
|
{
|
2024-01-19 20:08:55 +01:00
|
|
|
auto *client = getClient(peer_id, CS_DefinitionsSent);
|
|
|
|
assert(client);
|
|
|
|
|
|
|
|
infostream << "Server::sendRequestedMedia(): Sending "
|
|
|
|
<< tosend.size() << " files to " << client->getName() << std::endl;
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2024-01-20 13:24:54 +01:00
|
|
|
/* Read files and prepare bunches */
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2024-01-20 13:24:54 +01:00
|
|
|
// Put 5KB in one bunch (this is not accurate)
|
|
|
|
// This is a tradeoff between burdening the network with too many packets
|
|
|
|
// and burdening it with too large split packets.
|
2024-01-19 20:08:55 +01:00
|
|
|
const u32 bytes_per_bunch = 5000;
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2024-01-19 20:08:55 +01:00
|
|
|
std::vector<std::vector<SendableMedia>> file_bunches;
|
2017-08-14 01:06:12 +02:00
|
|
|
file_bunches.emplace_back();
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2024-01-20 13:24:54 +01:00
|
|
|
// Note that applying a "real" bin packing algorithm here is not necessarily
|
|
|
|
// an improvement (might even perform worse) since games usually have lots
|
2024-03-12 14:13:24 +01:00
|
|
|
// of files larger than 5KB and the current algorithm already minimizes
|
2024-01-20 13:24:54 +01:00
|
|
|
// the amount of bunches quite well (at the expense of overshooting).
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2024-01-20 13:24:54 +01:00
|
|
|
u32 file_size_bunch_total = 0;
|
2017-08-14 01:06:12 +02:00
|
|
|
for (const std::string &name : tosend) {
|
2024-01-19 20:08:55 +01:00
|
|
|
auto it = m_media.find(name);
|
|
|
|
|
|
|
|
if (it == m_media.end()) {
|
2012-03-25 10:50:29 +02:00
|
|
|
errorstream<<"Server::sendRequestedMedia(): Client asked for "
|
Rewrite client media download and support hash-based remote download
Move most of the media-related code in client.cpp into a new class
ClientMediaDownloader (clientmedia.cpp, clientmedia.h). Among other
things, this class does the following things:
- Download [remote_server][sha1] instead of [remote_server][name]. This
is to support servers that provide the same file name with different
contents.
- Initially fetch [remote_server]index.mth. This file should follow the
Minetest Hashset format (currently version 1) and contain a list of SHA1
hashes that exist on the server.
- The list of needed SHA1s is uploaded (via HTTP POST) when index.mth is
requested, so servers can optionally narrow down the list to the needs
of the client.
- If index.mth is missing (HTTP response code 404), we enter compat mode,
fetching [remote_server][name] as before this commit.
- remote_server can now contain multiple servers, separated by commas.
The downloader code attempts to split requests between the different
servers, as permitted by each server's index.mth. If one server claims
to have a file but actually doesn't (or something fails), we ask a
different server that also claims to have it.
- As before, when none of the remote servers provide a particular
file, we download it via the conventional method, i.e. using
the minetest protocol: TOSERVER_REQUEST_MEDIA / TOCLIENT_MEDIA.
- Bugfix: Every downloaded file's SHA1 is now verified against the SHA1
announced by the minetest server (before loading it and inserting it
into the file cache).
- Bugfix: Only send TOSERVER_RECEIVED_MEDIA when we actually have all
media. This should fix #863.
2013-08-29 05:22:18 +02:00
|
|
|
<<"unknown file \""<<(name)<<"\""<<std::endl;
|
2012-01-03 23:37:46 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-01-19 20:08:55 +01:00
|
|
|
const auto &m = it->second;
|
|
|
|
|
|
|
|
// no_announce <=> usually ephemeral dynamic media, which may
|
|
|
|
// have duplicate filenames. So we can't check it.
|
|
|
|
if (!m.no_announce) {
|
|
|
|
if (!client->markMediaSent(name)) {
|
|
|
|
infostream << "Server::sendRequestedMedia(): Client asked has "
|
|
|
|
"requested \"" << name << "\" before, not sending it again."
|
|
|
|
<< std::endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2012-01-02 12:31:50 +01:00
|
|
|
|
|
|
|
// Read data
|
2021-09-09 16:51:35 +02:00
|
|
|
std::string data;
|
2024-05-08 20:37:10 +02:00
|
|
|
if (!fs::ReadFile(m.path, data, true)) {
|
2012-01-02 12:31:50 +01:00
|
|
|
continue;
|
|
|
|
}
|
2021-09-09 16:51:35 +02:00
|
|
|
file_size_bunch_total += data.size();
|
|
|
|
|
2012-01-02 12:31:50 +01:00
|
|
|
// Put in list
|
2021-09-09 16:51:35 +02:00
|
|
|
file_bunches.back().emplace_back(name, m.path, std::move(data));
|
2012-01-02 12:31:50 +01:00
|
|
|
|
|
|
|
// Start next bunch if got enough data
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
if(file_size_bunch_total >= bytes_per_bunch) {
|
2017-08-14 01:06:12 +02:00
|
|
|
file_bunches.emplace_back();
|
2012-03-25 10:50:29 +02:00
|
|
|
file_size_bunch_total = 0;
|
2012-01-02 12:31:50 +01:00
|
|
|
}
|
2011-11-15 10:02:47 +01:00
|
|
|
}
|
|
|
|
|
2011-11-15 22:58:56 +01:00
|
|
|
/* Create and send packets */
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2024-01-19 20:08:55 +01:00
|
|
|
const u16 num_bunches = file_bunches.size();
|
2017-08-14 01:06:12 +02:00
|
|
|
for (u16 i = 0; i < num_bunches; i++) {
|
2024-01-19 20:08:55 +01:00
|
|
|
auto &bunch = file_bunches[i];
|
2012-03-25 10:50:29 +02:00
|
|
|
/*
|
2024-01-19 20:08:55 +01:00
|
|
|
u16 total number of media bunches
|
2012-03-25 10:50:29 +02:00
|
|
|
u16 index of this bunch
|
|
|
|
u32 number of files in this bunch
|
|
|
|
for each file {
|
|
|
|
u16 length of name
|
|
|
|
string name
|
|
|
|
u32 length of data
|
|
|
|
data
|
2011-11-15 22:58:56 +01:00
|
|
|
}
|
2012-03-25 10:50:29 +02:00
|
|
|
*/
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
|
2024-01-20 13:24:54 +01:00
|
|
|
|
|
|
|
const u32 bunch_size = bunch.size();
|
|
|
|
pkt << num_bunches << i << bunch_size;
|
2012-01-02 12:31:50 +01:00
|
|
|
|
2024-01-19 20:08:55 +01:00
|
|
|
for (auto &j : bunch) {
|
2017-08-14 01:06:12 +02:00
|
|
|
pkt << j.name;
|
|
|
|
pkt.putLongString(j.data);
|
2012-03-25 10:50:29 +02:00
|
|
|
}
|
2024-01-20 13:24:54 +01:00
|
|
|
bunch.clear(); // free memory early
|
2012-01-02 12:31:50 +01:00
|
|
|
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
verbosestream << "Server::sendRequestedMedia(): bunch "
|
|
|
|
<< i << "/" << num_bunches
|
2024-01-20 13:24:54 +01:00
|
|
|
<< " files=" << bunch_size
|
2015-03-13 22:01:49 +01:00
|
|
|
<< " size=" << pkt.getSize() << std::endl;
|
|
|
|
Send(&pkt);
|
2012-03-25 10:50:29 +02:00
|
|
|
}
|
2011-11-15 10:02:47 +01:00
|
|
|
}
|
|
|
|
|
2021-09-09 16:51:35 +02:00
|
|
|
void Server::stepPendingDynMediaCallbacks(float dtime)
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(m_env_mutex);
|
|
|
|
|
|
|
|
for (auto it = m_pending_dyn_media.begin(); it != m_pending_dyn_media.end();) {
|
|
|
|
it->second.expiry_timer -= dtime;
|
|
|
|
bool del = it->second.waiting_players.empty() || it->second.expiry_timer < 0;
|
|
|
|
|
|
|
|
if (!del) {
|
|
|
|
it++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto &name = it->second.filename;
|
|
|
|
if (!name.empty()) {
|
|
|
|
assert(m_media.count(name));
|
|
|
|
// if no_announce isn't set we're definitely deleting the wrong file!
|
|
|
|
sanity_check(m_media[name].no_announce);
|
|
|
|
|
|
|
|
fs::DeleteSingleFileOrEmptyDirectory(m_media[name].path);
|
|
|
|
m_media.erase(name);
|
|
|
|
}
|
|
|
|
getScriptIface()->freeDynamicMediaCallback(it->first);
|
|
|
|
it = m_pending_dyn_media.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 15:24:29 +02:00
|
|
|
void Server::SendMinimapModes(session_t peer_id,
|
|
|
|
std::vector<MinimapMode> &modes, size_t wanted_mode)
|
|
|
|
{
|
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
2024-03-10 13:24:35 +01:00
|
|
|
if (!player)
|
2020-10-04 15:24:29 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
NetworkPacket pkt(TOCLIENT_MINIMAP_MODES, 0, peer_id);
|
|
|
|
pkt << (u16)modes.size() << (u16)wanted_mode;
|
|
|
|
|
|
|
|
for (auto &mode : modes)
|
|
|
|
pkt << (u16)mode.type << mode.label << mode.size << mode.texture << mode.scale;
|
|
|
|
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
|
|
|
|
2020-05-07 22:38:41 +02:00
|
|
|
void Server::sendDetachedInventory(Inventory *inventory, const std::string &name, session_t peer_id)
|
2012-07-24 19:57:17 +02:00
|
|
|
{
|
2015-03-13 22:01:49 +01:00
|
|
|
NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
|
2018-10-10 20:48:58 +02:00
|
|
|
pkt << name;
|
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
2015-01-16 11:37:49 +01:00
|
|
|
|
2020-05-07 22:38:41 +02:00
|
|
|
if (!inventory) {
|
2018-10-10 20:48:58 +02:00
|
|
|
pkt << false; // Remove inventory
|
2016-11-26 17:35:25 +01:00
|
|
|
} else {
|
2018-10-10 20:48:58 +02:00
|
|
|
pkt << true; // Update inventory
|
|
|
|
|
|
|
|
// Serialization & NetworkPacket isn't a love story
|
|
|
|
std::ostringstream os(std::ios_base::binary);
|
2020-05-07 22:38:41 +02:00
|
|
|
inventory->serialize(os);
|
|
|
|
inventory->setModified(false);
|
2019-03-07 07:41:21 +01:00
|
|
|
|
2019-08-24 19:07:38 +02:00
|
|
|
const std::string &os_str = os.str();
|
2019-03-07 07:41:21 +01:00
|
|
|
pkt << static_cast<u16>(os_str.size()); // HACK: to keep compatibility with 5.0.0 clients
|
|
|
|
pkt.putRawString(os_str);
|
2012-07-24 19:57:17 +02:00
|
|
|
}
|
2018-10-10 20:48:58 +02:00
|
|
|
|
|
|
|
if (peer_id == PEER_ID_INEXISTENT)
|
|
|
|
m_clients.sendToAll(&pkt);
|
|
|
|
else
|
|
|
|
Send(&pkt);
|
2012-07-24 19:57:17 +02:00
|
|
|
}
|
|
|
|
|
2019-08-25 10:55:27 +02:00
|
|
|
void Server::sendDetachedInventories(session_t peer_id, bool incremental)
|
2012-07-24 19:57:17 +02:00
|
|
|
{
|
2020-05-07 22:38:41 +02:00
|
|
|
// Lookup player name, to filter detached inventories just after
|
|
|
|
std::string peer_name;
|
|
|
|
if (peer_id != PEER_ID_INEXISTENT) {
|
|
|
|
peer_name = getClient(peer_id, CS_Created)->getName();
|
2012-07-24 19:57:17 +02:00
|
|
|
}
|
2020-05-07 22:38:41 +02:00
|
|
|
|
|
|
|
auto send_cb = [this, peer_id](const std::string &name, Inventory *inv) {
|
|
|
|
sendDetachedInventory(inv, name, peer_id);
|
|
|
|
};
|
|
|
|
|
|
|
|
m_inventory_mgr->sendDetachedInventories(peer_name, incremental, send_cb);
|
2012-07-24 19:57:17 +02:00
|
|
|
}
|
|
|
|
|
2011-04-21 18:35:17 +02:00
|
|
|
/*
|
|
|
|
Something random
|
|
|
|
*/
|
|
|
|
|
2022-01-15 17:44:55 +01:00
|
|
|
void Server::HandlePlayerDeath(PlayerSAO *playersao, const PlayerHPChangeReason &reason)
|
2011-10-15 13:46:59 +02:00
|
|
|
{
|
2015-03-02 17:31:31 +01:00
|
|
|
infostream << "Server::DiePlayer(): Player "
|
|
|
|
<< playersao->getPlayer()->getName()
|
|
|
|
<< " dies" << std::endl;
|
2012-03-19 03:04:16 +01:00
|
|
|
|
2018-04-30 18:43:49 +02:00
|
|
|
playersao->clearParentAttachment();
|
2012-03-19 03:04:16 +01:00
|
|
|
|
2012-01-05 23:12:33 +01:00
|
|
|
// Trigger scripted stuff
|
2018-03-28 17:05:18 +02:00
|
|
|
m_script->on_dieplayer(playersao, reason);
|
2011-12-02 16:19:42 +01:00
|
|
|
|
2022-01-15 17:44:55 +01:00
|
|
|
SendDeathscreen(playersao->getPeerID(), false, v3f(0,0,0));
|
2011-10-15 13:46:59 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::RespawnPlayer(session_t peer_id)
|
2011-10-15 13:46:59 +02:00
|
|
|
{
|
2012-03-19 03:04:16 +01:00
|
|
|
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
|
|
|
assert(playersao);
|
|
|
|
|
2015-03-02 17:31:31 +01:00
|
|
|
infostream << "Server::RespawnPlayer(): Player "
|
|
|
|
<< playersao->getPlayer()->getName()
|
|
|
|
<< " respawns" << std::endl;
|
2012-03-19 03:04:16 +01:00
|
|
|
|
2022-05-25 19:29:11 +02:00
|
|
|
const auto *prop = playersao->accessObjectProperties();
|
|
|
|
playersao->setHP(prop->hp_max,
|
2018-03-28 17:05:18 +02:00
|
|
|
PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
|
2022-05-25 19:29:11 +02:00
|
|
|
playersao->setBreath(prop->breath_max);
|
2012-03-19 03:04:16 +01:00
|
|
|
|
2013-05-25 00:51:02 +02:00
|
|
|
bool repositioned = m_script->on_respawnplayer(playersao);
|
2016-12-22 19:29:15 +01:00
|
|
|
if (!repositioned) {
|
2015-03-04 12:19:26 +01:00
|
|
|
// setPos will send the new position to client
|
2017-04-23 14:35:08 +02:00
|
|
|
playersao->setPos(findSpawnPos());
|
2011-11-26 02:20:19 +01:00
|
|
|
}
|
2011-10-15 13:46:59 +02:00
|
|
|
}
|
2015-07-17 16:40:41 +02:00
|
|
|
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::DenySudoAccess(session_t peer_id)
|
2015-04-12 04:49:13 +02:00
|
|
|
{
|
|
|
|
NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
|
|
|
|
Send(&pkt);
|
|
|
|
}
|
2011-10-15 13:46:59 +02:00
|
|
|
|
2015-07-17 16:40:41 +02:00
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
|
2022-04-27 19:55:13 +02:00
|
|
|
const std::string &custom_reason, bool reconnect)
|
2013-08-04 07:17:07 +02:00
|
|
|
{
|
2022-04-27 19:55:13 +02:00
|
|
|
SendAccessDenied(peer_id, reason, custom_reason, reconnect);
|
2014-06-28 08:02:38 +02:00
|
|
|
m_clients.event(peer_id, CSE_SetDenied);
|
2017-09-26 00:11:20 +02:00
|
|
|
DisconnectPeer(peer_id);
|
|
|
|
}
|
|
|
|
|
2024-02-02 22:13:24 +01:00
|
|
|
void Server::kickAllPlayers(AccessDeniedCode reason,
|
|
|
|
const std::string &str_reason, bool reconnect)
|
|
|
|
{
|
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
|
|
|
for (const session_t client_id : clients) {
|
|
|
|
DenyAccess(client_id, reason, str_reason, reconnect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::DisconnectPeer(session_t peer_id)
|
2017-09-26 00:11:20 +02:00
|
|
|
{
|
|
|
|
m_modchannel_mgr->leaveAllChannels(peer_id);
|
2017-08-24 08:28:54 +02:00
|
|
|
m_con->DisconnectPeer(peer_id);
|
2013-08-04 07:17:07 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::acceptAuth(session_t peer_id, bool forSudoMode)
|
2015-04-12 04:49:13 +02:00
|
|
|
{
|
|
|
|
if (!forSudoMode) {
|
|
|
|
RemoteClient* client = getClient(peer_id, CS_Invalid);
|
|
|
|
|
|
|
|
NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
|
|
|
|
|
|
|
|
resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
|
|
|
|
<< g_settings->getFloat("dedicated_server_step")
|
2024-01-19 11:50:55 +01:00
|
|
|
<< client->allowed_auth_mechs;
|
2015-04-12 04:49:13 +02:00
|
|
|
|
|
|
|
Send(&resp_pkt);
|
|
|
|
m_clients.event(peer_id, CSE_AuthAccept);
|
|
|
|
} else {
|
|
|
|
NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
|
|
|
|
|
|
|
|
// We only support SRP right now
|
|
|
|
u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
|
|
|
|
|
|
|
|
resp_pkt << sudo_auth_mechs;
|
|
|
|
Send(&resp_pkt);
|
|
|
|
m_clients.event(peer_id, CSE_SudoSuccess);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
|
2013-08-04 07:17:07 +02:00
|
|
|
{
|
2014-01-31 00:24:00 +01:00
|
|
|
std::wstring message;
|
2013-08-04 07:17:07 +02:00
|
|
|
{
|
2014-01-31 00:24:00 +01:00
|
|
|
/*
|
|
|
|
Clear references to playing sounds
|
|
|
|
*/
|
2024-02-15 15:29:44 +01:00
|
|
|
for (auto i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
|
2014-01-31 00:24:00 +01:00
|
|
|
ServerPlayingSound &psound = i->second;
|
|
|
|
psound.clients.erase(peer_id);
|
2016-10-06 19:20:12 +02:00
|
|
|
if (psound.clients.empty())
|
2024-02-15 15:29:44 +01:00
|
|
|
i = m_playing_sounds.erase(i);
|
2014-01-31 00:24:00 +01:00
|
|
|
else
|
2015-08-25 22:23:05 +02:00
|
|
|
++i;
|
2014-01-31 00:24:00 +01:00
|
|
|
}
|
2013-08-04 07:17:07 +02:00
|
|
|
|
2018-02-18 22:33:42 +01:00
|
|
|
// clear formspec info so the next client can't abuse the current state
|
|
|
|
m_formspec_state_data.erase(peer_id);
|
|
|
|
|
2016-10-08 12:21:41 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
2013-08-04 07:17:07 +02:00
|
|
|
|
2014-01-31 00:24:00 +01:00
|
|
|
/* Run scripts and remove from environment */
|
2017-08-15 09:30:31 +02:00
|
|
|
if (player) {
|
2016-10-08 10:38:04 +02:00
|
|
|
PlayerSAO *playersao = player->getPlayerSAO();
|
|
|
|
assert(playersao);
|
2013-08-04 07:17:07 +02:00
|
|
|
|
2018-05-12 10:55:43 +02:00
|
|
|
playersao->clearChildAttachments();
|
|
|
|
playersao->clearParentAttachment();
|
|
|
|
|
2017-06-08 15:30:09 +02:00
|
|
|
// inform connected clients
|
2018-10-10 20:48:58 +02:00
|
|
|
const std::string &player_name = player->getName();
|
2017-06-08 15:30:09 +02:00
|
|
|
NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
|
|
|
|
// (u16) 1 + std::string represents a vector serialization representation
|
2018-10-10 20:48:58 +02:00
|
|
|
notice << (u8) PLAYER_LIST_REMOVE << (u16) 1 << player_name;
|
2017-06-08 15:30:09 +02:00
|
|
|
m_clients.sendToAll(¬ice);
|
|
|
|
// run scripts
|
2016-10-08 10:38:04 +02:00
|
|
|
m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
|
2013-08-04 07:17:07 +02:00
|
|
|
|
2016-10-08 10:38:04 +02:00
|
|
|
playersao->disconnected();
|
2013-08-04 07:17:07 +02:00
|
|
|
}
|
|
|
|
|
2014-01-31 00:24:00 +01:00
|
|
|
/*
|
|
|
|
Print out action
|
|
|
|
*/
|
2013-08-04 07:17:07 +02:00
|
|
|
{
|
2017-08-15 09:30:31 +02:00
|
|
|
if (player && reason != CDR_DENY) {
|
2014-01-31 00:24:00 +01:00
|
|
|
std::ostringstream os(std::ios_base::binary);
|
2017-09-27 23:48:06 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2017-09-27 23:48:06 +02:00
|
|
|
for (const session_t client_id : clients) {
|
2014-01-31 00:24:00 +01:00
|
|
|
// Get player
|
2017-08-14 01:06:12 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(client_id);
|
2016-10-08 16:31:22 +02:00
|
|
|
if (!player)
|
2014-01-31 00:24:00 +01:00
|
|
|
continue;
|
2015-03-04 16:30:24 +01:00
|
|
|
|
2014-01-31 00:24:00 +01:00
|
|
|
// Get name of player
|
2015-03-04 16:30:24 +01:00
|
|
|
os << player->getName() << " ";
|
2014-01-31 00:24:00 +01:00
|
|
|
}
|
2013-08-04 07:17:07 +02:00
|
|
|
|
2015-07-25 07:43:32 +02:00
|
|
|
std::string name = player->getName();
|
|
|
|
actionstream << name << " "
|
2015-03-04 16:30:24 +01:00
|
|
|
<< (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
|
|
|
|
<< " List of players: " << os.str() << std::endl;
|
2015-07-25 07:43:32 +02:00
|
|
|
if (m_admin_chat)
|
|
|
|
m_admin_chat->outgoing_queue.push_back(
|
|
|
|
new ChatEventNick(CET_NICK_REMOVE, name));
|
2014-01-31 00:24:00 +01:00
|
|
|
}
|
2013-08-04 07:17:07 +02:00
|
|
|
}
|
2014-02-12 19:47:27 +01:00
|
|
|
{
|
2015-04-07 12:13:12 +02:00
|
|
|
MutexAutoLock env_lock(m_env_mutex);
|
2014-02-12 19:47:27 +01:00
|
|
|
m_clients.DeleteClient(peer_id);
|
|
|
|
}
|
2013-08-04 07:17:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Send leave chat message to all remaining clients
|
2017-07-16 10:47:31 +02:00
|
|
|
if (!message.empty()) {
|
|
|
|
SendChatMessage(PEER_ID_INEXISTENT,
|
|
|
|
ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
|
|
|
|
}
|
2013-08-04 07:17:07 +02:00
|
|
|
}
|
|
|
|
|
2016-10-08 19:08:23 +02:00
|
|
|
void Server::UpdateCrafting(RemotePlayer *player)
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2018-05-05 22:37:07 +02:00
|
|
|
InventoryList *clist = player->inventory.getList("craft");
|
|
|
|
if (!clist || clist->getSize() == 0)
|
|
|
|
return;
|
|
|
|
|
2020-04-08 20:13:23 +02:00
|
|
|
if (!clist->checkModified())
|
2019-08-24 19:07:38 +02:00
|
|
|
return;
|
|
|
|
|
2012-01-21 21:21:41 +01:00
|
|
|
// Get a preview for crafting
|
|
|
|
ItemStack preview;
|
2013-10-26 11:25:28 +02:00
|
|
|
InventoryLocation loc;
|
|
|
|
loc.setPlayer(player->getName());
|
2015-06-02 20:30:04 +02:00
|
|
|
std::vector<ItemStack> output_replacements;
|
|
|
|
getCraftingResult(&player->inventory, preview, output_replacements, false, this);
|
2016-10-08 10:38:04 +02:00
|
|
|
m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
|
2018-05-05 22:37:07 +02:00
|
|
|
clist, loc);
|
2012-01-21 21:21:41 +01:00
|
|
|
|
|
|
|
InventoryList *plist = player->inventory.getList("craftpreview");
|
2018-05-05 22:37:07 +02:00
|
|
|
if (plist && plist->getSize() >= 1) {
|
|
|
|
// Put the new preview in
|
|
|
|
plist->changeItem(0, preview);
|
|
|
|
}
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:04:24 +01:00
|
|
|
void Server::handleChatInterfaceEvent(ChatEvent *evt)
|
|
|
|
{
|
|
|
|
if (evt->type == CET_NICK_ADD) {
|
|
|
|
// The terminal informed us of its nick choice
|
|
|
|
m_admin_nick = ((ChatEventNick *)evt)->nick;
|
|
|
|
if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
|
|
|
|
errorstream << "You haven't set up an account." << std::endl
|
|
|
|
<< "Please log in using the client as '"
|
|
|
|
<< m_admin_nick << "' with a secure password." << std::endl
|
|
|
|
<< "Until then, you can't execute admin tasks via the console," << std::endl
|
|
|
|
<< "and everybody can claim the user account instead of you," << std::endl
|
|
|
|
<< "giving them full control over this server." << std::endl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
assert(evt->type == CET_CHAT);
|
|
|
|
handleAdminChat((ChatEventChat *)evt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-29 14:03:27 +01:00
|
|
|
std::wstring Server::handleChat(const std::string &name,
|
2017-06-10 13:49:44 +02:00
|
|
|
std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
|
2015-07-25 07:43:32 +02:00
|
|
|
{
|
|
|
|
// If something goes wrong, this player is to blame
|
|
|
|
RollbackScopeActor rollback_scope(m_rollback,
|
2019-08-08 18:04:46 +02:00
|
|
|
std::string("player:") + name);
|
2015-07-25 07:43:32 +02:00
|
|
|
|
2017-06-10 13:49:44 +02:00
|
|
|
if (g_settings->getBool("strip_color_codes"))
|
|
|
|
wmessage = unescape_enriched(wmessage);
|
|
|
|
|
2016-10-06 03:32:52 +02:00
|
|
|
if (player) {
|
|
|
|
switch (player->canSendChatMessage()) {
|
2019-08-08 18:04:46 +02:00
|
|
|
case RPLAYER_CHATRESULT_FLOODING: {
|
|
|
|
std::wstringstream ws;
|
|
|
|
ws << L"You cannot send more messages. You are limited to "
|
|
|
|
<< g_settings->getFloat("chat_message_limit_per_10sec")
|
|
|
|
<< L" messages per 10 seconds.";
|
|
|
|
return ws.str();
|
|
|
|
}
|
|
|
|
case RPLAYER_CHATRESULT_KICK:
|
2022-04-27 19:55:13 +02:00
|
|
|
DenyAccess(player->getPeerId(), SERVER_ACCESSDENIED_CUSTOM_STRING,
|
|
|
|
"You have been kicked due to message flooding.");
|
2019-08-08 18:04:46 +02:00
|
|
|
return L"";
|
|
|
|
case RPLAYER_CHATRESULT_OK:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FATAL_ERROR("Unhandled chat filtering result found.");
|
2016-10-04 18:17:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 10:57:33 +01:00
|
|
|
if (m_max_chatmessage_length > 0
|
|
|
|
&& wmessage.length() > m_max_chatmessage_length) {
|
2016-10-04 18:17:12 +02:00
|
|
|
return L"Your message exceed the maximum chat message limit set on the server. "
|
2017-01-25 10:57:33 +01:00
|
|
|
L"It was refused. Send a shorter message";
|
2016-10-04 18:17:12 +02:00
|
|
|
}
|
|
|
|
|
2019-03-26 02:18:52 +01:00
|
|
|
auto message = trim(wide_to_utf8(wmessage));
|
2021-06-21 19:04:25 +02:00
|
|
|
if (message.empty())
|
|
|
|
return L"";
|
|
|
|
|
2019-03-26 02:18:52 +01:00
|
|
|
if (message.find_first_of("\n\r") != std::wstring::npos) {
|
2021-01-29 14:03:27 +01:00
|
|
|
return L"Newlines are not permitted in chat messages";
|
2019-03-26 02:18:52 +01:00
|
|
|
}
|
|
|
|
|
2017-01-25 10:57:33 +01:00
|
|
|
// Run script hook, exit if script ate the chat message
|
2019-03-26 02:18:52 +01:00
|
|
|
if (m_script->on_chat_message(name, message))
|
2017-01-25 10:57:33 +01:00
|
|
|
return L"";
|
|
|
|
|
|
|
|
// Line to send
|
|
|
|
std::wstring line;
|
|
|
|
// Whether to send line to the player that sent the message, or to all players
|
|
|
|
bool broadcast_line = true;
|
|
|
|
|
2017-04-08 20:03:57 +02:00
|
|
|
if (check_shout_priv && !checkPriv(name, "shout")) {
|
|
|
|
line += L"-!- You don't have permission to shout.";
|
2015-07-25 07:43:32 +02:00
|
|
|
broadcast_line = false;
|
|
|
|
} else {
|
2020-04-17 23:46:30 +02:00
|
|
|
/*
|
|
|
|
Workaround for fixing chat on Android. Lua doesn't handle
|
|
|
|
the Cyrillic alphabet and some characters on older Android devices
|
|
|
|
*/
|
|
|
|
#ifdef __ANDROID__
|
2021-01-29 14:03:27 +01:00
|
|
|
line += L"<" + utf8_to_wide(name) + L"> " + wmessage;
|
2020-04-17 23:46:30 +02:00
|
|
|
#else
|
2021-01-29 14:03:27 +01:00
|
|
|
line += utf8_to_wide(m_script->formatChatMessage(name,
|
|
|
|
wide_to_utf8(wmessage)));
|
2020-04-17 23:46:30 +02:00
|
|
|
#endif
|
2015-07-25 07:43:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Tell calling method to send the message to sender
|
|
|
|
*/
|
2017-08-14 01:06:12 +02:00
|
|
|
if (!broadcast_line)
|
2015-07-25 07:43:32 +02:00
|
|
|
return line;
|
|
|
|
|
2017-08-14 01:06:12 +02:00
|
|
|
/*
|
|
|
|
Send the message to others
|
|
|
|
*/
|
2021-01-29 14:03:27 +01:00
|
|
|
actionstream << "CHAT: " << wide_to_utf8(unescape_enriched(line)) << std::endl;
|
2015-07-25 07:43:32 +02:00
|
|
|
|
2021-01-29 14:03:27 +01:00
|
|
|
ChatMessage chatmsg(line);
|
2017-09-30 12:00:05 +02:00
|
|
|
|
2021-01-29 14:03:27 +01:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
|
|
|
for (u16 cid : clients)
|
|
|
|
SendChatMessage(cid, chatmsg);
|
2017-08-14 01:06:12 +02:00
|
|
|
|
2015-07-25 07:43:32 +02:00
|
|
|
return L"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Server::handleAdminChat(const ChatEventChat *evt)
|
|
|
|
{
|
|
|
|
std::string name = evt->nick;
|
|
|
|
std::wstring wmessage = evt->evt_msg;
|
|
|
|
|
2021-01-29 14:03:27 +01:00
|
|
|
std::wstring answer = handleChat(name, wmessage);
|
2015-07-25 07:43:32 +02:00
|
|
|
|
|
|
|
// If asked to send answer to sender
|
|
|
|
if (!answer.empty()) {
|
|
|
|
m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
|
2010-11-27 00:02:21 +01:00
|
|
|
{
|
2014-01-31 00:24:00 +01:00
|
|
|
RemoteClient *client = getClientNoEx(peer_id,state_min);
|
2013-08-04 07:17:07 +02:00
|
|
|
if(!client)
|
|
|
|
throw ClientNotFoundException("Client not found");
|
2014-01-31 00:24:00 +01:00
|
|
|
|
2013-08-04 07:17:07 +02:00
|
|
|
return client;
|
|
|
|
}
|
2017-09-27 19:47:36 +02:00
|
|
|
RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
|
2013-08-04 07:17:07 +02:00
|
|
|
{
|
2014-01-31 00:24:00 +01:00
|
|
|
return m_clients.getClientNoEx(peer_id, state_min);
|
2010-11-27 00:02:21 +01:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
std::string Server::getPlayerName(session_t peer_id)
|
2013-08-11 04:09:45 +02:00
|
|
|
{
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
2017-08-15 09:30:31 +02:00
|
|
|
if (!player)
|
2013-08-11 04:09:45 +02:00
|
|
|
return "[id="+itos(peer_id)+"]";
|
|
|
|
return player->getName();
|
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
PlayerSAO *Server::getPlayerSAO(session_t peer_id)
|
2013-08-11 04:09:45 +02:00
|
|
|
{
|
2016-10-08 12:21:41 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(peer_id);
|
2017-08-15 09:30:31 +02:00
|
|
|
if (!player)
|
2013-08-11 04:09:45 +02:00
|
|
|
return NULL;
|
|
|
|
return player->getPlayerSAO();
|
|
|
|
}
|
|
|
|
|
2021-01-29 14:03:27 +01:00
|
|
|
std::string Server::getStatusString()
|
2011-02-15 15:11:24 +01:00
|
|
|
{
|
2021-01-29 14:03:27 +01:00
|
|
|
std::ostringstream os(std::ios_base::binary);
|
|
|
|
os << "# Server: ";
|
2011-04-24 23:24:40 +02:00
|
|
|
// Version
|
2021-03-17 19:03:00 +01:00
|
|
|
os << "version: " << g_version_string;
|
2022-01-24 22:49:36 +01:00
|
|
|
// Game
|
2022-05-21 17:23:30 +02:00
|
|
|
os << " | game: " << (m_gamespec.title.empty() ? m_gamespec.id : m_gamespec.title);
|
2011-02-15 15:11:24 +01:00
|
|
|
// Uptime
|
2021-03-17 19:03:00 +01:00
|
|
|
os << " | uptime: " << duration_to_string((int) m_uptime_counter->get());
|
2013-08-03 22:16:37 +02:00
|
|
|
// Max lag estimate
|
2021-03-17 19:03:00 +01:00
|
|
|
os << " | max lag: " << std::setprecision(3);
|
|
|
|
os << (m_env ? m_env->getMaxLagEstimate() : 0) << "s";
|
2018-11-12 15:34:01 +01:00
|
|
|
|
2011-02-15 15:11:24 +01:00
|
|
|
// Information about clients
|
2014-01-31 00:24:00 +01:00
|
|
|
bool first = true;
|
2021-03-17 19:03:00 +01:00
|
|
|
os << " | clients: ";
|
2018-11-12 15:34:01 +01:00
|
|
|
if (m_env) {
|
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
|
|
|
for (session_t client_id : clients) {
|
|
|
|
RemotePlayer *player = m_env->getPlayer(client_id);
|
|
|
|
|
|
|
|
// Get name of player
|
2021-01-29 14:03:27 +01:00
|
|
|
const char *name = player ? player->getName() : "<unknown>";
|
2018-11-12 15:34:01 +01:00
|
|
|
|
|
|
|
// Add name to information string
|
|
|
|
if (!first)
|
2021-01-29 14:03:27 +01:00
|
|
|
os << ", ";
|
2018-11-12 15:34:01 +01:00
|
|
|
else
|
|
|
|
first = false;
|
|
|
|
os << name;
|
|
|
|
}
|
2011-02-15 15:11:24 +01:00
|
|
|
}
|
2017-08-14 01:06:12 +02:00
|
|
|
|
2018-11-12 15:34:01 +01:00
|
|
|
if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
|
2021-01-29 14:03:27 +01:00
|
|
|
os << std::endl << "# Server: " << " WARNING: Map saving is disabled.";
|
2017-08-14 01:06:12 +02:00
|
|
|
|
|
|
|
if (!g_settings->get("motd").empty())
|
2021-01-29 14:03:27 +01:00
|
|
|
os << std::endl << "# Server: " << g_settings->get("motd");
|
2018-11-12 15:34:01 +01:00
|
|
|
|
2011-02-15 15:11:24 +01:00
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
2012-03-30 17:42:18 +02:00
|
|
|
std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
|
2012-03-15 14:27:16 +01:00
|
|
|
{
|
2012-03-30 17:42:18 +02:00
|
|
|
std::set<std::string> privs;
|
2013-05-25 00:51:02 +02:00
|
|
|
m_script->getAuth(name, NULL, &privs);
|
2012-03-30 17:42:18 +02:00
|
|
|
return privs;
|
2012-03-15 14:27:16 +01:00
|
|
|
}
|
|
|
|
|
2012-03-30 17:42:18 +02:00
|
|
|
bool Server::checkPriv(const std::string &name, const std::string &priv)
|
2011-11-20 20:16:15 +01:00
|
|
|
{
|
2012-03-30 17:42:18 +02:00
|
|
|
std::set<std::string> privs = getPlayerEffectivePrivs(name);
|
|
|
|
return (privs.count(priv) != 0);
|
2011-11-20 20:16:15 +01:00
|
|
|
}
|
|
|
|
|
2012-03-31 15:23:26 +02:00
|
|
|
void Server::reportPrivsModified(const std::string &name)
|
|
|
|
{
|
2017-08-14 01:06:12 +02:00
|
|
|
if (name.empty()) {
|
2017-09-27 23:48:06 +02:00
|
|
|
std::vector<session_t> clients = m_clients.getClientIDs();
|
|
|
|
for (const session_t client_id : clients) {
|
2017-08-14 01:06:12 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(client_id);
|
2012-03-31 16:08:39 +02:00
|
|
|
reportPrivsModified(player->getName());
|
2012-03-31 15:23:26 +02:00
|
|
|
}
|
|
|
|
} else {
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(name.c_str());
|
2016-10-08 10:38:04 +02:00
|
|
|
if (!player)
|
2012-03-31 15:23:26 +02:00
|
|
|
return;
|
2017-09-30 12:00:05 +02:00
|
|
|
SendPlayerPrivileges(player->getPeerId());
|
2012-04-07 17:46:10 +02:00
|
|
|
PlayerSAO *sao = player->getPlayerSAO();
|
|
|
|
if(!sao)
|
|
|
|
return;
|
|
|
|
sao->updatePrivileges(
|
2012-04-01 12:19:50 +02:00
|
|
|
getPlayerEffectivePrivs(name),
|
|
|
|
isSingleplayer());
|
2012-03-31 15:23:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-19 13:09:16 +02:00
|
|
|
void Server::reportInventoryFormspecModified(const std::string &name)
|
|
|
|
{
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(name.c_str());
|
|
|
|
if (!player)
|
2012-07-19 13:09:16 +02:00
|
|
|
return;
|
2017-09-30 12:00:05 +02:00
|
|
|
SendPlayerInventoryFormspec(player->getPeerId());
|
2012-07-19 13:09:16 +02:00
|
|
|
}
|
|
|
|
|
2018-03-28 17:04:41 +02:00
|
|
|
void Server::reportFormspecPrependModified(const std::string &name)
|
|
|
|
{
|
|
|
|
RemotePlayer *player = m_env->getPlayer(name.c_str());
|
|
|
|
if (!player)
|
|
|
|
return;
|
|
|
|
SendPlayerFormspecPrepend(player->getPeerId());
|
|
|
|
}
|
|
|
|
|
2013-08-11 04:09:45 +02:00
|
|
|
void Server::setIpBanned(const std::string &ip, const std::string &name)
|
2011-10-12 12:53:38 +02:00
|
|
|
{
|
2013-08-11 04:09:45 +02:00
|
|
|
m_banmanager->add(ip, name);
|
2024-01-24 19:39:28 +01:00
|
|
|
|
|
|
|
auto clients = m_clients.getClientIDs(CS_Created);
|
|
|
|
for (const auto peer_id : clients) {
|
|
|
|
denyIfBanned(peer_id);
|
|
|
|
}
|
2013-08-11 04:09:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Server::unsetIpBanned(const std::string &ip_or_name)
|
|
|
|
{
|
|
|
|
m_banmanager->remove(ip_or_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Server::getBanDescription(const std::string &ip_or_name)
|
|
|
|
{
|
|
|
|
return m_banmanager->getBanDescription(ip_or_name);
|
2011-10-12 12:53:38 +02:00
|
|
|
}
|
|
|
|
|
2024-01-24 19:39:28 +01:00
|
|
|
bool Server::denyIfBanned(session_t peer_id)
|
|
|
|
{
|
|
|
|
Address address = getPeerAddress(peer_id);
|
|
|
|
std::string addr_s = address.serializeString();
|
|
|
|
|
|
|
|
if (m_banmanager->isIpBanned(addr_s)) {
|
|
|
|
std::string ban_name = m_banmanager->getBanName(addr_s);
|
|
|
|
actionstream << "Server: A banned client tried to connect from "
|
|
|
|
<< addr_s << "; banned name was " << ban_name << std::endl;
|
|
|
|
DenyAccess(peer_id, SERVER_ACCESSDENIED_CUSTOM_STRING,
|
|
|
|
"Your IP is banned. Banned name was " + ban_name);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-27 21:12:59 +01:00
|
|
|
void Server::notifyPlayer(const char *name, const std::wstring &msg)
|
2011-10-16 19:03:43 +02:00
|
|
|
{
|
2015-08-09 22:10:37 +02:00
|
|
|
// m_env will be NULL if the server is initializing
|
|
|
|
if (!m_env)
|
|
|
|
return;
|
|
|
|
|
2015-07-25 07:43:32 +02:00
|
|
|
if (m_admin_nick == name && !m_admin_nick.empty()) {
|
|
|
|
m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
|
|
|
|
}
|
|
|
|
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(name);
|
2024-03-10 13:24:35 +01:00
|
|
|
if (!player)
|
2014-02-02 01:55:24 +01:00
|
|
|
return;
|
|
|
|
|
2017-09-30 12:00:05 +02:00
|
|
|
SendChatMessage(player->getPeerId(), ChatMessage(msg));
|
2011-10-16 19:03:43 +02:00
|
|
|
}
|
|
|
|
|
2015-07-03 05:14:30 +02:00
|
|
|
bool Server::showFormspec(const char *playername, const std::string &formspec,
|
|
|
|
const std::string &formname)
|
2013-01-02 20:45:04 +01:00
|
|
|
{
|
2015-08-09 22:10:37 +02:00
|
|
|
// m_env will be NULL if the server is initializing
|
|
|
|
if (!m_env)
|
|
|
|
return false;
|
|
|
|
|
2016-10-08 16:31:22 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(playername);
|
2015-07-03 05:14:30 +02:00
|
|
|
if (!player)
|
2013-01-02 20:45:04 +01:00
|
|
|
return false;
|
|
|
|
|
2017-09-30 12:00:05 +02:00
|
|
|
SendShowFormspecMessage(player->getPeerId(), formspec, formname);
|
2013-01-02 20:45:04 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-08 12:21:41 +02:00
|
|
|
u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
|
2015-07-03 05:14:30 +02:00
|
|
|
{
|
2013-04-14 00:20:22 +02:00
|
|
|
if (!player)
|
|
|
|
return -1;
|
2014-12-17 09:20:17 +01:00
|
|
|
|
2014-05-25 14:34:32 +02:00
|
|
|
u32 id = player->addHud(form);
|
|
|
|
|
2017-09-30 12:00:05 +02:00
|
|
|
SendHUDAdd(player->getPeerId(), id, form);
|
2014-05-25 14:34:32 +02:00
|
|
|
|
2013-04-14 00:20:22 +02:00
|
|
|
return id;
|
2013-04-11 20:23:38 +02:00
|
|
|
}
|
|
|
|
|
2016-10-08 12:21:41 +02:00
|
|
|
bool Server::hudRemove(RemotePlayer *player, u32 id) {
|
2014-05-25 14:34:32 +02:00
|
|
|
if (!player)
|
2013-04-11 20:23:38 +02:00
|
|
|
return false;
|
|
|
|
|
2014-05-25 14:34:32 +02:00
|
|
|
HudElement* todel = player->removeHud(id);
|
|
|
|
|
|
|
|
if (!todel)
|
|
|
|
return false;
|
2014-12-17 09:20:17 +01:00
|
|
|
|
2014-05-25 14:34:32 +02:00
|
|
|
delete todel;
|
|
|
|
|
2017-09-30 12:00:05 +02:00
|
|
|
SendHUDRemove(player->getPeerId(), id);
|
2013-04-11 20:23:38 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-08 12:21:41 +02:00
|
|
|
bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
|
2015-07-03 05:14:30 +02:00
|
|
|
{
|
2013-04-14 00:20:22 +02:00
|
|
|
if (!player)
|
2013-04-11 20:23:38 +02:00
|
|
|
return false;
|
|
|
|
|
2017-09-30 12:00:05 +02:00
|
|
|
SendHUDChange(player->getPeerId(), id, stat, data);
|
2013-04-11 20:23:38 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-08 10:38:04 +02:00
|
|
|
bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
|
2015-07-03 05:14:30 +02:00
|
|
|
{
|
2013-04-24 12:52:46 +02:00
|
|
|
if (!player)
|
|
|
|
return false;
|
|
|
|
|
2022-02-08 19:28:32 +01:00
|
|
|
u32 new_hud_flags = (player->hud_flags & ~mask) | flags;
|
|
|
|
if (new_hud_flags == player->hud_flags) // no change
|
|
|
|
return true;
|
2022-07-13 11:57:12 +02:00
|
|
|
|
2017-09-30 12:00:05 +02:00
|
|
|
SendHUDSetFlags(player->getPeerId(), flags, mask);
|
2022-02-08 19:28:32 +01:00
|
|
|
player->hud_flags = new_hud_flags;
|
2014-12-17 09:20:17 +01:00
|
|
|
|
2014-08-21 17:27:52 +02:00
|
|
|
PlayerSAO* playersao = player->getPlayerSAO();
|
2014-12-17 09:20:17 +01:00
|
|
|
|
2017-08-14 01:06:12 +02:00
|
|
|
if (!playersao)
|
2014-08-21 17:27:52 +02:00
|
|
|
return false;
|
2014-04-28 23:41:27 +02:00
|
|
|
|
2014-08-21 17:27:52 +02:00
|
|
|
m_script->player_event(playersao, "hud_changed");
|
2013-04-24 12:52:46 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-08 10:38:04 +02:00
|
|
|
bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
|
2015-07-03 05:14:30 +02:00
|
|
|
{
|
2013-05-04 02:08:52 +02:00
|
|
|
if (!player)
|
|
|
|
return false;
|
2016-10-08 10:38:04 +02:00
|
|
|
|
2013-05-04 02:08:52 +02:00
|
|
|
if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
|
|
|
|
return false;
|
|
|
|
|
2024-02-29 14:56:13 +01:00
|
|
|
if (player->getHotbarItemcount() == hotbar_itemcount)
|
|
|
|
return true;
|
|
|
|
|
2015-05-26 14:10:08 +02:00
|
|
|
player->setHotbarItemcount(hotbar_itemcount);
|
2013-05-04 02:08:52 +02:00
|
|
|
std::ostringstream os(std::ios::binary);
|
|
|
|
writeS32(os, hotbar_itemcount);
|
2017-09-30 12:00:05 +02:00
|
|
|
SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
|
2013-05-04 02:08:52 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Optimize string (mis)handling (#8128)
* Optimize statbar drawing
The texture name of the statbar is a string passed by value.
That slows down the client and creates litter in the heap
as the content of the string is allocated there. Convert the
offending parameter to a const reference to avoid the
performance hit.
* Optimize texture cache
There is an unnecessary temporary created when the texture
path is being generated. This slows down the cache each time
a new texture is encountered and it needs to be loaded into
the cache. Additionally, the heap litter created by this
unnecessary temporary is particularly troublesome here as
the following code then piles another string (the resulting
full path of the texture) on top of it, followed by the
texture itself, which both are quite long term objects as
they are subsequently inserted into the cache where they can
remain for quite a while (especially if the texture turns
out to be a common one like dirt, grass or stone).
Use std::string.append to get rid of the temporary which
solves both issues (speed and heap fragmentation).
* Optimize animations in client
Each time an animated node is updated, an unnecessary copy of
the texture name is created, littering the heap with lots of
fragments. This can be specifically troublesome when looking
at oceans or large lava lakes as both of these nodes are
usually animated (the lava animation is pretty visible).
Convert the parameter of GenericCAO::updateTextures to a
const reference to get rid of the unnecessary copy.
There is a comment stating "std::string copy is mandatory as
mod can be a class member and there is a swap on those class
members ... do NOT pass by reference", reinforcing the
belief that the unnecessary copy is in fact necessary.
However one of the first things the code of the method does
is to assign the parameter to its class member, creating
another copy. By rearranging the code a little bit this
"another copy" can then be used by the subsequent code,
getting rid of the need to pass the parameter by value and
thus saving that copying effort.
* Optimize chat console history handling
The GUIChatConsole::replaceAndAddToHistory was getting the
line to work on by value which turns out to be unnecessary.
Get rid of that unnecessary copy by converting the parameter
to a const reference.
* Optimize gui texture setting
The code used to set the texture for GUI components was
getting the name of the texture by value, creating
unnecessary performance bottleneck for mods/games with
heavily textured GUIs. Get rid of the bottleneck by passing
the texture name as a const reference.
* Optimize sound playing code in GUIEngine
The GUIEngine's code receives the specification of the sound
to be played by value, which turns out to be most likely a
mistake as the underlying sound manager interface receives
the same thing by reference. Convert the offending parameter
to a const reference to get rid of the rather bulky copying
effort and the associated performance hit.
* Silence CLANG TIDY warnings for unit tests
Change "std::string" to "const std::string &" to avoid an
unnecessary local value copy, silencing the CLANG TIDY
process.
* Optimize formspec handling
The "formspec prepend" parameter was passed to the formspec
handling code by value, creating unnecessary copy of
std::string and slowing down the game if mods add things like
textured backgrounds for the player inventory and/or other
forms. Get rid of that performance bottleneck by converting
the parameter to a const reference.
* Optimize hotbar image handling
The code that sets the background images for the hotbar is
getting the name of the image by value, creating an
unnecessary std::string copying effort. Fix that by
converting the relevant parameters to const references.
* Optimize inventory deserialization
The inventory manager deserialization code gets the
serialized version of the inventory by value, slowing the
server and the client down when there are inventory updates.
This can get particularly troublesome with pipeworks which
adds nodes that can mess around with inventories
automatically or with mods that have mobs with inventories
that actively use them.
* Optimize texture scaling cache
There is an io::path parameter passed by value in the
procedure used to add images converted from textures,
leading to slowdown when the image is not yet created and
the conversion is thus needed. The performance hit is
quite significant as io::path is similar to std::string
so convert the parameter to a const reference to get rid of
it.
* Optimize translation file loader
Use "std::string::append" when calculating the final index
for the translation table to avoid unnecessary temporary
strings. This speeds the translation file loader up
significantly as std::string uses heap allocation which
tends to be rather slow. Additionally, the heap is no
longer being littered by these unnecessary string
temporaries, increasing performance of code that gets
executed after the translation file loader finishes.
* Optimize server map saving
When the directory structure for the world data is created
during server map saving, an unnecessary value passing of
the directory name slows things down. Remove that overhead
by converting the offending parameter to a const reference.
2019-05-18 17:19:13 +02:00
|
|
|
void Server::hudSetHotbarImage(RemotePlayer *player, const std::string &name)
|
2015-07-03 05:14:30 +02:00
|
|
|
{
|
2013-09-03 19:51:40 +02:00
|
|
|
if (!player)
|
|
|
|
return;
|
|
|
|
|
2024-02-29 14:56:13 +01:00
|
|
|
if (player->getHotbarImage() == name)
|
|
|
|
return;
|
|
|
|
|
2015-05-26 14:10:08 +02:00
|
|
|
player->setHotbarImage(name);
|
2017-09-30 12:00:05 +02:00
|
|
|
SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
|
2013-09-03 19:51:40 +02:00
|
|
|
}
|
|
|
|
|
Optimize string (mis)handling (#8128)
* Optimize statbar drawing
The texture name of the statbar is a string passed by value.
That slows down the client and creates litter in the heap
as the content of the string is allocated there. Convert the
offending parameter to a const reference to avoid the
performance hit.
* Optimize texture cache
There is an unnecessary temporary created when the texture
path is being generated. This slows down the cache each time
a new texture is encountered and it needs to be loaded into
the cache. Additionally, the heap litter created by this
unnecessary temporary is particularly troublesome here as
the following code then piles another string (the resulting
full path of the texture) on top of it, followed by the
texture itself, which both are quite long term objects as
they are subsequently inserted into the cache where they can
remain for quite a while (especially if the texture turns
out to be a common one like dirt, grass or stone).
Use std::string.append to get rid of the temporary which
solves both issues (speed and heap fragmentation).
* Optimize animations in client
Each time an animated node is updated, an unnecessary copy of
the texture name is created, littering the heap with lots of
fragments. This can be specifically troublesome when looking
at oceans or large lava lakes as both of these nodes are
usually animated (the lava animation is pretty visible).
Convert the parameter of GenericCAO::updateTextures to a
const reference to get rid of the unnecessary copy.
There is a comment stating "std::string copy is mandatory as
mod can be a class member and there is a swap on those class
members ... do NOT pass by reference", reinforcing the
belief that the unnecessary copy is in fact necessary.
However one of the first things the code of the method does
is to assign the parameter to its class member, creating
another copy. By rearranging the code a little bit this
"another copy" can then be used by the subsequent code,
getting rid of the need to pass the parameter by value and
thus saving that copying effort.
* Optimize chat console history handling
The GUIChatConsole::replaceAndAddToHistory was getting the
line to work on by value which turns out to be unnecessary.
Get rid of that unnecessary copy by converting the parameter
to a const reference.
* Optimize gui texture setting
The code used to set the texture for GUI components was
getting the name of the texture by value, creating
unnecessary performance bottleneck for mods/games with
heavily textured GUIs. Get rid of the bottleneck by passing
the texture name as a const reference.
* Optimize sound playing code in GUIEngine
The GUIEngine's code receives the specification of the sound
to be played by value, which turns out to be most likely a
mistake as the underlying sound manager interface receives
the same thing by reference. Convert the offending parameter
to a const reference to get rid of the rather bulky copying
effort and the associated performance hit.
* Silence CLANG TIDY warnings for unit tests
Change "std::string" to "const std::string &" to avoid an
unnecessary local value copy, silencing the CLANG TIDY
process.
* Optimize formspec handling
The "formspec prepend" parameter was passed to the formspec
handling code by value, creating unnecessary copy of
std::string and slowing down the game if mods add things like
textured backgrounds for the player inventory and/or other
forms. Get rid of that performance bottleneck by converting
the parameter to a const reference.
* Optimize hotbar image handling
The code that sets the background images for the hotbar is
getting the name of the image by value, creating an
unnecessary std::string copying effort. Fix that by
converting the relevant parameters to const references.
* Optimize inventory deserialization
The inventory manager deserialization code gets the
serialized version of the inventory by value, slowing the
server and the client down when there are inventory updates.
This can get particularly troublesome with pipeworks which
adds nodes that can mess around with inventories
automatically or with mods that have mobs with inventories
that actively use them.
* Optimize texture scaling cache
There is an io::path parameter passed by value in the
procedure used to add images converted from textures,
leading to slowdown when the image is not yet created and
the conversion is thus needed. The performance hit is
quite significant as io::path is similar to std::string
so convert the parameter to a const reference to get rid of
it.
* Optimize translation file loader
Use "std::string::append" when calculating the final index
for the translation table to avoid unnecessary temporary
strings. This speeds the translation file loader up
significantly as std::string uses heap allocation which
tends to be rather slow. Additionally, the heap is no
longer being littered by these unnecessary string
temporaries, increasing performance of code that gets
executed after the translation file loader finishes.
* Optimize server map saving
When the directory structure for the world data is created
during server map saving, an unnecessary value passing of
the directory name slows things down. Remove that overhead
by converting the offending parameter to a const reference.
2019-05-18 17:19:13 +02:00
|
|
|
void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &name)
|
2015-07-03 05:14:30 +02:00
|
|
|
{
|
2013-09-03 19:51:40 +02:00
|
|
|
if (!player)
|
|
|
|
return;
|
|
|
|
|
2024-02-29 14:56:13 +01:00
|
|
|
if (player->getHotbarSelectedImage() == name)
|
|
|
|
return;
|
|
|
|
|
2015-05-26 14:10:08 +02:00
|
|
|
player->setHotbarSelectedImage(name);
|
2017-09-30 12:00:05 +02:00
|
|
|
SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
|
2013-09-03 19:51:40 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
Address Server::getPeerAddress(session_t peer_id)
|
2017-08-24 08:28:54 +02:00
|
|
|
{
|
2021-01-31 20:36:47 +01:00
|
|
|
// Note that this is only set after Init was received in Server::handleCommand_Init
|
|
|
|
return getClient(peer_id, CS_Invalid)->getAddress();
|
2017-08-24 08:28:54 +02:00
|
|
|
}
|
|
|
|
|
2018-03-08 22:19:25 +01:00
|
|
|
void Server::setLocalPlayerAnimations(RemotePlayer *player,
|
2016-10-08 12:21:41 +02:00
|
|
|
v2s32 animation_frames[4], f32 frame_speed)
|
2014-01-08 13:47:53 +01:00
|
|
|
{
|
2018-03-08 22:19:25 +01:00
|
|
|
sanity_check(player);
|
2015-05-26 14:10:08 +02:00
|
|
|
player->setLocalAnimations(animation_frames, frame_speed);
|
2017-09-30 12:00:05 +02:00
|
|
|
SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
|
2014-01-08 13:47:53 +01:00
|
|
|
}
|
|
|
|
|
2024-02-29 14:56:13 +01:00
|
|
|
void Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third, v3f third_front)
|
2014-04-11 15:32:46 +02:00
|
|
|
{
|
2018-03-08 22:19:25 +01:00
|
|
|
sanity_check(player);
|
2024-02-29 14:56:13 +01:00
|
|
|
if (std::tie(player->eye_offset_first, player->eye_offset_third,
|
|
|
|
player->eye_offset_third_front) == std::tie(first, third, third_front))
|
|
|
|
return; // no change
|
|
|
|
|
2015-05-26 14:10:08 +02:00
|
|
|
player->eye_offset_first = first;
|
|
|
|
player->eye_offset_third = third;
|
2023-10-02 13:44:03 +02:00
|
|
|
player->eye_offset_third_front = third_front;
|
|
|
|
SendEyeOffset(player->getPeerId(), first, third, third_front);
|
2014-04-11 15:32:46 +02:00
|
|
|
}
|
|
|
|
|
2019-08-21 22:47:45 +02:00
|
|
|
void Server::setSky(RemotePlayer *player, const SkyboxParams ¶ms)
|
|
|
|
{
|
|
|
|
sanity_check(player);
|
|
|
|
player->setSky(params);
|
|
|
|
SendSetSky(player->getPeerId(), params);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Server::setSun(RemotePlayer *player, const SunParams ¶ms)
|
|
|
|
{
|
|
|
|
sanity_check(player);
|
|
|
|
player->setSun(params);
|
|
|
|
SendSetSun(player->getPeerId(), params);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Server::setMoon(RemotePlayer *player, const MoonParams ¶ms)
|
|
|
|
{
|
|
|
|
sanity_check(player);
|
|
|
|
player->setMoon(params);
|
|
|
|
SendSetMoon(player->getPeerId(), params);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Server::setStars(RemotePlayer *player, const StarParams ¶ms)
|
2013-05-02 22:52:50 +02:00
|
|
|
{
|
2018-03-08 22:19:25 +01:00
|
|
|
sanity_check(player);
|
2019-08-21 22:47:45 +02:00
|
|
|
player->setStars(params);
|
|
|
|
SendSetStars(player->getPeerId(), params);
|
2013-05-02 22:52:50 +02:00
|
|
|
}
|
|
|
|
|
2018-03-08 22:19:25 +01:00
|
|
|
void Server::setClouds(RemotePlayer *player, const CloudParams ¶ms)
|
2017-03-17 10:39:47 +01:00
|
|
|
{
|
2018-03-08 22:19:25 +01:00
|
|
|
sanity_check(player);
|
|
|
|
player->setCloudParams(params);
|
|
|
|
SendCloudParams(player->getPeerId(), params);
|
2017-03-17 10:39:47 +01:00
|
|
|
}
|
|
|
|
|
2020-05-07 22:38:41 +02:00
|
|
|
void Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
|
2015-07-03 05:14:30 +02:00
|
|
|
float ratio)
|
2013-10-18 10:53:19 +02:00
|
|
|
{
|
2020-05-07 22:38:41 +02:00
|
|
|
sanity_check(player);
|
2015-05-26 14:10:08 +02:00
|
|
|
player->overrideDayNightRatio(do_override, ratio);
|
2017-09-30 12:00:05 +02:00
|
|
|
SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
|
2013-10-18 10:53:19 +02:00
|
|
|
}
|
|
|
|
|
2022-03-26 16:58:26 +01:00
|
|
|
void Server::setLighting(RemotePlayer *player, const Lighting &lighting)
|
|
|
|
{
|
|
|
|
sanity_check(player);
|
|
|
|
player->setLighting(lighting);
|
|
|
|
SendSetLighting(player->getPeerId(), lighting);
|
|
|
|
}
|
|
|
|
|
2014-02-27 21:12:59 +01:00
|
|
|
void Server::notifyPlayers(const std::wstring &msg)
|
2011-10-17 23:01:50 +02:00
|
|
|
{
|
2017-07-16 10:47:31 +02:00
|
|
|
SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
|
2011-10-17 23:01:50 +02:00
|
|
|
}
|
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
void Server::spawnParticle(const std::string &playername,
|
|
|
|
const ParticleParameters &p)
|
2013-01-23 18:32:02 +01:00
|
|
|
{
|
2015-08-09 22:10:37 +02:00
|
|
|
// m_env will be NULL if the server is initializing
|
|
|
|
if (!m_env)
|
|
|
|
return;
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
session_t peer_id = PEER_ID_INEXISTENT;
|
|
|
|
u16 proto_ver = 0;
|
2017-08-14 01:06:12 +02:00
|
|
|
if (!playername.empty()) {
|
2016-10-08 19:08:23 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(playername.c_str());
|
2015-07-25 11:56:24 +02:00
|
|
|
if (!player)
|
|
|
|
return;
|
2017-09-30 12:00:05 +02:00
|
|
|
peer_id = player->getPeerId();
|
2017-01-14 16:48:49 +01:00
|
|
|
proto_ver = player->protocol_version;
|
2015-07-25 11:56:24 +02:00
|
|
|
}
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
SendSpawnParticle(peer_id, proto_ver, p);
|
2013-01-23 18:32:02 +01:00
|
|
|
}
|
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
u32 Server::addParticleSpawner(const ParticleSpawnerParameters &p,
|
|
|
|
ServerActiveObject *attached, const std::string &playername)
|
2013-01-23 18:32:02 +01:00
|
|
|
{
|
2015-08-09 22:10:37 +02:00
|
|
|
// m_env will be NULL if the server is initializing
|
|
|
|
if (!m_env)
|
|
|
|
return -1;
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
session_t peer_id = PEER_ID_INEXISTENT;
|
|
|
|
u16 proto_ver = 0;
|
2017-08-14 01:06:12 +02:00
|
|
|
if (!playername.empty()) {
|
2016-10-08 19:08:23 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(playername.c_str());
|
2015-07-25 11:56:24 +02:00
|
|
|
if (!player)
|
|
|
|
return -1;
|
2017-09-30 12:00:05 +02:00
|
|
|
peer_id = player->getPeerId();
|
2017-01-14 16:48:49 +01:00
|
|
|
proto_ver = player->protocol_version;
|
2013-01-23 18:32:02 +01:00
|
|
|
}
|
|
|
|
|
2016-08-04 22:09:21 +02:00
|
|
|
u16 attached_id = attached ? attached->getId() : 0;
|
|
|
|
|
|
|
|
u32 id;
|
|
|
|
if (attached_id == 0)
|
2020-05-22 13:23:25 +02:00
|
|
|
id = m_env->addParticleSpawner(p.time);
|
2016-08-04 22:09:21 +02:00
|
|
|
else
|
2020-05-22 13:23:25 +02:00
|
|
|
id = m_env->addParticleSpawner(p.time, attached_id);
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2020-05-22 13:23:25 +02:00
|
|
|
SendAddParticleSpawner(peer_id, proto_ver, p, attached_id, id);
|
2013-01-23 18:32:02 +01:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2015-07-25 11:56:24 +02:00
|
|
|
void Server::deleteParticleSpawner(const std::string &playername, u32 id)
|
2013-01-23 18:32:02 +01:00
|
|
|
{
|
2015-08-09 22:10:37 +02:00
|
|
|
// m_env will be NULL if the server is initializing
|
|
|
|
if (!m_env)
|
|
|
|
throw ServerError("Can't delete particle spawners during initialisation!");
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
session_t peer_id = PEER_ID_INEXISTENT;
|
2017-08-14 01:06:12 +02:00
|
|
|
if (!playername.empty()) {
|
2016-10-08 19:08:23 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(playername.c_str());
|
2015-07-25 11:56:24 +02:00
|
|
|
if (!player)
|
|
|
|
return;
|
2017-09-30 12:00:05 +02:00
|
|
|
peer_id = player->getPeerId();
|
2015-07-25 11:56:24 +02:00
|
|
|
}
|
2013-01-23 18:32:02 +01:00
|
|
|
|
2016-04-27 17:58:09 +02:00
|
|
|
m_env->deleteParticleSpawner(id);
|
2015-07-25 11:56:24 +02:00
|
|
|
SendDeleteParticleSpawner(peer_id, id);
|
2013-01-23 18:32:02 +01:00
|
|
|
}
|
|
|
|
|
2024-01-23 21:15:09 +01:00
|
|
|
namespace {
|
|
|
|
std::string writeToTempFile(std::string_view content)
|
|
|
|
{
|
|
|
|
auto filepath = fs::CreateTempFile();
|
|
|
|
if (filepath.empty())
|
|
|
|
return "";
|
2024-05-08 20:37:10 +02:00
|
|
|
auto os = open_ofstream(filepath.c_str(), true);
|
2024-01-23 21:15:09 +01:00
|
|
|
if (!os.good())
|
|
|
|
return "";
|
|
|
|
os << content;
|
|
|
|
os.close();
|
|
|
|
if (os.fail()) {
|
|
|
|
fs::DeleteSingleFileOrEmptyDirectory(filepath);
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
return filepath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Server::dynamicAddMedia(const DynamicMediaArgs &a)
|
|
|
|
{
|
|
|
|
std::string filename = a.filename;
|
|
|
|
std::string filepath;
|
|
|
|
|
|
|
|
// Deal with file -or- data, as provided
|
|
|
|
// (Note: caller must ensure validity, so sanity_check is okay)
|
|
|
|
if (a.filepath) {
|
|
|
|
sanity_check(!a.data);
|
|
|
|
filepath = *a.filepath;
|
|
|
|
if (filename.empty())
|
|
|
|
filename = fs::GetFilenameFromPath(filepath.c_str());
|
|
|
|
} else {
|
|
|
|
sanity_check(a.data);
|
|
|
|
sanity_check(!filename.empty());
|
|
|
|
|
|
|
|
// Write the file to disk. addMediaFile() will read it right back but this
|
|
|
|
// is the best way without turning the media loading code into spaghetti.
|
|
|
|
filepath = writeToTempFile(*a.data);
|
|
|
|
if (filepath.empty()) {
|
|
|
|
errorstream << "Server: failed writing media file \""
|
|
|
|
<< filename << "\" to disk" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
verbosestream << "Server: \"" << filename << "\" temporarily written to "
|
|
|
|
<< filepath << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do some checks
|
2021-09-09 16:51:35 +02:00
|
|
|
auto it = m_media.find(filename);
|
|
|
|
if (it != m_media.end()) {
|
|
|
|
// Allow the same path to be "added" again in certain conditions
|
2024-01-23 21:15:09 +01:00
|
|
|
if (a.ephemeral || it->second.path != filepath) {
|
2021-09-09 16:51:35 +02:00
|
|
|
errorstream << "Server::dynamicAddMedia(): file \"" << filename
|
|
|
|
<< "\" already exists in media cache" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
2020-06-13 19:03:26 +02:00
|
|
|
}
|
|
|
|
|
2024-01-23 21:15:09 +01:00
|
|
|
if (!m_env && (!a.to_player.empty() || a.ephemeral)) {
|
2024-01-22 20:37:26 +01:00
|
|
|
errorstream << "Server::dynamicAddMedia(): "
|
|
|
|
"adding ephemeral or player-specific media at startup is nonsense"
|
|
|
|
<< std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-06-13 19:03:26 +02:00
|
|
|
// Load the file and add it to our media cache
|
|
|
|
std::string filedata, raw_hash;
|
|
|
|
bool ok = addMediaFile(filename, filepath, &filedata, &raw_hash);
|
|
|
|
if (!ok)
|
|
|
|
return false;
|
2024-01-23 21:15:09 +01:00
|
|
|
assert(!filedata.empty());
|
|
|
|
|
|
|
|
const auto &media_it = m_media.find(filename);
|
|
|
|
assert(media_it != m_media.end());
|
|
|
|
|
|
|
|
if (a.ephemeral) {
|
|
|
|
if (!a.data) {
|
|
|
|
// Create a copy of the file and swap out the path, this removes the
|
|
|
|
// requirement that mods keep the file accessible at the original path.
|
|
|
|
filepath = writeToTempFile(filedata);
|
|
|
|
if (filepath.empty()) {
|
|
|
|
errorstream << "Server: failed creating a copy of media file \""
|
|
|
|
<< filename << "\"" << std::endl;
|
|
|
|
m_media.erase(filename);
|
2021-09-09 16:51:35 +02:00
|
|
|
return false;
|
2024-01-23 21:15:09 +01:00
|
|
|
}
|
|
|
|
verbosestream << "Server: \"" << filename << "\" temporarily copied to "
|
|
|
|
<< filepath << std::endl;
|
|
|
|
media_it->second.path = filepath;
|
2021-09-09 16:51:35 +02:00
|
|
|
}
|
|
|
|
|
2024-01-23 21:15:09 +01:00
|
|
|
media_it->second.no_announce = true;
|
|
|
|
// stepPendingDynMediaCallbacks will clean the file up later
|
|
|
|
} else if (a.data) {
|
|
|
|
// data is in a temporary file but not ephemeral, so the cleanup point
|
|
|
|
// is different.
|
|
|
|
media_it->second.delete_at_shutdown = true;
|
|
|
|
}
|
|
|
|
if (!a.to_player.empty()) {
|
|
|
|
// only sent to one player (who must be online), so shouldn't announce.
|
|
|
|
media_it->second.no_announce = true;
|
2021-09-09 16:51:35 +02:00
|
|
|
}
|
|
|
|
|
2024-01-22 20:37:26 +01:00
|
|
|
std::unordered_set<session_t> delivered, waiting;
|
|
|
|
|
2020-06-13 19:03:26 +02:00
|
|
|
// Push file to existing clients
|
2024-01-22 20:37:26 +01:00
|
|
|
if (m_env) {
|
|
|
|
NetworkPacket pkt(TOCLIENT_MEDIA_PUSH, 0);
|
2024-01-23 21:15:09 +01:00
|
|
|
pkt << raw_hash << filename << static_cast<bool>(a.ephemeral);
|
2021-09-09 16:51:35 +02:00
|
|
|
|
2024-01-22 20:37:26 +01:00
|
|
|
NetworkPacket legacy_pkt = pkt;
|
2020-06-13 19:03:26 +02:00
|
|
|
|
2024-01-22 20:37:26 +01:00
|
|
|
// Newer clients get asked to fetch the file (asynchronous)
|
2024-01-23 21:15:09 +01:00
|
|
|
pkt << a.token;
|
2024-01-22 20:37:26 +01:00
|
|
|
// Older clients have an awful hack that just throws the data at them
|
|
|
|
legacy_pkt.putLongString(filedata);
|
2021-09-09 16:51:35 +02:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
ClientInterface::AutoLock clientlock(m_clients);
|
|
|
|
for (auto &pair : m_clients.getClientList()) {
|
2024-01-23 21:15:09 +01:00
|
|
|
if (pair.second->getState() == CS_DefinitionsSent && !a.ephemeral) {
|
2022-02-02 02:49:19 +01:00
|
|
|
/*
|
|
|
|
If a client is in the DefinitionsSent state it is too late to
|
|
|
|
transfer the file via sendMediaAnnouncement() but at the same
|
|
|
|
time the client cannot accept a media push yet.
|
|
|
|
Short of artificially delaying the joining process there is no
|
|
|
|
way for the server to resolve this so we (currently) opt not to.
|
|
|
|
*/
|
|
|
|
warningstream << "The media \"" << filename << "\" (dynamic) could "
|
|
|
|
"not be delivered to " << pair.second->getName()
|
|
|
|
<< " due to a race condition." << std::endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (pair.second->getState() < CS_Active)
|
|
|
|
continue;
|
2022-01-09 20:43:25 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
const auto proto_ver = pair.second->net_proto_version;
|
|
|
|
if (proto_ver < 39)
|
|
|
|
continue;
|
2021-01-30 14:35:34 +01:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
const session_t peer_id = pair.second->peer_id;
|
2024-01-23 21:15:09 +01:00
|
|
|
if (!a.to_player.empty() && getPlayerName(peer_id) != a.to_player)
|
2022-02-02 02:49:19 +01:00
|
|
|
continue;
|
2021-09-09 16:51:35 +02:00
|
|
|
|
2022-02-02 02:49:19 +01:00
|
|
|
if (proto_ver < 40) {
|
|
|
|
delivered.emplace(peer_id);
|
|
|
|
/*
|
|
|
|
The network layer only guarantees ordered delivery inside a channel.
|
|
|
|
Since the very next packet could be one that uses the media, we have
|
|
|
|
to push the media over ALL channels to ensure it is processed before
|
|
|
|
it is used. In practice this means channels 1 and 0.
|
|
|
|
*/
|
2024-01-24 18:23:11 +01:00
|
|
|
m_clients.sendCustom(peer_id, 1, &legacy_pkt, true);
|
|
|
|
m_clients.sendCustom(peer_id, 0, &legacy_pkt, true);
|
2022-02-02 02:49:19 +01:00
|
|
|
} else {
|
|
|
|
waiting.emplace(peer_id);
|
|
|
|
Send(peer_id, &pkt);
|
|
|
|
}
|
2021-09-09 16:51:35 +02:00
|
|
|
}
|
2020-06-13 19:03:26 +02:00
|
|
|
}
|
|
|
|
|
2021-09-09 16:51:35 +02:00
|
|
|
// Run callback for players that already had the file delivered (legacy-only)
|
|
|
|
for (session_t peer_id : delivered) {
|
|
|
|
if (auto player = m_env->getPlayer(peer_id))
|
2024-01-23 21:15:09 +01:00
|
|
|
getScriptIface()->on_dynamic_media_added(a.token, player->getName());
|
2021-09-09 16:51:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Save all others in our pending state
|
2024-01-23 21:15:09 +01:00
|
|
|
auto &state = m_pending_dyn_media[a.token];
|
2021-09-09 16:51:35 +02:00
|
|
|
state.waiting_players = std::move(waiting);
|
|
|
|
// regardless of success throw away the callback after a while
|
|
|
|
state.expiry_timer = 60.0f;
|
2024-01-23 21:15:09 +01:00
|
|
|
if (a.ephemeral)
|
2021-09-09 16:51:35 +02:00
|
|
|
state.filename = filename;
|
|
|
|
|
2020-06-13 19:03:26 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-07-26 21:06:45 +02:00
|
|
|
// actions: time-reversed list
|
|
|
|
// Return value: success/failure
|
|
|
|
bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
|
|
|
|
std::list<std::string> *log)
|
|
|
|
{
|
|
|
|
infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
|
2024-03-12 14:13:24 +01:00
|
|
|
auto *map = &m_env->getServerMap();
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2012-07-26 21:06:45 +02:00
|
|
|
// Fail if no actions to handle
|
2018-04-04 08:40:21 +02:00
|
|
|
if (actions.empty()) {
|
|
|
|
assert(log);
|
2012-07-26 21:06:45 +02:00
|
|
|
log->push_back("Nothing to do.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int num_tried = 0;
|
|
|
|
int num_failed = 0;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2017-08-14 01:06:12 +02:00
|
|
|
for (const RollbackAction &action : actions) {
|
2012-07-26 21:06:45 +02:00
|
|
|
num_tried++;
|
2020-05-07 22:38:41 +02:00
|
|
|
bool success = action.applyRevert(map, m_inventory_mgr.get(), this);
|
2012-07-26 21:06:45 +02:00
|
|
|
if(!success){
|
|
|
|
num_failed++;
|
|
|
|
std::ostringstream os;
|
|
|
|
os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
|
|
|
|
infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
|
2017-08-14 01:06:12 +02:00
|
|
|
if (log)
|
2012-07-26 21:06:45 +02:00
|
|
|
log->push_back(os.str());
|
|
|
|
}else{
|
|
|
|
std::ostringstream os;
|
2012-12-17 16:46:54 +01:00
|
|
|
os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
|
2012-07-26 21:06:45 +02:00
|
|
|
infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
|
2017-08-14 01:06:12 +02:00
|
|
|
if (log)
|
2012-07-26 21:06:45 +02:00
|
|
|
log->push_back(os.str());
|
|
|
|
}
|
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2012-07-26 21:06:45 +02:00
|
|
|
infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
|
|
|
|
<<" failed"<<std::endl;
|
|
|
|
|
|
|
|
// Call it done if less than half failed
|
|
|
|
return num_failed <= num_tried/2;
|
|
|
|
}
|
|
|
|
|
2011-11-14 20:41:30 +01:00
|
|
|
// IGameDef interface
|
|
|
|
// Under envlock
|
2015-07-03 05:14:30 +02:00
|
|
|
IItemDefManager *Server::getItemDefManager()
|
2011-11-14 20:41:30 +01:00
|
|
|
{
|
2012-01-12 06:10:39 +01:00
|
|
|
return m_itemdef;
|
2011-11-14 20:41:30 +01:00
|
|
|
}
|
2015-07-03 05:14:30 +02:00
|
|
|
|
2018-02-10 21:04:16 +01:00
|
|
|
const NodeDefManager *Server::getNodeDefManager()
|
2011-11-14 20:41:30 +01:00
|
|
|
{
|
2011-11-16 13:08:31 +01:00
|
|
|
return m_nodedef;
|
2011-11-14 20:41:30 +01:00
|
|
|
}
|
2015-07-03 05:14:30 +02:00
|
|
|
|
|
|
|
ICraftDefManager *Server::getCraftDefManager()
|
2011-11-17 01:28:46 +01:00
|
|
|
{
|
|
|
|
return m_craftdef;
|
|
|
|
}
|
2014-10-21 05:12:15 +02:00
|
|
|
|
2011-11-16 12:03:28 +01:00
|
|
|
u16 Server::allocateUnknownNodeId(const std::string &name)
|
|
|
|
{
|
2011-11-16 13:08:31 +01:00
|
|
|
return m_nodedef->allocateDummy(name);
|
2011-11-16 12:03:28 +01:00
|
|
|
}
|
2015-07-03 05:14:30 +02:00
|
|
|
|
|
|
|
IWritableItemDefManager *Server::getWritableItemDefManager()
|
2011-11-15 01:03:28 +01:00
|
|
|
{
|
2012-01-12 06:10:39 +01:00
|
|
|
return m_itemdef;
|
2011-11-15 01:03:28 +01:00
|
|
|
}
|
2015-07-03 05:14:30 +02:00
|
|
|
|
2018-02-10 21:04:16 +01:00
|
|
|
NodeDefManager *Server::getWritableNodeDefManager()
|
2011-11-15 01:03:28 +01:00
|
|
|
{
|
2011-11-16 13:08:31 +01:00
|
|
|
return m_nodedef;
|
2011-11-15 01:03:28 +01:00
|
|
|
}
|
2015-07-03 05:14:30 +02:00
|
|
|
|
|
|
|
IWritableCraftDefManager *Server::getWritableCraftDefManager()
|
2011-11-17 01:28:46 +01:00
|
|
|
{
|
|
|
|
return m_craftdef;
|
|
|
|
}
|
2011-11-15 01:03:28 +01:00
|
|
|
|
2018-03-16 08:41:33 +01:00
|
|
|
const std::vector<ModSpec> & Server::getMods() const
|
|
|
|
{
|
|
|
|
return m_modmgr->getMods();
|
|
|
|
}
|
|
|
|
|
2015-07-03 05:14:30 +02:00
|
|
|
const ModSpec *Server::getModSpec(const std::string &modname) const
|
2011-12-11 15:49:40 +01:00
|
|
|
{
|
2018-03-16 08:41:33 +01:00
|
|
|
return m_modmgr->getModSpec(modname);
|
2011-12-11 15:49:40 +01:00
|
|
|
}
|
2015-07-03 05:14:30 +02:00
|
|
|
|
2017-01-28 18:31:23 +01:00
|
|
|
std::string Server::getBuiltinLuaPath()
|
2012-04-01 09:08:52 +02:00
|
|
|
{
|
|
|
|
return porting::path_share + DIR_DELIM + "builtin";
|
|
|
|
}
|
2011-12-11 15:49:40 +01:00
|
|
|
|
2023-07-03 20:34:02 +02:00
|
|
|
// Not thread-safe.
|
|
|
|
void Server::addShutdownError(const ModError &e)
|
|
|
|
{
|
|
|
|
// DO NOT TRANSLATE the `ModError`, it's used by `ui.lua`
|
|
|
|
std::string msg = fmtgettext("%s while shutting down: ", "ModError") +
|
|
|
|
e.what() + strgettext("\nCheck debug.txt for details.");
|
|
|
|
errorstream << msg << std::endl;
|
|
|
|
|
|
|
|
if (m_shutdown_errmsg) {
|
|
|
|
if (m_shutdown_errmsg->empty()) {
|
|
|
|
*m_shutdown_errmsg = msg;
|
|
|
|
} else {
|
|
|
|
*m_shutdown_errmsg += "\n\n" + msg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-03 09:04:02 +02:00
|
|
|
v3f Server::findSpawnPos()
|
2011-04-21 18:35:17 +02:00
|
|
|
{
|
2015-04-03 09:04:02 +02:00
|
|
|
ServerMap &map = m_env->getServerMap();
|
|
|
|
v3f nodeposf;
|
2019-08-07 23:07:51 +02:00
|
|
|
if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf))
|
2015-04-03 09:04:02 +02:00
|
|
|
return nodeposf * BS;
|
2011-06-25 03:25:14 +02:00
|
|
|
|
2015-04-03 09:04:02 +02:00
|
|
|
bool is_good = false;
|
2017-06-04 23:28:32 +02:00
|
|
|
// Limit spawn range to mapgen edges (determined by 'mapgen_limit')
|
|
|
|
s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
|
2015-04-03 09:04:02 +02:00
|
|
|
|
2011-04-21 18:35:17 +02:00
|
|
|
// Try to find a good place a few times
|
2019-08-07 23:07:51 +02:00
|
|
|
for (s32 i = 0; i < 4000 && !is_good; i++) {
|
2017-06-04 23:28:32 +02:00
|
|
|
s32 range = MYMIN(1 + i, range_max);
|
2011-04-21 18:35:17 +02:00
|
|
|
// We're going to try to throw the player to this position
|
2013-04-21 21:39:34 +02:00
|
|
|
v2s16 nodepos2d = v2s16(
|
2022-07-13 11:57:12 +02:00
|
|
|
-range + myrand_range(0, range*2),
|
|
|
|
-range + myrand_range(0, range*2));
|
2016-02-04 02:03:31 +01:00
|
|
|
// Get spawn level at point
|
|
|
|
s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
|
2019-08-07 23:07:51 +02:00
|
|
|
// Continue if MAX_MAP_GENERATION_LIMIT was returned by the mapgen to
|
|
|
|
// signify an unsuitable spawn position, or if outside limits.
|
|
|
|
if (spawn_level >= MAX_MAP_GENERATION_LIMIT ||
|
|
|
|
spawn_level <= -MAX_MAP_GENERATION_LIMIT)
|
2011-04-21 18:35:17 +02:00
|
|
|
continue;
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2016-02-04 02:03:31 +01:00
|
|
|
v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
|
2019-08-07 23:07:51 +02:00
|
|
|
// Consecutive empty nodes
|
2011-11-13 02:17:42 +01:00
|
|
|
s32 air_count = 0;
|
2019-08-07 23:07:51 +02:00
|
|
|
|
|
|
|
// Search upwards from 'spawn level' for 2 consecutive empty nodes, to
|
|
|
|
// avoid obstructions in already-generated mapblocks.
|
|
|
|
// In ungenerated mapblocks consisting of 'ignore' nodes, there will be
|
|
|
|
// no obstructions, but mapgen decorations are generated after spawn so
|
|
|
|
// the player may end up inside one.
|
|
|
|
for (s32 i = 0; i < 8; i++) {
|
2011-11-13 02:17:42 +01:00
|
|
|
v3s16 blockpos = getNodeBlockPos(nodepos);
|
|
|
|
map.emergeBlock(blockpos, true);
|
2019-08-10 19:45:44 +02:00
|
|
|
content_t c = map.getNode(nodepos).getContent();
|
2019-08-07 23:07:51 +02:00
|
|
|
|
|
|
|
// In generated mapblocks allow spawn in all 'airlike' drawtype nodes.
|
|
|
|
// In ungenerated mapblocks allow spawn in 'ignore' nodes.
|
|
|
|
if (m_nodedef->get(c).drawtype == NDT_AIRLIKE || c == CONTENT_IGNORE) {
|
2011-11-13 02:17:42 +01:00
|
|
|
air_count++;
|
2015-09-29 17:26:07 +02:00
|
|
|
if (air_count >= 2) {
|
2019-08-07 23:07:51 +02:00
|
|
|
// Spawn in lower empty node
|
|
|
|
nodepos.Y--;
|
2015-09-29 17:26:07 +02:00
|
|
|
nodeposf = intToFloat(nodepos, BS);
|
|
|
|
// Don't spawn the player outside map boundaries
|
|
|
|
if (objectpos_over_limit(nodeposf))
|
2019-08-07 23:07:51 +02:00
|
|
|
// Exit this loop, positions above are probably over limit
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Good position found, cause an exit from main loop
|
2011-11-13 02:17:42 +01:00
|
|
|
is_good = true;
|
|
|
|
break;
|
|
|
|
}
|
2019-08-07 23:07:51 +02:00
|
|
|
} else {
|
|
|
|
air_count = 0;
|
2011-11-13 02:17:42 +01:00
|
|
|
}
|
|
|
|
nodepos.Y++;
|
|
|
|
}
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
2012-11-26 03:16:48 +01:00
|
|
|
|
2019-08-07 23:07:51 +02:00
|
|
|
if (is_good)
|
|
|
|
return nodeposf;
|
|
|
|
|
|
|
|
// No suitable spawn point found, return fallback 0,0,0
|
|
|
|
return v3f(0.0f, 0.0f, 0.0f);
|
2011-04-21 18:35:17 +02:00
|
|
|
}
|
|
|
|
|
2017-04-15 23:19:18 +02:00
|
|
|
void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
|
|
|
|
{
|
|
|
|
if (delay == 0.0f) {
|
|
|
|
// No delay, shutdown immediately
|
2018-06-13 21:58:34 +02:00
|
|
|
m_shutdown_state.is_requested = true;
|
2017-06-04 21:00:04 +02:00
|
|
|
// only print to the infostream, a chat message saying
|
2017-04-21 19:31:59 +02:00
|
|
|
// "Server Shutting Down" is sent when the server destructs.
|
|
|
|
infostream << "*** Immediate Server shutdown requested." << std::endl;
|
2018-06-13 21:58:34 +02:00
|
|
|
} else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
|
|
|
|
// Negative delay, cancel shutdown if requested
|
|
|
|
m_shutdown_state.reset();
|
2017-04-15 23:19:18 +02:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
const char *s = "*** Server shutdown canceled.";
|
2017-04-15 23:19:18 +02:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
infostream << s << std::endl;
|
|
|
|
SendChatMessage(PEER_ID_INEXISTENT, utf8_to_wide(s));
|
|
|
|
// m_shutdown_state already handled, skip.
|
2018-06-11 13:43:12 +02:00
|
|
|
return;
|
2017-04-15 23:19:18 +02:00
|
|
|
} else if (delay > 0.0f) {
|
2017-04-21 19:31:59 +02:00
|
|
|
// Positive delay, tell the clients when the server will shut down
|
2024-03-12 14:13:24 +01:00
|
|
|
std::ostringstream oss;
|
2017-04-15 23:19:18 +02:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
oss << "*** Server shutting down in "
|
|
|
|
<< duration_to_string(myround(delay)) << ".";
|
2017-04-15 23:19:18 +02:00
|
|
|
|
2024-03-12 14:13:24 +01:00
|
|
|
infostream << oss.str() << std::endl;
|
|
|
|
SendChatMessage(PEER_ID_INEXISTENT, utf8_to_wide(oss.str()));
|
2017-04-15 23:19:18 +02:00
|
|
|
}
|
2018-06-11 13:43:12 +02:00
|
|
|
|
2018-06-13 21:58:34 +02:00
|
|
|
m_shutdown_state.trigger(delay, msg, reconnect);
|
2017-04-15 23:19:18 +02:00
|
|
|
}
|
|
|
|
|
2017-09-27 19:47:36 +02:00
|
|
|
PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
|
2011-01-15 02:28:19 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Try to get an existing player
|
|
|
|
*/
|
2016-10-08 17:56:38 +02:00
|
|
|
RemotePlayer *player = m_env->getPlayer(name);
|
2012-01-24 00:00:26 +01:00
|
|
|
|
2012-03-19 03:04:16 +01:00
|
|
|
// If player is already connected, cancel
|
2024-03-10 13:24:35 +01:00
|
|
|
if (player) {
|
2012-03-19 03:04:16 +01:00
|
|
|
infostream<<"emergePlayer(): Player already connected"<<std::endl;
|
|
|
|
return NULL;
|
2011-01-15 02:28:19 +01:00
|
|
|
}
|
2011-01-17 23:26:09 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
If player with the wanted peer_id already exists, cancel.
|
|
|
|
*/
|
2017-08-15 09:30:31 +02:00
|
|
|
if (m_env->getPlayer(peer_id)) {
|
2011-10-16 13:57:53 +02:00
|
|
|
infostream<<"emergePlayer(): Player with wrong name but same"
|
2011-01-17 23:26:09 +01:00
|
|
|
" peer_id already exists"<<std::endl;
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-03-19 03:04:16 +01:00
|
|
|
|
2024-02-02 22:13:24 +01:00
|
|
|
/*
|
|
|
|
Object construction sequence/hierarchy
|
|
|
|
--------------------------------------
|
|
|
|
1. RemoteClient (tightly connection-bound)
|
|
|
|
2. RemotePlayer (controls, in-game appearance)
|
|
|
|
3. PlayerSAO (movable object in-game)
|
|
|
|
PlayerSAO controls the peer_id assignment of RemotePlayer,
|
|
|
|
indicating whether the player is ready
|
|
|
|
|
|
|
|
Destruction sequence
|
|
|
|
--------------------
|
|
|
|
1. PlayerSAO pending removal flag
|
|
|
|
2. PlayerSAO save data before free
|
|
|
|
3. RemotePlayer, then PlayerSAO freed
|
|
|
|
4. RemoteClient freed
|
|
|
|
*/
|
|
|
|
|
2014-05-30 22:04:07 +02:00
|
|
|
if (!player) {
|
2017-04-23 14:35:08 +02:00
|
|
|
player = new RemotePlayer(name, idef());
|
2012-03-19 03:04:16 +01:00
|
|
|
}
|
2011-01-15 02:28:19 +01:00
|
|
|
|
2017-04-23 14:35:08 +02:00
|
|
|
bool newplayer = false;
|
2015-07-17 16:40:41 +02:00
|
|
|
|
2017-04-23 14:35:08 +02:00
|
|
|
// Load player
|
|
|
|
PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
|
2013-05-10 03:10:33 +02:00
|
|
|
|
2017-04-23 14:35:08 +02:00
|
|
|
// Complete init with server parts
|
|
|
|
playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
|
|
|
|
player->protocol_version = proto_version;
|
2011-01-15 02:28:19 +01:00
|
|
|
|
2012-03-19 03:04:16 +01:00
|
|
|
/* Run scripts */
|
2014-05-30 22:04:07 +02:00
|
|
|
if (newplayer) {
|
2013-05-25 00:51:02 +02:00
|
|
|
m_script->on_newplayer(playersao);
|
2014-05-30 22:04:07 +02:00
|
|
|
}
|
2012-03-19 03:04:16 +01:00
|
|
|
|
|
|
|
return playersao;
|
2011-01-15 02:28:19 +01:00
|
|
|
}
|
|
|
|
|
2011-02-15 15:11:24 +01:00
|
|
|
void dedicated_server_loop(Server &server, bool &kill)
|
2011-01-23 16:29:15 +01:00
|
|
|
{
|
2012-03-11 03:15:45 +01:00
|
|
|
verbosestream<<"dedicated_server_loop()"<<std::endl;
|
2011-05-30 23:15:43 +02:00
|
|
|
|
|
|
|
IntervalLimiter m_profiler_interval;
|
2011-01-23 16:29:15 +01:00
|
|
|
|
2023-03-29 11:42:50 +02:00
|
|
|
constexpr float steplen = 0.05f; // always 50 ms
|
|
|
|
const float profiler_print_interval = g_settings->getFloat("profiler_print_interval");
|
|
|
|
|
|
|
|
server.setStepSettings(Server::StepSettings{
|
|
|
|
g_settings->getFloat("dedicated_server_step"),
|
|
|
|
false
|
|
|
|
});
|
2015-09-02 21:21:55 +02:00
|
|
|
|
2019-11-14 17:38:15 +01:00
|
|
|
/*
|
2023-03-29 11:42:50 +02:00
|
|
|
* The dedicated server loop only provides a way to main.cpp to kill the
|
|
|
|
* server externally (bool &kill).
|
2019-11-14 17:38:15 +01:00
|
|
|
*/
|
|
|
|
|
2015-09-02 21:21:55 +02:00
|
|
|
for(;;) {
|
2011-01-23 16:29:15 +01:00
|
|
|
// This is kind of a hack but can be done like this
|
|
|
|
// because server.step() is very light
|
2023-03-29 11:42:50 +02:00
|
|
|
sleep_ms((int)(steplen*1000.0f));
|
|
|
|
server.step();
|
2011-01-23 16:29:15 +01:00
|
|
|
|
2018-06-13 21:58:34 +02:00
|
|
|
if (server.isShutdownRequested() || kill)
|
2017-03-19 18:17:59 +01:00
|
|
|
break;
|
|
|
|
|
2011-05-30 23:15:43 +02:00
|
|
|
/*
|
|
|
|
Profiler
|
|
|
|
*/
|
2024-04-11 12:42:12 +02:00
|
|
|
if (profiler_print_interval > 0) {
|
|
|
|
if (m_profiler_interval.step(steplen, profiler_print_interval)) {
|
|
|
|
infostream << "Profiler:" << std::endl;
|
2011-10-16 13:57:53 +02:00
|
|
|
g_profiler->print(infostream);
|
2011-10-12 12:53:38 +02:00
|
|
|
g_profiler->clear();
|
2011-05-30 23:15:43 +02:00
|
|
|
}
|
|
|
|
}
|
2011-01-23 16:29:15 +01:00
|
|
|
}
|
2015-10-15 19:04:15 +02:00
|
|
|
|
|
|
|
infostream << "Dedicated server quitting" << std::endl;
|
|
|
|
#if USE_CURL
|
|
|
|
if (g_settings->getBool("server_announce"))
|
|
|
|
ServerList::sendAnnounce(ServerList::AA_DELETE,
|
|
|
|
server.m_bind_addr.getPort());
|
|
|
|
#endif
|
2024-04-11 12:42:12 +02:00
|
|
|
|
|
|
|
if (profiler_print_interval > 0) {
|
|
|
|
infostream << "Profiler:" << std::endl;
|
|
|
|
g_profiler->print(infostream);
|
|
|
|
g_profiler->clear();
|
|
|
|
}
|
2011-01-23 16:29:15 +01:00
|
|
|
}
|
2017-09-26 00:11:20 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Mod channels
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
bool Server::joinModChannel(const std::string &channel)
|
|
|
|
{
|
|
|
|
return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
|
|
|
|
m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Server::leaveModChannel(const std::string &channel)
|
|
|
|
{
|
|
|
|
return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
|
|
|
|
{
|
|
|
|
if (!m_modchannel_mgr->canWriteOnChannel(channel))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ModChannel* Server::getModChannel(const std::string &channel)
|
|
|
|
{
|
|
|
|
return m_modchannel_mgr->getModChannel(channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Server::broadcastModChannelMessage(const std::string &channel,
|
2017-09-27 23:48:06 +02:00
|
|
|
const std::string &message, session_t from_peer)
|
2017-09-26 00:11:20 +02:00
|
|
|
{
|
|
|
|
const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
|
|
|
|
if (peers.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (message.size() > STRING_MAX_LEN) {
|
|
|
|
warningstream << "ModChannel message too long, dropping before sending "
|
|
|
|
<< " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
|
|
|
|
<< channel << ")" << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string sender;
|
|
|
|
if (from_peer != PEER_ID_SERVER) {
|
|
|
|
sender = getPlayerName(from_peer);
|
|
|
|
}
|
|
|
|
|
|
|
|
NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
|
|
|
|
2 + channel.size() + 2 + sender.size() + 2 + message.size());
|
|
|
|
resp_pkt << channel << sender << message;
|
2017-09-27 19:47:36 +02:00
|
|
|
for (session_t peer_id : peers) {
|
2017-09-26 00:11:20 +02:00
|
|
|
// Ignore sender
|
|
|
|
if (peer_id == from_peer)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Send(peer_id, &resp_pkt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from_peer != PEER_ID_SERVER) {
|
|
|
|
m_script->on_modchannel_message(channel, sender, message);
|
|
|
|
}
|
|
|
|
}
|
2020-04-25 07:20:00 +02:00
|
|
|
|
2020-09-16 15:51:11 +02:00
|
|
|
Translations *Server::getTranslationLanguage(const std::string &lang_code)
|
2020-04-25 07:20:00 +02:00
|
|
|
{
|
2020-09-16 15:51:11 +02:00
|
|
|
if (lang_code.empty())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
auto it = server_translations.find(lang_code);
|
|
|
|
if (it != server_translations.end())
|
|
|
|
return &it->second; // Already loaded
|
|
|
|
|
|
|
|
// [] will create an entry
|
|
|
|
auto *translations = &server_translations[lang_code];
|
2020-04-25 07:20:00 +02:00
|
|
|
|
|
|
|
std::string suffix = "." + lang_code + ".tr";
|
|
|
|
for (const auto &i : m_media) {
|
|
|
|
if (str_ends_with(i.first, suffix)) {
|
2020-09-16 15:51:11 +02:00
|
|
|
std::string data;
|
2024-05-08 20:37:10 +02:00
|
|
|
if (fs::ReadFile(i.second.path, data, true)) {
|
2020-09-16 15:51:11 +02:00
|
|
|
translations->loadTranslation(data);
|
|
|
|
}
|
2020-04-25 07:20:00 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-16 15:51:11 +02:00
|
|
|
|
|
|
|
return translations;
|
2020-04-25 07:20:00 +02:00
|
|
|
}
|
2022-01-07 19:28:49 +01:00
|
|
|
|
2024-01-20 16:26:05 +01:00
|
|
|
std::unordered_map<std::string, std::string> Server::getMediaList()
|
|
|
|
{
|
|
|
|
MutexAutoLock env_lock(m_env_mutex);
|
|
|
|
|
|
|
|
std::unordered_map<std::string, std::string> ret;
|
|
|
|
for (auto &it : m_media) {
|
|
|
|
if (it.second.no_announce)
|
|
|
|
continue;
|
|
|
|
ret.emplace(base64_decode(it.second.sha1_digest), it.second.path);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-11-23 23:25:34 +01:00
|
|
|
ModStorageDatabase *Server::openModStorageDatabase(const std::string &world_path)
|
2022-01-07 19:28:49 +01:00
|
|
|
{
|
|
|
|
std::string world_mt_path = world_path + DIR_DELIM + "world.mt";
|
|
|
|
Settings world_mt;
|
|
|
|
if (!world_mt.readConfigFile(world_mt_path.c_str()))
|
|
|
|
throw BaseException("Cannot read world.mt!");
|
|
|
|
|
|
|
|
std::string backend = world_mt.exists("mod_storage_backend") ?
|
|
|
|
world_mt.get("mod_storage_backend") : "files";
|
|
|
|
if (backend == "files")
|
|
|
|
warningstream << "/!\\ You are using the old mod storage files backend. "
|
|
|
|
<< "This backend is deprecated and may be removed in a future release /!\\"
|
|
|
|
<< std::endl << "Switching to SQLite3 is advised, "
|
|
|
|
<< "please read http://wiki.minetest.net/Database_backends." << std::endl;
|
|
|
|
|
|
|
|
return openModStorageDatabase(backend, world_path, world_mt);
|
|
|
|
}
|
|
|
|
|
2022-11-23 23:25:34 +01:00
|
|
|
ModStorageDatabase *Server::openModStorageDatabase(const std::string &backend,
|
2022-01-07 19:28:49 +01:00
|
|
|
const std::string &world_path, const Settings &world_mt)
|
|
|
|
{
|
|
|
|
if (backend == "sqlite3")
|
2022-11-23 23:25:34 +01:00
|
|
|
return new ModStorageDatabaseSQLite3(world_path);
|
2022-01-07 19:28:49 +01:00
|
|
|
|
2022-10-19 20:16:57 +02:00
|
|
|
#if USE_POSTGRESQL
|
|
|
|
if (backend == "postgresql") {
|
|
|
|
std::string connect_string;
|
|
|
|
world_mt.getNoEx("pgsql_mod_storage_connection", connect_string);
|
2022-11-23 23:25:34 +01:00
|
|
|
return new ModStorageDatabasePostgreSQL(connect_string);
|
2022-10-19 20:16:57 +02:00
|
|
|
}
|
|
|
|
#endif // USE_POSTGRESQL
|
|
|
|
|
2022-01-07 19:28:49 +01:00
|
|
|
if (backend == "files")
|
2022-11-23 23:25:34 +01:00
|
|
|
return new ModStorageDatabaseFiles(world_path);
|
2022-01-07 19:28:49 +01:00
|
|
|
|
|
|
|
if (backend == "dummy")
|
|
|
|
return new Database_Dummy();
|
|
|
|
|
|
|
|
throw BaseException("Mod storage database backend " + backend + " not supported");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Server::migrateModStorageDatabase(const GameParams &game_params, const Settings &cmd_args)
|
|
|
|
{
|
|
|
|
std::string migrate_to = cmd_args.get("migrate-mod-storage");
|
|
|
|
Settings world_mt;
|
|
|
|
std::string world_mt_path = game_params.world_path + DIR_DELIM + "world.mt";
|
|
|
|
if (!world_mt.readConfigFile(world_mt_path.c_str())) {
|
|
|
|
errorstream << "Cannot read world.mt!" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string backend = world_mt.exists("mod_storage_backend") ?
|
|
|
|
world_mt.get("mod_storage_backend") : "files";
|
|
|
|
if (backend == migrate_to) {
|
|
|
|
errorstream << "Cannot migrate: new backend is same"
|
|
|
|
<< " as the old one" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-11-23 23:25:34 +01:00
|
|
|
ModStorageDatabase *srcdb = nullptr;
|
|
|
|
ModStorageDatabase *dstdb = nullptr;
|
2022-01-07 19:28:49 +01:00
|
|
|
|
|
|
|
bool succeeded = false;
|
|
|
|
|
|
|
|
try {
|
|
|
|
srcdb = Server::openModStorageDatabase(backend, game_params.world_path, world_mt);
|
|
|
|
dstdb = Server::openModStorageDatabase(migrate_to, game_params.world_path, world_mt);
|
|
|
|
|
|
|
|
dstdb->beginSave();
|
|
|
|
|
|
|
|
std::vector<std::string> mod_list;
|
|
|
|
srcdb->listMods(&mod_list);
|
|
|
|
for (const std::string &modname : mod_list) {
|
|
|
|
StringMap meta;
|
|
|
|
srcdb->getModEntries(modname, &meta);
|
|
|
|
for (const auto &pair : meta) {
|
|
|
|
dstdb->setModEntry(modname, pair.first, pair.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dstdb->endSave();
|
|
|
|
|
|
|
|
succeeded = true;
|
|
|
|
|
|
|
|
actionstream << "Successfully migrated the metadata of "
|
|
|
|
<< mod_list.size() << " mods" << std::endl;
|
|
|
|
world_mt.set("mod_storage_backend", migrate_to);
|
|
|
|
if (!world_mt.updateConfigFile(world_mt_path.c_str()))
|
|
|
|
errorstream << "Failed to update world.mt!" << std::endl;
|
|
|
|
else
|
|
|
|
actionstream << "world.mt updated" << std::endl;
|
|
|
|
|
|
|
|
} catch (BaseException &e) {
|
|
|
|
errorstream << "An error occurred during migration: " << e.what() << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete srcdb;
|
|
|
|
delete dstdb;
|
|
|
|
|
|
|
|
if (succeeded && backend == "files") {
|
|
|
|
// Back up files
|
|
|
|
const std::string storage_path = game_params.world_path + DIR_DELIM + "mod_storage";
|
|
|
|
const std::string backup_path = game_params.world_path + DIR_DELIM + "mod_storage.bak";
|
|
|
|
if (!fs::Rename(storage_path, backup_path))
|
|
|
|
warningstream << "After migration, " << storage_path
|
|
|
|
<< " could not be renamed to " << backup_path << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return succeeded;
|
|
|
|
}
|
2023-12-21 18:53:30 +01:00
|
|
|
|
|
|
|
u16 Server::getProtocolVersionMin()
|
|
|
|
{
|
|
|
|
u16 min_proto = g_settings->getU16("protocol_version_min");
|
|
|
|
if (g_settings->getBool("strict_protocol_version_checking"))
|
|
|
|
min_proto = LATEST_PROTOCOL_VERSION;
|
|
|
|
return rangelim(min_proto,
|
|
|
|
SERVER_PROTOCOL_VERSION_MIN,
|
|
|
|
SERVER_PROTOCOL_VERSION_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 Server::getProtocolVersionMax()
|
|
|
|
{
|
|
|
|
return g_settings->getBool("strict_protocol_version_checking")
|
|
|
|
? LATEST_PROTOCOL_VERSION
|
|
|
|
: SERVER_PROTOCOL_VERSION_MAX;
|
|
|
|
}
|