1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/connection.h"
25 #include "network/networkprotocol.h"
26 #include "network/serveropcodes.h"
27 #include "ban.h"
28 #include "environment.h"
29 #include "map.h"
30 #include "threading/mutex_auto_lock.h"
31 #include "constants.h"
32 #include "voxel.h"
33 #include "config.h"
34 #include "version.h"
35 #include "filesys.h"
36 #include "mapblock.h"
37 #include "server/serveractiveobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_server.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen/mapgen.h"
47 #include "mapgen/mg_biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content/mods.h"
51 #include "modchannels.h"
52 #include "serverlist.h"
53 #include "util/string.h"
54 #include "rollback.h"
55 #include "util/serialize.h"
56 #include "util/thread.h"
57 #include "defaultsettings.h"
58 #include "server/mods.h"
59 #include "util/base64.h"
60 #include "util/sha1.h"
61 #include "util/hex.h"
62 #include "database/database.h"
63 #include "chatmessage.h"
64 #include "chat_interface.h"
65 #include "remoteplayer.h"
66 #include "server/player_sao.h"
67 #include "server/serverinventorymgr.h"
68 #include "translation.h"
69 
70 class ClientNotFoundException : public BaseException
71 {
72 public:
ClientNotFoundException(const char * s)73 	ClientNotFoundException(const char *s):
74 		BaseException(s)
75 	{}
76 };
77 
78 class ServerThread : public Thread
79 {
80 public:
81 
ServerThread(Server * server)82 	ServerThread(Server *server):
83 		Thread("Server"),
84 		m_server(server)
85 	{}
86 
87 	void *run();
88 
89 private:
90 	Server *m_server;
91 };
92 
run()93 void *ServerThread::run()
94 {
95 	BEGIN_DEBUG_EXCEPTION_HANDLER
96 
97 	/*
98 	 * The real business of the server happens on the ServerThread.
99 	 * How this works:
100 	 * AsyncRunStep() runs an actual server step as soon as enough time has
101 	 * passed (dedicated_server_loop keeps track of that).
102 	 * Receive() blocks at least(!) 30ms waiting for a packet (so this loop
103 	 * doesn't busy wait) and will process any remaining packets.
104 	 */
105 
106 	m_server->AsyncRunStep(true);
107 
108 	while (!stopRequested()) {
109 		try {
110 			m_server->AsyncRunStep();
111 
112 			m_server->Receive();
113 
114 		} catch (con::PeerNotFoundException &e) {
115 			infostream<<"Server: PeerNotFoundException"<<std::endl;
116 		} catch (ClientNotFoundException &e) {
117 		} catch (con::ConnectionBindFailed &e) {
118 			m_server->setAsyncFatalError(e.what());
119 		} catch (LuaError &e) {
120 			m_server->setAsyncFatalError(
121 					"ServerThread::run Lua: " + std::string(e.what()));
122 		}
123 	}
124 
125 	END_DEBUG_EXCEPTION_HANDLER
126 
127 	return nullptr;
128 }
129 
getPos(ServerEnvironment * env,bool * pos_exists) const130 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
131 {
132 	if(pos_exists) *pos_exists = false;
133 	switch(type){
134 	case SSP_LOCAL:
135 		return v3f(0,0,0);
136 	case SSP_POSITIONAL:
137 		if(pos_exists) *pos_exists = true;
138 		return pos;
139 	case SSP_OBJECT: {
140 		if(object == 0)
141 			return v3f(0,0,0);
142 		ServerActiveObject *sao = env->getActiveObject(object);
143 		if(!sao)
144 			return v3f(0,0,0);
145 		if(pos_exists) *pos_exists = true;
146 		return sao->getBasePosition(); }
147 	}
148 	return v3f(0,0,0);
149 }
150 
reset()151 void Server::ShutdownState::reset()
152 {
153 	m_timer = 0.0f;
154 	message.clear();
155 	should_reconnect = false;
156 	is_requested = false;
157 }
158 
trigger(float delay,const std::string & msg,bool reconnect)159 void Server::ShutdownState::trigger(float delay, const std::string &msg, bool reconnect)
160 {
161 	m_timer = delay;
162 	message = msg;
163 	should_reconnect = reconnect;
164 }
165 
tick(float dtime,Server * server)166 void Server::ShutdownState::tick(float dtime, Server *server)
167 {
168 	if (m_timer <= 0.0f)
169 		return;
170 
171 	// Timed shutdown
172 	static const float shutdown_msg_times[] =
173 	{
174 		1, 2, 3, 4, 5, 10, 20, 40, 60, 120, 180, 300, 600, 1200, 1800, 3600
175 	};
176 
177 	// Automated messages
178 	if (m_timer < shutdown_msg_times[ARRLEN(shutdown_msg_times) - 1]) {
179 		for (float t : shutdown_msg_times) {
180 			// If shutdown timer matches an automessage, shot it
181 			if (m_timer > t && m_timer - dtime < t) {
182 				std::wstring periodicMsg = getShutdownTimerMessage();
183 
184 				infostream << wide_to_utf8(periodicMsg).c_str() << std::endl;
185 				server->SendChatMessage(PEER_ID_INEXISTENT, periodicMsg);
186 				break;
187 			}
188 		}
189 	}
190 
191 	m_timer -= dtime;
192 	if (m_timer < 0.0f) {
193 		m_timer = 0.0f;
194 		is_requested = true;
195 	}
196 }
197 
getShutdownTimerMessage() const198 std::wstring Server::ShutdownState::getShutdownTimerMessage() const
199 {
200 	std::wstringstream ws;
201 	ws << L"*** Server shutting down in "
202 		<< duration_to_string(myround(m_timer)).c_str() << ".";
203 	return ws.str();
204 }
205 
206 /*
207 	Server
208 */
209 
Server(const std::string & path_world,const SubgameSpec & gamespec,bool simple_singleplayer_mode,Address bind_addr,bool dedicated,ChatInterface * iface,std::string * on_shutdown_errmsg)210 Server::Server(
211 		const std::string &path_world,
212 		const SubgameSpec &gamespec,
213 		bool simple_singleplayer_mode,
214 		Address bind_addr,
215 		bool dedicated,
216 		ChatInterface *iface,
217 		std::string *on_shutdown_errmsg
218 	):
219 	m_bind_addr(bind_addr),
220 	m_path_world(path_world),
221 	m_gamespec(gamespec),
222 	m_simple_singleplayer_mode(simple_singleplayer_mode),
223 	m_dedicated(dedicated),
224 	m_async_fatal_error(""),
225 	m_con(std::make_shared<con::Connection>(PROTOCOL_ID,
226 			512,
227 			CONNECTION_TIMEOUT,
228 			m_bind_addr.isIPv6(),
229 			this)),
230 	m_itemdef(createItemDefManager()),
231 	m_nodedef(createNodeDefManager()),
232 	m_craftdef(createCraftDefManager()),
233 	m_thread(new ServerThread(this)),
234 	m_clients(m_con),
235 	m_admin_chat(iface),
236 	m_on_shutdown_errmsg(on_shutdown_errmsg),
237 	m_modchannel_mgr(new ModChannelMgr())
238 {
239 	if (m_path_world.empty())
240 		throw ServerError("Supplied empty world path");
241 
242 	if (!gamespec.isValid())
243 		throw ServerError("Supplied invalid gamespec");
244 
245 #if USE_PROMETHEUS
246 	m_metrics_backend = std::unique_ptr<MetricsBackend>(createPrometheusMetricsBackend());
247 #else
248 	m_metrics_backend = std::unique_ptr<MetricsBackend>(new MetricsBackend());
249 #endif
250 
251 	m_uptime_counter = m_metrics_backend->addCounter("minetest_core_server_uptime", "Server uptime (in seconds)");
252 	m_player_gauge = m_metrics_backend->addGauge("minetest_core_player_number", "Number of connected players");
253 
254 	m_timeofday_gauge = m_metrics_backend->addGauge(
255 			"minetest_core_timeofday",
256 			"Time of day value");
257 
258 	m_lag_gauge = m_metrics_backend->addGauge(
259 			"minetest_core_latency",
260 			"Latency value (in seconds)");
261 
262 	m_aom_buffer_counter = m_metrics_backend->addCounter(
263 			"minetest_core_aom_generated_count",
264 			"Number of active object messages generated");
265 
266 	m_packet_recv_counter = m_metrics_backend->addCounter(
267 			"minetest_core_server_packet_recv",
268 			"Processable packets received");
269 
270 	m_packet_recv_processed_counter = m_metrics_backend->addCounter(
271 			"minetest_core_server_packet_recv_processed",
272 			"Valid received packets processed");
273 
274 	m_lag_gauge->set(g_settings->getFloat("dedicated_server_step"));
275 }
276 
~Server()277 Server::~Server()
278 {
279 
280 	// Send shutdown message
281 	SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE,
282 			L"*** Server shutting down"));
283 
284 	if (m_env) {
285 		MutexAutoLock envlock(m_env_mutex);
286 
287 		infostream << "Server: Saving players" << std::endl;
288 		m_env->saveLoadedPlayers();
289 
290 		infostream << "Server: Kicking players" << std::endl;
291 		std::string kick_msg;
292 		bool reconnect = false;
293 		if (isShutdownRequested()) {
294 			reconnect = m_shutdown_state.should_reconnect;
295 			kick_msg = m_shutdown_state.message;
296 		}
297 		if (kick_msg.empty()) {
298 			kick_msg = g_settings->get("kick_msg_shutdown");
299 		}
300 		m_env->saveLoadedPlayers(true);
301 		m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
302 			kick_msg, reconnect);
303 	}
304 
305 	actionstream << "Server: Shutting down" << std::endl;
306 
307 	// Do this before stopping the server in case mapgen callbacks need to access
308 	// server-controlled resources (like ModStorages). Also do them before
309 	// shutdown callbacks since they may modify state that is finalized in a
310 	// callback.
311 	if (m_emerge)
312 		m_emerge->stopThreads();
313 
314 	if (m_env) {
315 		MutexAutoLock envlock(m_env_mutex);
316 
317 		// Execute script shutdown hooks
318 		infostream << "Executing shutdown hooks" << std::endl;
319 		try {
320 			m_script->on_shutdown();
321 		} catch (ModError &e) {
322 			errorstream << "ModError: " << e.what() << std::endl;
323 			if (m_on_shutdown_errmsg) {
324 				if (m_on_shutdown_errmsg->empty()) {
325 					*m_on_shutdown_errmsg = std::string("ModError: ") + e.what();
326 				} else {
327 					*m_on_shutdown_errmsg += std::string("\nModError: ") + e.what();
328 				}
329 			}
330 		}
331 
332 		infostream << "Server: Saving environment metadata" << std::endl;
333 		m_env->saveMeta();
334 	}
335 
336 	// Stop threads
337 	if (m_thread) {
338 		stop();
339 		delete m_thread;
340 	}
341 
342 	// Delete things in the reverse order of creation
343 	delete m_emerge;
344 	delete m_env;
345 	delete m_rollback;
346 	delete m_banmanager;
347 	delete m_itemdef;
348 	delete m_nodedef;
349 	delete m_craftdef;
350 
351 	// Deinitialize scripting
352 	infostream << "Server: Deinitializing scripting" << std::endl;
353 	delete m_script;
354 	delete m_startup_server_map; // if available
355 	delete m_game_settings;
356 
357 	while (!m_unsent_map_edit_queue.empty()) {
358 		delete m_unsent_map_edit_queue.front();
359 		m_unsent_map_edit_queue.pop();
360 	}
361 }
362 
init()363 void Server::init()
364 {
365 	infostream << "Server created for gameid \"" << m_gamespec.id << "\"";
366 	if (m_simple_singleplayer_mode)
367 		infostream << " in simple singleplayer mode" << std::endl;
368 	else
369 		infostream << std::endl;
370 	infostream << "- world:  " << m_path_world << std::endl;
371 	infostream << "- game:   " << m_gamespec.path << std::endl;
372 
373 	m_game_settings = Settings::createLayer(SL_GAME);
374 
375 	// Create world if it doesn't exist
376 	try {
377 		loadGameConfAndInitWorld(m_path_world,
378 				fs::GetFilenameFromPath(m_path_world.c_str()),
379 				m_gamespec, false);
380 	} catch (const BaseException &e) {
381 		throw ServerError(std::string("Failed to initialize world: ") + e.what());
382 	}
383 
384 	// Create emerge manager
385 	m_emerge = new EmergeManager(this);
386 
387 	// Create ban manager
388 	std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
389 	m_banmanager = new BanManager(ban_path);
390 
391 	m_modmgr = std::unique_ptr<ServerModManager>(new ServerModManager(m_path_world));
392 	std::vector<ModSpec> unsatisfied_mods = m_modmgr->getUnsatisfiedMods();
393 	// complain about mods with unsatisfied dependencies
394 	if (!m_modmgr->isConsistent()) {
395 		m_modmgr->printUnsatisfiedModsError();
396 	}
397 
398 	//lock environment
399 	MutexAutoLock envlock(m_env_mutex);
400 
401 	// Create the Map (loads map_meta.txt, overriding configured mapgen params)
402 	ServerMap *servermap = new ServerMap(m_path_world, this, m_emerge, m_metrics_backend.get());
403 	m_startup_server_map = servermap;
404 
405 	// Initialize scripting
406 	infostream << "Server: Initializing Lua" << std::endl;
407 
408 	m_script = new ServerScripting(this);
409 
410 	// Must be created before mod loading because we have some inventory creation
411 	m_inventory_mgr = std::unique_ptr<ServerInventoryManager>(new ServerInventoryManager());
412 
413 	m_script->loadMod(getBuiltinLuaPath() + DIR_DELIM "init.lua", BUILTIN_MOD_NAME);
414 
415 	m_modmgr->loadMods(m_script);
416 
417 	// Read Textures and calculate sha1 sums
418 	fillMediaCache();
419 
420 	// Apply item aliases in the node definition manager
421 	m_nodedef->updateAliases(m_itemdef);
422 
423 	// Apply texture overrides from texturepack/override.txt
424 	std::vector<std::string> paths;
425 	fs::GetRecursiveDirs(paths, g_settings->get("texture_path"));
426 	fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
427 	for (const std::string &path : paths) {
428 		TextureOverrideSource override_source(path + DIR_DELIM + "override.txt");
429 		m_nodedef->applyTextureOverrides(override_source.getNodeTileOverrides());
430 		m_itemdef->applyTextureOverrides(override_source.getItemTextureOverrides());
431 	}
432 
433 	m_nodedef->setNodeRegistrationStatus(true);
434 
435 	// Perform pending node name resolutions
436 	m_nodedef->runNodeResolveCallbacks();
437 
438 	// unmap node names in cross-references
439 	m_nodedef->resolveCrossrefs();
440 
441 	// init the recipe hashes to speed up crafting
442 	m_craftdef->initHashes(this);
443 
444 	// Initialize Environment
445 	m_startup_server_map = nullptr; // Ownership moved to ServerEnvironment
446 	m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
447 
448 	m_inventory_mgr->setEnv(m_env);
449 	m_clients.setEnv(m_env);
450 
451 	if (!servermap->settings_mgr.makeMapgenParams())
452 		FATAL_ERROR("Couldn't create any mapgen type");
453 
454 	// Initialize mapgens
455 	m_emerge->initMapgens(servermap->getMapgenParams());
456 
457 	if (g_settings->getBool("enable_rollback_recording")) {
458 		// Create rollback manager
459 		m_rollback = new RollbackManager(m_path_world, this);
460 	}
461 
462 	// Give environment reference to scripting api
463 	m_script->initializeEnvironment(m_env);
464 
465 	// Register us to receive map edit events
466 	servermap->addEventReceiver(this);
467 
468 	m_env->loadMeta();
469 
470 	// Those settings can be overwritten in world.mt, they are
471 	// intended to be cached after environment loading.
472 	m_liquid_transform_every = g_settings->getFloat("liquid_update");
473 	m_max_chatmessage_length = g_settings->getU16("chat_message_max_size");
474 	m_csm_restriction_flags = g_settings->getU64("csm_restriction_flags");
475 	m_csm_restriction_noderange = g_settings->getU32("csm_restriction_noderange");
476 }
477 
start()478 void Server::start()
479 {
480 	init();
481 
482 	infostream << "Starting server on " << m_bind_addr.serializeString()
483 			<< "..." << std::endl;
484 
485 	// Stop thread if already running
486 	m_thread->stop();
487 
488 	// Initialize connection
489 	m_con->SetTimeoutMs(30);
490 	m_con->Serve(m_bind_addr);
491 
492 	// Start thread
493 	m_thread->start();
494 
495 	// ASCII art for the win!
496 	std::cerr
497 		<< "        .__               __                   __   " << std::endl
498 		<< "  _____ |__| ____   _____/  |_  ____   _______/  |_ " << std::endl
499 		<< " /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\" << std::endl
500 		<< "|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  " << std::endl
501 		<< "|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  " << std::endl
502 		<< "      \\/        \\/     \\/          \\/     \\/        " << std::endl;
503 	actionstream << "World at [" << m_path_world << "]" << std::endl;
504 	actionstream << "Server for gameid=\"" << m_gamespec.id
505 			<< "\" listening on " << m_bind_addr.serializeString() << ":"
506 			<< m_bind_addr.getPort() << "." << std::endl;
507 }
508 
stop()509 void Server::stop()
510 {
511 	infostream<<"Server: Stopping and waiting threads"<<std::endl;
512 
513 	// Stop threads (set run=false first so both start stopping)
514 	m_thread->stop();
515 	//m_emergethread.setRun(false);
516 	m_thread->wait();
517 	//m_emergethread.stop();
518 
519 	infostream<<"Server: Threads stopped"<<std::endl;
520 }
521 
step(float dtime)522 void Server::step(float dtime)
523 {
524 	// Limit a bit
525 	if (dtime > 2.0)
526 		dtime = 2.0;
527 	{
528 		MutexAutoLock lock(m_step_dtime_mutex);
529 		m_step_dtime += dtime;
530 	}
531 	// Throw if fatal error occurred in thread
532 	std::string async_err = m_async_fatal_error.get();
533 	if (!async_err.empty()) {
534 		if (!m_simple_singleplayer_mode) {
535 			m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
536 				g_settings->get("kick_msg_crash"),
537 				g_settings->getBool("ask_reconnect_on_crash"));
538 		}
539 		throw ServerError("AsyncErr: " + async_err);
540 	}
541 }
542 
AsyncRunStep(bool initial_step)543 void Server::AsyncRunStep(bool initial_step)
544 {
545 
546 	float dtime;
547 	{
548 		MutexAutoLock lock1(m_step_dtime_mutex);
549 		dtime = m_step_dtime;
550 	}
551 
552 	{
553 		// Send blocks to clients
554 		SendBlocks(dtime);
555 	}
556 
557 	if((dtime < 0.001) && !initial_step)
558 		return;
559 
560 	ScopeProfiler sp(g_profiler, "Server::AsyncRunStep()", SPT_AVG);
561 
562 	{
563 		MutexAutoLock lock1(m_step_dtime_mutex);
564 		m_step_dtime -= dtime;
565 	}
566 
567 	/*
568 		Update uptime
569 	*/
570 	m_uptime_counter->increment(dtime);
571 
572 	handlePeerChanges();
573 
574 	/*
575 		Update time of day and overall game time
576 	*/
577 	m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
578 
579 	/*
580 		Send to clients at constant intervals
581 	*/
582 
583 	m_time_of_day_send_timer -= dtime;
584 	if (m_time_of_day_send_timer < 0.0) {
585 		m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
586 		u16 time = m_env->getTimeOfDay();
587 		float time_speed = g_settings->getFloat("time_speed");
588 		SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
589 
590 		m_timeofday_gauge->set(time);
591 	}
592 
593 	{
594 		MutexAutoLock lock(m_env_mutex);
595 		// Figure out and report maximum lag to environment
596 		float max_lag = m_env->getMaxLagEstimate();
597 		max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
598 		if(dtime > max_lag){
599 			if(dtime > 0.1 && dtime > max_lag * 2.0)
600 				infostream<<"Server: Maximum lag peaked to "<<dtime
601 						<<" s"<<std::endl;
602 			max_lag = dtime;
603 		}
604 		m_env->reportMaxLagEstimate(max_lag);
605 		// Step environment
606 		m_env->step(dtime);
607 	}
608 
609 	static const float map_timer_and_unload_dtime = 2.92;
610 	if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
611 	{
612 		MutexAutoLock lock(m_env_mutex);
613 		// Run Map's timers and unload unused data
614 		ScopeProfiler sp(g_profiler, "Server: map timer and unload");
615 		m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
616 			g_settings->getFloat("server_unload_unused_data_timeout"),
617 			U32_MAX);
618 	}
619 
620 	/*
621 		Listen to the admin chat, if available
622 	*/
623 	if (m_admin_chat) {
624 		if (!m_admin_chat->command_queue.empty()) {
625 			MutexAutoLock lock(m_env_mutex);
626 			while (!m_admin_chat->command_queue.empty()) {
627 				ChatEvent *evt = m_admin_chat->command_queue.pop_frontNoEx();
628 				handleChatInterfaceEvent(evt);
629 				delete evt;
630 			}
631 		}
632 		m_admin_chat->outgoing_queue.push_back(
633 			new ChatEventTimeInfo(m_env->getGameTime(), m_env->getTimeOfDay()));
634 	}
635 
636 	/*
637 		Do background stuff
638 	*/
639 
640 	/* Transform liquids */
641 	m_liquid_transform_timer += dtime;
642 	if(m_liquid_transform_timer >= m_liquid_transform_every)
643 	{
644 		m_liquid_transform_timer -= m_liquid_transform_every;
645 
646 		MutexAutoLock lock(m_env_mutex);
647 
648 		ScopeProfiler sp(g_profiler, "Server: liquid transform");
649 
650 		std::map<v3s16, MapBlock*> modified_blocks;
651 		m_env->getMap().transformLiquids(modified_blocks, m_env);
652 
653 		/*
654 			Set the modified blocks unsent for all the clients
655 		*/
656 		if (!modified_blocks.empty()) {
657 			SetBlocksNotSent(modified_blocks);
658 		}
659 	}
660 	m_clients.step(dtime);
661 
662 	// increase/decrease lag gauge gradually
663 	if (m_lag_gauge->get() > dtime) {
664 		m_lag_gauge->decrement(dtime/100);
665 	} else {
666 		m_lag_gauge->increment(dtime/100);
667 	}
668 #if USE_CURL
669 	// send masterserver announce
670 	{
671 		float &counter = m_masterserver_timer;
672 		if (!isSingleplayer() && (!counter || counter >= 300.0) &&
673 				g_settings->getBool("server_announce")) {
674 			ServerList::sendAnnounce(counter ? ServerList::AA_UPDATE :
675 						ServerList::AA_START,
676 					m_bind_addr.getPort(),
677 					m_clients.getPlayerNames(),
678 					m_uptime_counter->get(),
679 					m_env->getGameTime(),
680 					m_lag_gauge->get(),
681 					m_gamespec.id,
682 					Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
683 					m_modmgr->getMods(),
684 					m_dedicated);
685 			counter = 0.01;
686 		}
687 		counter += dtime;
688 	}
689 #endif
690 
691 	/*
692 		Check added and deleted active objects
693 	*/
694 	{
695 		//infostream<<"Server: Checking added and deleted active objects"<<std::endl;
696 		MutexAutoLock envlock(m_env_mutex);
697 
698 		m_clients.lock();
699 		const RemoteClientMap &clients = m_clients.getClientList();
700 		ScopeProfiler sp(g_profiler, "Server: update objects within range");
701 
702 		m_player_gauge->set(clients.size());
703 		for (const auto &client_it : clients) {
704 			RemoteClient *client = client_it.second;
705 
706 			if (client->getState() < CS_DefinitionsSent)
707 				continue;
708 
709 			// This can happen if the client times out somehow
710 			if (!m_env->getPlayer(client->peer_id))
711 				continue;
712 
713 			PlayerSAO *playersao = getPlayerSAO(client->peer_id);
714 			if (!playersao)
715 				continue;
716 
717 			SendActiveObjectRemoveAdd(client, playersao);
718 		}
719 		m_clients.unlock();
720 
721 		// Save mod storages if modified
722 		m_mod_storage_save_timer -= dtime;
723 		if (m_mod_storage_save_timer <= 0.0f) {
724 			m_mod_storage_save_timer = g_settings->getFloat("server_map_save_interval");
725 			int n = 0;
726 			for (std::unordered_map<std::string, ModMetadata *>::const_iterator
727 				it = m_mod_storages.begin(); it != m_mod_storages.end(); ++it) {
728 				if (it->second->isModified()) {
729 					it->second->save(getModStoragePath());
730 					n++;
731 				}
732 			}
733 			if (n > 0)
734 				infostream << "Saved " << n << " modified mod storages." << std::endl;
735 		}
736 	}
737 
738 	/*
739 		Send object messages
740 	*/
741 	{
742 		MutexAutoLock envlock(m_env_mutex);
743 		ScopeProfiler sp(g_profiler, "Server: send SAO messages");
744 
745 		// Key = object id
746 		// Value = data sent by object
747 		std::unordered_map<u16, std::vector<ActiveObjectMessage>*> buffered_messages;
748 
749 		// Get active object messages from environment
750 		ActiveObjectMessage aom(0);
751 		u32 aom_count = 0;
752 		for(;;) {
753 			if (!m_env->getActiveObjectMessage(&aom))
754 				break;
755 
756 			std::vector<ActiveObjectMessage>* message_list = nullptr;
757 			auto n = buffered_messages.find(aom.id);
758 			if (n == buffered_messages.end()) {
759 				message_list = new std::vector<ActiveObjectMessage>;
760 				buffered_messages[aom.id] = message_list;
761 			} else {
762 				message_list = n->second;
763 			}
764 			message_list->push_back(std::move(aom));
765 			aom_count++;
766 		}
767 
768 		m_aom_buffer_counter->increment(aom_count);
769 
770 		m_clients.lock();
771 		const RemoteClientMap &clients = m_clients.getClientList();
772 		// Route data to every client
773 		std::string reliable_data, unreliable_data;
774 		for (const auto &client_it : clients) {
775 			reliable_data.clear();
776 			unreliable_data.clear();
777 			RemoteClient *client = client_it.second;
778 			PlayerSAO *player = getPlayerSAO(client->peer_id);
779 			// Go through all objects in message buffer
780 			for (const auto &buffered_message : buffered_messages) {
781 				// If object does not exist or is not known by client, skip it
782 				u16 id = buffered_message.first;
783 				ServerActiveObject *sao = m_env->getActiveObject(id);
784 				if (!sao || client->m_known_objects.find(id) == client->m_known_objects.end())
785 					continue;
786 
787 				// Get message list of object
788 				std::vector<ActiveObjectMessage>* list = buffered_message.second;
789 				// Go through every message
790 				for (const ActiveObjectMessage &aom : *list) {
791 					// Send position updates to players who do not see the attachment
792 					if (aom.datastring[0] == AO_CMD_UPDATE_POSITION) {
793 						if (sao->getId() == player->getId())
794 							continue;
795 
796 						// Do not send position updates for attached players
797 						// as long the parent is known to the client
798 						ServerActiveObject *parent = sao->getParent();
799 						if (parent && client->m_known_objects.find(parent->getId()) !=
800 								client->m_known_objects.end())
801 							continue;
802 					}
803 
804 					// Add full new data to appropriate buffer
805 					std::string &buffer = aom.reliable ? reliable_data : unreliable_data;
806 					char idbuf[2];
807 					writeU16((u8*) idbuf, aom.id);
808 					// u16 id
809 					// std::string data
810 					buffer.append(idbuf, sizeof(idbuf));
811 					buffer.append(serializeString16(aom.datastring));
812 				}
813 			}
814 			/*
815 				reliable_data and unreliable_data are now ready.
816 				Send them.
817 			*/
818 			if (!reliable_data.empty()) {
819 				SendActiveObjectMessages(client->peer_id, reliable_data);
820 			}
821 
822 			if (!unreliable_data.empty()) {
823 				SendActiveObjectMessages(client->peer_id, unreliable_data, false);
824 			}
825 		}
826 		m_clients.unlock();
827 
828 		// Clear buffered_messages
829 		for (auto &buffered_message : buffered_messages) {
830 			delete buffered_message.second;
831 		}
832 	}
833 
834 	/*
835 		Send queued-for-sending map edit events.
836 	*/
837 	{
838 		// We will be accessing the environment
839 		MutexAutoLock lock(m_env_mutex);
840 
841 		// Don't send too many at a time
842 		//u32 count = 0;
843 
844 		// Single change sending is disabled if queue size is not small
845 		bool disable_single_change_sending = false;
846 		if(m_unsent_map_edit_queue.size() >= 4)
847 			disable_single_change_sending = true;
848 
849 		int event_count = m_unsent_map_edit_queue.size();
850 
851 		// We'll log the amount of each
852 		Profiler prof;
853 
854 		std::list<v3s16> node_meta_updates;
855 
856 		while (!m_unsent_map_edit_queue.empty()) {
857 			MapEditEvent* event = m_unsent_map_edit_queue.front();
858 			m_unsent_map_edit_queue.pop();
859 
860 			// Players far away from the change are stored here.
861 			// Instead of sending the changes, MapBlocks are set not sent
862 			// for them.
863 			std::unordered_set<u16> far_players;
864 
865 			switch (event->type) {
866 			case MEET_ADDNODE:
867 			case MEET_SWAPNODE:
868 				prof.add("MEET_ADDNODE", 1);
869 				sendAddNode(event->p, event->n, &far_players,
870 						disable_single_change_sending ? 5 : 30,
871 						event->type == MEET_ADDNODE);
872 				break;
873 			case MEET_REMOVENODE:
874 				prof.add("MEET_REMOVENODE", 1);
875 				sendRemoveNode(event->p, &far_players,
876 						disable_single_change_sending ? 5 : 30);
877 				break;
878 			case MEET_BLOCK_NODE_METADATA_CHANGED: {
879 				prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
880 				if (!event->is_private_change) {
881 					// Don't send the change yet. Collect them to eliminate dupes.
882 					node_meta_updates.remove(event->p);
883 					node_meta_updates.push_back(event->p);
884 				}
885 
886 				if (MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(
887 						getNodeBlockPos(event->p))) {
888 					block->raiseModified(MOD_STATE_WRITE_NEEDED,
889 						MOD_REASON_REPORT_META_CHANGE);
890 				}
891 				break;
892 			}
893 			case MEET_OTHER:
894 				prof.add("MEET_OTHER", 1);
895 				for (const v3s16 &modified_block : event->modified_blocks) {
896 					m_clients.markBlockposAsNotSent(modified_block);
897 				}
898 				break;
899 			default:
900 				prof.add("unknown", 1);
901 				warningstream << "Server: Unknown MapEditEvent "
902 						<< ((u32)event->type) << std::endl;
903 				break;
904 			}
905 
906 			/*
907 				Set blocks not sent to far players
908 			*/
909 			if (!far_players.empty()) {
910 				// Convert list format to that wanted by SetBlocksNotSent
911 				std::map<v3s16, MapBlock*> modified_blocks2;
912 				for (const v3s16 &modified_block : event->modified_blocks) {
913 					modified_blocks2[modified_block] =
914 							m_env->getMap().getBlockNoCreateNoEx(modified_block);
915 				}
916 
917 				// Set blocks not sent
918 				for (const u16 far_player : far_players) {
919 					if (RemoteClient *client = getClient(far_player))
920 						client->SetBlocksNotSent(modified_blocks2);
921 				}
922 			}
923 
924 			delete event;
925 		}
926 
927 		if (event_count >= 5) {
928 			infostream << "Server: MapEditEvents:" << std::endl;
929 			prof.print(infostream);
930 		} else if (event_count != 0) {
931 			verbosestream << "Server: MapEditEvents:" << std::endl;
932 			prof.print(verbosestream);
933 		}
934 
935 		// Send all metadata updates
936 		if (node_meta_updates.size())
937 			sendMetadataChanged(node_meta_updates);
938 	}
939 
940 	/*
941 		Trigger emergethread (it somehow gets to a non-triggered but
942 		bysy state sometimes)
943 	*/
944 	{
945 		float &counter = m_emergethread_trigger_timer;
946 		counter += dtime;
947 		if (counter >= 2.0) {
948 			counter = 0.0;
949 
950 			m_emerge->startThreads();
951 		}
952 	}
953 
954 	// Save map, players and auth stuff
955 	{
956 		float &counter = m_savemap_timer;
957 		counter += dtime;
958 		static thread_local const float save_interval =
959 			g_settings->getFloat("server_map_save_interval");
960 		if (counter >= save_interval) {
961 			counter = 0.0;
962 			MutexAutoLock lock(m_env_mutex);
963 
964 			ScopeProfiler sp(g_profiler, "Server: map saving (sum)");
965 
966 			// Save ban file
967 			if (m_banmanager->isModified()) {
968 				m_banmanager->save();
969 			}
970 
971 			// Save changed parts of map
972 			m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
973 
974 			// Save players
975 			m_env->saveLoadedPlayers();
976 
977 			// Save environment metadata
978 			m_env->saveMeta();
979 		}
980 	}
981 
982 	m_shutdown_state.tick(dtime, this);
983 }
984 
Receive()985 void Server::Receive()
986 {
987 	NetworkPacket pkt;
988 	session_t peer_id;
989 	bool first = true;
990 	for (;;) {
991 		pkt.clear();
992 		peer_id = 0;
993 		try {
994 			/*
995 				In the first iteration *wait* for a packet, afterwards process
996 				all packets that are immediately available (no waiting).
997 			*/
998 			if (first) {
999 				m_con->Receive(&pkt);
1000 				first = false;
1001 			} else {
1002 				if (!m_con->TryReceive(&pkt))
1003 					return;
1004 			}
1005 
1006 			peer_id = pkt.getPeerId();
1007 			m_packet_recv_counter->increment();
1008 			ProcessData(&pkt);
1009 			m_packet_recv_processed_counter->increment();
1010 		} catch (const con::InvalidIncomingDataException &e) {
1011 			infostream << "Server::Receive(): InvalidIncomingDataException: what()="
1012 					<< e.what() << std::endl;
1013 		} catch (const SerializationError &e) {
1014 			infostream << "Server::Receive(): SerializationError: what()="
1015 					<< e.what() << std::endl;
1016 		} catch (const ClientStateError &e) {
1017 			errorstream << "ProcessData: peer=" << peer_id << " what()="
1018 					 << e.what() << std::endl;
1019 			DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect."
1020 					L"Try reconnecting or updating your client");
1021 		} catch (const con::PeerNotFoundException &e) {
1022 			// Do nothing
1023 		} catch (const con::NoIncomingDataException &e) {
1024 			return;
1025 		}
1026 	}
1027 }
1028 
StageTwoClientInit(session_t peer_id)1029 PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
1030 {
1031 	std::string playername;
1032 	PlayerSAO *playersao = NULL;
1033 	m_clients.lock();
1034 	try {
1035 		RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
1036 		if (client) {
1037 			playername = client->getName();
1038 			playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
1039 		}
1040 	} catch (std::exception &e) {
1041 		m_clients.unlock();
1042 		throw;
1043 	}
1044 	m_clients.unlock();
1045 
1046 	RemotePlayer *player = m_env->getPlayer(playername.c_str());
1047 
1048 	// If failed, cancel
1049 	if (!playersao || !player) {
1050 		if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
1051 			actionstream << "Server: Failed to emerge player \"" << playername
1052 					<< "\" (player allocated to an another client)" << std::endl;
1053 			DenyAccess_Legacy(peer_id, L"Another client is connected with this "
1054 					L"name. If your client closed unexpectedly, try again in "
1055 					L"a minute.");
1056 		} else {
1057 			errorstream << "Server: " << playername << ": Failed to emerge player"
1058 					<< std::endl;
1059 			DenyAccess_Legacy(peer_id, L"Could not allocate player.");
1060 		}
1061 		return NULL;
1062 	}
1063 
1064 	/*
1065 		Send complete position information
1066 	*/
1067 	SendMovePlayer(peer_id);
1068 
1069 	// Send privileges
1070 	SendPlayerPrivileges(peer_id);
1071 
1072 	// Send inventory formspec
1073 	SendPlayerInventoryFormspec(peer_id);
1074 
1075 	// Send inventory
1076 	SendInventory(playersao, false);
1077 
1078 	// Send HP or death screen
1079 	if (playersao->isDead())
1080 		SendDeathscreen(peer_id, false, v3f(0,0,0));
1081 	else
1082 		SendPlayerHPOrDie(playersao,
1083 				PlayerHPChangeReason(PlayerHPChangeReason::SET_HP));
1084 
1085 	// Send Breath
1086 	SendPlayerBreath(playersao);
1087 
1088 	/*
1089 		Print out action
1090 	*/
1091 	{
1092 		Address addr = getPeerAddress(player->getPeerId());
1093 		std::string ip_str = addr.serializeString();
1094 		const std::vector<std::string> &names = m_clients.getPlayerNames();
1095 
1096 		actionstream << player->getName() << " [" << ip_str << "] joins game. List of players: ";
1097 
1098 		for (const std::string &name : names) {
1099 			actionstream << name << " ";
1100 		}
1101 
1102 		actionstream << player->getName() <<std::endl;
1103 	}
1104 	return playersao;
1105 }
1106 
handleCommand(NetworkPacket * pkt)1107 inline void Server::handleCommand(NetworkPacket *pkt)
1108 {
1109 	const ToServerCommandHandler &opHandle = toServerCommandTable[pkt->getCommand()];
1110 	(this->*opHandle.handler)(pkt);
1111 }
1112 
ProcessData(NetworkPacket * pkt)1113 void Server::ProcessData(NetworkPacket *pkt)
1114 {
1115 	// Environment is locked first.
1116 	MutexAutoLock envlock(m_env_mutex);
1117 
1118 	ScopeProfiler sp(g_profiler, "Server: Process network packet (sum)");
1119 	u32 peer_id = pkt->getPeerId();
1120 
1121 	try {
1122 		Address address = getPeerAddress(peer_id);
1123 		std::string addr_s = address.serializeString();
1124 
1125 		if(m_banmanager->isIpBanned(addr_s)) {
1126 			std::string ban_name = m_banmanager->getBanName(addr_s);
1127 			infostream << "Server: A banned client tried to connect from "
1128 					<< addr_s << "; banned name was "
1129 					<< ban_name << std::endl;
1130 			// This actually doesn't seem to transfer to the client
1131 			DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
1132 					+ utf8_to_wide(ban_name));
1133 			return;
1134 		}
1135 	}
1136 	catch(con::PeerNotFoundException &e) {
1137 		/*
1138 		 * no peer for this packet found
1139 		 * most common reason is peer timeout, e.g. peer didn't
1140 		 * respond for some time, your server was overloaded or
1141 		 * things like that.
1142 		 */
1143 		infostream << "Server::ProcessData(): Canceling: peer "
1144 				<< peer_id << " not found" << std::endl;
1145 		return;
1146 	}
1147 
1148 	try {
1149 		ToServerCommand command = (ToServerCommand) pkt->getCommand();
1150 
1151 		// Command must be handled into ToServerCommandHandler
1152 		if (command >= TOSERVER_NUM_MSG_TYPES) {
1153 			infostream << "Server: Ignoring unknown command "
1154 					 << command << std::endl;
1155 			return;
1156 		}
1157 
1158 		if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1159 			handleCommand(pkt);
1160 			return;
1161 		}
1162 
1163 		u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1164 
1165 		if(peer_ser_ver == SER_FMT_VER_INVALID) {
1166 			errorstream << "Server::ProcessData(): Cancelling: Peer"
1167 					" serialization format invalid or not initialized."
1168 					" Skipping incoming command=" << command << std::endl;
1169 			return;
1170 		}
1171 
1172 		/* Handle commands related to client startup */
1173 		if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1174 			handleCommand(pkt);
1175 			return;
1176 		}
1177 
1178 		if (m_clients.getClientState(peer_id) < CS_Active) {
1179 			if (command == TOSERVER_PLAYERPOS) return;
1180 
1181 			errorstream << "Got packet command: " << command << " for peer id "
1182 					<< peer_id << " but client isn't active yet. Dropping packet "
1183 					<< std::endl;
1184 			return;
1185 		}
1186 
1187 		handleCommand(pkt);
1188 	} catch (SendFailedException &e) {
1189 		errorstream << "Server::ProcessData(): SendFailedException: "
1190 				<< "what=" << e.what()
1191 				<< std::endl;
1192 	} catch (PacketError &e) {
1193 		actionstream << "Server::ProcessData(): PacketError: "
1194 				<< "what=" << e.what()
1195 				<< std::endl;
1196 	}
1197 }
1198 
setTimeOfDay(u32 time)1199 void Server::setTimeOfDay(u32 time)
1200 {
1201 	m_env->setTimeOfDay(time);
1202 	m_time_of_day_send_timer = 0;
1203 }
1204 
onMapEditEvent(const MapEditEvent & event)1205 void Server::onMapEditEvent(const MapEditEvent &event)
1206 {
1207 	if (m_ignore_map_edit_events_area.contains(event.getArea()))
1208 		return;
1209 
1210 	m_unsent_map_edit_queue.push(new MapEditEvent(event));
1211 }
1212 
SetBlocksNotSent(std::map<v3s16,MapBlock * > & block)1213 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1214 {
1215 	std::vector<session_t> clients = m_clients.getClientIDs();
1216 	m_clients.lock();
1217 	// Set the modified blocks unsent for all the clients
1218 	for (const session_t client_id : clients) {
1219 			if (RemoteClient *client = m_clients.lockedGetClientNoEx(client_id))
1220 				client->SetBlocksNotSent(block);
1221 	}
1222 	m_clients.unlock();
1223 }
1224 
peerAdded(con::Peer * peer)1225 void Server::peerAdded(con::Peer *peer)
1226 {
1227 	verbosestream<<"Server::peerAdded(): peer->id="
1228 			<<peer->id<<std::endl;
1229 
1230 	m_peer_change_queue.push(con::PeerChange(con::PEER_ADDED, peer->id, false));
1231 }
1232 
deletingPeer(con::Peer * peer,bool timeout)1233 void Server::deletingPeer(con::Peer *peer, bool timeout)
1234 {
1235 	verbosestream<<"Server::deletingPeer(): peer->id="
1236 			<<peer->id<<", timeout="<<timeout<<std::endl;
1237 
1238 	m_clients.event(peer->id, CSE_Disconnect);
1239 	m_peer_change_queue.push(con::PeerChange(con::PEER_REMOVED, peer->id, timeout));
1240 }
1241 
getClientConInfo(session_t peer_id,con::rtt_stat_type type,float * retval)1242 bool Server::getClientConInfo(session_t peer_id, con::rtt_stat_type type, float* retval)
1243 {
1244 	*retval = m_con->getPeerStat(peer_id,type);
1245 	return *retval != -1;
1246 }
1247 
getClientInfo(session_t peer_id,ClientInfo & ret)1248 bool Server::getClientInfo(session_t peer_id, ClientInfo &ret)
1249 {
1250 	m_clients.lock();
1251 	RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1252 
1253 	if (!client) {
1254 		m_clients.unlock();
1255 		return false;
1256 	}
1257 
1258 	ret.state = client->getState();
1259 	ret.addr = client->getAddress();
1260 	ret.uptime = client->uptime();
1261 	ret.ser_vers = client->serialization_version;
1262 	ret.prot_vers = client->net_proto_version;
1263 
1264 	ret.major = client->getMajor();
1265 	ret.minor = client->getMinor();
1266 	ret.patch = client->getPatch();
1267 	ret.vers_string = client->getFullVer();
1268 
1269 	ret.lang_code = client->getLangCode();
1270 
1271 	m_clients.unlock();
1272 
1273 	return true;
1274 }
1275 
handlePeerChanges()1276 void Server::handlePeerChanges()
1277 {
1278 	while(!m_peer_change_queue.empty())
1279 	{
1280 		con::PeerChange c = m_peer_change_queue.front();
1281 		m_peer_change_queue.pop();
1282 
1283 		verbosestream<<"Server: Handling peer change: "
1284 				<<"id="<<c.peer_id<<", timeout="<<c.timeout
1285 				<<std::endl;
1286 
1287 		switch(c.type)
1288 		{
1289 		case con::PEER_ADDED:
1290 			m_clients.CreateClient(c.peer_id);
1291 			break;
1292 
1293 		case con::PEER_REMOVED:
1294 			DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1295 			break;
1296 
1297 		default:
1298 			FATAL_ERROR("Invalid peer change event received!");
1299 			break;
1300 		}
1301 	}
1302 }
1303 
printToConsoleOnly(const std::string & text)1304 void Server::printToConsoleOnly(const std::string &text)
1305 {
1306 	if (m_admin_chat) {
1307 		m_admin_chat->outgoing_queue.push_back(
1308 			new ChatEventChat("", utf8_to_wide(text)));
1309 	} else {
1310 		std::cout << text << std::endl;
1311 	}
1312 }
1313 
Send(NetworkPacket * pkt)1314 void Server::Send(NetworkPacket *pkt)
1315 {
1316 	Send(pkt->getPeerId(), pkt);
1317 }
1318 
Send(session_t peer_id,NetworkPacket * pkt)1319 void Server::Send(session_t peer_id, NetworkPacket *pkt)
1320 {
1321 	m_clients.send(peer_id,
1322 		clientCommandFactoryTable[pkt->getCommand()].channel,
1323 		pkt,
1324 		clientCommandFactoryTable[pkt->getCommand()].reliable);
1325 }
1326 
SendMovement(session_t peer_id)1327 void Server::SendMovement(session_t peer_id)
1328 {
1329 	std::ostringstream os(std::ios_base::binary);
1330 
1331 	NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1332 
1333 	pkt << g_settings->getFloat("movement_acceleration_default");
1334 	pkt << g_settings->getFloat("movement_acceleration_air");
1335 	pkt << g_settings->getFloat("movement_acceleration_fast");
1336 	pkt << g_settings->getFloat("movement_speed_walk");
1337 	pkt << g_settings->getFloat("movement_speed_crouch");
1338 	pkt << g_settings->getFloat("movement_speed_fast");
1339 	pkt << g_settings->getFloat("movement_speed_climb");
1340 	pkt << g_settings->getFloat("movement_speed_jump");
1341 	pkt << g_settings->getFloat("movement_liquid_fluidity");
1342 	pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1343 	pkt << g_settings->getFloat("movement_liquid_sink");
1344 	pkt << g_settings->getFloat("movement_gravity");
1345 
1346 	Send(&pkt);
1347 }
1348 
SendPlayerHPOrDie(PlayerSAO * playersao,const PlayerHPChangeReason & reason)1349 void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason &reason)
1350 {
1351 	if (playersao->isImmortal())
1352 		return;
1353 
1354 	session_t peer_id = playersao->getPeerID();
1355 	bool is_alive = !playersao->isDead();
1356 
1357 	if (is_alive)
1358 		SendPlayerHP(peer_id);
1359 	else
1360 		DiePlayer(peer_id, reason);
1361 }
1362 
SendHP(session_t peer_id,u16 hp)1363 void Server::SendHP(session_t peer_id, u16 hp)
1364 {
1365 	NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1366 	pkt << hp;
1367 	Send(&pkt);
1368 }
1369 
SendBreath(session_t peer_id,u16 breath)1370 void Server::SendBreath(session_t peer_id, u16 breath)
1371 {
1372 	NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1373 	pkt << (u16) breath;
1374 	Send(&pkt);
1375 }
1376 
SendAccessDenied(session_t peer_id,AccessDeniedCode reason,const std::string & custom_reason,bool reconnect)1377 void Server::SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
1378 		const std::string &custom_reason, bool reconnect)
1379 {
1380 	assert(reason < SERVER_ACCESSDENIED_MAX);
1381 
1382 	NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1383 	pkt << (u8)reason;
1384 	if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1385 		pkt << custom_reason;
1386 	else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1387 			reason == SERVER_ACCESSDENIED_CRASH)
1388 		pkt << custom_reason << (u8)reconnect;
1389 	Send(&pkt);
1390 }
1391 
SendAccessDenied_Legacy(session_t peer_id,const std::wstring & reason)1392 void Server::SendAccessDenied_Legacy(session_t peer_id,const std::wstring &reason)
1393 {
1394 	NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1395 	pkt << reason;
1396 	Send(&pkt);
1397 }
1398 
SendDeathscreen(session_t peer_id,bool set_camera_point_target,v3f camera_point_target)1399 void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
1400 		v3f camera_point_target)
1401 {
1402 	NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1403 	pkt << set_camera_point_target << camera_point_target;
1404 	Send(&pkt);
1405 }
1406 
SendItemDef(session_t peer_id,IItemDefManager * itemdef,u16 protocol_version)1407 void Server::SendItemDef(session_t peer_id,
1408 		IItemDefManager *itemdef, u16 protocol_version)
1409 {
1410 	NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1411 
1412 	/*
1413 		u16 command
1414 		u32 length of the next item
1415 		zlib-compressed serialized ItemDefManager
1416 	*/
1417 	std::ostringstream tmp_os(std::ios::binary);
1418 	itemdef->serialize(tmp_os, protocol_version);
1419 	std::ostringstream tmp_os2(std::ios::binary);
1420 	compressZlib(tmp_os.str(), tmp_os2);
1421 	pkt.putLongString(tmp_os2.str());
1422 
1423 	// Make data buffer
1424 	verbosestream << "Server: Sending item definitions to id(" << peer_id
1425 			<< "): size=" << pkt.getSize() << std::endl;
1426 
1427 	Send(&pkt);
1428 }
1429 
SendNodeDef(session_t peer_id,const NodeDefManager * nodedef,u16 protocol_version)1430 void Server::SendNodeDef(session_t peer_id,
1431 	const NodeDefManager *nodedef, u16 protocol_version)
1432 {
1433 	NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1434 
1435 	/*
1436 		u16 command
1437 		u32 length of the next item
1438 		zlib-compressed serialized NodeDefManager
1439 	*/
1440 	std::ostringstream tmp_os(std::ios::binary);
1441 	nodedef->serialize(tmp_os, protocol_version);
1442 	std::ostringstream tmp_os2(std::ios::binary);
1443 	compressZlib(tmp_os.str(), tmp_os2);
1444 
1445 	pkt.putLongString(tmp_os2.str());
1446 
1447 	// Make data buffer
1448 	verbosestream << "Server: Sending node definitions to id(" << peer_id
1449 			<< "): size=" << pkt.getSize() << std::endl;
1450 
1451 	Send(&pkt);
1452 }
1453 
1454 /*
1455 	Non-static send methods
1456 */
1457 
SendInventory(PlayerSAO * sao,bool incremental)1458 void Server::SendInventory(PlayerSAO *sao, bool incremental)
1459 {
1460 	RemotePlayer *player = sao->getPlayer();
1461 
1462 	// Do not send new format to old clients
1463 	incremental &= player->protocol_version >= 38;
1464 
1465 	UpdateCrafting(player);
1466 
1467 	/*
1468 		Serialize it
1469 	*/
1470 
1471 	NetworkPacket pkt(TOCLIENT_INVENTORY, 0, sao->getPeerID());
1472 
1473 	std::ostringstream os(std::ios::binary);
1474 	sao->getInventory()->serialize(os, incremental);
1475 	sao->getInventory()->setModified(false);
1476 	player->setModified(true);
1477 
1478 	const std::string &s = os.str();
1479 	pkt.putRawString(s.c_str(), s.size());
1480 	Send(&pkt);
1481 }
1482 
SendChatMessage(session_t peer_id,const ChatMessage & message)1483 void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
1484 {
1485 	NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1486 	u8 version = 1;
1487 	u8 type = message.type;
1488 	pkt << version << type << message.sender << message.message
1489 		<< static_cast<u64>(message.timestamp);
1490 
1491 	if (peer_id != PEER_ID_INEXISTENT) {
1492 		RemotePlayer *player = m_env->getPlayer(peer_id);
1493 		if (!player)
1494 			return;
1495 
1496 		Send(&pkt);
1497 	} else {
1498 		m_clients.sendToAll(&pkt);
1499 	}
1500 }
1501 
SendShowFormspecMessage(session_t peer_id,const std::string & formspec,const std::string & formname)1502 void Server::SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
1503 	const std::string &formname)
1504 {
1505 	NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0, peer_id);
1506 	if (formspec.empty()){
1507 		//the client should close the formspec
1508 		//but make sure there wasn't another one open in meantime
1509 		const auto it = m_formspec_state_data.find(peer_id);
1510 		if (it != m_formspec_state_data.end() && it->second == formname) {
1511 			m_formspec_state_data.erase(peer_id);
1512 		}
1513 		pkt.putLongString("");
1514 	} else {
1515 		m_formspec_state_data[peer_id] = formname;
1516 		pkt.putLongString(formspec);
1517 	}
1518 	pkt << formname;
1519 
1520 	Send(&pkt);
1521 }
1522 
1523 // Spawns a particle on peer with peer_id
SendSpawnParticle(session_t peer_id,u16 protocol_version,const ParticleParameters & p)1524 void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
1525 	const ParticleParameters &p)
1526 {
1527 	static thread_local const float radius =
1528 			g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1529 
1530 	if (peer_id == PEER_ID_INEXISTENT) {
1531 		std::vector<session_t> clients = m_clients.getClientIDs();
1532 		const v3f pos = p.pos * BS;
1533 		const float radius_sq = radius * radius;
1534 
1535 		for (const session_t client_id : clients) {
1536 			RemotePlayer *player = m_env->getPlayer(client_id);
1537 			if (!player)
1538 				continue;
1539 
1540 			PlayerSAO *sao = player->getPlayerSAO();
1541 			if (!sao)
1542 				continue;
1543 
1544 			// Do not send to distant clients
1545 			if (sao->getBasePosition().getDistanceFromSQ(pos) > radius_sq)
1546 				continue;
1547 
1548 			SendSpawnParticle(client_id, player->protocol_version, p);
1549 		}
1550 		return;
1551 	}
1552 	assert(protocol_version != 0);
1553 
1554 	NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1555 
1556 	{
1557 		// NetworkPacket and iostreams are incompatible...
1558 		std::ostringstream oss(std::ios_base::binary);
1559 		p.serialize(oss, protocol_version);
1560 		pkt.putRawString(oss.str());
1561 	}
1562 
1563 	Send(&pkt);
1564 }
1565 
1566 // Adds a ParticleSpawner on peer with peer_id
SendAddParticleSpawner(session_t peer_id,u16 protocol_version,const ParticleSpawnerParameters & p,u16 attached_id,u32 id)1567 void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
1568 	const ParticleSpawnerParameters &p, u16 attached_id, u32 id)
1569 {
1570 	static thread_local const float radius =
1571 			g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1572 
1573 	if (peer_id == PEER_ID_INEXISTENT) {
1574 		std::vector<session_t> clients = m_clients.getClientIDs();
1575 		const v3f pos = (p.minpos + p.maxpos) / 2.0f * BS;
1576 		const float radius_sq = radius * radius;
1577 		/* Don't send short-lived spawners to distant players.
1578 		 * This could be replaced with proper tracking at some point. */
1579 		const bool distance_check = !attached_id && p.time <= 1.0f;
1580 
1581 		for (const session_t client_id : clients) {
1582 			RemotePlayer *player = m_env->getPlayer(client_id);
1583 			if (!player)
1584 				continue;
1585 
1586 			if (distance_check) {
1587 				PlayerSAO *sao = player->getPlayerSAO();
1588 				if (!sao)
1589 					continue;
1590 				if (sao->getBasePosition().getDistanceFromSQ(pos) > radius_sq)
1591 					continue;
1592 			}
1593 
1594 			SendAddParticleSpawner(client_id, player->protocol_version,
1595 				p, attached_id, id);
1596 		}
1597 		return;
1598 	}
1599 	assert(protocol_version != 0);
1600 
1601 	NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 100, peer_id);
1602 
1603 	pkt << p.amount << p.time << p.minpos << p.maxpos << p.minvel
1604 		<< p.maxvel << p.minacc << p.maxacc << p.minexptime << p.maxexptime
1605 		<< p.minsize << p.maxsize << p.collisiondetection;
1606 
1607 	pkt.putLongString(p.texture);
1608 
1609 	pkt << id << p.vertical << p.collision_removal << attached_id;
1610 	{
1611 		std::ostringstream os(std::ios_base::binary);
1612 		p.animation.serialize(os, protocol_version);
1613 		pkt.putRawString(os.str());
1614 	}
1615 	pkt << p.glow << p.object_collision;
1616 	pkt << p.node.param0 << p.node.param2 << p.node_tile;
1617 
1618 	Send(&pkt);
1619 }
1620 
SendDeleteParticleSpawner(session_t peer_id,u32 id)1621 void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
1622 {
1623 	NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER, 4, peer_id);
1624 
1625 	pkt << id;
1626 
1627 	if (peer_id != PEER_ID_INEXISTENT)
1628 		Send(&pkt);
1629 	else
1630 		m_clients.sendToAll(&pkt);
1631 
1632 }
1633 
SendHUDAdd(session_t peer_id,u32 id,HudElement * form)1634 void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
1635 {
1636 	NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1637 
1638 	pkt << id << (u8) form->type << form->pos << form->name << form->scale
1639 			<< form->text << form->number << form->item << form->dir
1640 			<< form->align << form->offset << form->world_pos << form->size
1641 			<< form->z_index << form->text2;
1642 
1643 	Send(&pkt);
1644 }
1645 
SendHUDRemove(session_t peer_id,u32 id)1646 void Server::SendHUDRemove(session_t peer_id, u32 id)
1647 {
1648 	NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1649 	pkt << id;
1650 	Send(&pkt);
1651 }
1652 
SendHUDChange(session_t peer_id,u32 id,HudElementStat stat,void * value)1653 void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value)
1654 {
1655 	NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1656 	pkt << id << (u8) stat;
1657 
1658 	switch (stat) {
1659 		case HUD_STAT_POS:
1660 		case HUD_STAT_SCALE:
1661 		case HUD_STAT_ALIGN:
1662 		case HUD_STAT_OFFSET:
1663 			pkt << *(v2f *) value;
1664 			break;
1665 		case HUD_STAT_NAME:
1666 		case HUD_STAT_TEXT:
1667 		case HUD_STAT_TEXT2:
1668 			pkt << *(std::string *) value;
1669 			break;
1670 		case HUD_STAT_WORLD_POS:
1671 			pkt << *(v3f *) value;
1672 			break;
1673 		case HUD_STAT_SIZE:
1674 			pkt << *(v2s32 *) value;
1675 			break;
1676 		case HUD_STAT_NUMBER:
1677 		case HUD_STAT_ITEM:
1678 		case HUD_STAT_DIR:
1679 		default:
1680 			pkt << *(u32 *) value;
1681 			break;
1682 	}
1683 
1684 	Send(&pkt);
1685 }
1686 
SendHUDSetFlags(session_t peer_id,u32 flags,u32 mask)1687 void Server::SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask)
1688 {
1689 	NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1690 
1691 	flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1692 
1693 	pkt << flags << mask;
1694 
1695 	Send(&pkt);
1696 }
1697 
SendHUDSetParam(session_t peer_id,u16 param,const std::string & value)1698 void Server::SendHUDSetParam(session_t peer_id, u16 param, const std::string &value)
1699 {
1700 	NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1701 	pkt << param << value;
1702 	Send(&pkt);
1703 }
1704 
SendSetSky(session_t peer_id,const SkyboxParams & params)1705 void Server::SendSetSky(session_t peer_id, const SkyboxParams &params)
1706 {
1707 	NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1708 
1709 	// Handle prior clients here
1710 	if (m_clients.getProtocolVersion(peer_id) < 39) {
1711 		pkt << params.bgcolor << params.type << (u16) params.textures.size();
1712 
1713 		for (const std::string& texture : params.textures)
1714 			pkt << texture;
1715 
1716 		pkt << params.clouds;
1717 	} else { // Handle current clients and future clients
1718 		pkt << params.bgcolor << params.type
1719 		<< params.clouds << params.fog_sun_tint
1720 		<< params.fog_moon_tint << params.fog_tint_type;
1721 
1722 		if (params.type == "skybox") {
1723 			pkt << (u16) params.textures.size();
1724 			for (const std::string &texture : params.textures)
1725 				pkt << texture;
1726 		} else if (params.type == "regular") {
1727 			pkt << params.sky_color.day_sky << params.sky_color.day_horizon
1728 				<< params.sky_color.dawn_sky << params.sky_color.dawn_horizon
1729 				<< params.sky_color.night_sky << params.sky_color.night_horizon
1730 				<< params.sky_color.indoors;
1731 		}
1732 	}
1733 
1734 	Send(&pkt);
1735 }
1736 
SendSetSun(session_t peer_id,const SunParams & params)1737 void Server::SendSetSun(session_t peer_id, const SunParams &params)
1738 {
1739 	NetworkPacket pkt(TOCLIENT_SET_SUN, 0, peer_id);
1740 	pkt << params.visible << params.texture
1741 		<< params.tonemap << params.sunrise
1742 		<< params.sunrise_visible << params.scale;
1743 
1744 	Send(&pkt);
1745 }
SendSetMoon(session_t peer_id,const MoonParams & params)1746 void Server::SendSetMoon(session_t peer_id, const MoonParams &params)
1747 {
1748 	NetworkPacket pkt(TOCLIENT_SET_MOON, 0, peer_id);
1749 
1750 	pkt << params.visible << params.texture
1751 		<< params.tonemap << params.scale;
1752 
1753 	Send(&pkt);
1754 }
SendSetStars(session_t peer_id,const StarParams & params)1755 void Server::SendSetStars(session_t peer_id, const StarParams &params)
1756 {
1757 	NetworkPacket pkt(TOCLIENT_SET_STARS, 0, peer_id);
1758 
1759 	pkt << params.visible << params.count
1760 		<< params.starcolor << params.scale;
1761 
1762 	Send(&pkt);
1763 }
1764 
SendCloudParams(session_t peer_id,const CloudParams & params)1765 void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
1766 {
1767 	NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1768 	pkt << params.density << params.color_bright << params.color_ambient
1769 			<< params.height << params.thickness << params.speed;
1770 	Send(&pkt);
1771 }
1772 
SendOverrideDayNightRatio(session_t peer_id,bool do_override,float ratio)1773 void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
1774 		float ratio)
1775 {
1776 	NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1777 			1 + 2, peer_id);
1778 
1779 	pkt << do_override << (u16) (ratio * 65535);
1780 
1781 	Send(&pkt);
1782 }
1783 
SendTimeOfDay(session_t peer_id,u16 time,f32 time_speed)1784 void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
1785 {
1786 	NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1787 	pkt << time << time_speed;
1788 
1789 	if (peer_id == PEER_ID_INEXISTENT) {
1790 		m_clients.sendToAll(&pkt);
1791 	}
1792 	else {
1793 		Send(&pkt);
1794 	}
1795 }
1796 
SendPlayerHP(session_t peer_id)1797 void Server::SendPlayerHP(session_t peer_id)
1798 {
1799 	PlayerSAO *playersao = getPlayerSAO(peer_id);
1800 	assert(playersao);
1801 
1802 	SendHP(peer_id, playersao->getHP());
1803 	m_script->player_event(playersao,"health_changed");
1804 
1805 	// Send to other clients
1806 	playersao->sendPunchCommand();
1807 }
1808 
SendPlayerBreath(PlayerSAO * sao)1809 void Server::SendPlayerBreath(PlayerSAO *sao)
1810 {
1811 	assert(sao);
1812 
1813 	m_script->player_event(sao, "breath_changed");
1814 	SendBreath(sao->getPeerID(), sao->getBreath());
1815 }
1816 
SendMovePlayer(session_t peer_id)1817 void Server::SendMovePlayer(session_t peer_id)
1818 {
1819 	RemotePlayer *player = m_env->getPlayer(peer_id);
1820 	assert(player);
1821 	PlayerSAO *sao = player->getPlayerSAO();
1822 	assert(sao);
1823 
1824 	// Send attachment updates instantly to the client prior updating position
1825 	sao->sendOutdatedData();
1826 
1827 	NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1828 	pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
1829 
1830 	{
1831 		v3f pos = sao->getBasePosition();
1832 		verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1833 				<< " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1834 				<< " pitch=" << sao->getLookPitch()
1835 				<< " yaw=" << sao->getRotation().Y
1836 				<< std::endl;
1837 	}
1838 
1839 	Send(&pkt);
1840 }
1841 
SendPlayerFov(session_t peer_id)1842 void Server::SendPlayerFov(session_t peer_id)
1843 {
1844 	NetworkPacket pkt(TOCLIENT_FOV, 4 + 1 + 4, peer_id);
1845 
1846 	PlayerFovSpec fov_spec = m_env->getPlayer(peer_id)->getFov();
1847 	pkt << fov_spec.fov << fov_spec.is_multiplier << fov_spec.transition_time;
1848 
1849 	Send(&pkt);
1850 }
1851 
SendLocalPlayerAnimations(session_t peer_id,v2s32 animation_frames[4],f32 animation_speed)1852 void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
1853 		f32 animation_speed)
1854 {
1855 	NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1856 		peer_id);
1857 
1858 	pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1859 			<< animation_frames[3] << animation_speed;
1860 
1861 	Send(&pkt);
1862 }
1863 
SendEyeOffset(session_t peer_id,v3f first,v3f third)1864 void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
1865 {
1866 	NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1867 	pkt << first << third;
1868 	Send(&pkt);
1869 }
1870 
SendPlayerPrivileges(session_t peer_id)1871 void Server::SendPlayerPrivileges(session_t peer_id)
1872 {
1873 	RemotePlayer *player = m_env->getPlayer(peer_id);
1874 	assert(player);
1875 	if(player->getPeerId() == PEER_ID_INEXISTENT)
1876 		return;
1877 
1878 	std::set<std::string> privs;
1879 	m_script->getAuth(player->getName(), NULL, &privs);
1880 
1881 	NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1882 	pkt << (u16) privs.size();
1883 
1884 	for (const std::string &priv : privs) {
1885 		pkt << priv;
1886 	}
1887 
1888 	Send(&pkt);
1889 }
1890 
SendPlayerInventoryFormspec(session_t peer_id)1891 void Server::SendPlayerInventoryFormspec(session_t peer_id)
1892 {
1893 	RemotePlayer *player = m_env->getPlayer(peer_id);
1894 	assert(player);
1895 	if (player->getPeerId() == PEER_ID_INEXISTENT)
1896 		return;
1897 
1898 	NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1899 	pkt.putLongString(player->inventory_formspec);
1900 
1901 	Send(&pkt);
1902 }
1903 
SendPlayerFormspecPrepend(session_t peer_id)1904 void Server::SendPlayerFormspecPrepend(session_t peer_id)
1905 {
1906 	RemotePlayer *player = m_env->getPlayer(peer_id);
1907 	assert(player);
1908 	if (player->getPeerId() == PEER_ID_INEXISTENT)
1909 		return;
1910 
1911 	NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
1912 	pkt << player->formspec_prepend;
1913 	Send(&pkt);
1914 }
1915 
SendActiveObjectRemoveAdd(RemoteClient * client,PlayerSAO * playersao)1916 void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao)
1917 {
1918 	// Radius inside which objects are active
1919 	static thread_local const s16 radius =
1920 		g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
1921 
1922 	// Radius inside which players are active
1923 	static thread_local const bool is_transfer_limited =
1924 		g_settings->exists("unlimited_player_transfer_distance") &&
1925 		!g_settings->getBool("unlimited_player_transfer_distance");
1926 
1927 	static thread_local const s16 player_transfer_dist =
1928 		g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
1929 
1930 	s16 player_radius = player_transfer_dist == 0 && is_transfer_limited ?
1931 		radius : player_transfer_dist;
1932 
1933 	s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
1934 	if (my_radius <= 0)
1935 		my_radius = radius;
1936 
1937 	std::queue<u16> removed_objects, added_objects;
1938 	m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
1939 		client->m_known_objects, removed_objects);
1940 	m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
1941 		client->m_known_objects, added_objects);
1942 
1943 	int removed_count = removed_objects.size();
1944 	int added_count   = added_objects.size();
1945 
1946 	if (removed_objects.empty() && added_objects.empty())
1947 		return;
1948 
1949 	char buf[4];
1950 	std::string data;
1951 
1952 	// Handle removed objects
1953 	writeU16((u8*)buf, removed_objects.size());
1954 	data.append(buf, 2);
1955 	while (!removed_objects.empty()) {
1956 		// Get object
1957 		u16 id = removed_objects.front();
1958 		ServerActiveObject* obj = m_env->getActiveObject(id);
1959 
1960 		// Add to data buffer for sending
1961 		writeU16((u8*)buf, id);
1962 		data.append(buf, 2);
1963 
1964 		// Remove from known objects
1965 		client->m_known_objects.erase(id);
1966 
1967 		if (obj && obj->m_known_by_count > 0)
1968 			obj->m_known_by_count--;
1969 
1970 		removed_objects.pop();
1971 	}
1972 
1973 	// Handle added objects
1974 	writeU16((u8*)buf, added_objects.size());
1975 	data.append(buf, 2);
1976 	while (!added_objects.empty()) {
1977 		// Get object
1978 		u16 id = added_objects.front();
1979 		ServerActiveObject *obj = m_env->getActiveObject(id);
1980 		added_objects.pop();
1981 
1982 		if (!obj) {
1983 			warningstream << FUNCTION_NAME << ": NULL object id="
1984 				<< (int)id << std::endl;
1985 			continue;
1986 		}
1987 
1988 		// Get object type
1989 		u8 type = obj->getSendType();
1990 
1991 		// Add to data buffer for sending
1992 		writeU16((u8*)buf, id);
1993 		data.append(buf, 2);
1994 		writeU8((u8*)buf, type);
1995 		data.append(buf, 1);
1996 
1997 		data.append(serializeString32(
1998 			obj->getClientInitializationData(client->net_proto_version)));
1999 
2000 		// Add to known objects
2001 		client->m_known_objects.insert(id);
2002 
2003 		obj->m_known_by_count++;
2004 	}
2005 
2006 	NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, data.size(), client->peer_id);
2007 	pkt.putRawString(data.c_str(), data.size());
2008 	Send(&pkt);
2009 
2010 	verbosestream << "Server::SendActiveObjectRemoveAdd: "
2011 		<< removed_count << " removed, " << added_count << " added, "
2012 		<< "packet size is " << pkt.getSize() << std::endl;
2013 }
2014 
SendActiveObjectMessages(session_t peer_id,const std::string & datas,bool reliable)2015 void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
2016 		bool reliable)
2017 {
2018 	NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
2019 			datas.size(), peer_id);
2020 
2021 	pkt.putRawString(datas.c_str(), datas.size());
2022 
2023 	m_clients.send(pkt.getPeerId(),
2024 			reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
2025 			&pkt, reliable);
2026 }
2027 
SendCSMRestrictionFlags(session_t peer_id)2028 void Server::SendCSMRestrictionFlags(session_t peer_id)
2029 {
2030 	NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
2031 		sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
2032 	pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
2033 	Send(&pkt);
2034 }
2035 
SendPlayerSpeed(session_t peer_id,const v3f & added_vel)2036 void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
2037 {
2038 	NetworkPacket pkt(TOCLIENT_PLAYER_SPEED, 0, peer_id);
2039 	pkt << added_vel;
2040 	Send(&pkt);
2041 }
2042 
nextSoundId()2043 inline s32 Server::nextSoundId()
2044 {
2045 	s32 ret = m_next_sound_id;
2046 	if (m_next_sound_id == INT32_MAX)
2047 		m_next_sound_id = 0; // signed overflow is undefined
2048 	else
2049 		m_next_sound_id++;
2050 	return ret;
2051 }
2052 
playSound(const SimpleSoundSpec & spec,const ServerSoundParams & params,bool ephemeral)2053 s32 Server::playSound(const SimpleSoundSpec &spec,
2054 		const ServerSoundParams &params, bool ephemeral)
2055 {
2056 	// Find out initial position of sound
2057 	bool pos_exists = false;
2058 	v3f pos = params.getPos(m_env, &pos_exists);
2059 	// If position is not found while it should be, cancel sound
2060 	if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
2061 		return -1;
2062 
2063 	// Filter destination clients
2064 	std::vector<session_t> dst_clients;
2065 	if (!params.to_player.empty()) {
2066 		RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
2067 		if(!player){
2068 			infostream<<"Server::playSound: Player \""<<params.to_player
2069 					<<"\" not found"<<std::endl;
2070 			return -1;
2071 		}
2072 		if (player->getPeerId() == PEER_ID_INEXISTENT) {
2073 			infostream<<"Server::playSound: Player \""<<params.to_player
2074 					<<"\" not connected"<<std::endl;
2075 			return -1;
2076 		}
2077 		dst_clients.push_back(player->getPeerId());
2078 	} else {
2079 		std::vector<session_t> clients = m_clients.getClientIDs();
2080 
2081 		for (const session_t client_id : clients) {
2082 			RemotePlayer *player = m_env->getPlayer(client_id);
2083 			if (!player)
2084 				continue;
2085 			if (!params.exclude_player.empty() &&
2086 					params.exclude_player == player->getName())
2087 				continue;
2088 
2089 			PlayerSAO *sao = player->getPlayerSAO();
2090 			if (!sao)
2091 				continue;
2092 
2093 			if (pos_exists) {
2094 				if(sao->getBasePosition().getDistanceFrom(pos) >
2095 						params.max_hear_distance)
2096 					continue;
2097 			}
2098 			dst_clients.push_back(client_id);
2099 		}
2100 	}
2101 
2102 	if(dst_clients.empty())
2103 		return -1;
2104 
2105 	// Create the sound
2106 	s32 id;
2107 	ServerPlayingSound *psound = nullptr;
2108 	if (ephemeral) {
2109 		id = -1; // old clients will still use this, so pick a reserved ID
2110 	} else {
2111 		id = nextSoundId();
2112 		// The sound will exist as a reference in m_playing_sounds
2113 		m_playing_sounds[id] = ServerPlayingSound();
2114 		psound = &m_playing_sounds[id];
2115 		psound->params = params;
2116 		psound->spec = spec;
2117 	}
2118 
2119 	float gain = params.gain * spec.gain;
2120 	NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2121 	pkt << id << spec.name << gain
2122 			<< (u8) params.type << pos << params.object
2123 			<< params.loop << params.fade << params.pitch
2124 			<< ephemeral;
2125 
2126 	bool as_reliable = !ephemeral;
2127 
2128 	for (const u16 dst_client : dst_clients) {
2129 		if (psound)
2130 			psound->clients.insert(dst_client);
2131 		m_clients.send(dst_client, 0, &pkt, as_reliable);
2132 	}
2133 	return id;
2134 }
stopSound(s32 handle)2135 void Server::stopSound(s32 handle)
2136 {
2137 	// Get sound reference
2138 	std::unordered_map<s32, ServerPlayingSound>::iterator i =
2139 		m_playing_sounds.find(handle);
2140 	if (i == m_playing_sounds.end())
2141 		return;
2142 	ServerPlayingSound &psound = i->second;
2143 
2144 	NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2145 	pkt << handle;
2146 
2147 	for (std::unordered_set<session_t>::const_iterator si = psound.clients.begin();
2148 			si != psound.clients.end(); ++si) {
2149 		// Send as reliable
2150 		m_clients.send(*si, 0, &pkt, true);
2151 	}
2152 	// Remove sound reference
2153 	m_playing_sounds.erase(i);
2154 }
2155 
fadeSound(s32 handle,float step,float gain)2156 void Server::fadeSound(s32 handle, float step, float gain)
2157 {
2158 	// Get sound reference
2159 	std::unordered_map<s32, ServerPlayingSound>::iterator i =
2160 		m_playing_sounds.find(handle);
2161 	if (i == m_playing_sounds.end())
2162 		return;
2163 
2164 	ServerPlayingSound &psound = i->second;
2165 	psound.params.gain = gain;
2166 
2167 	NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2168 	pkt << handle << step << gain;
2169 
2170 	// Backwards compability
2171 	bool play_sound = gain > 0;
2172 	ServerPlayingSound compat_psound = psound;
2173 	compat_psound.clients.clear();
2174 
2175 	NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2176 	compat_pkt << handle;
2177 
2178 	for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2179 			it != psound.clients.end();) {
2180 		if (m_clients.getProtocolVersion(*it) >= 32) {
2181 			// Send as reliable
2182 			m_clients.send(*it, 0, &pkt, true);
2183 			++it;
2184 		} else {
2185 			compat_psound.clients.insert(*it);
2186 			// Stop old sound
2187 			m_clients.send(*it, 0, &compat_pkt, true);
2188 			psound.clients.erase(it++);
2189 		}
2190 	}
2191 
2192 	// Remove sound reference
2193 	if (!play_sound || psound.clients.empty())
2194 		m_playing_sounds.erase(i);
2195 
2196 	if (play_sound && !compat_psound.clients.empty()) {
2197 		// Play new sound volume on older clients
2198 		playSound(compat_psound.spec, compat_psound.params);
2199 	}
2200 }
2201 
sendRemoveNode(v3s16 p,std::unordered_set<u16> * far_players,float far_d_nodes)2202 void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
2203 		float far_d_nodes)
2204 {
2205 	float maxd = far_d_nodes * BS;
2206 	v3f p_f = intToFloat(p, BS);
2207 	v3s16 block_pos = getNodeBlockPos(p);
2208 
2209 	NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2210 	pkt << p;
2211 
2212 	std::vector<session_t> clients = m_clients.getClientIDs();
2213 	m_clients.lock();
2214 
2215 	for (session_t client_id : clients) {
2216 		RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2217 		if (!client)
2218 			continue;
2219 
2220 		RemotePlayer *player = m_env->getPlayer(client_id);
2221 		PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2222 
2223 		// If player is far away, only set modified blocks not sent
2224 		if (!client->isBlockSent(block_pos) || (sao &&
2225 				sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2226 			if (far_players)
2227 				far_players->emplace(client_id);
2228 			else
2229 				client->SetBlockNotSent(block_pos);
2230 			continue;
2231 		}
2232 
2233 		// Send as reliable
2234 		m_clients.send(client_id, 0, &pkt, true);
2235 	}
2236 
2237 	m_clients.unlock();
2238 }
2239 
sendAddNode(v3s16 p,MapNode n,std::unordered_set<u16> * far_players,float far_d_nodes,bool remove_metadata)2240 void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
2241 		float far_d_nodes, bool remove_metadata)
2242 {
2243 	float maxd = far_d_nodes * BS;
2244 	v3f p_f = intToFloat(p, BS);
2245 	v3s16 block_pos = getNodeBlockPos(p);
2246 
2247 	NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2248 	pkt << p << n.param0 << n.param1 << n.param2
2249 			<< (u8) (remove_metadata ? 0 : 1);
2250 
2251 	std::vector<session_t> clients = m_clients.getClientIDs();
2252 	m_clients.lock();
2253 
2254 	for (session_t client_id : clients) {
2255 		RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2256 		if (!client)
2257 			continue;
2258 
2259 		RemotePlayer *player = m_env->getPlayer(client_id);
2260 		PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2261 
2262 		// If player is far away, only set modified blocks not sent
2263 		if (!client->isBlockSent(block_pos) || (sao &&
2264 				sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2265 			if (far_players)
2266 				far_players->emplace(client_id);
2267 			else
2268 				client->SetBlockNotSent(block_pos);
2269 			continue;
2270 		}
2271 
2272 		// Send as reliable
2273 		m_clients.send(client_id, 0, &pkt, true);
2274 	}
2275 
2276 	m_clients.unlock();
2277 }
2278 
sendMetadataChanged(const std::list<v3s16> & meta_updates,float far_d_nodes)2279 void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far_d_nodes)
2280 {
2281 	float maxd = far_d_nodes * BS;
2282 	NodeMetadataList meta_updates_list(false);
2283 	std::vector<session_t> clients = m_clients.getClientIDs();
2284 
2285 	m_clients.lock();
2286 
2287 	for (session_t i : clients) {
2288 		RemoteClient *client = m_clients.lockedGetClientNoEx(i);
2289 		if (!client)
2290 			continue;
2291 
2292 		ServerActiveObject *player = m_env->getActiveObject(i);
2293 		v3f player_pos = player ? player->getBasePosition() : v3f();
2294 
2295 		for (const v3s16 &pos : meta_updates) {
2296 			NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos);
2297 
2298 			if (!meta)
2299 				continue;
2300 
2301 			v3s16 block_pos = getNodeBlockPos(pos);
2302 			if (!client->isBlockSent(block_pos) || (player &&
2303 					player_pos.getDistanceFrom(intToFloat(pos, BS)) > maxd)) {
2304 				client->SetBlockNotSent(block_pos);
2305 				continue;
2306 			}
2307 
2308 			// Add the change to send list
2309 			meta_updates_list.set(pos, meta);
2310 		}
2311 		if (meta_updates_list.size() == 0)
2312 			continue;
2313 
2314 		// Send the meta changes
2315 		std::ostringstream os(std::ios::binary);
2316 		meta_updates_list.serialize(os, client->net_proto_version, false, true);
2317 		std::ostringstream oss(std::ios::binary);
2318 		compressZlib(os.str(), oss);
2319 
2320 		NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0);
2321 		pkt.putLongString(oss.str());
2322 		m_clients.send(i, 0, &pkt, true);
2323 
2324 		meta_updates_list.clear();
2325 	}
2326 
2327 	m_clients.unlock();
2328 }
2329 
SendBlockNoLock(session_t peer_id,MapBlock * block,u8 ver,u16 net_proto_version)2330 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
2331 		u16 net_proto_version)
2332 {
2333 	/*
2334 		Create a packet with the block in the right format
2335 	*/
2336 	thread_local const int net_compression_level = rangelim(g_settings->getS16("map_compression_level_net"), -1, 9);
2337 	std::ostringstream os(std::ios_base::binary);
2338 	block->serialize(os, ver, false, net_compression_level);
2339 	block->serializeNetworkSpecific(os);
2340 	std::string s = os.str();
2341 
2342 	NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + s.size(), peer_id);
2343 
2344 	pkt << block->getPos();
2345 	pkt.putRawString(s.c_str(), s.size());
2346 	Send(&pkt);
2347 }
2348 
SendBlocks(float dtime)2349 void Server::SendBlocks(float dtime)
2350 {
2351 	MutexAutoLock envlock(m_env_mutex);
2352 	//TODO check if one big lock could be faster then multiple small ones
2353 
2354 	std::vector<PrioritySortedBlockTransfer> queue;
2355 
2356 	u32 total_sending = 0;
2357 
2358 	{
2359 		ScopeProfiler sp2(g_profiler, "Server::SendBlocks(): Collect list");
2360 
2361 		std::vector<session_t> clients = m_clients.getClientIDs();
2362 
2363 		m_clients.lock();
2364 		for (const session_t client_id : clients) {
2365 			RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2366 
2367 			if (!client)
2368 				continue;
2369 
2370 			total_sending += client->getSendingCount();
2371 			client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2372 		}
2373 		m_clients.unlock();
2374 	}
2375 
2376 	// Sort.
2377 	// Lowest priority number comes first.
2378 	// Lowest is most important.
2379 	std::sort(queue.begin(), queue.end());
2380 
2381 	m_clients.lock();
2382 
2383 	// Maximal total count calculation
2384 	// The per-client block sends is halved with the maximal online users
2385 	u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
2386 		g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
2387 
2388 	ScopeProfiler sp(g_profiler, "Server::SendBlocks(): Send to clients");
2389 	Map &map = m_env->getMap();
2390 
2391 	for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2392 		if (total_sending >= max_blocks_to_send)
2393 			break;
2394 
2395 		MapBlock *block = map.getBlockNoCreateNoEx(block_to_send.pos);
2396 		if (!block)
2397 			continue;
2398 
2399 		RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2400 				CS_Active);
2401 		if (!client)
2402 			continue;
2403 
2404 		SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2405 				client->net_proto_version);
2406 
2407 		client->SentBlock(block_to_send.pos);
2408 		total_sending++;
2409 	}
2410 	m_clients.unlock();
2411 }
2412 
SendBlock(session_t peer_id,const v3s16 & blockpos)2413 bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos)
2414 {
2415 	MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2416 	if (!block)
2417 		return false;
2418 
2419 	m_clients.lock();
2420 	RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Active);
2421 	if (!client || client->isBlockSent(blockpos)) {
2422 		m_clients.unlock();
2423 		return false;
2424 	}
2425 	SendBlockNoLock(peer_id, block, client->serialization_version,
2426 			client->net_proto_version);
2427 	m_clients.unlock();
2428 
2429 	return true;
2430 }
2431 
addMediaFile(const std::string & filename,const std::string & filepath,std::string * filedata_to,std::string * digest_to)2432 bool Server::addMediaFile(const std::string &filename,
2433 	const std::string &filepath, std::string *filedata_to,
2434 	std::string *digest_to)
2435 {
2436 	// If name contains illegal characters, ignore the file
2437 	if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2438 		infostream << "Server: ignoring illegal file name: \""
2439 				<< filename << "\"" << std::endl;
2440 		return false;
2441 	}
2442 	// If name is not in a supported format, ignore it
2443 	const char *supported_ext[] = {
2444 		".png", ".jpg", ".bmp", ".tga",
2445 		".pcx", ".ppm", ".psd", ".wal", ".rgb",
2446 		".ogg",
2447 		".x", ".b3d", ".md2", ".obj",
2448 		// Custom translation file format
2449 		".tr",
2450 		NULL
2451 	};
2452 	if (removeStringEnd(filename, supported_ext).empty()) {
2453 		infostream << "Server: ignoring unsupported file extension: \""
2454 				<< filename << "\"" << std::endl;
2455 		return false;
2456 	}
2457 	// Ok, attempt to load the file and add to cache
2458 
2459 	// Read data
2460 	std::string filedata;
2461 	if (!fs::ReadFile(filepath, filedata)) {
2462 		errorstream << "Server::addMediaFile(): Failed to open \""
2463 					<< filename << "\" for reading" << std::endl;
2464 		return false;
2465 	}
2466 
2467 	if (filedata.empty()) {
2468 		errorstream << "Server::addMediaFile(): Empty file \""
2469 				<< filepath << "\"" << std::endl;
2470 		return false;
2471 	}
2472 
2473 	SHA1 sha1;
2474 	sha1.addBytes(filedata.c_str(), filedata.length());
2475 
2476 	unsigned char *digest = sha1.getDigest();
2477 	std::string sha1_base64 = base64_encode(digest, 20);
2478 	std::string sha1_hex = hex_encode((char*) digest, 20);
2479 	if (digest_to)
2480 		*digest_to = std::string((char*) digest, 20);
2481 	free(digest);
2482 
2483 	// Put in list
2484 	m_media[filename] = MediaInfo(filepath, sha1_base64);
2485 	verbosestream << "Server: " << sha1_hex << " is " << filename
2486 			<< std::endl;
2487 
2488 	if (filedata_to)
2489 		*filedata_to = std::move(filedata);
2490 	return true;
2491 }
2492 
fillMediaCache()2493 void Server::fillMediaCache()
2494 {
2495 	infostream << "Server: Calculating media file checksums" << std::endl;
2496 
2497 	// Collect all media file paths
2498 	std::vector<std::string> paths;
2499 	// The paths are ordered in descending priority
2500 	fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2501 	fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
2502 	m_modmgr->getModsMediaPaths(paths);
2503 
2504 	// Collect media file information from paths into cache
2505 	for (const std::string &mediapath : paths) {
2506 		std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2507 		for (const fs::DirListNode &dln : dirlist) {
2508 			if (dln.dir) // Ignore dirs (already in paths)
2509 				continue;
2510 
2511 			const std::string &filename = dln.name;
2512 			if (m_media.find(filename) != m_media.end()) // Do not override
2513 				continue;
2514 
2515 			std::string filepath = mediapath;
2516 			filepath.append(DIR_DELIM).append(filename);
2517 			addMediaFile(filename, filepath);
2518 		}
2519 	}
2520 
2521 	infostream << "Server: " << m_media.size() << " media files collected" << std::endl;
2522 }
2523 
sendMediaAnnouncement(session_t peer_id,const std::string & lang_code)2524 void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
2525 {
2526 	// Make packet
2527 	NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2528 
2529 	u16 media_sent = 0;
2530 	std::string lang_suffix;
2531 	lang_suffix.append(".").append(lang_code).append(".tr");
2532 	for (const auto &i : m_media) {
2533 		if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2534 			continue;
2535 		media_sent++;
2536 	}
2537 
2538 	pkt << media_sent;
2539 
2540 	for (const auto &i : m_media) {
2541 		if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2542 			continue;
2543 		pkt << i.first << i.second.sha1_digest;
2544 	}
2545 
2546 	pkt << g_settings->get("remote_media");
2547 	Send(&pkt);
2548 
2549 	verbosestream << "Server: Announcing files to id(" << peer_id
2550 		<< "): count=" << media_sent << " size=" << pkt.getSize() << std::endl;
2551 }
2552 
2553 struct SendableMedia
2554 {
2555 	std::string name;
2556 	std::string path;
2557 	std::string data;
2558 
SendableMediaSendableMedia2559 	SendableMedia(const std::string &name_="", const std::string &path_="",
2560 	              const std::string &data_=""):
2561 		name(name_),
2562 		path(path_),
2563 		data(data_)
2564 	{}
2565 };
2566 
sendRequestedMedia(session_t peer_id,const std::vector<std::string> & tosend)2567 void Server::sendRequestedMedia(session_t peer_id,
2568 		const std::vector<std::string> &tosend)
2569 {
2570 	verbosestream<<"Server::sendRequestedMedia(): "
2571 			<<"Sending files to client"<<std::endl;
2572 
2573 	/* Read files */
2574 
2575 	// Put 5kB in one bunch (this is not accurate)
2576 	u32 bytes_per_bunch = 5000;
2577 
2578 	std::vector< std::vector<SendableMedia> > file_bunches;
2579 	file_bunches.emplace_back();
2580 
2581 	u32 file_size_bunch_total = 0;
2582 
2583 	for (const std::string &name : tosend) {
2584 		if (m_media.find(name) == m_media.end()) {
2585 			errorstream<<"Server::sendRequestedMedia(): Client asked for "
2586 					<<"unknown file \""<<(name)<<"\""<<std::endl;
2587 			continue;
2588 		}
2589 
2590 		//TODO get path + name
2591 		std::string tpath = m_media[name].path;
2592 
2593 		// Read data
2594 		std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2595 		if(!fis.good()){
2596 			errorstream<<"Server::sendRequestedMedia(): Could not open \""
2597 					<<tpath<<"\" for reading"<<std::endl;
2598 			continue;
2599 		}
2600 		std::ostringstream tmp_os(std::ios_base::binary);
2601 		bool bad = false;
2602 		for(;;) {
2603 			char buf[1024];
2604 			fis.read(buf, 1024);
2605 			std::streamsize len = fis.gcount();
2606 			tmp_os.write(buf, len);
2607 			file_size_bunch_total += len;
2608 			if(fis.eof())
2609 				break;
2610 			if(!fis.good()) {
2611 				bad = true;
2612 				break;
2613 			}
2614 		}
2615 		if (bad) {
2616 			errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2617 					<<name<<"\""<<std::endl;
2618 			continue;
2619 		}
2620 		/*infostream<<"Server::sendRequestedMedia(): Loaded \""
2621 				<<tname<<"\""<<std::endl;*/
2622 		// Put in list
2623 		file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2624 
2625 		// Start next bunch if got enough data
2626 		if(file_size_bunch_total >= bytes_per_bunch) {
2627 			file_bunches.emplace_back();
2628 			file_size_bunch_total = 0;
2629 		}
2630 
2631 	}
2632 
2633 	/* Create and send packets */
2634 
2635 	u16 num_bunches = file_bunches.size();
2636 	for (u16 i = 0; i < num_bunches; i++) {
2637 		/*
2638 			u16 command
2639 			u16 total number of texture bunches
2640 			u16 index of this bunch
2641 			u32 number of files in this bunch
2642 			for each file {
2643 				u16 length of name
2644 				string name
2645 				u32 length of data
2646 				data
2647 			}
2648 		*/
2649 
2650 		NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2651 		pkt << num_bunches << i << (u32) file_bunches[i].size();
2652 
2653 		for (const SendableMedia &j : file_bunches[i]) {
2654 			pkt << j.name;
2655 			pkt.putLongString(j.data);
2656 		}
2657 
2658 		verbosestream << "Server::sendRequestedMedia(): bunch "
2659 				<< i << "/" << num_bunches
2660 				<< " files=" << file_bunches[i].size()
2661 				<< " size="  << pkt.getSize() << std::endl;
2662 		Send(&pkt);
2663 	}
2664 }
2665 
SendMinimapModes(session_t peer_id,std::vector<MinimapMode> & modes,size_t wanted_mode)2666 void Server::SendMinimapModes(session_t peer_id,
2667 		std::vector<MinimapMode> &modes, size_t wanted_mode)
2668 {
2669 	RemotePlayer *player = m_env->getPlayer(peer_id);
2670 	assert(player);
2671 	if (player->getPeerId() == PEER_ID_INEXISTENT)
2672 		return;
2673 
2674 	NetworkPacket pkt(TOCLIENT_MINIMAP_MODES, 0, peer_id);
2675 	pkt << (u16)modes.size() << (u16)wanted_mode;
2676 
2677 	for (auto &mode : modes)
2678 		pkt << (u16)mode.type << mode.label << mode.size << mode.texture << mode.scale;
2679 
2680 	Send(&pkt);
2681 }
2682 
sendDetachedInventory(Inventory * inventory,const std::string & name,session_t peer_id)2683 void Server::sendDetachedInventory(Inventory *inventory, const std::string &name, session_t peer_id)
2684 {
2685 	NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2686 	pkt << name;
2687 
2688 	if (!inventory) {
2689 		pkt << false; // Remove inventory
2690 	} else {
2691 		pkt << true; // Update inventory
2692 
2693 		// Serialization & NetworkPacket isn't a love story
2694 		std::ostringstream os(std::ios_base::binary);
2695 		inventory->serialize(os);
2696 		inventory->setModified(false);
2697 
2698 		const std::string &os_str = os.str();
2699 		pkt << static_cast<u16>(os_str.size()); // HACK: to keep compatibility with 5.0.0 clients
2700 		pkt.putRawString(os_str);
2701 	}
2702 
2703 	if (peer_id == PEER_ID_INEXISTENT)
2704 		m_clients.sendToAll(&pkt);
2705 	else
2706 		Send(&pkt);
2707 }
2708 
sendDetachedInventories(session_t peer_id,bool incremental)2709 void Server::sendDetachedInventories(session_t peer_id, bool incremental)
2710 {
2711 	// Lookup player name, to filter detached inventories just after
2712 	std::string peer_name;
2713 	if (peer_id != PEER_ID_INEXISTENT) {
2714 		peer_name = getClient(peer_id, CS_Created)->getName();
2715 	}
2716 
2717 	auto send_cb = [this, peer_id](const std::string &name, Inventory *inv) {
2718 		sendDetachedInventory(inv, name, peer_id);
2719 	};
2720 
2721 	m_inventory_mgr->sendDetachedInventories(peer_name, incremental, send_cb);
2722 }
2723 
2724 /*
2725 	Something random
2726 */
2727 
DiePlayer(session_t peer_id,const PlayerHPChangeReason & reason)2728 void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
2729 {
2730 	PlayerSAO *playersao = getPlayerSAO(peer_id);
2731 	assert(playersao);
2732 
2733 	infostream << "Server::DiePlayer(): Player "
2734 			<< playersao->getPlayer()->getName()
2735 			<< " dies" << std::endl;
2736 
2737 	playersao->setHP(0, reason);
2738 	playersao->clearParentAttachment();
2739 
2740 	// Trigger scripted stuff
2741 	m_script->on_dieplayer(playersao, reason);
2742 
2743 	SendPlayerHP(peer_id);
2744 	SendDeathscreen(peer_id, false, v3f(0,0,0));
2745 }
2746 
RespawnPlayer(session_t peer_id)2747 void Server::RespawnPlayer(session_t peer_id)
2748 {
2749 	PlayerSAO *playersao = getPlayerSAO(peer_id);
2750 	assert(playersao);
2751 
2752 	infostream << "Server::RespawnPlayer(): Player "
2753 			<< playersao->getPlayer()->getName()
2754 			<< " respawns" << std::endl;
2755 
2756 	playersao->setHP(playersao->accessObjectProperties()->hp_max,
2757 			PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
2758 	playersao->setBreath(playersao->accessObjectProperties()->breath_max);
2759 
2760 	bool repositioned = m_script->on_respawnplayer(playersao);
2761 	if (!repositioned) {
2762 		// setPos will send the new position to client
2763 		playersao->setPos(findSpawnPos());
2764 	}
2765 
2766 	SendPlayerHP(peer_id);
2767 }
2768 
2769 
DenySudoAccess(session_t peer_id)2770 void Server::DenySudoAccess(session_t peer_id)
2771 {
2772 	NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2773 	Send(&pkt);
2774 }
2775 
2776 
DenyAccessVerCompliant(session_t peer_id,u16 proto_ver,AccessDeniedCode reason,const std::string & str_reason,bool reconnect)2777 void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
2778 		const std::string &str_reason, bool reconnect)
2779 {
2780 	SendAccessDenied(peer_id, reason, str_reason, reconnect);
2781 
2782 	m_clients.event(peer_id, CSE_SetDenied);
2783 	DisconnectPeer(peer_id);
2784 }
2785 
2786 
DenyAccess(session_t peer_id,AccessDeniedCode reason,const std::string & custom_reason)2787 void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
2788 		const std::string &custom_reason)
2789 {
2790 	SendAccessDenied(peer_id, reason, custom_reason);
2791 	m_clients.event(peer_id, CSE_SetDenied);
2792 	DisconnectPeer(peer_id);
2793 }
2794 
2795 // 13/03/15: remove this function when protocol version 25 will become
2796 // the minimum version for MT users, maybe in 1 year
DenyAccess_Legacy(session_t peer_id,const std::wstring & reason)2797 void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
2798 {
2799 	SendAccessDenied_Legacy(peer_id, reason);
2800 	m_clients.event(peer_id, CSE_SetDenied);
2801 	DisconnectPeer(peer_id);
2802 }
2803 
DisconnectPeer(session_t peer_id)2804 void Server::DisconnectPeer(session_t peer_id)
2805 {
2806 	m_modchannel_mgr->leaveAllChannels(peer_id);
2807 	m_con->DisconnectPeer(peer_id);
2808 }
2809 
acceptAuth(session_t peer_id,bool forSudoMode)2810 void Server::acceptAuth(session_t peer_id, bool forSudoMode)
2811 {
2812 	if (!forSudoMode) {
2813 		RemoteClient* client = getClient(peer_id, CS_Invalid);
2814 
2815 		NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2816 
2817 		// Right now, the auth mechs don't change between login and sudo mode.
2818 		u32 sudo_auth_mechs = client->allowed_auth_mechs;
2819 		client->allowed_sudo_mechs = sudo_auth_mechs;
2820 
2821 		resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2822 				<< g_settings->getFloat("dedicated_server_step")
2823 				<< sudo_auth_mechs;
2824 
2825 		Send(&resp_pkt);
2826 		m_clients.event(peer_id, CSE_AuthAccept);
2827 	} else {
2828 		NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2829 
2830 		// We only support SRP right now
2831 		u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2832 
2833 		resp_pkt << sudo_auth_mechs;
2834 		Send(&resp_pkt);
2835 		m_clients.event(peer_id, CSE_SudoSuccess);
2836 	}
2837 }
2838 
DeleteClient(session_t peer_id,ClientDeletionReason reason)2839 void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
2840 {
2841 	std::wstring message;
2842 	{
2843 		/*
2844 			Clear references to playing sounds
2845 		*/
2846 		for (std::unordered_map<s32, ServerPlayingSound>::iterator
2847 				 i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2848 			ServerPlayingSound &psound = i->second;
2849 			psound.clients.erase(peer_id);
2850 			if (psound.clients.empty())
2851 				m_playing_sounds.erase(i++);
2852 			else
2853 				++i;
2854 		}
2855 
2856 		// clear formspec info so the next client can't abuse the current state
2857 		m_formspec_state_data.erase(peer_id);
2858 
2859 		RemotePlayer *player = m_env->getPlayer(peer_id);
2860 
2861 		/* Run scripts and remove from environment */
2862 		if (player) {
2863 			PlayerSAO *playersao = player->getPlayerSAO();
2864 			assert(playersao);
2865 
2866 			playersao->clearChildAttachments();
2867 			playersao->clearParentAttachment();
2868 
2869 			// inform connected clients
2870 			const std::string &player_name = player->getName();
2871 			NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2872 			// (u16) 1 + std::string represents a vector serialization representation
2873 			notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
2874 			m_clients.sendToAll(&notice);
2875 			// run scripts
2876 			m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2877 
2878 			playersao->disconnected();
2879 		}
2880 
2881 		/*
2882 			Print out action
2883 		*/
2884 		{
2885 			if (player && reason != CDR_DENY) {
2886 				std::ostringstream os(std::ios_base::binary);
2887 				std::vector<session_t> clients = m_clients.getClientIDs();
2888 
2889 				for (const session_t client_id : clients) {
2890 					// Get player
2891 					RemotePlayer *player = m_env->getPlayer(client_id);
2892 					if (!player)
2893 						continue;
2894 
2895 					// Get name of player
2896 					os << player->getName() << " ";
2897 				}
2898 
2899 				std::string name = player->getName();
2900 				actionstream << name << " "
2901 						<< (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2902 						<< " List of players: " << os.str() << std::endl;
2903 				if (m_admin_chat)
2904 					m_admin_chat->outgoing_queue.push_back(
2905 						new ChatEventNick(CET_NICK_REMOVE, name));
2906 			}
2907 		}
2908 		{
2909 			MutexAutoLock env_lock(m_env_mutex);
2910 			m_clients.DeleteClient(peer_id);
2911 		}
2912 	}
2913 
2914 	// Send leave chat message to all remaining clients
2915 	if (!message.empty()) {
2916 		SendChatMessage(PEER_ID_INEXISTENT,
2917 				ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2918 	}
2919 }
2920 
UpdateCrafting(RemotePlayer * player)2921 void Server::UpdateCrafting(RemotePlayer *player)
2922 {
2923 	InventoryList *clist = player->inventory.getList("craft");
2924 	if (!clist || clist->getSize() == 0)
2925 		return;
2926 
2927 	if (!clist->checkModified())
2928 		return;
2929 
2930 	// Get a preview for crafting
2931 	ItemStack preview;
2932 	InventoryLocation loc;
2933 	loc.setPlayer(player->getName());
2934 	std::vector<ItemStack> output_replacements;
2935 	getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2936 	m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2937 			clist, loc);
2938 
2939 	InventoryList *plist = player->inventory.getList("craftpreview");
2940 	if (plist && plist->getSize() >= 1) {
2941 		// Put the new preview in
2942 		plist->changeItem(0, preview);
2943 	}
2944 }
2945 
handleChatInterfaceEvent(ChatEvent * evt)2946 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2947 {
2948 	if (evt->type == CET_NICK_ADD) {
2949 		// The terminal informed us of its nick choice
2950 		m_admin_nick = ((ChatEventNick *)evt)->nick;
2951 		if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2952 			errorstream << "You haven't set up an account." << std::endl
2953 				<< "Please log in using the client as '"
2954 				<< m_admin_nick << "' with a secure password." << std::endl
2955 				<< "Until then, you can't execute admin tasks via the console," << std::endl
2956 				<< "and everybody can claim the user account instead of you," << std::endl
2957 				<< "giving them full control over this server." << std::endl;
2958 		}
2959 	} else {
2960 		assert(evt->type == CET_CHAT);
2961 		handleAdminChat((ChatEventChat *)evt);
2962 	}
2963 }
2964 
handleChat(const std::string & name,std::wstring wmessage,bool check_shout_priv,RemotePlayer * player)2965 std::wstring Server::handleChat(const std::string &name,
2966 	std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2967 {
2968 	// If something goes wrong, this player is to blame
2969 	RollbackScopeActor rollback_scope(m_rollback,
2970 			std::string("player:") + name);
2971 
2972 	if (g_settings->getBool("strip_color_codes"))
2973 		wmessage = unescape_enriched(wmessage);
2974 
2975 	if (player) {
2976 		switch (player->canSendChatMessage()) {
2977 		case RPLAYER_CHATRESULT_FLOODING: {
2978 			std::wstringstream ws;
2979 			ws << L"You cannot send more messages. You are limited to "
2980 					<< g_settings->getFloat("chat_message_limit_per_10sec")
2981 					<< L" messages per 10 seconds.";
2982 			return ws.str();
2983 		}
2984 		case RPLAYER_CHATRESULT_KICK:
2985 			DenyAccess_Legacy(player->getPeerId(),
2986 					L"You have been kicked due to message flooding.");
2987 			return L"";
2988 		case RPLAYER_CHATRESULT_OK:
2989 			break;
2990 		default:
2991 			FATAL_ERROR("Unhandled chat filtering result found.");
2992 		}
2993 	}
2994 
2995 	if (m_max_chatmessage_length > 0
2996 			&& wmessage.length() > m_max_chatmessage_length) {
2997 		return L"Your message exceed the maximum chat message limit set on the server. "
2998 				L"It was refused. Send a shorter message";
2999 	}
3000 
3001 	auto message = trim(wide_to_utf8(wmessage));
3002 	if (message.find_first_of("\n\r") != std::wstring::npos) {
3003 		return L"Newlines are not permitted in chat messages";
3004 	}
3005 
3006 	// Run script hook, exit if script ate the chat message
3007 	if (m_script->on_chat_message(name, message))
3008 		return L"";
3009 
3010 	// Line to send
3011 	std::wstring line;
3012 	// Whether to send line to the player that sent the message, or to all players
3013 	bool broadcast_line = true;
3014 
3015 	if (check_shout_priv && !checkPriv(name, "shout")) {
3016 		line += L"-!- You don't have permission to shout.";
3017 		broadcast_line = false;
3018 	} else {
3019 		/*
3020 			Workaround for fixing chat on Android. Lua doesn't handle
3021 			the Cyrillic alphabet and some characters on older Android devices
3022 		*/
3023 #ifdef __ANDROID__
3024 		line += L"<" + utf8_to_wide(name) + L"> " + wmessage;
3025 #else
3026 		line += utf8_to_wide(m_script->formatChatMessage(name,
3027 				wide_to_utf8(wmessage)));
3028 #endif
3029 	}
3030 
3031 	/*
3032 		Tell calling method to send the message to sender
3033 	*/
3034 	if (!broadcast_line)
3035 		return line;
3036 
3037 	/*
3038 		Send the message to others
3039 	*/
3040 	actionstream << "CHAT: " << wide_to_utf8(unescape_enriched(line)) << std::endl;
3041 
3042 	ChatMessage chatmsg(line);
3043 
3044 	std::vector<session_t> clients = m_clients.getClientIDs();
3045 	for (u16 cid : clients)
3046 		SendChatMessage(cid, chatmsg);
3047 
3048 	return L"";
3049 }
3050 
handleAdminChat(const ChatEventChat * evt)3051 void Server::handleAdminChat(const ChatEventChat *evt)
3052 {
3053 	std::string name = evt->nick;
3054 	std::wstring wmessage = evt->evt_msg;
3055 
3056 	std::wstring answer = handleChat(name, wmessage);
3057 
3058 	// If asked to send answer to sender
3059 	if (!answer.empty()) {
3060 		m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
3061 	}
3062 }
3063 
getClient(session_t peer_id,ClientState state_min)3064 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
3065 {
3066 	RemoteClient *client = getClientNoEx(peer_id,state_min);
3067 	if(!client)
3068 		throw ClientNotFoundException("Client not found");
3069 
3070 	return client;
3071 }
getClientNoEx(session_t peer_id,ClientState state_min)3072 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
3073 {
3074 	return m_clients.getClientNoEx(peer_id, state_min);
3075 }
3076 
getPlayerName(session_t peer_id)3077 std::string Server::getPlayerName(session_t peer_id)
3078 {
3079 	RemotePlayer *player = m_env->getPlayer(peer_id);
3080 	if (!player)
3081 		return "[id="+itos(peer_id)+"]";
3082 	return player->getName();
3083 }
3084 
getPlayerSAO(session_t peer_id)3085 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
3086 {
3087 	RemotePlayer *player = m_env->getPlayer(peer_id);
3088 	if (!player)
3089 		return NULL;
3090 	return player->getPlayerSAO();
3091 }
3092 
getStatusString()3093 std::string Server::getStatusString()
3094 {
3095 	std::ostringstream os(std::ios_base::binary);
3096 	os << "# Server: ";
3097 	// Version
3098 	os << "version=" << g_version_string;
3099 	// Uptime
3100 	os << ", uptime=" << m_uptime_counter->get();
3101 	// Max lag estimate
3102 	os << ", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
3103 
3104 	// Information about clients
3105 	bool first = true;
3106 	os << ", clients={";
3107 	if (m_env) {
3108 		std::vector<session_t> clients = m_clients.getClientIDs();
3109 		for (session_t client_id : clients) {
3110 			RemotePlayer *player = m_env->getPlayer(client_id);
3111 
3112 			// Get name of player
3113 			const char *name = player ? player->getName() : "<unknown>";
3114 
3115 			// Add name to information string
3116 			if (!first)
3117 				os << ", ";
3118 			else
3119 				first = false;
3120 			os << name;
3121 		}
3122 	}
3123 	os << "}";
3124 
3125 	if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
3126 		os << std::endl << "# Server: " << " WARNING: Map saving is disabled.";
3127 
3128 	if (!g_settings->get("motd").empty())
3129 		os << std::endl << "# Server: " << g_settings->get("motd");
3130 
3131 	return os.str();
3132 }
3133 
getPlayerEffectivePrivs(const std::string & name)3134 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3135 {
3136 	std::set<std::string> privs;
3137 	m_script->getAuth(name, NULL, &privs);
3138 	return privs;
3139 }
3140 
checkPriv(const std::string & name,const std::string & priv)3141 bool Server::checkPriv(const std::string &name, const std::string &priv)
3142 {
3143 	std::set<std::string> privs = getPlayerEffectivePrivs(name);
3144 	return (privs.count(priv) != 0);
3145 }
3146 
reportPrivsModified(const std::string & name)3147 void Server::reportPrivsModified(const std::string &name)
3148 {
3149 	if (name.empty()) {
3150 		std::vector<session_t> clients = m_clients.getClientIDs();
3151 		for (const session_t client_id : clients) {
3152 			RemotePlayer *player = m_env->getPlayer(client_id);
3153 			reportPrivsModified(player->getName());
3154 		}
3155 	} else {
3156 		RemotePlayer *player = m_env->getPlayer(name.c_str());
3157 		if (!player)
3158 			return;
3159 		SendPlayerPrivileges(player->getPeerId());
3160 		PlayerSAO *sao = player->getPlayerSAO();
3161 		if(!sao)
3162 			return;
3163 		sao->updatePrivileges(
3164 				getPlayerEffectivePrivs(name),
3165 				isSingleplayer());
3166 	}
3167 }
3168 
reportInventoryFormspecModified(const std::string & name)3169 void Server::reportInventoryFormspecModified(const std::string &name)
3170 {
3171 	RemotePlayer *player = m_env->getPlayer(name.c_str());
3172 	if (!player)
3173 		return;
3174 	SendPlayerInventoryFormspec(player->getPeerId());
3175 }
3176 
reportFormspecPrependModified(const std::string & name)3177 void Server::reportFormspecPrependModified(const std::string &name)
3178 {
3179 	RemotePlayer *player = m_env->getPlayer(name.c_str());
3180 	if (!player)
3181 		return;
3182 	SendPlayerFormspecPrepend(player->getPeerId());
3183 }
3184 
setIpBanned(const std::string & ip,const std::string & name)3185 void Server::setIpBanned(const std::string &ip, const std::string &name)
3186 {
3187 	m_banmanager->add(ip, name);
3188 }
3189 
unsetIpBanned(const std::string & ip_or_name)3190 void Server::unsetIpBanned(const std::string &ip_or_name)
3191 {
3192 	m_banmanager->remove(ip_or_name);
3193 }
3194 
getBanDescription(const std::string & ip_or_name)3195 std::string Server::getBanDescription(const std::string &ip_or_name)
3196 {
3197 	return m_banmanager->getBanDescription(ip_or_name);
3198 }
3199 
notifyPlayer(const char * name,const std::wstring & msg)3200 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3201 {
3202 	// m_env will be NULL if the server is initializing
3203 	if (!m_env)
3204 		return;
3205 
3206 	if (m_admin_nick == name && !m_admin_nick.empty()) {
3207 		m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3208 	}
3209 
3210 	RemotePlayer *player = m_env->getPlayer(name);
3211 	if (!player) {
3212 		return;
3213 	}
3214 
3215 	if (player->getPeerId() == PEER_ID_INEXISTENT)
3216 		return;
3217 
3218 	SendChatMessage(player->getPeerId(), ChatMessage(msg));
3219 }
3220 
showFormspec(const char * playername,const std::string & formspec,const std::string & formname)3221 bool Server::showFormspec(const char *playername, const std::string &formspec,
3222 	const std::string &formname)
3223 {
3224 	// m_env will be NULL if the server is initializing
3225 	if (!m_env)
3226 		return false;
3227 
3228 	RemotePlayer *player = m_env->getPlayer(playername);
3229 	if (!player)
3230 		return false;
3231 
3232 	SendShowFormspecMessage(player->getPeerId(), formspec, formname);
3233 	return true;
3234 }
3235 
hudAdd(RemotePlayer * player,HudElement * form)3236 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3237 {
3238 	if (!player)
3239 		return -1;
3240 
3241 	u32 id = player->addHud(form);
3242 
3243 	SendHUDAdd(player->getPeerId(), id, form);
3244 
3245 	return id;
3246 }
3247 
hudRemove(RemotePlayer * player,u32 id)3248 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3249 	if (!player)
3250 		return false;
3251 
3252 	HudElement* todel = player->removeHud(id);
3253 
3254 	if (!todel)
3255 		return false;
3256 
3257 	delete todel;
3258 
3259 	SendHUDRemove(player->getPeerId(), id);
3260 	return true;
3261 }
3262 
hudChange(RemotePlayer * player,u32 id,HudElementStat stat,void * data)3263 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3264 {
3265 	if (!player)
3266 		return false;
3267 
3268 	SendHUDChange(player->getPeerId(), id, stat, data);
3269 	return true;
3270 }
3271 
hudSetFlags(RemotePlayer * player,u32 flags,u32 mask)3272 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3273 {
3274 	if (!player)
3275 		return false;
3276 
3277 	SendHUDSetFlags(player->getPeerId(), flags, mask);
3278 	player->hud_flags &= ~mask;
3279 	player->hud_flags |= flags;
3280 
3281 	PlayerSAO* playersao = player->getPlayerSAO();
3282 
3283 	if (!playersao)
3284 		return false;
3285 
3286 	m_script->player_event(playersao, "hud_changed");
3287 	return true;
3288 }
3289 
hudSetHotbarItemcount(RemotePlayer * player,s32 hotbar_itemcount)3290 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3291 {
3292 	if (!player)
3293 		return false;
3294 
3295 	if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3296 		return false;
3297 
3298 	player->setHotbarItemcount(hotbar_itemcount);
3299 	std::ostringstream os(std::ios::binary);
3300 	writeS32(os, hotbar_itemcount);
3301 	SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3302 	return true;
3303 }
3304 
hudSetHotbarImage(RemotePlayer * player,const std::string & name)3305 void Server::hudSetHotbarImage(RemotePlayer *player, const std::string &name)
3306 {
3307 	if (!player)
3308 		return;
3309 
3310 	player->setHotbarImage(name);
3311 	SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3312 }
3313 
hudSetHotbarSelectedImage(RemotePlayer * player,const std::string & name)3314 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &name)
3315 {
3316 	if (!player)
3317 		return;
3318 
3319 	player->setHotbarSelectedImage(name);
3320 	SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3321 }
3322 
getPeerAddress(session_t peer_id)3323 Address Server::getPeerAddress(session_t peer_id)
3324 {
3325 	// Note that this is only set after Init was received in Server::handleCommand_Init
3326 	return getClient(peer_id, CS_Invalid)->getAddress();
3327 }
3328 
setLocalPlayerAnimations(RemotePlayer * player,v2s32 animation_frames[4],f32 frame_speed)3329 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3330 		v2s32 animation_frames[4], f32 frame_speed)
3331 {
3332 	sanity_check(player);
3333 	player->setLocalAnimations(animation_frames, frame_speed);
3334 	SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3335 }
3336 
setPlayerEyeOffset(RemotePlayer * player,const v3f & first,const v3f & third)3337 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3338 {
3339 	sanity_check(player);
3340 	player->eye_offset_first = first;
3341 	player->eye_offset_third = third;
3342 	SendEyeOffset(player->getPeerId(), first, third);
3343 }
3344 
setSky(RemotePlayer * player,const SkyboxParams & params)3345 void Server::setSky(RemotePlayer *player, const SkyboxParams &params)
3346 {
3347 	sanity_check(player);
3348 	player->setSky(params);
3349 	SendSetSky(player->getPeerId(), params);
3350 }
3351 
setSun(RemotePlayer * player,const SunParams & params)3352 void Server::setSun(RemotePlayer *player, const SunParams &params)
3353 {
3354 	sanity_check(player);
3355 	player->setSun(params);
3356 	SendSetSun(player->getPeerId(), params);
3357 }
3358 
setMoon(RemotePlayer * player,const MoonParams & params)3359 void Server::setMoon(RemotePlayer *player, const MoonParams &params)
3360 {
3361 	sanity_check(player);
3362 	player->setMoon(params);
3363 	SendSetMoon(player->getPeerId(), params);
3364 }
3365 
setStars(RemotePlayer * player,const StarParams & params)3366 void Server::setStars(RemotePlayer *player, const StarParams &params)
3367 {
3368 	sanity_check(player);
3369 	player->setStars(params);
3370 	SendSetStars(player->getPeerId(), params);
3371 }
3372 
setClouds(RemotePlayer * player,const CloudParams & params)3373 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3374 {
3375 	sanity_check(player);
3376 	player->setCloudParams(params);
3377 	SendCloudParams(player->getPeerId(), params);
3378 }
3379 
overrideDayNightRatio(RemotePlayer * player,bool do_override,float ratio)3380 void Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3381 	float ratio)
3382 {
3383 	sanity_check(player);
3384 	player->overrideDayNightRatio(do_override, ratio);
3385 	SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3386 }
3387 
notifyPlayers(const std::wstring & msg)3388 void Server::notifyPlayers(const std::wstring &msg)
3389 {
3390 	SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3391 }
3392 
spawnParticle(const std::string & playername,const ParticleParameters & p)3393 void Server::spawnParticle(const std::string &playername,
3394 	const ParticleParameters &p)
3395 {
3396 	// m_env will be NULL if the server is initializing
3397 	if (!m_env)
3398 		return;
3399 
3400 	session_t peer_id = PEER_ID_INEXISTENT;
3401 	u16 proto_ver = 0;
3402 	if (!playername.empty()) {
3403 		RemotePlayer *player = m_env->getPlayer(playername.c_str());
3404 		if (!player)
3405 			return;
3406 		peer_id = player->getPeerId();
3407 		proto_ver = player->protocol_version;
3408 	}
3409 
3410 	SendSpawnParticle(peer_id, proto_ver, p);
3411 }
3412 
addParticleSpawner(const ParticleSpawnerParameters & p,ServerActiveObject * attached,const std::string & playername)3413 u32 Server::addParticleSpawner(const ParticleSpawnerParameters &p,
3414 	ServerActiveObject *attached, const std::string &playername)
3415 {
3416 	// m_env will be NULL if the server is initializing
3417 	if (!m_env)
3418 		return -1;
3419 
3420 	session_t peer_id = PEER_ID_INEXISTENT;
3421 	u16 proto_ver = 0;
3422 	if (!playername.empty()) {
3423 		RemotePlayer *player = m_env->getPlayer(playername.c_str());
3424 		if (!player)
3425 			return -1;
3426 		peer_id = player->getPeerId();
3427 		proto_ver = player->protocol_version;
3428 	}
3429 
3430 	u16 attached_id = attached ? attached->getId() : 0;
3431 
3432 	u32 id;
3433 	if (attached_id == 0)
3434 		id = m_env->addParticleSpawner(p.time);
3435 	else
3436 		id = m_env->addParticleSpawner(p.time, attached_id);
3437 
3438 	SendAddParticleSpawner(peer_id, proto_ver, p, attached_id, id);
3439 	return id;
3440 }
3441 
deleteParticleSpawner(const std::string & playername,u32 id)3442 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3443 {
3444 	// m_env will be NULL if the server is initializing
3445 	if (!m_env)
3446 		throw ServerError("Can't delete particle spawners during initialisation!");
3447 
3448 	session_t peer_id = PEER_ID_INEXISTENT;
3449 	if (!playername.empty()) {
3450 		RemotePlayer *player = m_env->getPlayer(playername.c_str());
3451 		if (!player)
3452 			return;
3453 		peer_id = player->getPeerId();
3454 	}
3455 
3456 	m_env->deleteParticleSpawner(id);
3457 	SendDeleteParticleSpawner(peer_id, id);
3458 }
3459 
dynamicAddMedia(const std::string & filepath,std::vector<RemotePlayer * > & sent_to)3460 bool Server::dynamicAddMedia(const std::string &filepath,
3461 	std::vector<RemotePlayer*> &sent_to)
3462 {
3463 	std::string filename = fs::GetFilenameFromPath(filepath.c_str());
3464 	if (m_media.find(filename) != m_media.end()) {
3465 		errorstream << "Server::dynamicAddMedia(): file \"" << filename
3466 			<< "\" already exists in media cache" << std::endl;
3467 		return false;
3468 	}
3469 
3470 	// Load the file and add it to our media cache
3471 	std::string filedata, raw_hash;
3472 	bool ok = addMediaFile(filename, filepath, &filedata, &raw_hash);
3473 	if (!ok)
3474 		return false;
3475 
3476 	// Push file to existing clients
3477 	NetworkPacket pkt(TOCLIENT_MEDIA_PUSH, 0);
3478 	pkt << raw_hash << filename << (bool) true;
3479 	pkt.putLongString(filedata);
3480 
3481 	m_clients.lock();
3482 	for (auto &pair : m_clients.getClientList()) {
3483 		if (pair.second->getState() < CS_DefinitionsSent)
3484 			continue;
3485 		if (pair.second->net_proto_version < 39)
3486 			continue;
3487 
3488 		if (auto player = m_env->getPlayer(pair.second->peer_id))
3489 			sent_to.emplace_back(player);
3490 		/*
3491 			FIXME: this is a very awful hack
3492 			The network layer only guarantees ordered delivery inside a channel.
3493 			Since the very next packet could be one that uses the media, we have
3494 			to push the media over ALL channels to ensure it is processed before
3495 			it is used.
3496 			In practice this means we have to send it twice:
3497 			- channel 1 (HUD)
3498 			- channel 0 (everything else: e.g. play_sound, object messages)
3499 		*/
3500 		m_clients.send(pair.second->peer_id, 1, &pkt, true);
3501 		m_clients.send(pair.second->peer_id, 0, &pkt, true);
3502 	}
3503 	m_clients.unlock();
3504 
3505 	return true;
3506 }
3507 
3508 // actions: time-reversed list
3509 // Return value: success/failure
rollbackRevertActions(const std::list<RollbackAction> & actions,std::list<std::string> * log)3510 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3511 		std::list<std::string> *log)
3512 {
3513 	infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3514 	ServerMap *map = (ServerMap*)(&m_env->getMap());
3515 
3516 	// Fail if no actions to handle
3517 	if (actions.empty()) {
3518 		assert(log);
3519 		log->push_back("Nothing to do.");
3520 		return false;
3521 	}
3522 
3523 	int num_tried = 0;
3524 	int num_failed = 0;
3525 
3526 	for (const RollbackAction &action : actions) {
3527 		num_tried++;
3528 		bool success = action.applyRevert(map, m_inventory_mgr.get(), this);
3529 		if(!success){
3530 			num_failed++;
3531 			std::ostringstream os;
3532 			os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3533 			infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3534 			if (log)
3535 				log->push_back(os.str());
3536 		}else{
3537 			std::ostringstream os;
3538 			os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3539 			infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3540 			if (log)
3541 				log->push_back(os.str());
3542 		}
3543 	}
3544 
3545 	infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3546 			<<" failed"<<std::endl;
3547 
3548 	// Call it done if less than half failed
3549 	return num_failed <= num_tried/2;
3550 }
3551 
3552 // IGameDef interface
3553 // Under envlock
getItemDefManager()3554 IItemDefManager *Server::getItemDefManager()
3555 {
3556 	return m_itemdef;
3557 }
3558 
getNodeDefManager()3559 const NodeDefManager *Server::getNodeDefManager()
3560 {
3561 	return m_nodedef;
3562 }
3563 
getCraftDefManager()3564 ICraftDefManager *Server::getCraftDefManager()
3565 {
3566 	return m_craftdef;
3567 }
3568 
allocateUnknownNodeId(const std::string & name)3569 u16 Server::allocateUnknownNodeId(const std::string &name)
3570 {
3571 	return m_nodedef->allocateDummy(name);
3572 }
3573 
getWritableItemDefManager()3574 IWritableItemDefManager *Server::getWritableItemDefManager()
3575 {
3576 	return m_itemdef;
3577 }
3578 
getWritableNodeDefManager()3579 NodeDefManager *Server::getWritableNodeDefManager()
3580 {
3581 	return m_nodedef;
3582 }
3583 
getWritableCraftDefManager()3584 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3585 {
3586 	return m_craftdef;
3587 }
3588 
getMods() const3589 const std::vector<ModSpec> & Server::getMods() const
3590 {
3591 	return m_modmgr->getMods();
3592 }
3593 
getModSpec(const std::string & modname) const3594 const ModSpec *Server::getModSpec(const std::string &modname) const
3595 {
3596 	return m_modmgr->getModSpec(modname);
3597 }
3598 
getModNames(std::vector<std::string> & modlist)3599 void Server::getModNames(std::vector<std::string> &modlist)
3600 {
3601 	m_modmgr->getModNames(modlist);
3602 }
3603 
getBuiltinLuaPath()3604 std::string Server::getBuiltinLuaPath()
3605 {
3606 	return porting::path_share + DIR_DELIM + "builtin";
3607 }
3608 
getModStoragePath() const3609 std::string Server::getModStoragePath() const
3610 {
3611 	return m_path_world + DIR_DELIM + "mod_storage";
3612 }
3613 
findSpawnPos()3614 v3f Server::findSpawnPos()
3615 {
3616 	ServerMap &map = m_env->getServerMap();
3617 	v3f nodeposf;
3618 	if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf))
3619 		return nodeposf * BS;
3620 
3621 	bool is_good = false;
3622 	// Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3623 	s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3624 
3625 	// Try to find a good place a few times
3626 	for (s32 i = 0; i < 4000 && !is_good; i++) {
3627 		s32 range = MYMIN(1 + i, range_max);
3628 		// We're going to try to throw the player to this position
3629 		v2s16 nodepos2d = v2s16(
3630 			-range + (myrand() % (range * 2)),
3631 			-range + (myrand() % (range * 2)));
3632 		// Get spawn level at point
3633 		s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3634 		// Continue if MAX_MAP_GENERATION_LIMIT was returned by the mapgen to
3635 		// signify an unsuitable spawn position, or if outside limits.
3636 		if (spawn_level >= MAX_MAP_GENERATION_LIMIT ||
3637 				spawn_level <= -MAX_MAP_GENERATION_LIMIT)
3638 			continue;
3639 
3640 		v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3641 		// Consecutive empty nodes
3642 		s32 air_count = 0;
3643 
3644 		// Search upwards from 'spawn level' for 2 consecutive empty nodes, to
3645 		// avoid obstructions in already-generated mapblocks.
3646 		// In ungenerated mapblocks consisting of 'ignore' nodes, there will be
3647 		// no obstructions, but mapgen decorations are generated after spawn so
3648 		// the player may end up inside one.
3649 		for (s32 i = 0; i < 8; i++) {
3650 			v3s16 blockpos = getNodeBlockPos(nodepos);
3651 			map.emergeBlock(blockpos, true);
3652 			content_t c = map.getNode(nodepos).getContent();
3653 
3654 			// In generated mapblocks allow spawn in all 'airlike' drawtype nodes.
3655 			// In ungenerated mapblocks allow spawn in 'ignore' nodes.
3656 			if (m_nodedef->get(c).drawtype == NDT_AIRLIKE || c == CONTENT_IGNORE) {
3657 				air_count++;
3658 				if (air_count >= 2) {
3659 					// Spawn in lower empty node
3660 					nodepos.Y--;
3661 					nodeposf = intToFloat(nodepos, BS);
3662 					// Don't spawn the player outside map boundaries
3663 					if (objectpos_over_limit(nodeposf))
3664 						// Exit this loop, positions above are probably over limit
3665 						break;
3666 
3667 					// Good position found, cause an exit from main loop
3668 					is_good = true;
3669 					break;
3670 				}
3671 			} else {
3672 				air_count = 0;
3673 			}
3674 			nodepos.Y++;
3675 		}
3676 	}
3677 
3678 	if (is_good)
3679 		return nodeposf;
3680 
3681 	// No suitable spawn point found, return fallback 0,0,0
3682 	return v3f(0.0f, 0.0f, 0.0f);
3683 }
3684 
requestShutdown(const std::string & msg,bool reconnect,float delay)3685 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3686 {
3687 	if (delay == 0.0f) {
3688 	// No delay, shutdown immediately
3689 		m_shutdown_state.is_requested = true;
3690 		// only print to the infostream, a chat message saying
3691 		// "Server Shutting Down" is sent when the server destructs.
3692 		infostream << "*** Immediate Server shutdown requested." << std::endl;
3693 	} else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
3694 		// Negative delay, cancel shutdown if requested
3695 		m_shutdown_state.reset();
3696 		std::wstringstream ws;
3697 
3698 		ws << L"*** Server shutdown canceled.";
3699 
3700 		infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3701 		SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3702 		// m_shutdown_* are already handled, skip.
3703 		return;
3704 	} else if (delay > 0.0f) {
3705 	// Positive delay, tell the clients when the server will shut down
3706 		std::wstringstream ws;
3707 
3708 		ws << L"*** Server shutting down in "
3709 				<< duration_to_string(myround(delay)).c_str()
3710 				<< ".";
3711 
3712 		infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3713 		SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3714 	}
3715 
3716 	m_shutdown_state.trigger(delay, msg, reconnect);
3717 }
3718 
emergePlayer(const char * name,session_t peer_id,u16 proto_version)3719 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3720 {
3721 	/*
3722 		Try to get an existing player
3723 	*/
3724 	RemotePlayer *player = m_env->getPlayer(name);
3725 
3726 	// If player is already connected, cancel
3727 	if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3728 		infostream<<"emergePlayer(): Player already connected"<<std::endl;
3729 		return NULL;
3730 	}
3731 
3732 	/*
3733 		If player with the wanted peer_id already exists, cancel.
3734 	*/
3735 	if (m_env->getPlayer(peer_id)) {
3736 		infostream<<"emergePlayer(): Player with wrong name but same"
3737 				" peer_id already exists"<<std::endl;
3738 		return NULL;
3739 	}
3740 
3741 	if (!player) {
3742 		player = new RemotePlayer(name, idef());
3743 	}
3744 
3745 	bool newplayer = false;
3746 
3747 	// Load player
3748 	PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3749 
3750 	// Complete init with server parts
3751 	playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3752 	player->protocol_version = proto_version;
3753 
3754 	/* Run scripts */
3755 	if (newplayer) {
3756 		m_script->on_newplayer(playersao);
3757 	}
3758 
3759 	return playersao;
3760 }
3761 
registerModStorage(ModMetadata * storage)3762 bool Server::registerModStorage(ModMetadata *storage)
3763 {
3764 	if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3765 		errorstream << "Unable to register same mod storage twice. Storage name: "
3766 				<< storage->getModName() << std::endl;
3767 		return false;
3768 	}
3769 
3770 	m_mod_storages[storage->getModName()] = storage;
3771 	return true;
3772 }
3773 
unregisterModStorage(const std::string & name)3774 void Server::unregisterModStorage(const std::string &name)
3775 {
3776 	std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3777 	if (it != m_mod_storages.end()) {
3778 		// Save unconditionaly on unregistration
3779 		it->second->save(getModStoragePath());
3780 		m_mod_storages.erase(name);
3781 	}
3782 }
3783 
dedicated_server_loop(Server & server,bool & kill)3784 void dedicated_server_loop(Server &server, bool &kill)
3785 {
3786 	verbosestream<<"dedicated_server_loop()"<<std::endl;
3787 
3788 	IntervalLimiter m_profiler_interval;
3789 
3790 	static thread_local const float steplen =
3791 			g_settings->getFloat("dedicated_server_step");
3792 	static thread_local const float profiler_print_interval =
3793 			g_settings->getFloat("profiler_print_interval");
3794 
3795 	/*
3796 	 * The dedicated server loop only does time-keeping (in Server::step) and
3797 	 * provides a way to main.cpp to kill the server externally (bool &kill).
3798 	 */
3799 
3800 	for(;;) {
3801 		// This is kind of a hack but can be done like this
3802 		// because server.step() is very light
3803 		sleep_ms((int)(steplen*1000.0));
3804 		server.step(steplen);
3805 
3806 		if (server.isShutdownRequested() || kill)
3807 			break;
3808 
3809 		/*
3810 			Profiler
3811 		*/
3812 		if (profiler_print_interval != 0) {
3813 			if(m_profiler_interval.step(steplen, profiler_print_interval))
3814 			{
3815 				infostream<<"Profiler:"<<std::endl;
3816 				g_profiler->print(infostream);
3817 				g_profiler->clear();
3818 			}
3819 		}
3820 	}
3821 
3822 	infostream << "Dedicated server quitting" << std::endl;
3823 #if USE_CURL
3824 	if (g_settings->getBool("server_announce"))
3825 		ServerList::sendAnnounce(ServerList::AA_DELETE,
3826 			server.m_bind_addr.getPort());
3827 #endif
3828 }
3829 
3830 /*
3831  * Mod channels
3832  */
3833 
3834 
joinModChannel(const std::string & channel)3835 bool Server::joinModChannel(const std::string &channel)
3836 {
3837 	return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3838 			m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3839 }
3840 
leaveModChannel(const std::string & channel)3841 bool Server::leaveModChannel(const std::string &channel)
3842 {
3843 	return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3844 }
3845 
sendModChannelMessage(const std::string & channel,const std::string & message)3846 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3847 {
3848 	if (!m_modchannel_mgr->canWriteOnChannel(channel))
3849 		return false;
3850 
3851 	broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3852 	return true;
3853 }
3854 
getModChannel(const std::string & channel)3855 ModChannel* Server::getModChannel(const std::string &channel)
3856 {
3857 	return m_modchannel_mgr->getModChannel(channel);
3858 }
3859 
broadcastModChannelMessage(const std::string & channel,const std::string & message,session_t from_peer)3860 void Server::broadcastModChannelMessage(const std::string &channel,
3861 		const std::string &message, session_t from_peer)
3862 {
3863 	const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3864 	if (peers.empty())
3865 		return;
3866 
3867 	if (message.size() > STRING_MAX_LEN) {
3868 		warningstream << "ModChannel message too long, dropping before sending "
3869 				<< " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3870 				<< channel << ")" << std::endl;
3871 		return;
3872 	}
3873 
3874 	std::string sender;
3875 	if (from_peer != PEER_ID_SERVER) {
3876 		sender = getPlayerName(from_peer);
3877 	}
3878 
3879 	NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3880 			2 + channel.size() + 2 + sender.size() + 2 + message.size());
3881 	resp_pkt << channel << sender << message;
3882 	for (session_t peer_id : peers) {
3883 		// Ignore sender
3884 		if (peer_id == from_peer)
3885 			continue;
3886 
3887 		Send(peer_id, &resp_pkt);
3888 	}
3889 
3890 	if (from_peer != PEER_ID_SERVER) {
3891 		m_script->on_modchannel_message(channel, sender, message);
3892 	}
3893 }
3894 
getTranslationLanguage(const std::string & lang_code)3895 Translations *Server::getTranslationLanguage(const std::string &lang_code)
3896 {
3897 	if (lang_code.empty())
3898 		return nullptr;
3899 
3900 	auto it = server_translations.find(lang_code);
3901 	if (it != server_translations.end())
3902 		return &it->second; // Already loaded
3903 
3904 	// [] will create an entry
3905 	auto *translations = &server_translations[lang_code];
3906 
3907 	std::string suffix = "." + lang_code + ".tr";
3908 	for (const auto &i : m_media) {
3909 		if (str_ends_with(i.first, suffix)) {
3910 			std::string data;
3911 			if (fs::ReadFile(i.second.path, data)) {
3912 				translations->loadTranslation(data);
3913 			}
3914 		}
3915 	}
3916 
3917 	return translations;
3918 }
3919