1 /*
2 server.cpp
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 */
5 
6 /*
7 This file is part of Freeminer.
8 
9 Freeminer is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Freeminer  is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Freeminer.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #include "server.h"
24 #include <iostream>
25 #include <queue>
26 #include <algorithm>
27 #include "clientserver.h"
28 #include "ban.h"
29 #include "environment.h"
30 #include "map.h"
31 #include "jthread/jmutexautolock.h"
32 #include "main.h"
33 #include "constants.h"
34 #include "voxel.h"
35 #include "config.h"
36 #include "version.h"
37 #include "filesys.h"
38 #include "mapblock.h"
39 #include "serverobject.h"
40 #include "genericobject.h"
41 #include "settings.h"
42 #include "profiler.h"
43 #include "log.h"
44 #include "scripting_game.h"
45 #include "nodedef.h"
46 #include "itemdef.h"
47 #include "craftdef.h"
48 #include "emerge.h"
49 #include "mapgen.h"
50 #include "mg_biome.h"
51 #include "content_mapnode.h"
52 #include "content_nodemeta.h"
53 #include "content_abm.h"
54 #include "content_sao.h"
55 #include "mods.h"
56 #include "sha1.h"
57 #include "base64.h"
58 #include "tool.h"
59 #include "sound.h" // dummySoundManager
60 #include "event_manager.h"
61 #include "hex.h"
62 #include "serverlist.h"
63 #include "util/string.h"
64 #include "util/pointedthing.h"
65 #include "util/mathconstants.h"
66 #include "rollback.h"
67 #include "util/serialize.h"
68 #include "util/thread.h"
69 #include "defaultsettings.h"
70 #include "circuit.h"
71 //#include "stat.h"
72 
73 #include <chrono>
74 #include "util/thread_pool.h"
75 #include "key_value_storage.h"
76 #include "database.h"
77 
78 
79 class ClientNotFoundException : public BaseException
80 {
81 public:
ClientNotFoundException(const char * s)82 	ClientNotFoundException(const char *s):
83 		BaseException(s)
84 	{}
85 };
86 
87 class MapThread : public thread_pool
88 {
89 	Server *m_server;
90 public:
91 
MapThread(Server * server)92 	MapThread(Server *server):
93 		m_server(server)
94 	{}
95 
Thread()96 	void * Thread() {
97 		log_register_thread("MapThread");
98 
99 		DSTACK(__FUNCTION_NAME);
100 		BEGIN_DEBUG_EXCEPTION_HANDLER
101 		ThreadStarted();
102 
103 		porting::setThreadName("Map");
104 		porting::setThreadPriority(15);
105 		auto time = porting::getTimeMs();
106 		while(!StopRequested()) {
107 			auto time_now = porting::getTimeMs();
108 			try {
109 				if (!m_server->AsyncRunMapStep((time_now - time)/1000.0f))
110 					std::this_thread::sleep_for(std::chrono::milliseconds(100));
111 				else
112 					std::this_thread::sleep_for(std::chrono::milliseconds(10));
113 #ifdef NDEBUG
114 			} catch (BaseException &e) {
115 				errorstream<<"MapThread: exception: "<<e.what()<<std::endl;
116 			} catch(std::exception &e) {
117 				errorstream<<"MapThread: exception: "<<e.what()<<std::endl;
118 			} catch (...) {
119 				errorstream<<"MapThread: Ooops..."<<std::endl;
120 #else
121 			} catch (int) { //nothing
122 #endif
123 			}
124 			time = time_now;
125 		}
126 		END_DEBUG_EXCEPTION_HANDLER(errorstream)
127 		return nullptr;
128 	}
129 };
130 
131 class SendBlocksThread : public thread_pool
132 {
133 	Server *m_server;
134 public:
135 
SendBlocksThread(Server * server)136 	SendBlocksThread(Server *server):
137 		m_server(server)
138 	{}
139 
Thread()140 	void * Thread() {
141 		log_register_thread("SendBlocksThread");
142 
143 		DSTACK(__FUNCTION_NAME);
144 		BEGIN_DEBUG_EXCEPTION_HANDLER
145 
146 		ThreadStarted();
147 
148 		porting::setThreadName("SendBlocksThread");
149 		porting::setThreadPriority(30);
150 		auto time = porting::getTimeMs();
151 		while(!StopRequested()) {
152 			//infostream<<"S run d="<<m_server->m_step_dtime<< " myt="<<(porting::getTimeMs() - time)/1000.0f<<std::endl;
153 			try {
154 				auto time_now = porting::getTimeMs();
155 				auto sent = m_server->SendBlocks((time_now - time)/1000.0f);
156 				time = time_now;
157 				std::this_thread::sleep_for(std::chrono::milliseconds(sent ? 5 : 100));
158 #ifdef NDEBUG
159 			} catch (BaseException &e) {
160 				errorstream<<"SendBlocksThread: exception: "<<e.what()<<std::endl;
161 			} catch(std::exception &e) {
162 				errorstream<<"SendBlocksThread: exception: "<<e.what()<<std::endl;
163 			} catch (...) {
164 				errorstream<<"SendBlocksThread: Ooops..."<<std::endl;
165 #else
166 			} catch (int) { //nothing
167 #endif
168 			}
169 		}
170 		END_DEBUG_EXCEPTION_HANDLER(errorstream)
171 	return nullptr;
172 	}
173 };
174 
175 
176 class LiquidThread : public thread_pool
177 {
178 	Server *m_server;
179 public:
180 
LiquidThread(Server * server)181 	LiquidThread(Server *server):
182 		m_server(server)
183 	{}
184 
Thread()185 	void * Thread() {
186 		log_register_thread("Liquid");
187 
188 		DSTACK(__FUNCTION_NAME);
189 		BEGIN_DEBUG_EXCEPTION_HANDLER
190 
191 		ThreadStarted();
192 
193 		porting::setThreadName("Liquid");
194 		porting::setThreadPriority(4);
195 		int max_cycle_ms = 1000;
196 		while(!StopRequested()) {
197 			try {
198 				//shared_map<v3POS, MapBlock*> modified_blocks; //not used
199 				int res = m_server->getEnv().getMap().transformLiquids(m_server, max_cycle_ms);
200 				std::this_thread::sleep_for(std::chrono::milliseconds(std::max(300-res,1)));
201 #ifdef NDEBUG
202 			} catch (BaseException &e) {
203 				errorstream<<"Liquid: exception: "<<e.what()<<std::endl;
204 			} catch(std::exception &e) {
205 				errorstream<<"Liquid: exception: "<<e.what()<<std::endl;
206 			} catch (...) {
207 				errorstream<<"Liquid: Ooops..."<<std::endl;
208 #else
209 			} catch (int) { //nothing
210 #endif
211 			}
212 		}
213 		END_DEBUG_EXCEPTION_HANDLER(errorstream)
214 	return nullptr;
215 	}
216 };
217 
218 class EnvThread : public thread_pool
219 {
220 	Server *m_server;
221 public:
222 
EnvThread(Server * server)223 	EnvThread(Server *server):
224 		m_server(server)
225 	{}
226 
Thread()227 	void * Thread() {
228 		log_register_thread("Env");
229 
230 		DSTACK(__FUNCTION_NAME);
231 		BEGIN_DEBUG_EXCEPTION_HANDLER
232 
233 		ThreadStarted();
234 
235 		porting::setThreadName("Env");
236 		porting::setThreadPriority(20);
237 		unsigned int max_cycle_ms = 1000;
238 		unsigned int time = porting::getTimeMs();
239 		while(!StopRequested()) {
240 			try {
241 				auto ctime = porting::getTimeMs();
242 				unsigned int dtimems = ctime - time;
243 				time = ctime;
244 				m_server->getEnv().step(dtimems/1000.0f, m_server->m_uptime.get(), max_cycle_ms);
245 				std::this_thread::sleep_for(std::chrono::milliseconds(dtimems > 100 ? 1 : 100 - dtimems));
246 #ifdef NDEBUG
247 			} catch (BaseException &e) {
248 				errorstream<<"Env: exception: "<<e.what()<<std::endl;
249 			} catch(std::exception &e) {
250 				errorstream<<"Env: exception: "<<e.what()<<std::endl;
251 			} catch (...) {
252 				errorstream<<"Env: Ooops..."<<std::endl;
253 #else
254 			} catch (int) { //nothing
255 #endif
256 			}
257 		}
258 		END_DEBUG_EXCEPTION_HANDLER(errorstream)
259 	return nullptr;
260 	}
261 };
262 
263 class ServerThread : public thread_pool
264 {
265 	Server *m_server;
266 
267 public:
268 
ServerThread(Server * server)269 	ServerThread(Server *server):
270 		m_server(server)
271 	{
272 	}
273 
274 	void * Thread();
275 };
276 
Thread()277 void * ServerThread::Thread()
278 {
279 	log_register_thread("ServerThread");
280 
281 	DSTACK(__FUNCTION_NAME);
282 	BEGIN_DEBUG_EXCEPTION_HANDLER
283 
284 	f32 dedicated_server_step = g_settings->getFloat("dedicated_server_step");
285 	m_server->AsyncRunStep(0.1, true);
286 
287 	ThreadStarted();
288 
289 	porting::setThreadName("ServerThread");
290 	porting::setThreadPriority(40);
291 
292 	auto time = porting::getTimeMs();
293 	while(!StopRequested())
294 	{
295 		try{
296 			//TimeTaker timer("AsyncRunStep() + Receive()");
297 			auto time_now = porting::getTimeMs();
298 			m_server->AsyncRunStep((time_now - time)/1000.0f);
299 			time = time_now;
300 
301 			// Loop used only when 100% cpu load or on old slow hardware.
302 			// usually only one packet recieved here
303 			u32 end_ms = porting::getTimeMs() + u32(1000 * dedicated_server_step);
304 			for (u16 i = 0; i < 1000; ++i)
305 				if (!m_server->Receive() || porting::getTimeMs() > end_ms)
306 					break;
307 		}
308 		catch(con::NoIncomingDataException &e)
309 		{
310 		}
311 		catch(con::PeerNotFoundException &e)
312 		{
313 			infostream<<"Server: PeerNotFoundException"<<std::endl;
314 		}
315 		catch(ClientNotFoundException &e)
316 		{
317 		}
318 		catch(con::ConnectionBindFailed &e)
319 		{
320 			m_server->setAsyncFatalError(e.what());
321 		}
322 		catch(LuaError &e)
323 		{
324 			m_server->setAsyncFatalError(e.what());
325 #ifdef NDEBUG
326 		} catch(std::exception &e) {
327 				errorstream<<"ServerThread: exception: "<<e.what()<<std::endl;
328 		} catch (...) {
329 				errorstream<<"ServerThread: Ooops..."<<std::endl;
330 #endif
331 		}
332 	}
333 
334 	END_DEBUG_EXCEPTION_HANDLER(errorstream)
335 
336 	return NULL;
337 }
338 
getPos(ServerEnvironment * env,bool * pos_exists) const339 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
340 {
341 	if(pos_exists) *pos_exists = false;
342 	switch(type){
343 	case SSP_LOCAL:
344 		return v3f(0,0,0);
345 	case SSP_POSITIONAL:
346 		if(pos_exists) *pos_exists = true;
347 		return pos;
348 	case SSP_OBJECT: {
349 		if(object == 0)
350 			return v3f(0,0,0);
351 		ServerActiveObject *sao = env->getActiveObject(object);
352 		if(!sao)
353 			return v3f(0,0,0);
354 		if(pos_exists) *pos_exists = true;
355 		return sao->getBasePosition(); }
356 	}
357 	return v3f(0,0,0);
358 }
359 
360 /*
361 	Server
362 */
363 
Server(const std::string & path_world,const SubgameSpec & gamespec,bool simple_singleplayer_mode,bool ipv6)364 Server::Server(
365 		const std::string &path_world,
366 		const SubgameSpec &gamespec,
367 		bool simple_singleplayer_mode,
368 		bool ipv6
369 	):
370 	m_path_world(path_world),
371 	m_gamespec(gamespec),
372 	m_simple_singleplayer_mode(simple_singleplayer_mode),
373 	m_async_fatal_error(""),
374 	m_env(NULL),
375 	m_con(PROTOCOL_ID,
376 			simple_singleplayer_mode ? MAX_PACKET_SIZE_SINGLEPLAYER : MAX_PACKET_SIZE,
377 			CONNECTION_TIMEOUT,
378 			ipv6,
379 			this),
380 	m_banmanager(NULL),
381 	m_rollback(NULL),
382 	m_enable_rollback_recording(false),
383 	m_emerge(NULL),
384 	m_script(NULL),
385 	m_circuit(NULL),
386 	stat(path_world),
387 	m_itemdef(createItemDefManager()),
388 	m_nodedef(createNodeDefManager()),
389 	m_craftdef(createCraftDefManager()),
390 	m_event(new EventManager()),
391 	m_thread(NULL),
392 	m_map_thread(nullptr),
393 	m_sendblocks(nullptr),
394 	m_liquid(nullptr),
395 	m_envthread(nullptr),
396 	m_time_of_day_send_timer(0),
397 	m_uptime(0),
398 	m_clients(&m_con),
399 	m_shutdown_requested(false),
400 	m_ignore_map_edit_events(false),
401 	m_ignore_map_edit_events_peer_id(0)
402 
403 {
404 	m_liquid_transform_timer = 0.0;
405 	m_liquid_transform_interval = 1.0;
406 	m_liquid_send_timer = 0.0;
407 	m_liquid_send_interval = 1.0;
408 	maintenance_status = 0;
409 	m_print_info_timer = 0.0;
410 	m_masterserver_timer = 0.0;
411 	m_objectdata_timer = 0.0;
412 	m_emergethread_trigger_timer = 0.0;
413 	m_savemap_timer = 0.0;
414 
415 	m_step_dtime = 0.0;
416 	m_lag = g_settings->getFloat("dedicated_server_step");
417 #if CMAKE_THREADS
418 	more_threads = g_settings->getBool("more_threads");
419 #else
420 	more_threads = 0;
421 #endif
422 
423 	if(path_world == "")
424 		throw ServerError("Supplied empty world path");
425 
426 	if(!gamespec.isValid())
427 		throw ServerError("Supplied invalid gamespec");
428 
429 	infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
430 	if(m_simple_singleplayer_mode)
431 		infostream<<" in simple singleplayer mode"<<std::endl;
432 	else
433 		infostream<<std::endl;
434 	infostream<<"- world:  "<<m_path_world<<std::endl;
435 	infostream<<"- game:   "<<m_gamespec.path<<std::endl;
436 
437 	// Initialize default settings and override defaults with those provided
438 	// by the game
439 	set_default_settings(g_settings);
440 	Settings gamedefaults;
441 	getGameMinetestConfig(gamespec.path, gamedefaults);
442 	override_default_settings(g_settings, &gamedefaults);
443 
444 	// Create server thread
445 	m_thread = new ServerThread(this);
446 
447 	// Create emerge manager
448 	m_emerge = new EmergeManager(this);
449 
450 	if (more_threads) {
451 		m_map_thread = new MapThread(this);
452 		m_sendblocks = new SendBlocksThread(this);
453 		m_liquid = new LiquidThread(this);
454 		m_envthread = new EnvThread(this);
455 	}
456 
457 	// Create world if it doesn't exist
458 	if(!initializeWorld(m_path_world, m_gamespec.id))
459 		throw ServerError("Failed to initialize world");
460 
461 	// Create ban manager
462 	std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
463 	m_banmanager = new BanManager(ban_path);
464 
465 	// Create rollback manager
466 	m_rollback = new RollbackManager(m_path_world, this);
467 
468 	ModConfiguration modconf(m_path_world);
469 	m_mods = modconf.getMods();
470 	std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
471 	// complain about mods with unsatisfied dependencies
472 	if(!modconf.isConsistent())
473 	{
474 		for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
475 			it != unsatisfied_mods.end(); ++it)
476 		{
477 			ModSpec mod = *it;
478 			errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
479 			for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
480 				dep_it != mod.unsatisfied_depends.end(); ++dep_it)
481 				errorstream << " \"" << *dep_it << "\"";
482 			errorstream << std::endl;
483 		}
484 	}
485 
486 	Settings worldmt_settings;
487 	std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
488 	worldmt_settings.readConfigFile(worldmt.c_str());
489 	std::vector<std::string> names = worldmt_settings.getNames();
490 	std::set<std::string> load_mod_names;
491 	for(std::vector<std::string>::iterator it = names.begin();
492 		it != names.end(); ++it)
493 	{
494 		std::string name = *it;
495 		if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
496 			load_mod_names.insert(name.substr(9));
497 	}
498 	// complain about mods declared to be loaded, but not found
499 	for(std::vector<ModSpec>::iterator it = m_mods.begin();
500 			it != m_mods.end(); ++it)
501 		load_mod_names.erase((*it).name);
502 	for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
503 			it != unsatisfied_mods.end(); ++it)
504 		load_mod_names.erase((*it).name);
505 	if(!load_mod_names.empty())
506 	{
507 		errorstream << "The following mods could not be found:";
508 		for(std::set<std::string>::iterator it = load_mod_names.begin();
509 			it != load_mod_names.end(); ++it)
510 			errorstream << " \"" << (*it) << "\"";
511 		errorstream << std::endl;
512 	}
513 
514 	// Lock environment
515 	//JMutexAutoLock envlock(m_env_mutex);
516 
517 	// Initialize scripting
518 	infostream<<"Server: Initializing Lua"<<std::endl;
519 
520 	m_script = new GameScripting(this);
521 
522 	std::string scriptpath = getBuiltinLuaPath() + DIR_DELIM "init.lua";
523 
524 	if (!m_script->loadScript(scriptpath)) {
525 		throw ModError("Failed to load and run " + scriptpath);
526 	}
527 
528 
529 	// Print 'em
530 	infostream<<"Server: Loading mods: ";
531 	for(std::vector<ModSpec>::iterator i = m_mods.begin();
532 			i != m_mods.end(); i++){
533 		const ModSpec &mod = *i;
534 		infostream<<mod.name<<" ";
535 	}
536 	infostream<<std::endl;
537 	// Load and run "mod" scripts
538 	for(std::vector<ModSpec>::iterator i = m_mods.begin();
539 			i != m_mods.end(); i++){
540 		const ModSpec &mod = *i;
541 		std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
542 		infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
543 				<<scriptpath<<"\"]"<<std::endl;
544 		bool success = m_script->loadMod(scriptpath, mod.name);
545 		if(!success){
546 			errorstream<<"Server: Failed to load and run "
547 					<<scriptpath<<std::endl;
548 			throw ModError("Failed to load and run "+scriptpath);
549 		}
550 	}
551 
552 	// Read Textures and calculate sha1 sums
553 	fillMediaCache();
554 
555 	// Apply item aliases in the node definition manager
556 	m_nodedef->updateAliases(m_itemdef);
557 	m_nodedef->updateTextures(this);
558 
559 	// Perform pending node name resolutions
560 	m_nodedef->getResolver()->resolveNodes();
561 
562 	// Load the mapgen params from global settings now after any
563 	// initial overrides have been set by the mods
564 	m_emerge->loadMapgenParams();
565 
566 	// Initialize Environment
567 	ServerMap *servermap = new ServerMap(path_world, this, m_emerge, m_circuit);
568 	m_circuit = new Circuit(m_script, servermap, ndef(), path_world);
569 	m_env = new ServerEnvironment(servermap, m_script, m_circuit, this, m_path_world);
570 	m_emerge->env = m_env;
571 
572 	m_clients.setEnv(m_env);
573 
574 	// Run some callbacks after the MG params have been set up but before activation
575 	m_script->environment_OnMapgenInit(&m_emerge->params);
576 
577 	// Initialize mapgens
578 	m_emerge->initMapgens();
579 
580 	// Give environment reference to scripting api
581 	m_script->initializeEnvironment(m_env);
582 
583 	// Register us to receive map edit events
584 	servermap->addEventReceiver(this);
585 
586 	// If file exists, load environment metadata
587 	if(fs::PathExists(m_path_world + DIR_DELIM "env_meta.txt"))
588 	{
589 		infostream<<"Server: Loading environment metadata"<<std::endl;
590 		m_env->loadMeta();
591 	}
592 
593 	// Add some test ActiveBlockModifiers to environment
594 	add_legacy_abms(m_env, m_nodedef);
595 
596 	m_liquid_transform_interval = g_settings->getFloat("liquid_update");
597 	m_liquid_send_interval = g_settings->getFloat("liquid_send");
598 }
599 
~Server()600 Server::~Server()
601 {
602 	infostream<<"Server destructing"<<std::endl;
603 
604 	// Send shutdown message
605 	SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
606 
607 	{
608 		//JMutexAutoLock envlock(m_env_mutex);
609 
610 		// Execute script shutdown hooks
611 		m_script->on_shutdown();
612 
613 		infostream<<"Server: Saving players"<<std::endl;
614 		m_env->saveLoadedPlayers();
615 
616 		infostream<<"Server: Saving environment metadata"<<std::endl;
617 		m_env->saveMeta();
618 	}
619 
620 	// Stop threads
621 	stop();
622 	delete m_thread;
623 
624 	if (m_liquid)
625 		delete m_liquid;
626 	if (m_sendblocks)
627 		delete m_sendblocks;
628 	if (m_map_thread)
629 		delete m_map_thread;
630 	if(m_envthread)
631 		delete m_envthread;
632 
633 	// stop all emerge threads before deleting players that may have
634 	// requested blocks to be emerged
635 	m_emerge->stopThreads();
636 
637 	// Delete things in the reverse order of creation
638 	delete m_env;
639 
640 	// N.B. the EmergeManager should be deleted after the Environment since Map
641 	// depends on EmergeManager to write its current params to the map meta
642 	delete m_emerge;
643 	delete m_rollback;
644 	delete m_banmanager;
645 	delete m_event;
646 	delete m_itemdef;
647 	delete m_nodedef;
648 	delete m_craftdef;
649 	delete m_circuit;
650 
651 	// Deinitialize scripting
652 	infostream<<"Server: Deinitializing scripting"<<std::endl;
653 	delete m_script;
654 
655 	// Delete detached inventories
656 	for (std::map<std::string, Inventory*>::iterator
657 			i = m_detached_inventories.begin();
658 			i != m_detached_inventories.end(); i++) {
659 		delete i->second;
660 	}
661 }
662 
start(Address bind_addr)663 void Server::start(Address bind_addr)
664 {
665 	DSTACK(__FUNCTION_NAME);
666 	infostream<<"Starting server on "
667 			<< bind_addr.serializeString() <<"..."<<std::endl;
668 
669 	// Initialize connection
670 	m_con.SetTimeoutMs(30);
671 	m_con.Serve(bind_addr);
672 
673 	// Start thread
674 	m_thread->restart();
675 	if (m_map_thread)
676 		m_map_thread->restart();
677 	if (m_sendblocks)
678 		m_sendblocks->restart();
679 	if (m_liquid)
680 		m_liquid->restart();
681 	if(m_envthread)
682 		m_envthread->restart();
683 
684 	actionstream << "\033[1mfree\033[1;33mminer \033[1;36mv" << minetest_version_hash << "\033[0m \t"
685 #if CMAKE_THREADS
686 			<< " THREADS \t"
687 #endif
688 #ifndef NDEBUG
689 			<< " DEBUG \t"
690 #endif
691 			<< " cpp="<<__cplusplus<<" \t"
692 			<< " cores="<< porting::getNumberOfProcessors()
693 			<< std::endl;
694 	actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
695 	actionstream<<"Server for gameid=\""<<m_gamespec.id
696 			<<"\" mapgen=\""<<m_emerge->params.mg_name
697 			<<"\" listening on "<<bind_addr.serializeString()<<":"
698 			<<bind_addr.getPort() << "."<<std::endl;
699 }
700 
stop()701 void Server::stop()
702 {
703 	DSTACK(__FUNCTION_NAME);
704 
705 	infostream<<"Server: Stopping and waiting threads"<<std::endl;
706 
707 	// Stop threads (set run=false first so both start stopping)
708 	//m_emergethread.setRun(false);
709 	m_thread->join();
710 	//m_emergethread.stop();
711 	if (m_liquid)
712 		m_liquid->join();
713 	if (m_sendblocks)
714 		m_sendblocks->join();
715 	if (m_map_thread)
716 		m_map_thread->join();
717 	if(m_envthread)
718 		m_envthread->join();
719 
720 	infostream<<"Server: Threads stopped"<<std::endl;
721 }
722 
step(float dtime)723 void Server::step(float dtime)
724 {
725 	DSTACK(__FUNCTION_NAME);
726 	// Limit a bit
727 	if(dtime > 2.0)
728 		dtime = 2.0;
729 	{
730 		JMutexAutoLock lock(m_step_dtime_mutex);
731 		m_step_dtime += dtime;
732 	}
733 	// Throw if fatal error occurred in thread
734 	std::string async_err = m_async_fatal_error.get();
735 	if(async_err != ""){
736 		throw ServerError(async_err);
737 	}
738 }
739 
AsyncRunStep(float dtime,bool initial_step)740 void Server::AsyncRunStep(float dtime, bool initial_step)
741 {
742 	DSTACK(__FUNCTION_NAME);
743 
744 	TimeTaker timer_step("Server step");
745 	g_profiler->add("Server::AsyncRunStep (num)", 1);
746 
747 /*
748 	float dtime;
749 	{
750 		JMutexAutoLock lock1(m_step_dtime_mutex);
751 		dtime = m_step_dtime;
752 	}
753 */
754 
755 	if (!more_threads)
756 	{
757 		TimeTaker timer_step("Server step: SendBlocks");
758 		// Send blocks to clients
759 		SendBlocks(dtime);
760 	}
761 
762 	if((dtime < 0.001) && (initial_step == false))
763 		return;
764 
765 /*
766 	g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
767 */
768 	ScopeProfiler sp(g_profiler, "Server::AsyncRunStep, avg", SPT_AVG);
769 	//infostream<<"Server steps "<<dtime<<std::endl;
770 	//infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
771 
772 /*
773 	{
774 		TimeTaker timer_step("Server step: SendBlocks");
775 		JMutexAutoLock lock1(m_step_dtime_mutex);
776 		m_step_dtime -= dtime;
777 	}
778 */
779 
780 	/*
781 		Update uptime
782 	*/
783 	{
784 		m_uptime.set(m_uptime.get() + dtime);
785 	}
786 
787 	f32 dedicated_server_step = g_settings->getFloat("dedicated_server_step");
788 	//u32 max_cycle_ms = 1000 * (m_lag > dedicated_server_step ? dedicated_server_step/(m_lag/dedicated_server_step) : dedicated_server_step);
789 	u32 max_cycle_ms = 1000 * (dedicated_server_step/(m_lag/dedicated_server_step));
790 	if (max_cycle_ms < 40)
791 		max_cycle_ms = 40;
792 
793 	{
794 		TimeTaker timer_step("Server step: handlePeerChanges");
795 		// This has to be called so that the client list gets synced
796 		// with the peer list of the connection
797 		handlePeerChanges();
798 	}
799 
800 	/*
801 		Update time of day and overall game time
802 	*/
803 	{
804 		TimeTaker timer_step("Server step: pdate time of day and overall game time");
805 		//JMutexAutoLock envlock(m_env_mutex);
806 
807 		m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
808 
809 		/*
810 			Send to clients at constant intervals
811 		*/
812 
813 		m_time_of_day_send_timer -= dtime;
814 		if(m_time_of_day_send_timer < 0.0)
815 		{
816 			m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
817 			u16 time = m_env->getTimeOfDay();
818 			float time_speed = g_settings->getFloat("time_speed");
819 			SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
820 		}
821 	}
822 
823 	{
824 		//TimeTaker timer_step("Server step: m_env->step");
825 		//JMutexAutoLock lock(m_env_mutex);
826 		// Figure out and report maximum lag to environment
827 		float max_lag = m_env->getMaxLagEstimate();
828 		max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
829 		if(dtime > max_lag){
830 			if(dtime > dedicated_server_step && dtime > max_lag * 2.0)
831 				infostream<<"Server: Maximum lag peaked to "<<dtime
832 						<<" s"<<std::endl;
833 			max_lag = dtime;
834 		}
835 		m_env->reportMaxLagEstimate(max_lag);
836 		// Step environment
837 		ScopeProfiler sp(g_profiler, "SEnv step");
838 		if (!more_threads)
839 		m_env->step(dtime, m_uptime.get(), max_cycle_ms);
840 	}
841 
842 	/*
843 		Do background stuff
844 	*/
845 
846 	/*
847 		Handle players
848 	*/
849 	{
850 		//TimeTaker timer_step("Server step: Handle players");
851 		//JMutexAutoLock lock(m_env_mutex);
852 
853 		std::list<u16> clientids = m_clients.getClientIDs();
854 
855 		//ScopeProfiler sp(g_profiler, "Server: handle players");
856 
857 		for(std::list<u16>::iterator
858 			i = clientids.begin();
859 			i != clientids.end(); ++i)
860 		{
861 			PlayerSAO *playersao = getPlayerSAO(*i);
862 			if(playersao == NULL)
863 				continue;
864 
865 			/*
866 				Handle player HPs (die if hp=0)
867 			*/
868 			if(playersao->m_hp_not_sent && g_settings->getBool("enable_damage"))
869 			{
870 				if(playersao->getHP() == 0)
871 					DiePlayer(*i);
872 				else
873 					SendPlayerHP(*i);
874 			}
875 
876 			/*
877 				Send player breath if changed
878 			*/
879 			if(playersao->m_breath_not_sent) {
880 				SendPlayerBreath(*i);
881 			}
882 
883 			/*
884 				Send player inventories if necessary
885 			*/
886 			if(playersao->m_moved){
887 				SendMovePlayer(*i);
888 				playersao->m_moved = false;
889 			}
890 			if(playersao->m_inventory_not_sent){
891 				UpdateCrafting(*i);
892 				SendInventory(*i);
893 			}
894 		}
895 	}
896 
897 	if (!more_threads)
898 		AsyncRunMapStep(dtime, false);
899 
900 	m_clients.step(dtime);
901 
902 	m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
903 #if USE_CURL
904 	// send masterserver announce
905 	{
906 		float &counter = m_masterserver_timer;
907 		if(!isSingleplayer() && (!counter || counter >= 300.0) &&
908 				g_settings->getBool("server_announce"))
909 		{
910 			ServerList::sendAnnounce(counter ? "update" : "start",
911 					m_clients.getPlayerNames(),
912 					m_uptime.get(),
913 					m_env->getGameTime(),
914 					m_lag,
915 					m_gamespec.id,
916 					m_emerge->params.mg_name,
917 					m_mods);
918 			counter = 0.01;
919 		}
920 		counter += dtime;
921 	}
922 #endif
923 
924 	/*
925 		Check added and deleted active objects
926 	*/
927 	{
928 		TimeTaker timer_step("Server step: Check added and deleted active objects");
929 		//infostream<<"Server: Checking added and deleted active objects"<<std::endl;
930 		//JMutexAutoLock envlock(m_env_mutex);
931 
932 		auto clients = m_clients.getClientList();
933 		ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
934 
935 		// Radius inside which objects are active
936 		s16 radius = g_settings->getS16("active_object_send_range_blocks");
937 		s16 player_radius = g_settings->getS16("player_transfer_distance");
938 
939 		if (player_radius == 0 && g_settings->exists("unlimited_player_transfer_distance") &&
940 				!g_settings->getBool("unlimited_player_transfer_distance"))
941 			player_radius = radius;
942 
943 		radius *= MAP_BLOCKSIZE;
944 		s16 radius_deactivate = radius*3;
945 		player_radius *= MAP_BLOCKSIZE;
946 
947 		for(auto & client : clients)
948 		{
949 			// If definitions and textures have not been sent, don't
950 			// send objects either
951 			if (client->getState() < CS_DefinitionsSent)
952 				continue;
953 
954 			Player *player = m_env->getPlayer(client->peer_id);
955 			if(player==NULL)
956 			{
957 				// This can happen if the client timeouts somehow
958 				/*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client "
959 						<<client->peer_id
960 						<<" has no associated player"<<std::endl;*/
961 				continue;
962 			}
963 			v3s16 pos = floatToInt(player->getPosition(), BS);
964 
965 			std::set<u16> removed_objects;
966 			std::set<u16> added_objects;
967 			m_env->getRemovedActiveObjects(pos, radius_deactivate, player_radius,
968 					client->m_known_objects, removed_objects);
969 			m_env->getAddedActiveObjects(pos, radius, player_radius,
970 					client->m_known_objects, added_objects);
971 
972 			// Ignore if nothing happened
973 			if(removed_objects.size() == 0 && added_objects.size() == 0)
974 			{
975 				//infostream<<"active objects: none changed"<<std::endl;
976 				continue;
977 			}
978 
979 			std::string data_buffer;
980 
981 			char buf[4];
982 
983 			// Handle removed objects
984 			writeU16((u8*)buf, removed_objects.size());
985 			data_buffer.append(buf, 2);
986 			for(std::set<u16>::iterator
987 					i = removed_objects.begin();
988 					i != removed_objects.end(); ++i)
989 			{
990 				// Get object
991 				u16 id = *i;
992 				ServerActiveObject* obj = m_env->getActiveObject(id);
993 
994 				// Add to data buffer for sending
995 				writeU16((u8*)buf, id);
996 				data_buffer.append(buf, 2);
997 
998 				// Remove from known objects
999 				client->m_known_objects.erase(id);
1000 
1001 				if(obj && obj->m_known_by_count > 0)
1002 					obj->m_known_by_count--;
1003 			}
1004 
1005 			// Handle added objects
1006 			writeU16((u8*)buf, added_objects.size());
1007 			data_buffer.append(buf, 2);
1008 			for(std::set<u16>::iterator
1009 					i = added_objects.begin();
1010 					i != added_objects.end(); ++i)
1011 			{
1012 				// Get object
1013 				u16 id = *i;
1014 				ServerActiveObject* obj = m_env->getActiveObject(id);
1015 
1016 				// Get object type
1017 				u8 type = ACTIVEOBJECT_TYPE_INVALID;
1018 				if(obj == NULL)
1019 					infostream<<"WARNING: "<<__FUNCTION_NAME
1020 							<<": NULL object"<<std::endl;
1021 				else
1022 					type = obj->getSendType();
1023 
1024 				// Add to data buffer for sending
1025 				writeU16((u8*)buf, id);
1026 				data_buffer.append(buf, 2);
1027 				writeU8((u8*)buf, type);
1028 				data_buffer.append(buf, 1);
1029 
1030 				if(obj)
1031 					data_buffer.append(serializeLongString(
1032 							obj->getClientInitializationData(client->net_proto_version)));
1033 				else
1034 					data_buffer.append(serializeLongString(""));
1035 
1036 				// Add to known objects
1037 				client->m_known_objects.set(id, true);
1038 
1039 				if(obj)
1040 					obj->m_known_by_count++;
1041 			}
1042 
1043 			// Send packet
1044 			SharedBuffer<u8> reply(2 + data_buffer.size());
1045 			writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD);
1046 			memcpy((char*)&reply[2], data_buffer.c_str(),
1047 					data_buffer.size());
1048 			// Send as reliable
1049 			m_clients.send(client->peer_id, 0, reply, true);
1050 
1051 /*
1052 			verbosestream<<"Server: Sent object remove/add: "
1053 					<<removed_objects.size()<<" removed, "
1054 					<<added_objects.size()<<" added, "
1055 					<<"packet size is "<<reply.getSize()<<std::endl;
1056 */
1057 		}
1058 #if 0
1059 		/*
1060 			Collect a list of all the objects known by the clients
1061 			and report it back to the environment.
1062 		*/
1063 
1064 		core::map<u16, bool> all_known_objects;
1065 
1066 		for(core::map<u16, RemoteClient*>::Iterator
1067 			i = m_clients.getIterator();
1068 			i.atEnd() == false; i++)
1069 		{
1070 			RemoteClient *client = i.getNode()->getValue();
1071 			// Go through all known objects of client
1072 			for(core::map<u16, bool>::Iterator
1073 					i = client->m_known_objects.getIterator();
1074 					i.atEnd()==false; i++)
1075 			{
1076 				u16 id = i.getNode()->getKey();
1077 				all_known_objects[id] = true;
1078 			}
1079 		}
1080 
1081 		m_env->setKnownActiveObjects(whatever);
1082 #endif
1083 
1084 	}
1085 
1086 	/*
1087 		Send object messages
1088 	*/
1089 	{
1090 		TimeTaker timer_step("Server step: Send object messages");
1091 		//JMutexAutoLock envlock(m_env_mutex);
1092 		ScopeProfiler sp(g_profiler, "Server: sending object messages");
1093 
1094 		// Key = object id
1095 		// Value = data sent by object
1096 		std::map<u16, std::list<ActiveObjectMessage>* > buffered_messages;
1097 
1098 		// Get active object messages from environment
1099 		for(;;)
1100 		{
1101 			ActiveObjectMessage aom = m_env->getActiveObjectMessage();
1102 			if(aom.id == 0)
1103 				break;
1104 
1105 			std::list<ActiveObjectMessage>* message_list = NULL;
1106 			std::map<u16, std::list<ActiveObjectMessage>* >::iterator n;
1107 			n = buffered_messages.find(aom.id);
1108 			if(n == buffered_messages.end())
1109 			{
1110 				message_list = new std::list<ActiveObjectMessage>;
1111 				buffered_messages[aom.id] = message_list;
1112 			}
1113 			else
1114 			{
1115 				message_list = n->second;
1116 			}
1117 			message_list->push_back(aom);
1118 		}
1119 
1120 
1121 
1122 
1123 
1124 		auto clients = m_clients.getClientList();
1125 		{
1126 		// Route data to every client
1127 		for(auto & client : clients)
1128 		{
1129 			std::string reliable_data;
1130 			std::string unreliable_data;
1131 			// Go through all objects in message buffer
1132 			for(std::map<u16, std::list<ActiveObjectMessage>* >::iterator
1133 					j = buffered_messages.begin();
1134 					j != buffered_messages.end(); ++j)
1135 			{
1136 				// If object is not known by client, skip it
1137 				u16 id = j->first;
1138 				if(client->m_known_objects.find(id) == client->m_known_objects.end())
1139 					continue;
1140 				// Get message list of object
1141 				std::list<ActiveObjectMessage>* list = j->second;
1142 				// Go through every message
1143 				for(std::list<ActiveObjectMessage>::iterator
1144 						k = list->begin(); k != list->end(); ++k)
1145 				{
1146 					// Compose the full new data with header
1147 					ActiveObjectMessage aom = *k;
1148 					std::string new_data;
1149 					// Add object id
1150 					char buf[2];
1151 					writeU16((u8*)&buf[0], aom.id);
1152 					new_data.append(buf, 2);
1153 					// Add data
1154 					new_data += serializeString(aom.datastring);
1155 					// Add data to buffer
1156 					if(aom.reliable)
1157 						reliable_data += new_data;
1158 					else
1159 						unreliable_data += new_data;
1160 				}
1161 			}
1162 			/*
1163 				reliable_data and unreliable_data are now ready.
1164 				Send them.
1165 			*/
1166 			if(reliable_data.size() > 0)
1167 			{
1168 				SharedBuffer<u8> reply(2 + reliable_data.size());
1169 				writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
1170 				memcpy((char*)&reply[2], reliable_data.c_str(),
1171 						reliable_data.size());
1172 				// Send as reliable
1173 				m_clients.send(client->peer_id, 0, reply, true);
1174 			}
1175 			if(unreliable_data.size() > 0)
1176 			{
1177 				SharedBuffer<u8> reply(2 + unreliable_data.size());
1178 				writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
1179 				memcpy((char*)&reply[2], unreliable_data.c_str(),
1180 						unreliable_data.size());
1181 				// Send as unreliable
1182 				m_clients.send(client->peer_id, 1, reply, false);
1183 			}
1184 
1185 			/*if(reliable_data.size() > 0 || unreliable_data.size() > 0)
1186 			{
1187 				infostream<<"Server: Size of object message data: "
1188 						<<"reliable: "<<reliable_data.size()
1189 						<<", unreliable: "<<unreliable_data.size()
1190 						<<std::endl;
1191 			}*/
1192 		}
1193 		}
1194 		// Clear buffered_messages
1195 		for(std::map<u16, std::list<ActiveObjectMessage>* >::iterator
1196 				i = buffered_messages.begin();
1197 				i != buffered_messages.end(); ++i)
1198 		{
1199 			delete i->second;
1200 		}
1201 	}
1202 
1203 	/*
1204 		Send queued-for-sending map edit events.
1205 	*/
1206 	{
1207 		TimeTaker timer_step("Server step: Send queued-for-sending map edit events.");
1208 		ScopeProfiler sp(g_profiler, "Server: Map events process");
1209 		// We will be accessing the environment
1210 		//JMutexAutoLock lock(m_env_mutex);
1211 
1212 		// Don't send too many at a time
1213 		u32 count = 0;
1214 
1215 		// Single change sending is disabled if queue size is not small
1216 		bool disable_single_change_sending = false;
1217 		if(m_unsent_map_edit_queue.size() >= 4)
1218 			disable_single_change_sending = true;
1219 
1220 		//int event_count = m_unsent_map_edit_queue.size();
1221 
1222 		// We'll log the amount of each
1223 		Profiler prof;
1224 
1225 		u32 end_ms = porting::getTimeMs() + max_cycle_ms;
1226 		while(m_unsent_map_edit_queue.size() != 0)
1227 		{
1228 			MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
1229 
1230 			// Players far away from the change are stored here.
1231 			// Instead of sending the changes, MapBlocks are set not sent
1232 			// for them.
1233 			std::list<u16> far_players;
1234 
1235 			if(event->type == MEET_ADDNODE || event->type == MEET_SWAPNODE)
1236 			{
1237 				//infostream<<"Server: MEET_ADDNODE"<<std::endl;
1238 				prof.add("MEET_ADDNODE", 1);
1239 				if(disable_single_change_sending)
1240 					sendAddNode(event->p, event->n, event->already_known_by_peer,
1241 							&far_players, 5, event->type == MEET_ADDNODE);
1242 				else
1243 					sendAddNode(event->p, event->n, event->already_known_by_peer,
1244 							&far_players, 30, event->type == MEET_ADDNODE);
1245 			}
1246 			else if(event->type == MEET_REMOVENODE)
1247 			{
1248 				//infostream<<"Server: MEET_REMOVENODE"<<std::endl;
1249 				prof.add("MEET_REMOVENODE", 1);
1250 				if(disable_single_change_sending)
1251 					sendRemoveNode(event->p, event->already_known_by_peer,
1252 							&far_players, 5);
1253 				else
1254 					sendRemoveNode(event->p, event->already_known_by_peer,
1255 							&far_players, 30);
1256 			}
1257 			else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
1258 			{
1259 /*
1260 				infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
1261 */
1262 				prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
1263 				setBlockNotSent(event->p);
1264 			}
1265 			else if(event->type == MEET_OTHER)
1266 			{
1267 /*
1268 				infostream<<"Server: MEET_OTHER"<<std::endl;
1269 */
1270 				prof.add("MEET_OTHER", 1);
1271 				for(std::set<v3s16>::iterator
1272 						i = event->modified_blocks.begin();
1273 						i != event->modified_blocks.end(); ++i)
1274 				{
1275 					setBlockNotSent(*i);
1276 				}
1277 			}
1278 			else
1279 			{
1280 				prof.add("unknown", 1);
1281 				infostream<<"WARNING: Server: Unknown MapEditEvent "
1282 						<<((u32)event->type)<<std::endl;
1283 			}
1284 
1285 			/*
1286 				Set blocks not sent to far players
1287 			*/
1288 			if(far_players.size() > 0)
1289 			{
1290 				// Convert list format to that wanted by SetBlocksNotSent
1291 				std::map<v3s16, MapBlock*> modified_blocks2;
1292 				for(std::set<v3s16>::iterator
1293 						i = event->modified_blocks.begin();
1294 						i != event->modified_blocks.end(); ++i)
1295 				{
1296 					modified_blocks2[*i] =
1297 							m_env->getMap().getBlockNoCreateNoEx(*i);
1298 				}
1299 				// Set blocks not sent
1300 				for(std::list<u16>::iterator
1301 						i = far_players.begin();
1302 						i != far_players.end(); ++i)
1303 				{
1304 					u16 peer_id = *i;
1305 					RemoteClient *client = getClient(peer_id);
1306 					if(client==NULL)
1307 						continue;
1308 					client->SetBlocksNotSent(modified_blocks2);
1309 				}
1310 			}
1311 
1312 			delete event;
1313 
1314 			++count;
1315 			/*// Don't send too many at a time
1316 			if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
1317 				break;*/
1318 			if (porting::getTimeMs() > end_ms)
1319 				break;
1320 		}
1321 
1322 /*
1323 		if(event_count >= 10){
1324 			infostream<<"Server: MapEditEvents count="<<count<<"/"<<event_count<<" :"<<std::endl;
1325 			prof.print(infostream);
1326 		} else if(event_count != 0){
1327 			verbosestream<<"Server: MapEditEvents count="<<count<<"/"<<event_count<<" :"<<std::endl;
1328 			prof.print(verbosestream);
1329 		}
1330 */
1331 
1332 	}
1333 
1334 	/*
1335 		Trigger emergethread (it somehow gets to a non-triggered but
1336 		bysy state sometimes)
1337 	*/
1338 	if (!maintenance_status)
1339 	{
1340 		TimeTaker timer_step("Server step: Trigger emergethread");
1341 		float &counter = m_emergethread_trigger_timer;
1342 		counter += dtime;
1343 		if(counter >= 2.0)
1344 		{
1345 			counter = 0.0;
1346 
1347 			m_emerge->startThreads();
1348 
1349 			// Update m_enable_rollback_recording here too
1350 			m_enable_rollback_recording =
1351 					g_settings->getBool("enable_rollback_recording");
1352 		}
1353 	}
1354 
1355 	{
1356 		if (porting::g_sighup) {
1357 			porting::g_sighup = false;
1358 			if(!maintenance_status) {
1359 				maintenance_status = 1;
1360 				maintenance_start();
1361 				maintenance_status = 2;
1362 			} else if(maintenance_status == 2) {
1363 				maintenance_status = 3;
1364 				maintenance_end();
1365 				maintenance_status = 0;
1366 			}
1367 		}
1368 		if (porting::g_siginfo) {
1369 			// todo: add here more info
1370 			porting::g_siginfo = false;
1371 			infostream<<"uptime="<< (int)m_uptime.get()<<std::endl;
1372 			m_clients.UpdatePlayerList(); //print list
1373 			g_profiler->print(infostream);
1374 			g_profiler->clear();
1375 		}
1376 	}
1377 }
1378 
AsyncRunMapStep(float dtime,bool async)1379 int Server::AsyncRunMapStep(float dtime, bool async) {
1380 	DSTACK(__FUNCTION_NAME);
1381 
1382 	TimeTaker timer_step("Server map step");
1383 	g_profiler->add("Server::AsyncRunMapStep (num)", 1);
1384 
1385 	int ret = 0;
1386 
1387 /*
1388 	float dtime;
1389 	{
1390 		JMutexAutoLock lock1(m_step_dtime_mutex);
1391 		dtime = m_step_dtime;
1392 	}
1393 */
1394 
1395 	u32 max_cycle_ms = async ? 2000 : 300;
1396 
1397 	const float map_timer_and_unload_dtime = 10.92;
1398 	if(!maintenance_status && m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
1399 	{
1400 		TimeTaker timer_step("Server step: Run Map's timers and unload unused data");
1401 		//JMutexAutoLock lock(m_env_mutex);
1402 		// Run Map's timers and unload unused data
1403 		ScopeProfiler sp(g_profiler, "Server: map timer and unload");
1404 		if(m_env->getMap().timerUpdate(m_uptime.get(), g_settings->getFloat("server_unload_unused_data_timeout"), max_cycle_ms)) {
1405 			m_map_timer_and_unload_interval.run_next(map_timer_and_unload_dtime);
1406 			++ret;
1407 		}
1408 	}
1409 
1410 	/* Transform liquids */
1411 	m_liquid_transform_timer += dtime;
1412 	if(!more_threads && m_liquid_transform_timer >= m_liquid_transform_interval)
1413 	{
1414 		TimeTaker timer_step("Server step: liquid transform");
1415 		m_liquid_transform_timer -= m_liquid_transform_interval;
1416 		if (m_liquid_transform_timer > m_liquid_transform_interval * 2)
1417 			m_liquid_transform_timer = 0;
1418 
1419 		//JMutexAutoLock lock(m_env_mutex);
1420 
1421 		ScopeProfiler sp(g_profiler, "Server: liquid transform");
1422 
1423 		// not all liquid was processed per step, forcing on next step
1424 		//shared_map<v3POS, MapBlock*> modified_blocks; //not used
1425 		if (m_env->getMap().transformLiquids(this, max_cycle_ms) > 0) {
1426 			m_liquid_transform_timer = m_liquid_transform_interval /*  *0.8  */;
1427 			++ret;
1428 		}
1429 	}
1430 
1431 		/*
1432 			Set the modified blocks unsent for all the clients
1433 		*/
1434 
1435 	m_liquid_send_timer += dtime;
1436 	if(m_liquid_send_timer >= m_liquid_send_interval)
1437 	{
1438 		TimeTaker timer_step("Server step: set the modified blocks unsent for all the clients");
1439 		m_liquid_send_timer -= m_liquid_send_interval;
1440 		if (m_liquid_send_timer > m_liquid_send_interval * 2)
1441 			m_liquid_send_timer = 0;
1442 
1443 		shared_map<v3POS, MapBlock*> modified_blocks; //not used
1444 
1445 		if (m_env->getMap().updateLighting(m_env->getMap().lighting_modified_blocks, modified_blocks, max_cycle_ms)) {
1446 			m_liquid_send_timer = m_liquid_send_interval;
1447 			++ret;
1448 			goto no_send;
1449 		}
1450 
1451 		auto clients = m_clients.getClientList();
1452 		for (auto & client : clients)
1453 			if (client->m_nearest_unsent_nearest) {
1454 				client->m_nearest_unsent_d = 0;
1455 				client->m_nearest_unsent_nearest = 0;
1456 			}
1457 
1458 		//JMutexAutoLock lock(m_env_mutex);
1459 		//JMutexAutoLock lock2(m_con_mutex);
1460 
1461 /*
1462 		if(m_modified_blocks.size() > 0)
1463 		{
1464 			SetBlocksNotSent(m_modified_blocks);
1465 		}
1466 		m_modified_blocks.clear();
1467 */
1468 	}
1469 	no_send:
1470 
1471 	ret += save(dtime, true);
1472 
1473 	return ret;
1474 }
1475 
save(float dtime,bool breakable)1476 int Server::save(float dtime, bool breakable) {
1477 	// Save map, players and auth stuff
1478 	int ret = 0;
1479 		float &counter = m_savemap_timer;
1480 		counter += dtime;
1481 		if(counter >= g_settings->getFloat("server_map_save_interval"))
1482 		{
1483 			counter = 0.0;
1484 			TimeTaker timer_step("Server step: Save map, players and auth stuff");
1485 			//JMutexAutoLock lock(m_env_mutex);
1486 
1487 			ScopeProfiler sp(g_profiler, "Server: saving stuff");
1488 
1489 			// Save changed parts of map
1490 			if(m_env->getMap().save(MOD_STATE_WRITE_NEEDED, breakable)) {
1491 				// partial save, will continue on next step
1492 				counter = g_settings->getFloat("server_map_save_interval");
1493 				++ret;
1494 				if (breakable)
1495 					goto save_break;
1496 			}
1497 
1498 			// Save ban file
1499 			if (m_banmanager->isModified()) {
1500 				m_banmanager->save();
1501 			}
1502 
1503 			// Save players
1504 			m_env->saveLoadedPlayers();
1505 
1506 			// Save environment metadata
1507 			m_env->saveMeta();
1508 
1509 			stat.save();
1510 		}
1511 		save_break:;
1512 
1513 	return ret;
1514 }
1515 
Receive()1516 u16 Server::Receive()
1517 {
1518 	DSTACK(__FUNCTION_NAME);
1519 	SharedBuffer<u8> data;
1520 	u16 peer_id;
1521 	u32 datasize;
1522 	u16 received = 0;
1523 	try{
1524 		datasize = m_con.Receive(peer_id,data);
1525 		ProcessData(*data, datasize, peer_id);
1526 		++received;
1527 	}
1528 	catch(con::InvalidIncomingDataException &e)
1529 	{
1530 		infostream<<"Server::Receive(): "
1531 				"InvalidIncomingDataException: what()="
1532 				<<e.what()<<std::endl;
1533 	}
1534 	catch(SerializationError &e) {
1535 		infostream<<"Server::Receive(): "
1536 				"SerializationError: what()="
1537 				<<e.what()<<std::endl;
1538 	}
1539 	catch(ClientStateError &e)
1540 	{
1541 		errorstream << "ProcessData: peer=" << peer_id  << e.what() << std::endl;
1542 		DenyAccess(peer_id, L"Your client sent something server didn't expect."
1543 				L"Try reconnecting or updating your client");
1544 	}
1545 	catch(con::PeerNotFoundException &e)
1546 	{
1547 		// Do nothing
1548 	}
1549 	return received;
1550 }
1551 
StageTwoClientInit(u16 peer_id)1552 PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
1553 {
1554 	std::string playername = "";
1555 	PlayerSAO *playersao = NULL;
1556 		RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
1557 		if (client != NULL) {
1558 			playername = client->getName();
1559 			playersao = emergePlayer(playername.c_str(), peer_id);
1560 		}
1561 
1562 	RemotePlayer *player =
1563 		static_cast<RemotePlayer*>(m_env->getPlayer(playername));
1564 
1565 	// If failed, cancel
1566 	if((playersao == NULL) || (player == NULL))
1567 	{
1568 		if(player && player->peer_id != 0){
1569 			errorstream<<"Server: "<<playername<<": Failed to emerge player"
1570 					<<" (player allocated to an another client)"<<std::endl;
1571 			DenyAccess(peer_id, L"Another client is connected with this "
1572 					L"name. If your client closed unexpectedly, try again in "
1573 					L"a minute.");
1574 		} else {
1575 			errorstream<<"Server: "<<playername<<": Failed to emerge player"
1576 					<<std::endl;
1577 			DenyAccess(peer_id, L"Could not allocate player.");
1578 		}
1579 		return NULL;
1580 	}
1581 
1582 	/*
1583 		Send complete position information
1584 	*/
1585 	SendMovePlayer(peer_id);
1586 
1587 	// Send privileges
1588 	SendPlayerPrivileges(peer_id);
1589 
1590 	// Send inventory formspec
1591 	SendPlayerInventoryFormspec(peer_id);
1592 
1593 	// Send inventory
1594 	UpdateCrafting(peer_id);
1595 	SendInventory(peer_id);
1596 
1597 	// Send HP
1598 	if(g_settings->getBool("enable_damage"))
1599 		SendPlayerHP(peer_id);
1600 
1601 	// Send Breath
1602 	SendPlayerBreath(peer_id);
1603 
1604 	// Show death screen if necessary
1605 	if(player->hp == 0)
1606 		SendDeathscreen(peer_id, false, v3f(0,0,0));
1607 
1608 	// Note things in chat if not in simple singleplayer mode
1609 	if(!m_simple_singleplayer_mode)
1610 	{
1611 		// Send information about server to player in chat
1612 		SendChatMessage(peer_id, getStatusString());
1613 
1614 		// Send information about joining in chat
1615 		if (0)
1616 		{
1617 			std::wstring name = L"unknown";
1618 			Player *player = m_env->getPlayer(peer_id);
1619 			if(player != NULL)
1620 				name = narrow_to_wide(player->getName());
1621 
1622 			std::wstring message;
1623 			message += L"*** ";
1624 			message += name;
1625 			message += L" joined the game.";
1626 			SendChatMessage(PEER_ID_INEXISTENT,message);
1627 		}
1628 	}
1629 
1630 /*
1631 	Address addr = getPeerAddress(player->peer_id);
1632 	std::string ip_str = addr.serializeString();
1633 	actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1634 */
1635 	/*
1636 		Print out action
1637 	*/
1638 	{
1639 		std::vector<std::string> names = m_clients.getPlayerNames();
1640 
1641 		actionstream<<player->getName() << " ["<<getPeerAddress(player->peer_id).serializeString()<<"] "<<
1642 		" joins game. List of players: ";
1643 
1644 		for (std::vector<std::string>::iterator i = names.begin();
1645 				i != names.end(); i++)
1646 		{
1647 			actionstream << *i << " ";
1648 		}
1649 
1650 		actionstream << player->getName() <<std::endl;
1651 	}
1652 	return playersao;
1653 }
1654 
ProcessData(u8 * data,u32 datasize,u16 peer_id)1655 void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
1656 {
1657 	DSTACK(__FUNCTION_NAME);
1658 	// Environment is locked first.
1659 	//JMutexAutoLock envlock(m_env_mutex);
1660 
1661 	ScopeProfiler sp(g_profiler, "Server::ProcessData");
1662 
1663 	std::string addr_s;
1664 	try{
1665 		Address address = getPeerAddress(peer_id);
1666 		addr_s = address.serializeString();
1667 
1668 		// drop player if is ip is banned
1669 		if(m_banmanager->isIpBanned(addr_s)){
1670 			std::string ban_name = m_banmanager->getBanName(addr_s);
1671 			infostream<<"Server: A banned client tried to connect from "
1672 					<<addr_s<<"; banned name was "
1673 					<<ban_name<<std::endl;
1674 			// This actually doesn't seem to transfer to the client
1675 			DenyAccess(peer_id, L"Your ip is banned. Banned name was "
1676 					+narrow_to_wide(ban_name));
1677 			return;
1678 		}
1679 	}
1680 	catch(con::PeerNotFoundException &e)
1681 	{
1682 		/*
1683 		 * no peer for this packet found
1684 		 * most common reason is peer timeout, e.g. peer didn't
1685 		 * respond for some time, your server was overloaded or
1686 		 * things like that.
1687 		 */
1688 		verbosestream<<"Server::ProcessData(): Cancelling: peer "
1689 				<<peer_id<<" not found"<<std::endl;
1690 		return;
1691 	}
1692 
1693 	try
1694 	{
1695 
1696 	if(datasize < 2)
1697 		return;
1698 
1699 	ToServerCommand command = (ToServerCommand)readU16(&data[0]);
1700 
1701 	if(command == TOSERVER_INIT)
1702 	{
1703 		// [0] u16 TOSERVER_INIT
1704 		// [2] u8 SER_FMT_VER_HIGHEST_READ
1705 		// [3] u8[20] player_name
1706 		// [23] u8[28] password <--- can be sent without this, from old versions
1707 
1708 		if(datasize < 2+1+PLAYERNAME_SIZE)
1709 			return;
1710 
1711 		RemoteClient* client = getClient(peer_id, CS_Created);
1712 
1713 		// If net_proto_version is set, this client has already been handled
1714 		if(client->getState() > CS_Created)
1715 		{
1716 			verbosestream<<"Server: Ignoring multiple TOSERVER_INITs from "
1717 					<<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
1718 			return;
1719 		}
1720 
1721 		verbosestream<<"Server: Got TOSERVER_INIT from "<<addr_s<<" (peer_id="
1722 				<<peer_id<<")"<<std::endl;
1723 
1724 		// Do not allow multiple players in simple singleplayer mode.
1725 		// This isn't a perfect way to do it, but will suffice for now
1726 		if(m_simple_singleplayer_mode && m_clients.getClientIDs().size() > 1){
1727 			infostream<<"Server: Not allowing another client ("<<addr_s
1728 					<<") to connect in simple singleplayer mode"<<std::endl;
1729 			DenyAccess(peer_id, L"Running in simple singleplayer mode.");
1730 			return;
1731 		}
1732 
1733 		// First byte after command is maximum supported
1734 		// serialization version
1735 		u8 client_max = data[2];
1736 		u8 our_max = SER_FMT_VER_HIGHEST_READ;
1737 		// Use the highest version supported by both
1738 		u8 deployed = std::min(client_max, our_max);
1739 		// If it's lower than the lowest supported, give up.
1740 		if(deployed < SER_FMT_VER_LOWEST)
1741 			deployed = SER_FMT_VER_INVALID;
1742 
1743 		if(deployed == SER_FMT_VER_INVALID)
1744 		{
1745 			actionstream<<"Server: A mismatched client tried to connect from "
1746 					<<addr_s<<std::endl;
1747 			infostream<<"Server: Cannot negotiate serialization version with "
1748 					<<addr_s<<std::endl;
1749 			DenyAccess(peer_id, std::wstring(
1750 					L"Your client's version is not supported.\n"
1751 					L"Server version is ")
1752 					+ narrow_to_wide(minetest_version_simple) + L"."
1753 			);
1754 			return;
1755 		}
1756 
1757 		client->setPendingSerializationVersion(deployed);
1758 
1759 		/*
1760 			Read and check network protocol version
1761 		*/
1762 
1763 		u16 min_net_proto_version = 0;
1764 		if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
1765 			min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
1766 
1767 		// Use same version as minimum and maximum if maximum version field
1768 		// doesn't exist (backwards compatibility)
1769 		u16 max_net_proto_version = min_net_proto_version;
1770 		if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2)
1771 			max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]);
1772 
1773 		// Start with client's maximum version
1774 		u16 net_proto_version = max_net_proto_version;
1775 
1776 		// Figure out a working version if it is possible at all
1777 		if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN ||
1778 				min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX)
1779 		{
1780 			// If maximum is larger than our maximum, go with our maximum
1781 			if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1782 				net_proto_version = SERVER_PROTOCOL_VERSION_MAX;
1783 			// Else go with client's maximum
1784 			else
1785 				net_proto_version = max_net_proto_version;
1786 		}
1787 
1788 		verbosestream<<"Server: "<<addr_s<<": Protocol version: min: "
1789 				<<min_net_proto_version<<", max: "<<max_net_proto_version
1790 				<<", chosen: "<<net_proto_version<<std::endl;
1791 
1792 		client->net_proto_version = net_proto_version;
1793 
1794 		if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN ||
1795 				net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1796 		{
1797 			actionstream<<"Server: A mismatched client tried to connect from "
1798 					<<addr_s<<std::endl;
1799 			DenyAccess(peer_id, std::wstring(
1800 					L"Your client's version is not supported.\n"
1801 					L"Server version is ")
1802 					+ narrow_to_wide(minetest_version_simple) + L",\n"
1803 					+ L"server's PROTOCOL_VERSION is "
1804 					+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN))
1805 					+ L"..."
1806 					+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX))
1807 					+ L", client's PROTOCOL_VERSION is "
1808 					+ narrow_to_wide(itos(min_net_proto_version))
1809 					+ L"..."
1810 					+ narrow_to_wide(itos(max_net_proto_version))
1811 			);
1812 			return;
1813 		}
1814 
1815 		if(g_settings->getBool("strict_protocol_version_checking"))
1816 		{
1817 			if(net_proto_version != LATEST_PROTOCOL_VERSION)
1818 			{
1819 				actionstream<<"Server: A mismatched (strict) client tried to "
1820 						<<"connect from "<<addr_s<<std::endl;
1821 				DenyAccess(peer_id, std::wstring(
1822 						L"Your client's version is not supported.\n"
1823 						L"Server version is ")
1824 						+ narrow_to_wide(minetest_version_simple) + L",\n"
1825 						+ L"server's PROTOCOL_VERSION (strict) is "
1826 						+ narrow_to_wide(itos(LATEST_PROTOCOL_VERSION))
1827 						+ L", client's PROTOCOL_VERSION is "
1828 						+ narrow_to_wide(itos(min_net_proto_version))
1829 						+ L"..."
1830 						+ narrow_to_wide(itos(max_net_proto_version))
1831 				);
1832 				return;
1833 			}
1834 		}
1835 
1836 		/*
1837 			Set up player
1838 		*/
1839 		char playername[PLAYERNAME_SIZE];
1840 		unsigned int playername_length = 0;
1841 		for (; playername_length < PLAYERNAME_SIZE; playername_length++ ) {
1842 			playername[playername_length] = data[3+playername_length];
1843 			if (data[3+playername_length] == 0)
1844 				break;
1845 		}
1846 
1847 		if (playername_length == PLAYERNAME_SIZE) {
1848 			actionstream<<"Server: Player with name exceeding max length "
1849 					<<"tried to connect from "<<addr_s<<std::endl;
1850 			DenyAccess(peer_id, L"Name too long");
1851 			return;
1852 		}
1853 
1854 
1855 		if(playername[0]=='\0')
1856 		{
1857 			actionstream<<"Server: Player with an empty name "
1858 					<<"tried to connect from "<<addr_s<<std::endl;
1859 			DenyAccess(peer_id, L"Empty name");
1860 			return;
1861 		}
1862 
1863 		if(!g_settings->getBool("enable_any_name") && string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
1864 		{
1865 			actionstream<<"Server: Player with an invalid name ["<<playername
1866 					<<"] tried to connect from "<<addr_s<<std::endl;
1867 			DenyAccess(peer_id, L"Name contains unallowed characters");
1868 			return;
1869 		}
1870 
1871 		if(!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0)
1872 		{
1873 			actionstream<<"Server: Player with the name \"singleplayer\" "
1874 					<<"tried to connect from "<<addr_s<<std::endl;
1875 			DenyAccess(peer_id, L"Name is not allowed");
1876 			return;
1877 		}
1878 
1879 		{
1880 			std::string reason;
1881 			if(m_script->on_prejoinplayer(playername, addr_s, reason))
1882 			{
1883 				actionstream<<"Server: Player with the name \""<<playername<<"\" "
1884 						<<"tried to connect from "<<addr_s<<" "
1885 						<<"but it was disallowed for the following reason: "
1886 						<<reason<<std::endl;
1887 				DenyAccess(peer_id, narrow_to_wide(reason.c_str()));
1888 				return;
1889 			}
1890 		}
1891 
1892 		infostream<<"Server: New connection: \""<<playername<<"\" from "
1893 				<<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
1894 
1895 		// Get password
1896 		char given_password[PASSWORD_SIZE];
1897 		if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
1898 		{
1899 			// old version - assume blank password
1900 			given_password[0] = 0;
1901 		}
1902 		else
1903 		{
1904 			for(u32 i=0; i<PASSWORD_SIZE-1; i++)
1905 			{
1906 				given_password[i] = data[23+i];
1907 			}
1908 			given_password[PASSWORD_SIZE-1] = 0;
1909 		}
1910 
1911 		if(!base64_is_valid(given_password)){
1912 			actionstream<<"Server: "<<playername
1913 					<<" supplied invalid password hash"<<std::endl;
1914 			DenyAccess(peer_id, L"Invalid password hash");
1915 			return;
1916 		}
1917 
1918 		// Enforce user limit.
1919 		// Don't enforce for users that have some admin right
1920 		if(m_clients.getClientIDs(CS_Created).size() >= g_settings->getU16("max_users") &&
1921 				!checkPriv(playername, "server") &&
1922 				!checkPriv(playername, "ban") &&
1923 				!checkPriv(playername, "privs") &&
1924 				!checkPriv(playername, "password") &&
1925 				playername != g_settings->get("name"))
1926 		{
1927 			actionstream<<"Server: "<<playername<<" tried to join, but there"
1928 					<<" are already max_users="
1929 					<<g_settings->getU16("max_users")<<" players."<<std::endl;
1930 			DenyAccess(peer_id, L"Too many users.");
1931 			return;
1932 		}
1933 
1934 		std::string checkpwd; // Password hash to check against
1935 		bool has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1936 
1937 		// If no authentication info exists for user, create it
1938 		if(!has_auth){
1939 			if(!isSingleplayer() &&
1940 					g_settings->getBool("disallow_empty_password") &&
1941 					std::string(given_password) == ""){
1942 				actionstream<<"Server: "<<playername
1943 						<<" supplied empty password"<<std::endl;
1944 				DenyAccess(peer_id, L"Empty passwords are "
1945 						L"disallowed. Set a password and try again.");
1946 				return;
1947 			}
1948 			std::wstring raw_default_password =
1949 				narrow_to_wide(g_settings->get("default_password"));
1950 			std::string initial_password =
1951 				translatePassword(playername, raw_default_password);
1952 
1953 			// If default_password is empty, allow any initial password
1954 			if (raw_default_password.length() == 0)
1955 				initial_password = given_password;
1956 
1957 			m_script->createAuth(playername, initial_password);
1958 		}
1959 
1960 		has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1961 
1962 		if(!has_auth){
1963 			actionstream<<"Server: "<<playername<<" cannot be authenticated"
1964 					<<" (auth handler does not work?)"<<std::endl;
1965 			DenyAccess(peer_id, L"Not allowed to login");
1966 			return;
1967 		}
1968 
1969 		if(given_password != checkpwd){
1970 			actionstream<<"Server: "<<playername<<" supplied wrong password"
1971 					<<std::endl;
1972 			DenyAccess(peer_id, L"Wrong password");
1973 			return;
1974 		}
1975 
1976 		RemotePlayer *player =
1977 				static_cast<RemotePlayer*>(m_env->getPlayer(playername));
1978 
1979 		if(player && player->peer_id != 0){
1980 			errorstream<<"Server: "<<playername<<": Failed to emerge player"
1981 					<<" (player allocated to an another client)"<<std::endl;
1982 			DenyAccess(peer_id, L"Another client is connected with this "
1983 					L"name. If your client closed unexpectedly, try again in "
1984 					L"a minute.");
1985 		}
1986 
1987 		m_clients.setPlayerName(peer_id,playername);
1988 
1989 		/*
1990 			Answer with a TOCLIENT_INIT
1991 		*/
1992 		{
1993 			SharedBuffer<u8> reply(2+1+6+8+4);
1994 			writeU16(&reply[0], TOCLIENT_INIT);
1995 			writeU8(&reply[2], deployed);
1996 			//send dummy pos for legacy reasons only
1997 			writeV3S16(&reply[2+1], floatToInt(v3f(0,0,0), BS));
1998 			writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
1999 			writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step"));
2000 
2001 			// Send as reliable
2002 			m_clients.send(peer_id, 0, reply, true);
2003 			m_clients.event(peer_id, CSE_Init);
2004 		}
2005 
2006 		return;
2007 	}
2008 
2009 	if(command == TOSERVER_INIT2)
2010 	{
2011 
2012 		verbosestream<<"Server: Got TOSERVER_INIT2 from "
2013 				<<peer_id<<std::endl;
2014 
2015 		m_clients.event(peer_id, CSE_GotInit2);
2016 		u16 protocol_version = m_clients.getProtocolVersion(peer_id);
2017 
2018 
2019 		///// begin compatibility code
2020 		PlayerSAO* playersao = NULL;
2021 		if (protocol_version <= 22) {
2022 			playersao = StageTwoClientInit(peer_id);
2023 
2024 			if (playersao == NULL) {
2025 				errorstream
2026 					<< "TOSERVER_INIT2 stage 2 client init failed for peer "
2027 					<< peer_id << std::endl;
2028 				return;
2029 			}
2030 		}
2031 		///// end compatibility code
2032 
2033 		/*
2034 			Send some initialization data
2035 		*/
2036 
2037 		infostream<<"Server: Sending content to "
2038 				<<getPlayerName(peer_id)<<std::endl;
2039 
2040 		// Send player movement settings
2041 		SendMovement(peer_id);
2042 
2043 		// Send item definitions
2044 		SendItemDef(peer_id, m_itemdef, protocol_version);
2045 
2046 		// Send node definitions
2047 		SendNodeDef(peer_id, m_nodedef, protocol_version);
2048 
2049 		m_clients.event(peer_id, CSE_SetDefinitionsSent);
2050 
2051 		// Send media announcement
2052 		sendMediaAnnouncement(peer_id);
2053 
2054 		// Send detached inventories
2055 		sendDetachedInventories(peer_id);
2056 
2057 		// Send time of day
2058 		u16 time = m_env->getTimeOfDay();
2059 		float time_speed = g_settings->getFloat("time_speed");
2060 		SendTimeOfDay(peer_id, time, time_speed);
2061 
2062 		///// begin compatibility code
2063 		if (protocol_version <= 22) {
2064 			m_clients.event(peer_id, CSE_SetClientReady);
2065 			m_script->on_joinplayer(playersao);
2066 		}
2067 		///// end compatibility code
2068 
2069 		// Warnings about protocol version can be issued here
2070 		if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
2071 		{
2072 			SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S "
2073 					L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!");
2074 		}
2075 
2076 		return;
2077 	}
2078 
2079 	u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
2080 	u16 peer_proto_ver = getClient(peer_id, CS_InitDone)->net_proto_version;
2081 
2082 	if(peer_ser_ver == SER_FMT_VER_INVALID)
2083 	{
2084 		errorstream<<"Server::ProcessData(): Cancelling: Peer"
2085 				" serialization format invalid or not initialized."
2086 				" Skipping incoming command="<<command<<std::endl;
2087 		return;
2088 	}
2089 
2090 	/* Handle commands relate to client startup */
2091 	if(command == TOSERVER_REQUEST_MEDIA) {
2092 		std::string datastring((char*)&data[2], datasize-2);
2093 		std::istringstream is(datastring, std::ios_base::binary);
2094 
2095 		std::list<std::string> tosend;
2096 		u16 numfiles = readU16(is);
2097 
2098 		infostream<<"Sending "<<numfiles<<" files to "
2099 				<<getPlayerName(peer_id)<<std::endl;
2100 		verbosestream<<"TOSERVER_REQUEST_MEDIA: "<<std::endl;
2101 
2102 		for(int i = 0; i < numfiles; i++) {
2103 			std::string name = deSerializeString(is);
2104 			tosend.push_back(name);
2105 			verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
2106 					<<name<<std::endl;
2107 		}
2108 
2109 		sendRequestedMedia(peer_id, tosend);
2110 		return;
2111 	}
2112 	else if(command == TOSERVER_RECEIVED_MEDIA) {
2113 		return;
2114 	}
2115 	else if(command == TOSERVER_CLIENT_READY) {
2116 		// clients <= protocol version 22 did not send ready message,
2117 		// they're already initialized
2118 		if (peer_proto_ver <= 22) {
2119 			infostream << "Client sent message not expected by a "
2120 				<< "client using protocol version <= 22,"
2121 				<< "disconnecing peer_id: " << peer_id << std::endl;
2122 			m_con.DisconnectPeer(peer_id);
2123 			return;
2124 		}
2125 
2126 		PlayerSAO* playersao = StageTwoClientInit(peer_id);
2127 
2128 		if (playersao == NULL) {
2129 			errorstream
2130 				<< "TOSERVER_CLIENT_READY stage 2 client init failed for peer_id: "
2131 				<< peer_id << std::endl;
2132 			m_con.DisconnectPeer(peer_id);
2133 			return;
2134 		}
2135 
2136 		if(datasize < 2+8) {
2137 			errorstream
2138 				<< "TOSERVER_CLIENT_READY client sent inconsistent data, disconnecting peer_id: "
2139 				<< peer_id << std::endl;
2140 			m_con.DisconnectPeer(peer_id);
2141 			return;
2142 		}
2143 
2144 		m_clients.setClientVersion(
2145 				peer_id,
2146 				data[2], data[3], data[4],
2147 				std::string((char*) &data[8],(u16) data[6]));
2148 
2149 		m_clients.event(peer_id, CSE_SetClientReady);
2150 		m_script->on_joinplayer(playersao);
2151 
2152 		stat.add("join", playersao->getPlayer()->getName());
2153 	}
2154 	else if(command == TOSERVER_GOTBLOCKS) // TODO: REMOVE IN NEXT, move wanted_range to new packet
2155 	{
2156 		if(datasize < 2+1)
2157 			return;
2158 
2159 		/*
2160 			[0] u16 command
2161 			[2] u8 count
2162 			[3] v3s16 pos_0
2163 			[3+6] v3s16 pos_1
2164 			[9] wanted range
2165 			...
2166 		*/
2167 
2168 		u16 count = data[2];
2169 		RemoteClient *client = getClient(peer_id);
2170 		for(u16 i=0; i<count; i++)
2171 		{
2172 			if((s16)datasize < 2+1+(i+1)*6)
2173 				throw con::InvalidIncomingDataException
2174 					("GOTBLOCKS length is too short");
2175 			readV3S16(&data[2+1+i*6]);
2176 			/*infostream<<"Server: GOTBLOCKS ("
2177 					<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2178 		}
2179 		if((s16)datasize > 2+1+(count)*6) // only freeminer client
2180 			client->wanted_range = readU16(&data[2+1+(count*6)]);
2181 		return;
2182 	}
2183 
2184 	if (m_clients.getClientState(peer_id) < CS_Active)
2185 	{
2186 		if (command == TOSERVER_PLAYERPOS) return;
2187 
2188 		errorstream<<"Got packet command: " << command << " for peer id "
2189 				<< peer_id << " but client isn't active yet. Dropping packet "
2190 				<<std::endl;
2191 		return;
2192 	}
2193 
2194 	Player *player = m_env->getPlayer(peer_id);
2195 	if(player == NULL) {
2196 /*
2197 		verbosestream<<"Server::ProcessData(): Cancelling: "
2198 				"No player for peer_id="<<peer_id
2199 				<< " disconnecting peer!" <<std::endl;
2200 */
2201 		m_con.DisconnectPeer(peer_id);
2202 		return;
2203 	}
2204 
2205 	PlayerSAO *playersao = player->getPlayerSAO();
2206 	if(playersao == NULL) {
2207 		errorstream<<"Server::ProcessData(): Cancelling: "
2208 				"No player object for peer_id="<<peer_id
2209 				<< " disconnecting peer!" <<std::endl;
2210 		m_con.DisconnectPeer(peer_id);
2211 		return;
2212 	}
2213 
2214 	if(command == TOSERVER_PLAYERPOS)
2215 	{
2216 		if(datasize < 2+12+12+4+4)
2217 			return;
2218 
2219 		u32 start = 0;
2220 		v3s32 ps = readV3S32(&data[start+2]);
2221 		v3s32 ss = readV3S32(&data[start+2+12]);
2222 		f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
2223 		f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
2224 		u32 keyPressed = 0;
2225 		if(datasize >= 2+12+12+4+4+4)
2226 			keyPressed = (u32)readU32(&data[2+12+12+4+4]);
2227 		v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
2228 		v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
2229 		pitch = wrapDegrees(pitch);
2230 		yaw = wrapDegrees(yaw);
2231 
2232 		player->setPosition(position);
2233 		player->setSpeed(speed);
2234 		player->setPitch(pitch);
2235 		player->setYaw(yaw);
2236 		player->keyPressed=keyPressed;
2237 		player->control.up = (bool)(keyPressed&1);
2238 		player->control.down = (bool)(keyPressed&2);
2239 		player->control.left = (bool)(keyPressed&4);
2240 		player->control.right = (bool)(keyPressed&8);
2241 		player->control.jump = (bool)(keyPressed&16);
2242 		player->control.aux1 = (bool)(keyPressed&32);
2243 		player->control.sneak = (bool)(keyPressed&64);
2244 		player->control.LMB = (bool)(keyPressed&128);
2245 		player->control.RMB = (bool)(keyPressed&256);
2246 
2247 		auto old_pos = playersao->m_last_good_position;
2248 		bool cheated = playersao->checkMovementCheat();
2249 		if(cheated){
2250 			// Call callbacks
2251 			m_script->on_cheat(playersao, "moved_too_fast");
2252 		}
2253 		else {
2254 			auto dist = (old_pos/BS).getDistanceFrom(playersao->m_last_good_position/BS);
2255 			if (dist)
2256 				stat.add("move", playersao->getPlayer()->getName(), dist);
2257 		}
2258 
2259 		auto obj = playersao; // copypasted from server step:
2260 		auto uptime = m_uptime.get();
2261 		if (!obj->m_uptime_last)  // not very good place, but minimum modifications
2262 			obj->m_uptime_last = uptime - 0.1;
2263 		obj->step(uptime - obj->m_uptime_last, true); //todo: maybe limit count per time
2264 		obj->m_uptime_last = uptime;
2265 
2266 		/*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
2267 				<<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
2268 				<<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
2269 	}
2270 	else if(command == TOSERVER_DELETEDBLOCKS)
2271 	{
2272 		if(datasize < 2+1)
2273 			return;
2274 
2275 		/*
2276 			[0] u16 command
2277 			[2] u8 count
2278 			[3] v3s16 pos_0
2279 			[3+6] v3s16 pos_1
2280 			...
2281 		*/
2282 
2283 		u16 count = data[2];
2284 		for(u16 i=0; i<count; i++)
2285 		{
2286 			if((s16)datasize < 2+1+(i+1)*6)
2287 				throw con::InvalidIncomingDataException
2288 					("DELETEDBLOCKS length is too short");
2289 			v3s16 p = readV3S16(&data[2+1+i*6]);
2290 			/*infostream<<"Server: DELETEDBLOCKS ("
2291 					<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2292 			RemoteClient *client = getClient(peer_id);
2293 			client->SetBlockDeleted(p);
2294 		}
2295 	}
2296 	else if(command == TOSERVER_CLICK_OBJECT)
2297 	{
2298 		infostream<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
2299 		return;
2300 	}
2301 	else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
2302 	{
2303 		infostream<<"Server: CLICK_ACTIVEOBJECT not supported anymore"<<std::endl;
2304 		return;
2305 	}
2306 	else if(command == TOSERVER_GROUND_ACTION)
2307 	{
2308 		infostream<<"Server: GROUND_ACTION not supported anymore"<<std::endl;
2309 		return;
2310 
2311 	}
2312 	else if(command == TOSERVER_RELEASE)
2313 	{
2314 		infostream<<"Server: RELEASE not supported anymore"<<std::endl;
2315 		return;
2316 	}
2317 	else if(command == TOSERVER_SIGNTEXT)
2318 	{
2319 		infostream<<"Server: SIGNTEXT not supported anymore"
2320 				<<std::endl;
2321 		return;
2322 	}
2323 	else if(command == TOSERVER_SIGNNODETEXT)
2324 	{
2325 		infostream<<"Server: SIGNNODETEXT not supported anymore"
2326 				<<std::endl;
2327 		return;
2328 	}
2329 	else if(command == TOSERVER_INVENTORY_ACTION)
2330 	{
2331 		// Strip command and create a stream
2332 		std::string datastring((char*)&data[2], datasize-2);
2333 		verbosestream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
2334 		std::istringstream is(datastring, std::ios_base::binary);
2335 		// Create an action
2336 		InventoryAction *a = InventoryAction::deSerialize(is);
2337 		if(a == NULL)
2338 		{
2339 			infostream<<"TOSERVER_INVENTORY_ACTION: "
2340 					<<"InventoryAction::deSerialize() returned NULL"
2341 					<<std::endl;
2342 			return;
2343 		}
2344 
2345 		// If something goes wrong, this player is to blame
2346 		RollbackScopeActor rollback_scope(m_rollback,
2347 				std::string("player:")+player->getName());
2348 
2349 		/*
2350 			Note: Always set inventory not sent, to repair cases
2351 			where the client made a bad prediction.
2352 		*/
2353 
2354 		/*
2355 			Handle restrictions and special cases of the move action
2356 		*/
2357 		if(a->getType() == IACTION_MOVE)
2358 		{
2359 			IMoveAction *ma = (IMoveAction*)a;
2360 
2361 			ma->from_inv.applyCurrentPlayer(player->getName());
2362 			ma->to_inv.applyCurrentPlayer(player->getName());
2363 
2364 			setInventoryModified(ma->from_inv);
2365 			setInventoryModified(ma->to_inv);
2366 
2367 			bool from_inv_is_current_player =
2368 				(ma->from_inv.type == InventoryLocation::PLAYER) &&
2369 				(ma->from_inv.name == player->getName());
2370 
2371 			bool to_inv_is_current_player =
2372 				(ma->to_inv.type == InventoryLocation::PLAYER) &&
2373 				(ma->to_inv.name == player->getName());
2374 
2375 			/*
2376 				Disable moving items out of craftpreview
2377 			*/
2378 			if(ma->from_list == "craftpreview")
2379 			{
2380 				infostream<<"Ignoring IMoveAction from "
2381 						<<(ma->from_inv.dump())<<":"<<ma->from_list
2382 						<<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2383 						<<" because src is "<<ma->from_list<<std::endl;
2384 				delete a;
2385 				return;
2386 			}
2387 
2388 			/*
2389 				Disable moving items into craftresult and craftpreview
2390 			*/
2391 			if(ma->to_list == "craftpreview" || ma->to_list == "craftresult")
2392 			{
2393 				infostream<<"Ignoring IMoveAction from "
2394 						<<(ma->from_inv.dump())<<":"<<ma->from_list
2395 						<<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2396 						<<" because dst is "<<ma->to_list<<std::endl;
2397 				delete a;
2398 				return;
2399 			}
2400 
2401 			// Disallow moving items in elsewhere than player's inventory
2402 			// if not allowed to interact
2403 			if(!checkPriv(player->getName(), "interact") &&
2404 					(!from_inv_is_current_player ||
2405 					!to_inv_is_current_player))
2406 			{
2407 				infostream<<"Cannot move outside of player's inventory: "
2408 						<<"No interact privilege"<<std::endl;
2409 				delete a;
2410 				return;
2411 			}
2412 		}
2413 		/*
2414 			Handle restrictions and special cases of the drop action
2415 		*/
2416 		else if(a->getType() == IACTION_DROP)
2417 		{
2418 			IDropAction *da = (IDropAction*)a;
2419 
2420 			da->from_inv.applyCurrentPlayer(player->getName());
2421 
2422 			setInventoryModified(da->from_inv);
2423 
2424 			/*
2425 				Disable dropping items out of craftpreview
2426 			*/
2427 			if(da->from_list == "craftpreview")
2428 			{
2429 				infostream<<"Ignoring IDropAction from "
2430 						<<(da->from_inv.dump())<<":"<<da->from_list
2431 						<<" because src is "<<da->from_list<<std::endl;
2432 				delete a;
2433 				return;
2434 			}
2435 
2436 			// Disallow dropping items if not allowed to interact
2437 			if(!checkPriv(player->getName(), "interact"))
2438 			{
2439 				delete a;
2440 				return;
2441 			}
2442 			stat.add("drop", player->getName());
2443 		}
2444 		/*
2445 			Handle restrictions and special cases of the craft action
2446 		*/
2447 		else if(a->getType() == IACTION_CRAFT)
2448 		{
2449 			ICraftAction *ca = (ICraftAction*)a;
2450 
2451 			ca->craft_inv.applyCurrentPlayer(player->getName());
2452 
2453 			setInventoryModified(ca->craft_inv);
2454 
2455 			//bool craft_inv_is_current_player =
2456 			//	(ca->craft_inv.type == InventoryLocation::PLAYER) &&
2457 			//	(ca->craft_inv.name == player->getName());
2458 
2459 			// Disallow crafting if not allowed to interact
2460 			if(!checkPriv(player->getName(), "interact"))
2461 			{
2462 				infostream<<"Cannot craft: "
2463 						<<"No interact privilege"<<std::endl;
2464 				delete a;
2465 				return;
2466 			}
2467 			stat.add("craft", player->getName());
2468 		}
2469 
2470 		// Do the action
2471 		a->apply(this, playersao, this);
2472 		// Eat the action
2473 		delete a;
2474 	}
2475 	else if(command == TOSERVER_CHAT_MESSAGE)
2476 	{
2477 		/*
2478 			u16 command
2479 			u16 length
2480 			wstring message
2481 		*/
2482 		u8 buf[6];
2483 		std::string datastring((char*)&data[2], datasize-2);
2484 		std::istringstream is(datastring, std::ios_base::binary);
2485 
2486 		// Read stuff
2487 		is.read((char*)buf, 2);
2488 		u16 len = readU16(buf);
2489 
2490 		std::wstring message;
2491 		for(u16 i=0; i<len; i++)
2492 		{
2493 			is.read((char*)buf, 2);
2494 			message += (wchar_t)readU16(buf);
2495 		}
2496 
2497 		// If something goes wrong, this player is to blame
2498 		RollbackScopeActor rollback_scope(m_rollback,
2499 				std::string("player:")+player->getName());
2500 
2501 		// Get player name of this client
2502 		std::wstring name = narrow_to_wide(player->getName());
2503 
2504 		// Run script hook
2505 		bool ate = m_script->on_chat_message(player->getName(),
2506 				wide_to_narrow(message));
2507 		// If script ate the message, don't proceed
2508 		if(ate)
2509 			return;
2510 
2511 		// Line to send to players
2512 		std::wstring line;
2513 		// Whether to send to the player that sent the line
2514 		bool send_to_sender_only = false;
2515 
2516 		// Commands are implemented in Lua, so only catch invalid
2517 		// commands that were not "eaten" and send an error back
2518 		if(message[0] == L'/')
2519 		{
2520 			message = message.substr(1);
2521 			send_to_sender_only = true;
2522 			if(message.length() == 0)
2523 				line += L"-!- Empty command";
2524 			else
2525 				line += L"-!- Invalid command: " + str_split(message, L' ')[0];
2526 		}
2527 		else
2528 		{
2529 			if(checkPriv(player->getName(), "shout")){
2530 				line += L"<";
2531 				line += name;
2532 				line += L"> ";
2533 				line += message;
2534 				stat.add("chat", player->getName());
2535 			} else {
2536 				line += L"-!- You don't have permission to shout.";
2537 				send_to_sender_only = true;
2538 			}
2539 		}
2540 
2541 		if(line != L"")
2542 		{
2543 			/*
2544 				Send the message to sender
2545 			*/
2546 			if (send_to_sender_only)
2547 			{
2548 				SendChatMessage(peer_id, line);
2549 			}
2550 			/*
2551 				Send the message to others
2552 			*/
2553 			else
2554 			{
2555 				actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2556 
2557 				std::list<u16> clients = m_clients.getClientIDs();
2558 
2559 				for(std::list<u16>::iterator
2560 					i = clients.begin();
2561 					i != clients.end(); ++i)
2562 				{
2563 					if (*i != peer_id)
2564 						SendChatMessage(*i, line);
2565 				}
2566 			}
2567 		}
2568 	}
2569 	else if(command == TOSERVER_DAMAGE)
2570 	{
2571 		std::string datastring((char*)&data[2], datasize-2);
2572 		std::istringstream is(datastring, std::ios_base::binary);
2573 		u8 damage = readU8(is);
2574 
2575 		if(g_settings->getBool("enable_damage"))
2576 		{
2577 			actionstream<<player->getName()<<" damaged by "
2578 					<<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2579 					<<std::endl;
2580 
2581 			playersao->setHP(playersao->getHP() - damage);
2582 
2583 			if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
2584 				DiePlayer(peer_id);
2585 
2586 			if(playersao->m_hp_not_sent)
2587 				SendPlayerHP(peer_id);
2588 			stat.add("damage", player->getName(), damage);
2589 		}
2590 	}
2591 	else if(command == TOSERVER_BREATH)
2592 	{
2593 		std::string datastring((char*)&data[2], datasize-2);
2594 		std::istringstream is(datastring, std::ios_base::binary);
2595 		u16 breath = readU16(is);
2596 		playersao->setBreath(breath);
2597 		m_script->player_event(playersao,"breath_changed");
2598 	}
2599 	else if(command == TOSERVER_PASSWORD)
2600 	{
2601 		/*
2602 			[0] u16 TOSERVER_PASSWORD
2603 			[2] u8[28] old password
2604 			[30] u8[28] new password
2605 		*/
2606 
2607 		if(datasize != 2+PASSWORD_SIZE*2)
2608 			return;
2609 		/*char password[PASSWORD_SIZE];
2610 		for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2611 			password[i] = data[2+i];
2612 		password[PASSWORD_SIZE-1] = 0;*/
2613 		std::string oldpwd;
2614 		for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2615 		{
2616 			char c = data[2+i];
2617 			if(c == 0)
2618 				break;
2619 			oldpwd += c;
2620 		}
2621 		std::string newpwd;
2622 		for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2623 		{
2624 			char c = data[2+PASSWORD_SIZE+i];
2625 			if(c == 0)
2626 				break;
2627 			newpwd += c;
2628 		}
2629 
2630 		if(!base64_is_valid(newpwd)){
2631 			infostream<<"Server: "<<player->getName()<<" supplied invalid password hash"<<std::endl;
2632 			// Wrong old password supplied!!
2633 			SendChatMessage(peer_id, L"Invalid new password hash supplied. Password NOT changed.");
2634 			return;
2635 		}
2636 
2637 		infostream<<"Server: Client requests a password change from "
2638 				<<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2639 
2640 		std::string playername = player->getName();
2641 
2642 		std::string checkpwd;
2643 		m_script->getAuth(playername, &checkpwd, NULL);
2644 
2645 		if(oldpwd != checkpwd)
2646 		{
2647 			infostream<<"Server: invalid old password"<<std::endl;
2648 			// Wrong old password supplied!!
2649 			SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2650 			return;
2651 		}
2652 
2653 		bool success = m_script->setPassword(playername, newpwd);
2654 		if(success){
2655 			actionstream<<player->getName()<<" changes password"<<std::endl;
2656 			SendChatMessage(peer_id, L"Password change successful.");
2657 		} else {
2658 			actionstream<<player->getName()<<" tries to change password but "
2659 					<<"it fails"<<std::endl;
2660 			SendChatMessage(peer_id, L"Password change failed or inavailable.");
2661 		}
2662 	}
2663 	else if(command == TOSERVER_PLAYERITEM)
2664 	{
2665 		if (datasize < 2+2)
2666 			return;
2667 
2668 		u16 item = readU16(&data[2]);
2669 		playersao->setWieldIndex(item);
2670 	}
2671 	else if(command == TOSERVER_RESPAWN)
2672 	{
2673 		if(player->hp != 0 || !g_settings->getBool("enable_damage"))
2674 			return;
2675 
2676 		RespawnPlayer(peer_id);
2677 
2678 		actionstream<<player->getName()<<" respawns at "
2679 				<<PP(player->getPosition()/BS)<<std::endl;
2680 
2681 		// ActiveObject is added to environment in AsyncRunStep after
2682 		// the previous addition has been succesfully removed
2683 	}
2684 	else if(command == TOSERVER_INTERACT)
2685 	{
2686 		std::string datastring((char*)&data[2], datasize-2);
2687 		std::istringstream is(datastring, std::ios_base::binary);
2688 
2689 		/*
2690 			[0] u16 command
2691 			[2] u8 action
2692 			[3] u16 item
2693 			[5] u32 length of the next item
2694 			[9] serialized PointedThing
2695 			actions:
2696 			0: start digging (from undersurface) or use
2697 			1: stop digging (all parameters ignored)
2698 			2: digging completed
2699 			3: place block or item (to abovesurface)
2700 			4: use item
2701 		*/
2702 		u8 action = readU8(is);
2703 		u16 item_i = readU16(is);
2704 		std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2705 		PointedThing pointed;
2706 		pointed.deSerialize(tmp_is);
2707 
2708 /*
2709 		verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2710 				<<item_i<<", pointed="<<pointed.dump()<<std::endl;
2711 */
2712 
2713 		if(player->hp == 0)
2714 		{
2715 			verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
2716 				<<" tried to interact, but is dead!"<<std::endl;
2717 			return;
2718 		}
2719 
2720 		v3f player_pos = playersao->getLastGoodPosition();
2721 
2722 		// Update wielded item
2723 		playersao->setWieldIndex(item_i);
2724 
2725 		// Get pointed to node (undefined if not POINTEDTYPE_NODE)
2726 		v3s16 p_under = pointed.node_undersurface;
2727 		v3s16 p_above = pointed.node_abovesurface;
2728 
2729 		// Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2730 		ServerActiveObject *pointed_object = NULL;
2731 		if(pointed.type == POINTEDTHING_OBJECT)
2732 		{
2733 			pointed_object = m_env->getActiveObject(pointed.object_id);
2734 			if(pointed_object == NULL)
2735 			{
2736 				verbosestream<<"TOSERVER_INTERACT: "
2737 					"pointed object is NULL"<<std::endl;
2738 				return;
2739 			}
2740 
2741 		}
2742 
2743 		v3f pointed_pos_under = player_pos;
2744 		v3f pointed_pos_above = player_pos;
2745 		if(pointed.type == POINTEDTHING_NODE)
2746 		{
2747 			pointed_pos_under = intToFloat(p_under, BS);
2748 			pointed_pos_above = intToFloat(p_above, BS);
2749 		}
2750 		else if(pointed.type == POINTEDTHING_OBJECT)
2751 		{
2752 			pointed_pos_under = pointed_object->getBasePosition();
2753 			pointed_pos_above = pointed_pos_under;
2754 		}
2755 
2756 		/*
2757 			Check that target is reasonably close
2758 			(only when digging or placing things)
2759 		*/
2760 		if(action == 0 || action == 2 || action == 3)
2761 		{
2762 			float d = player_pos.getDistanceFrom(pointed_pos_under);
2763 			float max_d = BS * 14; // Just some large enough value
2764 			if(d > max_d){
2765 				actionstream<<"Player "<<player->getName()
2766 						<<" tried to access "<<pointed.dump()
2767 						<<" from too far: "
2768 						<<"d="<<d<<", max_d="<<max_d
2769 						<<". ignoring."<<std::endl;
2770 				// Re-send block to revert change on client-side
2771 				RemoteClient *client = getClient(peer_id);
2772 				v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2773 				client->SetBlockNotSent(blockpos);
2774 				// Call callbacks
2775 				m_script->on_cheat(playersao, "interacted_too_far");
2776 				// Do nothing else
2777 				return;
2778 			}
2779 		}
2780 
2781 		/*
2782 			Make sure the player is allowed to do it
2783 		*/
2784 		if(!checkPriv(player->getName(), "interact"))
2785 		{
2786 			actionstream<<player->getName()<<" attempted to interact with "
2787 					<<pointed.dump()<<" without 'interact' privilege"
2788 					<<std::endl;
2789 			// Re-send block to revert change on client-side
2790 			RemoteClient *client = getClient(peer_id);
2791 			// Digging completed -> under
2792 			if(action == 2){
2793 				v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2794 				client->SetBlockNotSent(blockpos);
2795 			}
2796 			// Placement -> above
2797 			if(action == 3){
2798 				v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2799 				client->SetBlockNotSent(blockpos);
2800 			}
2801 			stat.add("interact_denied", player->getName());
2802 			return;
2803 		}
2804 
2805 		/*
2806 			If something goes wrong, this player is to blame
2807 		*/
2808 		RollbackScopeActor rollback_scope(m_rollback,
2809 				std::string("player:")+player->getName());
2810 
2811 		/*
2812 			0: start digging or punch object
2813 		*/
2814 		if(action == 0)
2815 		{
2816 			if(pointed.type == POINTEDTHING_NODE)
2817 			{
2818 				/*
2819 					NOTE: This can be used in the future to check if
2820 					somebody is cheating, by checking the timing.
2821 				*/
2822 				MapNode n(CONTENT_IGNORE);
2823 				bool pos_ok;
2824 				n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
2825 				if (pos_ok)
2826 					n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
2827 
2828 				if (!pos_ok) {
2829 					infostream<<"Server: Not punching: Node not found."
2830 							<<" Adding block to emerge queue."
2831 							<<std::endl;
2832 					m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2833 				}
2834 
2835 				if(n.getContent() != CONTENT_IGNORE)
2836 					m_script->node_on_punch(p_under, n, playersao, pointed);
2837 				// Cheat prevention
2838 				playersao->noCheatDigStart(p_under);
2839 			}
2840 			else if(pointed.type == POINTEDTHING_OBJECT)
2841 			{
2842 				// Skip if object has been removed
2843 				if(pointed_object->m_removed)
2844 					return;
2845 
2846 				actionstream<<player->getName()<<" punches object "
2847 						<<pointed.object_id<<": "
2848 						<<pointed_object->getDescription()<<std::endl;
2849 
2850 				ItemStack punchitem = playersao->getWieldedItem();
2851 				ToolCapabilities toolcap =
2852 						punchitem.getToolCapabilities(m_itemdef);
2853 				v3f dir = (pointed_object->getBasePosition() -
2854 						(player->getPosition() + player->getEyeOffset())
2855 							).normalize();
2856 				float time_from_last_punch =
2857 					playersao->resetTimeFromLastPunch();
2858 				pointed_object->punch(dir, &toolcap, playersao,
2859 						time_from_last_punch);
2860 				stat.add("punch", player->getName());
2861 			}
2862 
2863 		} // action == 0
2864 
2865 		/*
2866 			1: stop digging
2867 		*/
2868 		else if(action == 1)
2869 		{
2870 		} // action == 1
2871 
2872 		/*
2873 			2: Digging completed
2874 		*/
2875 		else if(action == 2)
2876 		{
2877 			// Only digging of nodes
2878 			if(pointed.type == POINTEDTHING_NODE)
2879 			{
2880 				bool pos_ok;
2881 				MapNode n = m_env->getMap().getNodeNoEx(p_under, &pos_ok);
2882 				if (!pos_ok) {
2883 					infostream << "Server: Not finishing digging: Node not found."
2884 					           << " Adding block to emerge queue."
2885 					           << std::endl;
2886 					m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2887 				}
2888 
2889 				/* Cheat prevention */
2890 				bool is_valid_dig = true;
2891 				if(!isSingleplayer() && !g_settings->getBool("disable_anticheat"))
2892 				{
2893 					v3s16 nocheat_p = playersao->getNoCheatDigPos();
2894 					float nocheat_t = playersao->getNoCheatDigTime();
2895 					playersao->noCheatDigEnd();
2896 					// If player didn't start digging this, ignore dig
2897 					if(nocheat_p != p_under){
2898 						infostream<<"Server: NoCheat: "<<player->getName()
2899 								<<" started digging "
2900 								<<PP(nocheat_p)<<" and completed digging "
2901 								<<PP(p_under)<<"; not digging."<<std::endl;
2902 						is_valid_dig = false;
2903 						// Call callbacks
2904 						m_script->on_cheat(playersao, "finished_unknown_dig");
2905 					}
2906 					// Get player's wielded item
2907 					ItemStack playeritem;
2908 					InventoryList *mlist = playersao->getInventory()->getList("main");
2909 					if(mlist != NULL)
2910 						playeritem = mlist->getItem(playersao->getWieldIndex());
2911 					ToolCapabilities playeritem_toolcap =
2912 							playeritem.getToolCapabilities(m_itemdef);
2913 					// Get diggability and expected digging time
2914 					DigParams params = getDigParams(m_nodedef->get(n).groups,
2915 							&playeritem_toolcap);
2916 					// If can't dig, try hand
2917 					if(!params.diggable){
2918 						const ItemDefinition &hand = m_itemdef->get("");
2919 						const ToolCapabilities *tp = hand.tool_capabilities;
2920 						if(tp)
2921 							params = getDigParams(m_nodedef->get(n).groups, tp);
2922 					}
2923 					// If can't dig, ignore dig
2924 					if(!params.diggable){
2925 						infostream<<"Server: NoCheat: "<<player->getName()
2926 								<<" completed digging "<<PP(p_under)
2927 								<<", which is not diggable with tool. not digging."
2928 								<<std::endl;
2929 						is_valid_dig = false;
2930 						// Call callbacks
2931 						m_script->on_cheat(playersao, "dug_unbreakable");
2932 					}
2933 					// Check digging time
2934 					// If already invalidated, we don't have to
2935 					if(!is_valid_dig){
2936 						// Well not our problem then
2937 					}
2938 					// Clean and long dig
2939 					else if(params.time > 2.0 && nocheat_t * 1.2 > params.time){
2940 						// All is good, but grab time from pool; don't care if
2941 						// it's actually available
2942 						playersao->getDigPool().grab(params.time);
2943 					}
2944 					// Short or laggy dig
2945 					// Try getting the time from pool
2946 					else if(playersao->getDigPool().grab(params.time)){
2947 						// All is good
2948 					}
2949 					// Dig not possible
2950 					else{
2951 						infostream<<"Server: NoCheat: "<<player->getName()
2952 								<<" completed digging "<<PP(p_under)
2953 								<<"too fast; not digging."<<std::endl;
2954 						is_valid_dig = false;
2955 						// Call callbacks
2956 						m_script->on_cheat(playersao, "dug_too_fast");
2957 					}
2958 				}
2959 
2960 				/* Actually dig node */
2961 
2962 				if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
2963 				{
2964 					m_script->node_on_dig(p_under, n, playersao);
2965 					stat.add("dig", player->getName());
2966 					stat.add("dig_"+ m_nodedef->get(n).name , player->getName());
2967 				}
2968 
2969 				v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2970 				RemoteClient *client = getClient(peer_id);
2971 				// Send unusual result (that is, node not being removed)
2972 				if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
2973 				{
2974 					// Re-send block to revert change on client-side
2975 					client->SetBlockNotSent(blockpos);
2976 				}
2977 				else {
2978 					client->ResendBlockIfOnWire(blockpos);
2979 				}
2980 			}
2981 		} // action == 2
2982 
2983 		/*
2984 			3: place block or right-click object
2985 		*/
2986 		else if(action == 3)
2987 		{
2988 			ItemStack item = playersao->getWieldedItem();
2989 
2990 			// Reset build time counter
2991 			if(pointed.type == POINTEDTHING_NODE &&
2992 					item.getDefinition(m_itemdef).type == ITEM_NODE)
2993 				getClient(peer_id)->m_time_from_building = 0.0;
2994 
2995 			if(pointed.type == POINTEDTHING_OBJECT)
2996 			{
2997 				// Right click object
2998 
2999 				// Skip if object has been removed
3000 				if(pointed_object->m_removed)
3001 					return;
3002 
3003 /* android bug - too many
3004 				actionstream<<player->getName()<<" right-clicks object "
3005 						<<pointed.object_id<<": "
3006 						<<pointed_object->getDescription()<<std::endl;
3007 */
3008 
3009 				// Do stuff
3010 				pointed_object->rightClick(playersao);
3011 			}
3012 			else if(m_script->item_OnPlace(
3013 					item, playersao, pointed))
3014 			{
3015 				// Placement was handled in lua
3016 
3017 				// Apply returned ItemStack
3018 				playersao->setWieldedItem(item);
3019 				stat.add("place", player->getName());
3020 				//stat.add("place_" + item.name, player->getName());
3021 			}
3022 
3023 			// If item has node placement prediction, always send the
3024 			// blocks to make sure the client knows what exactly happened
3025 			RemoteClient *client = getClient(peer_id);
3026 			v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
3027 			v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
3028 			if(item.getDefinition(m_itemdef).node_placement_prediction != "") {
3029 				client->SetBlockNotSent(blockpos);
3030 				if(blockpos2 != blockpos) {
3031 					client->SetBlockNotSent(blockpos2);
3032 				}
3033 			}
3034 			else {
3035 				client->ResendBlockIfOnWire(blockpos);
3036 				if(blockpos2 != blockpos) {
3037 					client->ResendBlockIfOnWire(blockpos2);
3038 				}
3039 			}
3040 		} // action == 3
3041 
3042 		/*
3043 			4: use
3044 		*/
3045 		else if(action == 4)
3046 		{
3047 			ItemStack item = playersao->getWieldedItem();
3048 
3049 			actionstream<<player->getName()<<" uses "<<item.name
3050 					<<", pointing at "<<pointed.dump()<<std::endl;
3051 
3052 			if(m_script->item_OnUse(
3053 					item, playersao, pointed))
3054 			{
3055 				// Apply returned ItemStack
3056 				playersao->setWieldedItem(item);
3057 				stat.add("use", player->getName());
3058 				stat.add("use_" + item.name, player->getName());
3059 			}
3060 
3061 		} // action == 4
3062 
3063 
3064 		/*
3065 			Catch invalid actions
3066 		*/
3067 		else
3068 		{
3069 			infostream<<"WARNING: Server: Invalid action "
3070 					<<action<<std::endl;
3071 		}
3072 	}
3073 	else if(command == TOSERVER_REMOVED_SOUNDS)
3074 	{
3075 		std::string datastring((char*)&data[2], datasize-2);
3076 		std::istringstream is(datastring, std::ios_base::binary);
3077 
3078 		int num = readU16(is);
3079 		for(int k=0; k<num; k++){
3080 			s32 id = readS32(is);
3081 			std::map<s32, ServerPlayingSound>::iterator i =
3082 					m_playing_sounds.find(id);
3083 			if(i == m_playing_sounds.end())
3084 				continue;
3085 			ServerPlayingSound &psound = i->second;
3086 			psound.clients.erase(peer_id);
3087 			if(psound.clients.size() == 0)
3088 				m_playing_sounds.erase(i++);
3089 		}
3090 	}
3091 	else if(command == TOSERVER_NODEMETA_FIELDS)
3092 	{
3093 		std::string datastring((char*)&data[2], datasize-2);
3094 		std::istringstream is(datastring, std::ios_base::binary);
3095 
3096 		v3s16 p = readV3S16(is);
3097 		std::string formname = deSerializeString(is);
3098 		int num = readU16(is);
3099 		std::map<std::string, std::string> fields;
3100 		for(int k=0; k<num; k++){
3101 			std::string fieldname = deSerializeString(is);
3102 			std::string fieldvalue = deSerializeLongString(is);
3103 			fields[fieldname] = fieldvalue;
3104 		}
3105 
3106 		// If something goes wrong, this player is to blame
3107 		RollbackScopeActor rollback_scope(m_rollback,
3108 				std::string("player:")+player->getName());
3109 
3110 		// Check the target node for rollback data; leave others unnoticed
3111 		RollbackNode rn_old(&m_env->getMap(), p, this);
3112 
3113 		m_script->node_on_receive_fields(p, formname, fields,playersao);
3114 
3115 		// Report rollback data
3116 		RollbackNode rn_new(&m_env->getMap(), p, this);
3117 		if(rollback() && rn_new != rn_old){
3118 			RollbackAction action;
3119 			action.setSetNode(p, rn_old, rn_new);
3120 			rollback()->reportAction(action);
3121 		}
3122 	}
3123 	else if(command == TOSERVER_INVENTORY_FIELDS)
3124 	{
3125 		std::string datastring((char*)&data[2], datasize-2);
3126 		std::istringstream is(datastring, std::ios_base::binary);
3127 
3128 		std::string formname = deSerializeString(is);
3129 		int num = readU16(is);
3130 		std::map<std::string, std::string> fields;
3131 		for(int k=0; k<num; k++){
3132 			std::string fieldname = deSerializeString(is);
3133 			std::string fieldvalue = deSerializeLongString(is);
3134 			fields[fieldname] = fieldvalue;
3135 		}
3136 
3137 		m_script->on_playerReceiveFields(playersao, formname, fields);
3138 	}
3139 	else
3140 	{
3141 		infostream<<"Server::ProcessData(): Ignoring "
3142 				"unknown command "<<command<<std::endl;
3143 	}
3144 
3145 	} //try
3146 	catch(SendFailedException &e)
3147 	{
3148 		errorstream<<"Server::ProcessData(): SendFailedException: "
3149 				<<"what="<<e.what()
3150 				<<std::endl;
3151 	}
3152 }
3153 
setTimeOfDay(u32 time)3154 void Server::setTimeOfDay(u32 time)
3155 {
3156 	m_env->setTimeOfDay(time);
3157 	m_time_of_day_send_timer = 0;
3158 }
3159 
onMapEditEvent(MapEditEvent * event)3160 void Server::onMapEditEvent(MapEditEvent *event)
3161 {
3162 	//infostream<<"Server::onMapEditEvent()"<<std::endl;
3163 	if(m_ignore_map_edit_events)
3164 		return;
3165 	if(m_ignore_map_edit_events_area.contains(event->getArea()))
3166 		return;
3167 	MapEditEvent *e = event->clone();
3168 	m_unsent_map_edit_queue.push_back(e);
3169 }
3170 
getInventory(const InventoryLocation & loc)3171 Inventory* Server::getInventory(const InventoryLocation &loc)
3172 {
3173 	switch(loc.type){
3174 	case InventoryLocation::UNDEFINED:
3175 	{}
3176 	break;
3177 	case InventoryLocation::CURRENT_PLAYER:
3178 	{}
3179 	break;
3180 	case InventoryLocation::PLAYER:
3181 	{
3182 		Player *player = m_env->getPlayer(loc.name.c_str());
3183 		if(!player)
3184 			return NULL;
3185 		PlayerSAO *playersao = player->getPlayerSAO();
3186 		if(!playersao)
3187 			return NULL;
3188 		return playersao->getInventory();
3189 	}
3190 	break;
3191 	case InventoryLocation::NODEMETA:
3192 	{
3193 		NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3194 		if(!meta)
3195 			return NULL;
3196 		return meta->getInventory();
3197 	}
3198 	break;
3199 	case InventoryLocation::DETACHED:
3200 	{
3201 		if(m_detached_inventories.count(loc.name) == 0)
3202 			return NULL;
3203 		return m_detached_inventories[loc.name];
3204 	}
3205 	break;
3206 	default:
3207 		assert(0);
3208 	}
3209 	return NULL;
3210 }
setInventoryModified(const InventoryLocation & loc)3211 void Server::setInventoryModified(const InventoryLocation &loc)
3212 {
3213 	switch(loc.type){
3214 	case InventoryLocation::UNDEFINED:
3215 	{}
3216 	break;
3217 	case InventoryLocation::PLAYER:
3218 	{
3219 		Player *player = m_env->getPlayer(loc.name.c_str());
3220 		if(!player)
3221 			return;
3222 		PlayerSAO *playersao = player->getPlayerSAO();
3223 		if(!playersao)
3224 			return;
3225 		playersao->m_inventory_not_sent = true;
3226 		playersao->m_wielded_item_not_sent = true;
3227 	}
3228 	break;
3229 	case InventoryLocation::NODEMETA:
3230 	{
3231 		v3s16 blockpos = getNodeBlockPos(loc.p);
3232 
3233 		MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3234 		if(block)
3235 			block->raiseModified(MOD_STATE_WRITE_NEEDED, "inventoryModified");
3236 
3237 		setBlockNotSent(blockpos);
3238 	}
3239 	break;
3240 	case InventoryLocation::DETACHED:
3241 	{
3242 		sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
3243 	}
3244 	break;
3245 	default:
3246 		assert(0);
3247 	}
3248 }
3249 
SetBlocksNotSent(std::map<v3s16,MapBlock * > & block)3250 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
3251 {
3252 	std::list<u16> clients = m_clients.getClientIDs();
3253 	// Set the modified blocks unsent for all the clients
3254 	for (std::list<u16>::iterator
3255 		 i = clients.begin();
3256 		 i != clients.end(); ++i) {
3257 			RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
3258 			if (client != NULL)
3259 				client->SetBlocksNotSent(block);
3260 		}
3261 }
3262 
peerAdded(con::Peer * peer)3263 void Server::peerAdded(con::Peer *peer)
3264 {
3265 	DSTACK(__FUNCTION_NAME);
3266 	verbosestream<<"Server::peerAdded(): peer->id="
3267 			<<peer->id<<std::endl;
3268 
3269 	con::PeerChange c;
3270 	c.type = con::PEER_ADDED;
3271 	c.peer_id = peer->id;
3272 	c.timeout = false;
3273 	m_peer_change_queue.push_back(c);
3274 }
3275 
deletingPeer(con::Peer * peer,bool timeout)3276 void Server::deletingPeer(con::Peer *peer, bool timeout)
3277 {
3278 	DSTACK(__FUNCTION_NAME);
3279 	verbosestream<<"Server::deletingPeer(): peer->id="
3280 			<<peer->id<<", timeout="<<timeout<<std::endl;
3281 
3282 	m_clients.event(peer->id, CSE_Disconnect);
3283 	con::PeerChange c;
3284 	c.type = con::PEER_REMOVED;
3285 	c.peer_id = peer->id;
3286 	c.timeout = timeout;
3287 	m_peer_change_queue.push_back(c);
3288 }
3289 
getClientConInfo(u16 peer_id,con::rtt_stat_type type,float * retval)3290 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
3291 {
3292 	*retval = m_con.getPeerStat(peer_id,type);
3293 	if (*retval == -1) return false;
3294 	return true;
3295 }
3296 
getClientInfo(u16 peer_id,ClientState * state,u32 * uptime,u8 * ser_vers,u16 * prot_vers,u8 * major,u8 * minor,u8 * patch,std::string * vers_string)3297 bool Server::getClientInfo(
3298 		u16          peer_id,
3299 		ClientState* state,
3300 		u32*         uptime,
3301 		u8*          ser_vers,
3302 		u16*         prot_vers,
3303 		u8*          major,
3304 		u8*          minor,
3305 		u8*          patch,
3306 		std::string* vers_string
3307 	)
3308 {
3309 	*state = m_clients.getClientState(peer_id);
3310 	RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
3311 
3312 	if (client == NULL) {
3313 		return false;
3314 	}
3315 
3316 	*uptime = client->uptime();
3317 	*ser_vers = client->serialization_version;
3318 	*prot_vers = client->net_proto_version;
3319 
3320 	*major = client->getMajor();
3321 	*minor = client->getMinor();
3322 	*patch = client->getPatch();
3323 	*vers_string = client->getPatch();
3324 
3325 	return true;
3326 }
3327 
handlePeerChanges()3328 void Server::handlePeerChanges()
3329 {
3330 	while(m_peer_change_queue.size() > 0)
3331 	{
3332 		con::PeerChange c = m_peer_change_queue.pop_front();
3333 
3334 		verbosestream<<"Server: Handling peer change: "
3335 				<<"id="<<c.peer_id<<", timeout="<<c.timeout
3336 				<<std::endl;
3337 
3338 		switch(c.type)
3339 		{
3340 		case con::PEER_ADDED:
3341 			m_clients.CreateClient(c.peer_id);
3342 			break;
3343 
3344 		case con::PEER_REMOVED:
3345 			DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
3346 			break;
3347 
3348 		default:
3349 			assert("Invalid peer change event received!" == 0);
3350 			break;
3351 		}
3352 	}
3353 }
3354 
SendMovement(u16 peer_id)3355 void Server::SendMovement(u16 peer_id)
3356 {
3357 	DSTACK(__FUNCTION_NAME);
3358 	std::ostringstream os(std::ios_base::binary);
3359 
3360 	writeU16(os, TOCLIENT_MOVEMENT);
3361 	writeF1000(os, g_settings->getFloat("movement_acceleration_default"));
3362 	writeF1000(os, g_settings->getFloat("movement_acceleration_air"));
3363 	writeF1000(os, g_settings->getFloat("movement_acceleration_fast"));
3364 	writeF1000(os, g_settings->getFloat("movement_speed_walk"));
3365 	writeF1000(os, g_settings->getFloat("movement_speed_crouch"));
3366 	writeF1000(os, g_settings->getFloat("movement_speed_fast"));
3367 	writeF1000(os, g_settings->getFloat("movement_speed_climb"));
3368 	writeF1000(os, g_settings->getFloat("movement_speed_jump"));
3369 	writeF1000(os, g_settings->getFloat("movement_liquid_fluidity"));
3370 	writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth"));
3371 	writeF1000(os, g_settings->getFloat("movement_liquid_sink"));
3372 	writeF1000(os, g_settings->getFloat("movement_gravity"));
3373 
3374 	// Make data buffer
3375 	std::string s = os.str();
3376 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3377 	// Send as reliable
3378 	m_clients.send(peer_id, 0, data, true);
3379 }
3380 
SendHP(u16 peer_id,u8 hp)3381 void Server::SendHP(u16 peer_id, u8 hp)
3382 {
3383 	DSTACK(__FUNCTION_NAME);
3384 	std::ostringstream os(std::ios_base::binary);
3385 
3386 	writeU16(os, TOCLIENT_HP);
3387 	writeU8(os, hp);
3388 
3389 	// Make data buffer
3390 	std::string s = os.str();
3391 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3392 	// Send as reliable
3393 	m_clients.send(peer_id, 0, data, true);
3394 }
3395 
SendBreath(u16 peer_id,u16 breath)3396 void Server::SendBreath(u16 peer_id, u16 breath)
3397 {
3398 	DSTACK(__FUNCTION_NAME);
3399 	std::ostringstream os(std::ios_base::binary);
3400 
3401 	writeU16(os, TOCLIENT_BREATH);
3402 	writeU16(os, breath);
3403 
3404 	// Make data buffer
3405 	std::string s = os.str();
3406 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3407 	// Send as reliable
3408 	m_clients.send(peer_id, 0, data, true);
3409 }
3410 
SendAccessDenied(u16 peer_id,const std::wstring & reason)3411 void Server::SendAccessDenied(u16 peer_id,const std::wstring &reason)
3412 {
3413 	DSTACK(__FUNCTION_NAME);
3414 	std::ostringstream os(std::ios_base::binary);
3415 
3416 	writeU16(os, TOCLIENT_ACCESS_DENIED);
3417 	os<<serializeWideString(reason);
3418 
3419 	// Make data buffer
3420 	std::string s = os.str();
3421 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3422 	// Send as reliable
3423 	m_clients.send(peer_id, 0, data, true);
3424 }
3425 
SendDeathscreen(u16 peer_id,bool set_camera_point_target,v3f camera_point_target)3426 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
3427 		v3f camera_point_target)
3428 {
3429 	DSTACK(__FUNCTION_NAME);
3430 	std::ostringstream os(std::ios_base::binary);
3431 
3432 	writeU16(os, TOCLIENT_DEATHSCREEN);
3433 	writeU8(os, set_camera_point_target);
3434 	writeV3F1000(os, camera_point_target);
3435 
3436 	// Make data buffer
3437 	std::string s = os.str();
3438 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3439 	// Send as reliable
3440 	m_clients.send(peer_id, 0, data, true);
3441 }
3442 
SendItemDef(u16 peer_id,IItemDefManager * itemdef,u16 protocol_version)3443 void Server::SendItemDef(u16 peer_id,
3444 		IItemDefManager *itemdef, u16 protocol_version)
3445 {
3446 	DSTACK(__FUNCTION_NAME);
3447 	std::ostringstream os(std::ios_base::binary);
3448 
3449 	/*
3450 		u16 command
3451 		u32 length of the next item
3452 		zlib-compressed serialized ItemDefManager
3453 	*/
3454 	writeU16(os, TOCLIENT_ITEMDEF);
3455 	std::ostringstream tmp_os(std::ios::binary);
3456 	itemdef->serialize(tmp_os, protocol_version);
3457 	std::ostringstream tmp_os2(std::ios::binary);
3458 	compressZlib(tmp_os.str(), tmp_os2);
3459 	os<<serializeLongString(tmp_os2.str());
3460 
3461 	// Make data buffer
3462 	std::string s = os.str();
3463 	verbosestream<<"Server: Sending item definitions to id("<<peer_id
3464 			<<"): size="<<s.size()<<std::endl;
3465 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3466 	// Send as reliable
3467 	m_clients.send(peer_id, 0, data, true);
3468 }
3469 
SendNodeDef(u16 peer_id,INodeDefManager * nodedef,u16 protocol_version)3470 void Server::SendNodeDef(u16 peer_id,
3471 		INodeDefManager *nodedef, u16 protocol_version)
3472 {
3473 	DSTACK(__FUNCTION_NAME);
3474 	std::ostringstream os(std::ios_base::binary);
3475 
3476 	/*
3477 		u16 command
3478 		u32 length of the next item
3479 		zlib-compressed serialized NodeDefManager
3480 	*/
3481 	writeU16(os, TOCLIENT_NODEDEF);
3482 	std::ostringstream tmp_os(std::ios::binary);
3483 	nodedef->serialize(tmp_os, protocol_version);
3484 	std::ostringstream tmp_os2(std::ios::binary);
3485 	compressZlib(tmp_os.str(), tmp_os2);
3486 	os<<serializeLongString(tmp_os2.str());
3487 
3488 	// Make data buffer
3489 	std::string s = os.str();
3490 	verbosestream<<"Server: Sending node definitions to id("<<peer_id
3491 			<<"): size="<<s.size()<<std::endl;
3492 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3493 	// Send as reliable
3494 	m_clients.send(peer_id, 0, data, true);
3495 }
3496 
3497 /*
3498 	Non-static send methods
3499 */
3500 
SendInventory(u16 peer_id)3501 void Server::SendInventory(u16 peer_id)
3502 {
3503 	DSTACK(__FUNCTION_NAME);
3504 
3505 	PlayerSAO *playersao = getPlayerSAO(peer_id);
3506 	assert(playersao);
3507 
3508 	playersao->m_inventory_not_sent = false;
3509 
3510 	/*
3511 		Serialize it
3512 	*/
3513 
3514 	std::ostringstream os;
3515 	playersao->getInventory()->serialize(os);
3516 
3517 	std::string s = os.str();
3518 
3519 	SharedBuffer<u8> data(s.size()+2);
3520 	writeU16(&data[0], TOCLIENT_INVENTORY);
3521 	memcpy(&data[2], s.c_str(), s.size());
3522 
3523 	// Send as reliable
3524 	m_clients.send(peer_id, 0, data, true);
3525 }
3526 
SendChatMessage(u16 peer_id,const std::wstring & message)3527 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3528 {
3529 	DSTACK(__FUNCTION_NAME);
3530 
3531 	std::ostringstream os(std::ios_base::binary);
3532 	u8 buf[12];
3533 
3534 	// Write command
3535 	writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3536 	os.write((char*)buf, 2);
3537 
3538 	// Write length
3539 	writeU16(buf, message.size());
3540 	os.write((char*)buf, 2);
3541 
3542 	// Write string
3543 	for(u32 i=0; i<message.size(); i++)
3544 	{
3545 		u16 w = message[i];
3546 		writeU16(buf, w);
3547 		os.write((char*)buf, 2);
3548 	}
3549 
3550 	// Make data buffer
3551 	std::string s = os.str();
3552 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3553 
3554 	if (peer_id != PEER_ID_INEXISTENT)
3555 	{
3556 		// Send as reliable
3557 		m_clients.send(peer_id, 0, data, true);
3558 	}
3559 	else
3560 	{
3561 		m_clients.sendToAll(0,data,true);
3562 	}
3563 }
3564 
SendShowFormspecMessage(u16 peer_id,const std::string & formspec,const std::string & formname)3565 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
3566                                      const std::string &formname)
3567 {
3568 	DSTACK(__FUNCTION_NAME);
3569 
3570 	std::ostringstream os(std::ios_base::binary);
3571 	u8 buf[12];
3572 
3573 
3574 	// Write command
3575 	writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3576 	os.write((char*)buf, 2);
3577 	os<<serializeLongString(FORMSPEC_VERSION_STRING + formspec);
3578 	os<<serializeString(formname);
3579 
3580 	// Make data buffer
3581 	std::string s = os.str();
3582 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3583 	// Send as reliable
3584 	m_clients.send(peer_id, 0, data, true);
3585 }
3586 
3587 // Spawns a particle on peer with peer_id
SendSpawnParticle(u16 peer_id,v3f pos,v3f velocity,v3f acceleration,float expirationtime,float size,bool collisiondetection,bool vertical,std::string texture)3588 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
3589 				float expirationtime, float size, bool collisiondetection,
3590 				bool vertical, std::string texture)
3591 {
3592 	DSTACK(__FUNCTION_NAME);
3593 
3594 	std::ostringstream os(std::ios_base::binary);
3595 	writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3596 	writeV3F1000(os, pos);
3597 	writeV3F1000(os, velocity);
3598 	writeV3F1000(os, acceleration);
3599 	writeF1000(os, expirationtime);
3600 	writeF1000(os, size);
3601 	writeU8(os,  collisiondetection);
3602 	os<<serializeLongString(texture);
3603 	writeU8(os, vertical);
3604 
3605 	// Make data buffer
3606 	std::string s = os.str();
3607 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3608 
3609 	if (peer_id != PEER_ID_INEXISTENT)
3610 	{
3611 	// Send as reliable
3612 		m_clients.send(peer_id, 0, data, true);
3613 	}
3614 	else
3615 	{
3616 		m_clients.sendToAll(0,data,true);
3617 	}
3618 }
3619 
3620 // Adds a ParticleSpawner on peer with peer_id
SendAddParticleSpawner(u16 peer_id,u16 amount,float spawntime,v3f minpos,v3f maxpos,v3f minvel,v3f maxvel,v3f minacc,v3f maxacc,float minexptime,float maxexptime,float minsize,float maxsize,bool collisiondetection,bool vertical,std::string texture,u32 id)3621 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3622 	v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3623 	float minsize, float maxsize, bool collisiondetection, bool vertical, std::string texture, u32 id)
3624 {
3625 	DSTACK(__FUNCTION_NAME);
3626 
3627 	std::ostringstream os(std::ios_base::binary);
3628 	writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3629 
3630 	writeU16(os, amount);
3631 	writeF1000(os, spawntime);
3632 	writeV3F1000(os, minpos);
3633 	writeV3F1000(os, maxpos);
3634 	writeV3F1000(os, minvel);
3635 	writeV3F1000(os, maxvel);
3636 	writeV3F1000(os, minacc);
3637 	writeV3F1000(os, maxacc);
3638 	writeF1000(os, minexptime);
3639 	writeF1000(os, maxexptime);
3640 	writeF1000(os, minsize);
3641 	writeF1000(os, maxsize);
3642 	writeU8(os,  collisiondetection);
3643 	os<<serializeLongString(texture);
3644 	writeU32(os, id);
3645 	writeU8(os, vertical);
3646 
3647 	// Make data buffer
3648 	std::string s = os.str();
3649 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3650 
3651 	if (peer_id != PEER_ID_INEXISTENT)
3652 	{
3653 		// Send as reliable
3654 		m_clients.send(peer_id, 0, data, true);
3655 	}
3656 	else {
3657 		m_clients.sendToAll(0,data,true);
3658 	}
3659 }
3660 
SendDeleteParticleSpawner(u16 peer_id,u32 id)3661 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3662 {
3663 	DSTACK(__FUNCTION_NAME);
3664 
3665 	std::ostringstream os(std::ios_base::binary);
3666 	writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3667 
3668 	writeU16(os, id);
3669 
3670 	// Make data buffer
3671 	std::string s = os.str();
3672 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3673 
3674 	if (peer_id != PEER_ID_INEXISTENT) {
3675 		// Send as reliable
3676 		m_clients.send(peer_id, 0, data, true);
3677 	}
3678 	else {
3679 		m_clients.sendToAll(0,data,true);
3680 	}
3681 
3682 }
3683 
SendHUDAdd(u16 peer_id,u32 id,HudElement * form)3684 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
3685 {
3686 	std::ostringstream os(std::ios_base::binary);
3687 
3688 	// Write command
3689 	writeU16(os, TOCLIENT_HUDADD);
3690 	writeU32(os, id);
3691 	writeU8(os, (u8)form->type);
3692 	writeV2F1000(os, form->pos);
3693 	os << serializeString(form->name);
3694 	writeV2F1000(os, form->scale);
3695 	os << serializeString(form->text);
3696 	writeU32(os, form->number);
3697 	writeU32(os, form->item);
3698 	writeU32(os, form->dir);
3699 	writeV2F1000(os, form->align);
3700 	writeV2F1000(os, form->offset);
3701 	writeV3F1000(os, form->world_pos);
3702 	writeV2S32(os,form->size);
3703 
3704 	// Make data buffer
3705 	std::string s = os.str();
3706 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3707 	// Send as reliable
3708 	m_clients.send(peer_id, 1, data, true);
3709 }
3710 
SendHUDRemove(u16 peer_id,u32 id)3711 void Server::SendHUDRemove(u16 peer_id, u32 id)
3712 {
3713 	std::ostringstream os(std::ios_base::binary);
3714 
3715 	// Write command
3716 	writeU16(os, TOCLIENT_HUDRM);
3717 	writeU32(os, id);
3718 
3719 	// Make data buffer
3720 	std::string s = os.str();
3721 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3722 	// Send as reliable
3723 
3724 	m_clients.send(peer_id, 1, data, true);
3725 }
3726 
SendHUDChange(u16 peer_id,u32 id,HudElementStat stat,void * value)3727 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
3728 {
3729 	std::ostringstream os(std::ios_base::binary);
3730 
3731 	// Write command
3732 	writeU16(os, TOCLIENT_HUDCHANGE);
3733 	writeU32(os, id);
3734 	writeU8(os, (u8)stat);
3735 	switch (stat) {
3736 		case HUD_STAT_POS:
3737 		case HUD_STAT_SCALE:
3738 		case HUD_STAT_ALIGN:
3739 		case HUD_STAT_OFFSET:
3740 			writeV2F1000(os, *(v2f *)value);
3741 			break;
3742 		case HUD_STAT_NAME:
3743 		case HUD_STAT_TEXT:
3744 			os << serializeString(*(std::string *)value);
3745 			break;
3746 		case HUD_STAT_WORLD_POS:
3747 			writeV3F1000(os, *(v3f *)value);
3748 			break;
3749 		case HUD_STAT_SIZE:
3750 			writeV2S32(os,*(v2s32 *)value);
3751 			break;
3752 		case HUD_STAT_NUMBER:
3753 		case HUD_STAT_ITEM:
3754 		case HUD_STAT_DIR:
3755 		default:
3756 			writeU32(os, *(u32 *)value);
3757 			break;
3758 	}
3759 
3760 	// Make data buffer
3761 	std::string s = os.str();
3762 	SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3763 	// Send as reliable
3764 	m_clients.send(peer_id, 0, data, true);
3765 }
3766 
SendHUDSetFlags(u16 peer_id,u32 flags,u32 mask)3767 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
3768 {
3769 	std::ostringstream os(std::ios_base::binary);
3770 
3771 	// Write command
3772 	writeU16(os, TOCLIENT_HUD_SET_FLAGS);
3773 
3774 	//////////////////////////// compatibility code to be removed //////////////
3775 	flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
3776 	////////////////////////////////////////////////////////////////////////////
3777 	writeU32(os, flags);
3778 	writeU32(os, mask);
3779 
3780 	// Make data buffer
3781 	std::string s = os.str();
3782 	SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3783 	// Send as reliable
3784 	m_clients.send(peer_id, 0, data, true);
3785 }
3786 
SendHUDSetParam(u16 peer_id,u16 param,const std::string & value)3787 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
3788 {
3789 	std::ostringstream os(std::ios_base::binary);
3790 
3791 	// Write command
3792 	writeU16(os, TOCLIENT_HUD_SET_PARAM);
3793 	writeU16(os, param);
3794 	os<<serializeString(value);
3795 
3796 	// Make data buffer
3797 	std::string s = os.str();
3798 	SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3799 	// Send as reliable
3800 	m_clients.send(peer_id, 0, data, true);
3801 }
3802 
SendSetSky(u16 peer_id,const video::SColor & bgcolor,const std::string & type,const std::vector<std::string> & params)3803 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
3804 		const std::string &type, const std::vector<std::string> &params)
3805 {
3806 	std::ostringstream os(std::ios_base::binary);
3807 
3808 	// Write command
3809 	writeU16(os, TOCLIENT_SET_SKY);
3810 	writeARGB8(os, bgcolor);
3811 	os<<serializeString(type);
3812 	writeU16(os, params.size());
3813 	for(size_t i=0; i<params.size(); i++)
3814 		os<<serializeString(params[i]);
3815 
3816 	// Make data buffer
3817 	std::string s = os.str();
3818 	SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3819 	// Send as reliable
3820 	m_clients.send(peer_id, 0, data, true);
3821 }
3822 
SendOverrideDayNightRatio(u16 peer_id,bool do_override,float ratio)3823 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
3824 		float ratio)
3825 {
3826 	std::ostringstream os(std::ios_base::binary);
3827 
3828 	// Write command
3829 	writeU16(os, TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO);
3830 	writeU8(os, do_override);
3831 	writeU16(os, ratio*65535);
3832 
3833 	// Make data buffer
3834 	std::string s = os.str();
3835 	SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3836 	// Send as reliable
3837 	m_clients.send(peer_id, 0, data, true);
3838 }
3839 
SendTimeOfDay(u16 peer_id,u16 time,f32 time_speed)3840 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
3841 {
3842 	DSTACK(__FUNCTION_NAME);
3843 
3844 	// Make packet
3845 	SharedBuffer<u8> data(2+2+4);
3846 	writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
3847 	writeU16(&data[2], time);
3848 	writeF1000(&data[4], time_speed);
3849 
3850 	if (peer_id == PEER_ID_INEXISTENT) {
3851 		m_clients.sendToAll(0,data,true);
3852 	}
3853 	else {
3854 		// Send as reliable
3855 		m_clients.send(peer_id, 0, data, true);
3856 	}
3857 }
3858 
SendPlayerHP(u16 peer_id)3859 void Server::SendPlayerHP(u16 peer_id)
3860 {
3861 	DSTACK(__FUNCTION_NAME);
3862 	PlayerSAO *playersao = getPlayerSAO(peer_id);
3863 	assert(playersao);
3864 	playersao->m_hp_not_sent = false;
3865 	SendHP(peer_id, playersao->getHP());
3866 	m_script->player_event(playersao,"health_changed");
3867 
3868 	// Send to other clients
3869 	std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
3870 	ActiveObjectMessage aom(playersao->getId(), true, str);
3871 	playersao->m_messages_out.push_back(aom);
3872 }
3873 
SendPlayerBreath(u16 peer_id)3874 void Server::SendPlayerBreath(u16 peer_id)
3875 {
3876 	DSTACK(__FUNCTION_NAME);
3877 	PlayerSAO *playersao = getPlayerSAO(peer_id);
3878 	assert(playersao);
3879 	playersao->m_breath_not_sent = false;
3880 	m_script->player_event(playersao,"breath_changed");
3881 	SendBreath(peer_id, playersao->getBreath());
3882 }
3883 
SendMovePlayer(u16 peer_id)3884 void Server::SendMovePlayer(u16 peer_id)
3885 {
3886 	DSTACK(__FUNCTION_NAME);
3887 	Player *player = m_env->getPlayer(peer_id);
3888 	assert(player);
3889 
3890 	std::ostringstream os(std::ios_base::binary);
3891 	writeU16(os, TOCLIENT_MOVE_PLAYER);
3892 	writeV3F1000(os, player->getPosition());
3893 	writeF1000(os, player->getPitch());
3894 	writeF1000(os, player->getYaw());
3895 
3896 	{
3897 		v3f pos = player->getPosition();
3898 		f32 pitch = player->getPitch();
3899 		f32 yaw = player->getYaw();
3900 		verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3901 				<<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3902 				<<" pitch="<<pitch
3903 				<<" yaw="<<yaw
3904 				<<std::endl;
3905 	}
3906 
3907 	// Make data buffer
3908 	std::string s = os.str();
3909 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3910 	// Send as reliable
3911 	m_clients.send(peer_id, 0, data, true);
3912 }
3913 
SendLocalPlayerAnimations(u16 peer_id,v2s32 animation_frames[4],f32 animation_speed)3914 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
3915 {
3916 	std::ostringstream os(std::ios_base::binary);
3917 
3918 	writeU16(os, TOCLIENT_LOCAL_PLAYER_ANIMATIONS);
3919 	writeV2S32(os, animation_frames[0]);
3920 	writeV2S32(os, animation_frames[1]);
3921 	writeV2S32(os, animation_frames[2]);
3922 	writeV2S32(os, animation_frames[3]);
3923 	writeF1000(os, animation_speed);
3924 
3925 	// Make data buffer
3926 	std::string s = os.str();
3927 	SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3928 	// Send as reliable
3929 	m_clients.send(peer_id, 0, data, true);
3930 }
3931 
SendEyeOffset(u16 peer_id,v3f first,v3f third)3932 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
3933 {
3934 	std::ostringstream os(std::ios_base::binary);
3935 
3936 	writeU16(os, TOCLIENT_EYE_OFFSET);
3937 	writeV3F1000(os, first);
3938 	writeV3F1000(os, third);
3939 
3940 	// Make data buffer
3941 	std::string s = os.str();
3942 	SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3943 	// Send as reliable
3944 	m_clients.send(peer_id, 0, data, true);
3945 }
SendPlayerPrivileges(u16 peer_id)3946 void Server::SendPlayerPrivileges(u16 peer_id)
3947 {
3948 	Player *player = m_env->getPlayer(peer_id);
3949 	assert(player);
3950 	if(player->peer_id == PEER_ID_INEXISTENT)
3951 		return;
3952 
3953 	std::set<std::string> privs;
3954 	m_script->getAuth(player->getName(), NULL, &privs);
3955 
3956 	std::ostringstream os(std::ios_base::binary);
3957 	writeU16(os, TOCLIENT_PRIVILEGES);
3958 	writeU16(os, privs.size());
3959 	for(std::set<std::string>::const_iterator i = privs.begin();
3960 			i != privs.end(); i++){
3961 		os<<serializeString(*i);
3962 	}
3963 
3964 	// Make data buffer
3965 	std::string s = os.str();
3966 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3967 	// Send as reliable
3968 	m_clients.send(peer_id, 0, data, true);
3969 }
3970 
SendPlayerInventoryFormspec(u16 peer_id)3971 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3972 {
3973 	Player *player = m_env->getPlayer(peer_id);
3974 	assert(player);
3975 	if(player->peer_id == PEER_ID_INEXISTENT)
3976 		return;
3977 
3978 	std::ostringstream os(std::ios_base::binary);
3979 	writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3980 	os<<serializeLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
3981 
3982 	// Make data buffer
3983 	std::string s = os.str();
3984 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3985 	// Send as reliable
3986 	m_clients.send(peer_id, 0, data, true);
3987 }
3988 
playSound(const SimpleSoundSpec & spec,const ServerSoundParams & params)3989 s32 Server::playSound(const SimpleSoundSpec &spec,
3990 		const ServerSoundParams &params)
3991 {
3992 	// Find out initial position of sound
3993 	bool pos_exists = false;
3994 	v3f pos = params.getPos(m_env, &pos_exists);
3995 	// If position is not found while it should be, cancel sound
3996 	if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3997 		return -1;
3998 
3999 	// Filter destination clients
4000 	std::list<u16> dst_clients;
4001 	if(params.to_player != "")
4002 	{
4003 		Player *player = m_env->getPlayer(params.to_player.c_str());
4004 		if(!player){
4005 			infostream<<"Server::playSound: Player \""<<params.to_player
4006 					<<"\" not found"<<std::endl;
4007 			return -1;
4008 		}
4009 		if(player->peer_id == PEER_ID_INEXISTENT){
4010 			infostream<<"Server::playSound: Player \""<<params.to_player
4011 					<<"\" not connected"<<std::endl;
4012 			return -1;
4013 		}
4014 		dst_clients.push_back(player->peer_id);
4015 	}
4016 	else
4017 	{
4018 		std::list<u16> clients = m_clients.getClientIDs();
4019 
4020 		for(std::list<u16>::iterator
4021 				i = clients.begin(); i != clients.end(); ++i)
4022 		{
4023 			Player *player = m_env->getPlayer(*i);
4024 			if(!player)
4025 				continue;
4026 			if(pos_exists){
4027 				if(player->getPosition().getDistanceFrom(pos) >
4028 						params.max_hear_distance)
4029 					continue;
4030 			}
4031 			dst_clients.push_back(*i);
4032 		}
4033 	}
4034 	if(dst_clients.size() == 0)
4035 		return -1;
4036 
4037 	// Create the sound
4038 	s32 id = m_next_sound_id++;
4039 	// The sound will exist as a reference in m_playing_sounds
4040 	m_playing_sounds[id] = ServerPlayingSound();
4041 	ServerPlayingSound &psound = m_playing_sounds[id];
4042 	psound.params = params;
4043 	for(std::list<u16>::iterator i = dst_clients.begin();
4044 			i != dst_clients.end(); i++)
4045 		psound.clients.insert(*i);
4046 	// Create packet
4047 	std::ostringstream os(std::ios_base::binary);
4048 	writeU16(os, TOCLIENT_PLAY_SOUND);
4049 	writeS32(os, id);
4050 	os<<serializeString(spec.name);
4051 	writeF1000(os, spec.gain * params.gain);
4052 	writeU8(os, params.type);
4053 	writeV3F1000(os, pos);
4054 	writeU16(os, params.object);
4055 	writeU8(os, params.loop);
4056 	// Make data buffer
4057 	std::string s = os.str();
4058 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4059 	// Send
4060 	for(std::list<u16>::iterator i = dst_clients.begin();
4061 			i != dst_clients.end(); i++){
4062 		// Send as reliable
4063 		m_clients.send(*i, 0, data, true);
4064 	}
4065 	return id;
4066 }
stopSound(s32 handle)4067 void Server::stopSound(s32 handle)
4068 {
4069 	// Get sound reference
4070 	std::map<s32, ServerPlayingSound>::iterator i =
4071 			m_playing_sounds.find(handle);
4072 	if(i == m_playing_sounds.end())
4073 		return;
4074 	ServerPlayingSound &psound = i->second;
4075 	// Create packet
4076 	std::ostringstream os(std::ios_base::binary);
4077 	writeU16(os, TOCLIENT_STOP_SOUND);
4078 	writeS32(os, handle);
4079 	// Make data buffer
4080 	std::string s = os.str();
4081 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4082 	// Send
4083 	for(std::set<u16>::iterator i = psound.clients.begin();
4084 			i != psound.clients.end(); i++){
4085 		// Send as reliable
4086 		m_clients.send(*i, 0, data, true);
4087 	}
4088 	// Remove sound reference
4089 	m_playing_sounds.erase(i);
4090 }
4091 
sendRemoveNode(v3s16 p,u16 ignore_id,std::list<u16> * far_players,float far_d_nodes)4092 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
4093 	std::list<u16> *far_players, float far_d_nodes)
4094 {
4095 	float maxd = far_d_nodes*BS;
4096 	v3f p_f = intToFloat(p, BS);
4097 
4098 	// Create packet
4099 	u32 replysize = 8;
4100 	SharedBuffer<u8> reply(replysize);
4101 	writeU16(&reply[0], TOCLIENT_REMOVENODE);
4102 	writeS16(&reply[2], p.X);
4103 	writeS16(&reply[4], p.Y);
4104 	writeS16(&reply[6], p.Z);
4105 
4106 	std::list<u16> clients = m_clients.getClientIDs();
4107 	for(std::list<u16>::iterator
4108 		i = clients.begin();
4109 		i != clients.end(); ++i)
4110 	{
4111 		if(far_players)
4112 		{
4113 			// Get player
4114 			Player *player = m_env->getPlayer(*i);
4115 			if(player)
4116 			{
4117 				// If player is far away, only set modified blocks not sent
4118 				v3f player_pos = player->getPosition();
4119 				if(player_pos.getDistanceFrom(p_f) > maxd)
4120 				{
4121 					far_players->push_back(*i);
4122 					continue;
4123 				}
4124 			}
4125 		}
4126 
4127 		// Send as reliable
4128 		m_clients.send(*i, 0, reply, true);
4129 	}
4130 }
4131 
sendAddNode(v3s16 p,MapNode n,u16 ignore_id,std::list<u16> * far_players,float far_d_nodes,bool remove_metadata)4132 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
4133 		std::list<u16> *far_players, float far_d_nodes,
4134 		bool remove_metadata)
4135 {
4136 	float maxd = far_d_nodes*BS;
4137 	v3f p_f = intToFloat(p, BS);
4138 
4139 	std::list<u16> clients = m_clients.getClientIDs();
4140 		for(std::list<u16>::iterator
4141 			i = clients.begin();
4142 			i != clients.end(); ++i)
4143 		{
4144 
4145 		if(far_players)
4146 		{
4147 			// Get player
4148 			Player *player = m_env->getPlayer(*i);
4149 			if(player)
4150 			{
4151 				// If player is far away, only set modified blocks not sent
4152 				v3f player_pos = player->getPosition();
4153 				if(player_pos.getDistanceFrom(p_f) > maxd)
4154 				{
4155 					far_players->push_back(*i);
4156 					continue;
4157 				}
4158 			}
4159 		}
4160 		SharedBuffer<u8> reply(0);
4161 		RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
4162 		if (client != 0)
4163 		{
4164 			// Create packet
4165 			u32 replysize = 9 + MapNode::serializedLength(client->serialization_version);
4166 			reply = SharedBuffer<u8>(replysize);
4167 			writeU16(&reply[0], TOCLIENT_ADDNODE);
4168 			writeS16(&reply[2], p.X);
4169 			writeS16(&reply[4], p.Y);
4170 			writeS16(&reply[6], p.Z);
4171 			n.serialize(&reply[8], client->serialization_version);
4172 			u32 index = 8 + MapNode::serializedLength(client->serialization_version);
4173 			writeU8(&reply[index], remove_metadata ? 0 : 1);
4174 
4175 			if (!remove_metadata) {
4176 				if (client->net_proto_version <= 21) {
4177 					// Old clients always clear metadata; fix it
4178 					// by sending the full block again.
4179 					client->SetBlockNotSent(p);
4180 				}
4181 			}
4182 		}
4183 
4184 		// Send as reliable
4185 		if (reply.getSize() > 0)
4186 			m_clients.send(*i, 0, reply, true);
4187 	}
4188 }
4189 
setBlockNotSent(v3s16 p)4190 void Server::setBlockNotSent(v3s16 p)
4191 {
4192 	auto clients = m_clients.getClientIDs();
4193 	for(std::list<u16>::iterator
4194 		i = clients.begin();
4195 		i != clients.end(); ++i)
4196 	{
4197 		RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
4198 		client->SetBlockNotSent(p);
4199 	}
4200 }
4201 
SendBlockNoLock(u16 peer_id,MapBlock * block,u8 ver,u16 net_proto_version,bool reliable)4202 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version, bool reliable)
4203 {
4204 	DSTACK(__FUNCTION_NAME);
4205 
4206 	g_profiler->add("Connection: blocks sent", 1);
4207 
4208 	v3s16 p = block->getPos();
4209 
4210 #if 0
4211 	// Analyze it a bit
4212 	bool completely_air = true;
4213 	for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
4214 	for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
4215 	for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
4216 	{
4217 		if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
4218 		{
4219 			completely_air = false;
4220 			x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
4221 		}
4222 	}
4223 
4224 	// Print result
4225 	infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
4226 	if(completely_air)
4227 		infostream<<"[completely air] ";
4228 	infostream<<std::endl;
4229 #endif
4230 
4231 	/*
4232 		Create a packet with the block in the right format
4233 	*/
4234 
4235 	std::ostringstream os(std::ios_base::binary);
4236 	block->serialize(os, ver, false);
4237 	block->serializeNetworkSpecific(os, net_proto_version);
4238 	std::string s = os.str();
4239 	SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
4240 
4241 	u32 replysize = 8 + blockdata.getSize();
4242 	SharedBuffer<u8> reply(replysize);
4243 	writeU16(&reply[0], TOCLIENT_BLOCKDATA);
4244 	writeS16(&reply[2], p.X);
4245 	writeS16(&reply[4], p.Y);
4246 	writeS16(&reply[6], p.Z);
4247 	memcpy(&reply[8], *blockdata, blockdata.getSize());
4248 
4249 	/*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
4250 			<<":  \tpacket size: "<<replysize<<std::endl;*/
4251 
4252 	//JMutexAutoLock lock(m_env_mutex);
4253 	/*
4254 		Send packet
4255 	*/
4256 	m_clients.send(peer_id, 2, reply, reliable);
4257 }
4258 
SendBlocks(float dtime)4259 int Server::SendBlocks(float dtime)
4260 {
4261 	DSTACK(__FUNCTION_NAME);
4262 	//TimeTaker timer("SendBlocks inside");
4263 
4264 	//JMutexAutoLock envlock(m_env_mutex);
4265 	//TODO check if one big lock could be faster then multiple small ones
4266 
4267 	//ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
4268 
4269 	int total = 0;
4270 
4271 	std::vector<PrioritySortedBlockTransfer> queue;
4272 
4273 	{
4274 		//ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
4275 
4276 		std::list<u16> clients = m_clients.getClientIDs();
4277 
4278 		for(std::list<u16>::iterator
4279 			i = clients.begin();
4280 			i != clients.end(); ++i)
4281 		{
4282 			auto client = m_clients.getClient(*i, CS_Active);
4283 
4284 			if (client == NULL)
4285 				continue;
4286 
4287 			total += client->GetNextBlocks(m_env, m_emerge, dtime, m_uptime.get() + m_env->m_game_time_start, queue);
4288 		}
4289 	}
4290 
4291 	// Sort.
4292 	// Lowest priority number comes first.
4293 	// Lowest is most important.
4294 	std::sort(queue.begin(), queue.end());
4295 
4296 	for(u32 i=0; i<queue.size(); i++)
4297 	{
4298 		//TODO: Calculate limit dynamically
4299 
4300 		PrioritySortedBlockTransfer q = queue[i];
4301 
4302 		MapBlock *block = NULL;
4303 		try
4304 		{
4305 			block = m_env->getMap().getBlockNoCreate(q.pos);
4306 		}
4307 		catch(InvalidPositionException &e)
4308 		{
4309 			continue;
4310 		}
4311 
4312 		RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
4313 
4314 		if(!client)
4315 			continue;
4316 
4317 		{
4318 		auto lock = block->try_lock_shared_rec();
4319 		if (!lock->owns_lock())
4320 			continue;
4321 
4322 		// maybe sometimes blocks will not load (must wait 1+ minute), but reduce network load: q.priority<=4
4323 		SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version, 1);
4324 		}
4325 
4326 		client->SentBlock(q.pos, m_uptime.get() + m_env->m_game_time_start);
4327 		++total;
4328 	}
4329 	return total;
4330 }
4331 
fillMediaCache()4332 void Server::fillMediaCache()
4333 {
4334 	DSTACK(__FUNCTION_NAME);
4335 
4336 	infostream<<"Server: Calculating media file checksums"<<std::endl;
4337 
4338 	// Collect all media file paths
4339 	std::list<std::string> paths;
4340 	for(std::vector<ModSpec>::iterator i = m_mods.begin();
4341 			i != m_mods.end(); i++){
4342 		const ModSpec &mod = *i;
4343 		paths.push_back(mod.path + DIR_DELIM + "textures");
4344 		paths.push_back(mod.path + DIR_DELIM + "sounds");
4345 		paths.push_back(mod.path + DIR_DELIM + "media");
4346 		paths.push_back(mod.path + DIR_DELIM + "models");
4347 	}
4348 	paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
4349 
4350 	// Collect media file information from paths into cache
4351 	for(std::list<std::string>::iterator i = paths.begin();
4352 			i != paths.end(); i++)
4353 	{
4354 		std::string mediapath = *i;
4355 		std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
4356 		for(u32 j=0; j<dirlist.size(); j++){
4357 			if(dirlist[j].dir) // Ignode dirs
4358 				continue;
4359 			std::string filename = dirlist[j].name;
4360 			// If name contains illegal characters, ignore the file
4361 			if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
4362 				infostream<<"Server: ignoring illegal file name: \""
4363 						<<filename<<"\""<<std::endl;
4364 				continue;
4365 			}
4366 			// If name is not in a supported format, ignore it
4367 			const char *supported_ext[] = {
4368 				".png", ".jpg", ".bmp", ".tga",
4369 				".pcx", ".ppm", ".psd", ".wal", ".rgb",
4370 				".ogg",
4371 				".x", ".b3d", ".md2", ".obj",
4372 				NULL
4373 			};
4374 			if(removeStringEnd(filename, supported_ext) == ""){
4375 				infostream<<"Server: ignoring unsupported file extension: \""
4376 						<<filename<<"\""<<std::endl;
4377 				continue;
4378 			}
4379 			// Ok, attempt to load the file and add to cache
4380 			std::string filepath = mediapath + DIR_DELIM + filename;
4381 			// Read data
4382 			std::ifstream fis(filepath.c_str(), std::ios_base::binary);
4383 			if(fis.good() == false){
4384 				errorstream<<"Server::fillMediaCache(): Could not open \""
4385 						<<filename<<"\" for reading"<<std::endl;
4386 				continue;
4387 			}
4388 			std::ostringstream tmp_os(std::ios_base::binary);
4389 			bool bad = false;
4390 			for(;;){
4391 				char buf[1024];
4392 				fis.read(buf, 1024);
4393 				std::streamsize len = fis.gcount();
4394 				tmp_os.write(buf, len);
4395 				if(fis.eof())
4396 					break;
4397 				if(!fis.good()){
4398 					bad = true;
4399 					break;
4400 				}
4401 			}
4402 			if(bad){
4403 				errorstream<<"Server::fillMediaCache(): Failed to read \""
4404 						<<filename<<"\""<<std::endl;
4405 				continue;
4406 			}
4407 			if(tmp_os.str().length() == 0){
4408 				errorstream<<"Server::fillMediaCache(): Empty file \""
4409 						<<filepath<<"\""<<std::endl;
4410 				continue;
4411 			}
4412 
4413 			SHA1 sha1;
4414 			sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
4415 
4416 			unsigned char *digest = sha1.getDigest();
4417 			std::string sha1_base64 = base64_encode(digest, 20);
4418 			std::string sha1_hex = hex_encode((char*)digest, 20);
4419 			free(digest);
4420 
4421 			// Put in list
4422 			this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4423 			verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4424 		}
4425 	}
4426 }
4427 
4428 struct SendableMediaAnnouncement
4429 {
4430 	std::string name;
4431 	std::string sha1_digest;
4432 
SendableMediaAnnouncementSendableMediaAnnouncement4433 	SendableMediaAnnouncement(const std::string &name_="",
4434 	                          const std::string &sha1_digest_=""):
4435 		name(name_),
4436 		sha1_digest(sha1_digest_)
4437 	{}
4438 };
4439 
sendMediaAnnouncement(u16 peer_id)4440 void Server::sendMediaAnnouncement(u16 peer_id)
4441 {
4442 	DSTACK(__FUNCTION_NAME);
4443 
4444 	verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4445 			<<std::endl;
4446 
4447 	std::list<SendableMediaAnnouncement> file_announcements;
4448 
4449 	for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4450 			i != m_media.end(); i++){
4451 		// Put in list
4452 		file_announcements.push_back(
4453 				SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4454 	}
4455 
4456 	// Make packet
4457 	std::ostringstream os(std::ios_base::binary);
4458 
4459 	/*
4460 		u16 command
4461 		u32 number of files
4462 		for each texture {
4463 			u16 length of name
4464 			string name
4465 			u16 length of sha1_digest
4466 			string sha1_digest
4467 		}
4468 	*/
4469 
4470 	writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4471 	writeU16(os, file_announcements.size());
4472 
4473 	for(std::list<SendableMediaAnnouncement>::iterator
4474 			j = file_announcements.begin();
4475 			j != file_announcements.end(); ++j){
4476 		os<<serializeString(j->name);
4477 		os<<serializeString(j->sha1_digest);
4478 	}
4479 	os<<serializeString(g_settings->get("remote_media"));
4480 
4481 	// Make data buffer
4482 	std::string s = os.str();
4483 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4484 
4485 	// Send as reliable
4486 	m_clients.send(peer_id, 0, data, true);
4487 }
4488 
4489 struct SendableMedia
4490 {
4491 	std::string name;
4492 	std::string path;
4493 	std::string data;
4494 
SendableMediaSendableMedia4495 	SendableMedia(const std::string &name_="", const std::string &path_="",
4496 	              const std::string &data_=""):
4497 		name(name_),
4498 		path(path_),
4499 		data(data_)
4500 	{}
4501 };
4502 
sendRequestedMedia(u16 peer_id,const std::list<std::string> & tosend)4503 void Server::sendRequestedMedia(u16 peer_id,
4504 		const std::list<std::string> &tosend)
4505 {
4506 	DSTACK(__FUNCTION_NAME);
4507 
4508 	verbosestream<<"Server::sendRequestedMedia(): "
4509 			<<"Sending files to client"<<std::endl;
4510 
4511 	/* Read files */
4512 
4513 	// Put 5kB in one bunch (this is not accurate)
4514 	u32 bytes_per_bunch = 5000;
4515 
4516 	std::vector< std::list<SendableMedia> > file_bunches;
4517 	file_bunches.push_back(std::list<SendableMedia>());
4518 
4519 	u32 file_size_bunch_total = 0;
4520 
4521 	for(std::list<std::string>::const_iterator i = tosend.begin();
4522 			i != tosend.end(); ++i)
4523 	{
4524 		const std::string &name = *i;
4525 
4526 		if(m_media.find(name) == m_media.end()){
4527 			errorstream<<"Server::sendRequestedMedia(): Client asked for "
4528 					<<"unknown file \""<<(name)<<"\""<<std::endl;
4529 			continue;
4530 		}
4531 
4532 		//TODO get path + name
4533 		std::string tpath = m_media[name].path;
4534 
4535 		// Read data
4536 		std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4537 		if(fis.good() == false){
4538 			errorstream<<"Server::sendRequestedMedia(): Could not open \""
4539 					<<tpath<<"\" for reading"<<std::endl;
4540 			continue;
4541 		}
4542 		std::ostringstream tmp_os(std::ios_base::binary);
4543 		bool bad = false;
4544 		for(;;){
4545 			char buf[1024];
4546 			fis.read(buf, 1024);
4547 			std::streamsize len = fis.gcount();
4548 			tmp_os.write(buf, len);
4549 			file_size_bunch_total += len;
4550 			if(fis.eof())
4551 				break;
4552 			if(!fis.good()){
4553 				bad = true;
4554 				break;
4555 			}
4556 		}
4557 		if(bad){
4558 			errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4559 					<<name<<"\""<<std::endl;
4560 			continue;
4561 		}
4562 		/*infostream<<"Server::sendRequestedMedia(): Loaded \""
4563 				<<tname<<"\""<<std::endl;*/
4564 		// Put in list
4565 		file_bunches[file_bunches.size()-1].push_back(
4566 				SendableMedia(name, tpath, tmp_os.str()));
4567 
4568 		// Start next bunch if got enough data
4569 		if(file_size_bunch_total >= bytes_per_bunch){
4570 			file_bunches.push_back(std::list<SendableMedia>());
4571 			file_size_bunch_total = 0;
4572 		}
4573 
4574 	}
4575 
4576 	/* Create and send packets */
4577 
4578 	u32 num_bunches = file_bunches.size();
4579 	for(u32 i=0; i<num_bunches; i++)
4580 	{
4581 		std::ostringstream os(std::ios_base::binary);
4582 
4583 		/*
4584 			u16 command
4585 			u16 total number of texture bunches
4586 			u16 index of this bunch
4587 			u32 number of files in this bunch
4588 			for each file {
4589 				u16 length of name
4590 				string name
4591 				u32 length of data
4592 				data
4593 			}
4594 		*/
4595 
4596 		writeU16(os, TOCLIENT_MEDIA);
4597 		writeU16(os, num_bunches);
4598 		writeU16(os, i);
4599 		writeU32(os, file_bunches[i].size());
4600 
4601 		for(std::list<SendableMedia>::iterator
4602 				j = file_bunches[i].begin();
4603 				j != file_bunches[i].end(); ++j){
4604 			os<<serializeString(j->name);
4605 			os<<serializeLongString(j->data);
4606 		}
4607 
4608 		// Make data buffer
4609 		std::string s = os.str();
4610 		verbosestream<<"Server::sendRequestedMedia(): bunch "
4611 				<<i<<"/"<<num_bunches
4612 				<<" files="<<file_bunches[i].size()
4613 				<<" size=" <<s.size()<<std::endl;
4614 		SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4615 		// Send as reliable
4616 		m_clients.send(peer_id, 2, data, true);
4617 	}
4618 }
4619 
sendDetachedInventory(const std::string & name,u16 peer_id)4620 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
4621 {
4622 	if(m_detached_inventories.count(name) == 0){
4623 		errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
4624 		return;
4625 	}
4626 	Inventory *inv = m_detached_inventories[name];
4627 
4628 	std::ostringstream os(std::ios_base::binary);
4629 	writeU16(os, TOCLIENT_DETACHED_INVENTORY);
4630 	os<<serializeString(name);
4631 	inv->serialize(os);
4632 
4633 	// Make data buffer
4634 	std::string s = os.str();
4635 	SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4636 
4637 	if (peer_id != PEER_ID_INEXISTENT)
4638 	{
4639 		// Send as reliable
4640 		m_clients.send(peer_id, 0, data, true);
4641 	}
4642 	else
4643 	{
4644 		m_clients.sendToAll(0,data,true);
4645 	}
4646 }
4647 
sendDetachedInventories(u16 peer_id)4648 void Server::sendDetachedInventories(u16 peer_id)
4649 {
4650 	DSTACK(__FUNCTION_NAME);
4651 
4652 	for(std::map<std::string, Inventory*>::iterator
4653 			i = m_detached_inventories.begin();
4654 			i != m_detached_inventories.end(); i++){
4655 		const std::string &name = i->first;
4656 		//Inventory *inv = i->second;
4657 		sendDetachedInventory(name, peer_id);
4658 	}
4659 }
4660 
4661 /*
4662 	Something random
4663 */
4664 
DiePlayer(u16 peer_id)4665 void Server::DiePlayer(u16 peer_id)
4666 {
4667 	DSTACK(__FUNCTION_NAME);
4668 
4669 	PlayerSAO *playersao = getPlayerSAO(peer_id);
4670 	assert(playersao);
4671 
4672 	infostream<<"Server::DiePlayer(): Player "
4673 			<<playersao->getPlayer()->getName()
4674 			<<" dies"<<std::endl;
4675 
4676 	playersao->setHP(0);
4677 
4678 	// Trigger scripted stuff
4679 	m_script->on_dieplayer(playersao);
4680 
4681 	SendPlayerHP(peer_id);
4682 	SendDeathscreen(peer_id, false, v3f(0,0,0));
4683 
4684 	stat.add("die", playersao->getPlayer()->getName());
4685 }
4686 
RespawnPlayer(u16 peer_id)4687 void Server::RespawnPlayer(u16 peer_id)
4688 {
4689 	DSTACK(__FUNCTION_NAME);
4690 
4691 	PlayerSAO *playersao = getPlayerSAO(peer_id);
4692 	assert(playersao);
4693 
4694 	infostream<<"Server::RespawnPlayer(): Player "
4695 			<<playersao->getPlayer()->getName()
4696 			<<" respawns"<<std::endl;
4697 
4698 	playersao->setHP(PLAYER_MAX_HP);
4699 
4700 	bool repositioned = m_script->on_respawnplayer(playersao);
4701 	if(!repositioned){
4702 		v3f pos = findSpawnPos(m_env->getServerMap());
4703 		playersao->setPos(pos);
4704 	}
4705 
4706 	stat.add("respawn", playersao->getPlayer()->getName());
4707 }
4708 
DenyAccess(u16 peer_id,const std::wstring & reason)4709 void Server::DenyAccess(u16 peer_id, const std::wstring &reason)
4710 {
4711 	DSTACK(__FUNCTION_NAME);
4712 
4713 	SendAccessDenied(peer_id, reason);
4714 	m_clients.event(peer_id, CSE_SetDenied);
4715 	m_con.DisconnectPeer(peer_id);
4716 }
4717 
DeleteClient(u16 peer_id,ClientDeletionReason reason)4718 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
4719 {
4720 	DSTACK(__FUNCTION_NAME);
4721 	std::wstring message;
4722 	{
4723 		/*
4724 			Clear references to playing sounds
4725 		*/
4726 		for(std::map<s32, ServerPlayingSound>::iterator
4727 				i = m_playing_sounds.begin();
4728 				i != m_playing_sounds.end();)
4729 		{
4730 			ServerPlayingSound &psound = i->second;
4731 			psound.clients.erase(peer_id);
4732 			if(psound.clients.size() == 0)
4733 				m_playing_sounds.erase(i++);
4734 			else
4735 				i++;
4736 		}
4737 
4738 		Player *player = m_env->getPlayer(peer_id);
4739 
4740 		// Collect information about leaving in chat
4741 		{
4742 			if(player != NULL && reason != CDR_DENY)
4743 			{
4744 				std::wstring name = narrow_to_wide(player->getName());
4745 				message += L"*** ";
4746 				message += name;
4747 				message += L" left the game.";
4748 				if(reason == CDR_TIMEOUT)
4749 					message += L" (timed out)";
4750 			}
4751 		}
4752 
4753 		/* Run scripts and remove from environment */
4754 		{
4755 			if(player != NULL)
4756 			{
4757 				PlayerSAO *playersao = player->getPlayerSAO();
4758 				assert(playersao);
4759 
4760 				//JMutexAutoLock env_lock(m_env_mutex);
4761 				m_script->on_leaveplayer(playersao);
4762 
4763 				playersao->disconnected();
4764 			}
4765 		}
4766 
4767 		/*
4768 			Print out action
4769 		*/
4770 		{
4771 			if(player != NULL && reason != CDR_DENY)
4772 			{
4773 				std::ostringstream os(std::ios_base::binary);
4774 				std::list<u16> clients = m_clients.getClientIDs();
4775 
4776 				for(std::list<u16>::iterator
4777 					i = clients.begin();
4778 					i != clients.end(); ++i)
4779 				{
4780 					// Get player
4781 					Player *player = m_env->getPlayer(*i);
4782 					if(!player)
4783 						continue;
4784 					// Get name of player
4785 					os<<player->getName()<<" ";
4786 				}
4787 
4788 				actionstream<<player->getName()<<" "
4789 						<<(reason==CDR_TIMEOUT?"times out.":"leaves game.")
4790 						<<" List of players: "<<os.str()<<std::endl;
4791 			}
4792 		}
4793 		{
4794 			//JMutexAutoLock env_lock(m_env_mutex);
4795 			m_clients.DeleteClient(peer_id);
4796 		}
4797 	}
4798 
4799 	// Send leave chat message to all remaining clients
4800 	if(message.length() != 0)
4801 		SendChatMessage(PEER_ID_INEXISTENT,message);
4802 }
4803 
UpdateCrafting(u16 peer_id)4804 void Server::UpdateCrafting(u16 peer_id)
4805 {
4806 	DSTACK(__FUNCTION_NAME);
4807 
4808 	Player* player = m_env->getPlayer(peer_id);
4809 	assert(player);
4810 
4811 	// Get a preview for crafting
4812 	ItemStack preview;
4813 	InventoryLocation loc;
4814 	loc.setPlayer(player->getName());
4815 	getCraftingResult(&player->inventory, preview, false, this);
4816 	m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
4817 
4818 	// Put the new preview in
4819 	InventoryList *plist = player->inventory.getList("craftpreview");
4820 	assert(plist);
4821 	assert(plist->getSize() >= 1);
4822 	plist->changeItem(0, preview);
4823 }
4824 
getClient(u16 peer_id,ClientState state_min)4825 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
4826 {
4827 	RemoteClient *client = getClientNoEx(peer_id,state_min);
4828 	if(!client)
4829 		throw ClientNotFoundException("Client not found");
4830 
4831 	return client;
4832 }
getClientNoEx(u16 peer_id,ClientState state_min)4833 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
4834 {
4835 	return m_clients.getClientNoEx(peer_id, state_min);
4836 }
4837 
getPlayerName(u16 peer_id)4838 std::string Server::getPlayerName(u16 peer_id)
4839 {
4840 	Player *player = m_env->getPlayer(peer_id);
4841 	if(player == NULL)
4842 		return "[id="+itos(peer_id)+"]";
4843 	return player->getName();
4844 }
4845 
getPlayerSAO(u16 peer_id)4846 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
4847 {
4848 	Player *player = m_env->getPlayer(peer_id);
4849 	if(player == NULL)
4850 		return NULL;
4851 	return player->getPlayerSAO();
4852 }
4853 
getStatusString()4854 std::wstring Server::getStatusString()
4855 {
4856 	std::wostringstream os(std::ios_base::binary);
4857 	os<<L"# Server: ";
4858 	// Version
4859 	os<<L"version="<<narrow_to_wide(minetest_version_simple);
4860 	// Uptime
4861 	os<<L", uptime="<<m_uptime.get();
4862 	// Max lag estimate
4863 	os<<L", max_lag="<<m_env->getMaxLagEstimate();
4864 	// Information about clients
4865 	bool first = true;
4866 	os<<L", clients={";
4867 	std::list<u16> clients = m_clients.getClientIDs();
4868 	for(std::list<u16>::iterator i = clients.begin();
4869 		i != clients.end(); ++i)
4870 	{
4871 		// Get player
4872 		Player *player = m_env->getPlayer(*i);
4873 		// Get name of player
4874 		std::wstring name = L"unknown";
4875 		if(player != NULL)
4876 			name = narrow_to_wide(player->getName());
4877 		// Add name to information string
4878 		if(!first)
4879 			os<<L", ";
4880 		else
4881 			first = false;
4882 		os<<name;
4883 	}
4884 	os<<L"}";
4885 	if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4886 		os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4887 	if(g_settings->get("motd") != "")
4888 		os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4889 	return os.str();
4890 }
4891 
getPlayerEffectivePrivs(const std::string & name)4892 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
4893 {
4894 	std::set<std::string> privs;
4895 	m_script->getAuth(name, NULL, &privs);
4896 	return privs;
4897 }
4898 
checkPriv(const std::string & name,const std::string & priv)4899 bool Server::checkPriv(const std::string &name, const std::string &priv)
4900 {
4901 	std::set<std::string> privs = getPlayerEffectivePrivs(name);
4902 	return (privs.count(priv) != 0);
4903 }
4904 
reportPrivsModified(const std::string & name)4905 void Server::reportPrivsModified(const std::string &name)
4906 {
4907 	if(name == ""){
4908 		std::list<u16> clients = m_clients.getClientIDs();
4909 		for(std::list<u16>::iterator
4910 				i = clients.begin();
4911 				i != clients.end(); ++i){
4912 			Player *player = m_env->getPlayer(*i);
4913 			reportPrivsModified(player->getName());
4914 		}
4915 	} else {
4916 		Player *player = m_env->getPlayer(name.c_str());
4917 		if(!player)
4918 			return;
4919 		SendPlayerPrivileges(player->peer_id);
4920 		PlayerSAO *sao = player->getPlayerSAO();
4921 		if(!sao)
4922 			return;
4923 		sao->updatePrivileges(
4924 				getPlayerEffectivePrivs(name),
4925 				isSingleplayer());
4926 	}
4927 }
4928 
reportInventoryFormspecModified(const std::string & name)4929 void Server::reportInventoryFormspecModified(const std::string &name)
4930 {
4931 	Player *player = m_env->getPlayer(name.c_str());
4932 	if(!player)
4933 		return;
4934 	SendPlayerInventoryFormspec(player->peer_id);
4935 }
4936 
setIpBanned(const std::string & ip,const std::string & name)4937 void Server::setIpBanned(const std::string &ip, const std::string &name)
4938 {
4939 	m_banmanager->add(ip, name);
4940 }
4941 
unsetIpBanned(const std::string & ip_or_name)4942 void Server::unsetIpBanned(const std::string &ip_or_name)
4943 {
4944 	m_banmanager->remove(ip_or_name);
4945 }
4946 
getBanDescription(const std::string & ip_or_name)4947 std::string Server::getBanDescription(const std::string &ip_or_name)
4948 {
4949 	return m_banmanager->getBanDescription(ip_or_name);
4950 }
4951 
notifyPlayer(const char * name,const std::wstring & msg)4952 void Server::notifyPlayer(const char *name, const std::wstring &msg)
4953 {
4954 	Player *player = m_env->getPlayer(name);
4955 	if(!player)
4956 		return;
4957 
4958 	if (player->peer_id == PEER_ID_INEXISTENT)
4959 		return;
4960 
4961 	SendChatMessage(player->peer_id, std::wstring(L"\vffffff")+msg);
4962 }
4963 
showFormspec(const char * playername,const std::string & formspec,const std::string & formname)4964 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
4965 {
4966 	Player *player = m_env->getPlayer(playername);
4967 
4968 	if(!player)
4969 	{
4970 		infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
4971 		return false;
4972 	}
4973 
4974 	SendShowFormspecMessage(player->peer_id, formspec, formname);
4975 	return true;
4976 }
4977 
hudAdd(Player * player,HudElement * form)4978 u32 Server::hudAdd(Player *player, HudElement *form) {
4979 	if (!player)
4980 		return -1;
4981 
4982 	u32 id = player->addHud(form);
4983 
4984 	SendHUDAdd(player->peer_id, id, form);
4985 
4986 	return id;
4987 }
4988 
hudRemove(Player * player,u32 id)4989 bool Server::hudRemove(Player *player, u32 id) {
4990 	if (!player)
4991 		return false;
4992 
4993 	HudElement* todel = player->removeHud(id);
4994 
4995 	if (!todel)
4996 		return false;
4997 
4998 	delete todel;
4999 
5000 	SendHUDRemove(player->peer_id, id);
5001 	return true;
5002 }
5003 
hudChange(Player * player,u32 id,HudElementStat stat,void * data)5004 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
5005 	if (!player)
5006 		return false;
5007 
5008 	SendHUDChange(player->peer_id, id, stat, data);
5009 	return true;
5010 }
5011 
hudSetFlags(Player * player,u32 flags,u32 mask)5012 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
5013 	if (!player)
5014 		return false;
5015 
5016 	SendHUDSetFlags(player->peer_id, flags, mask);
5017 	player->hud_flags = flags;
5018 
5019 	PlayerSAO* playersao = player->getPlayerSAO();
5020 
5021 	if (playersao == NULL)
5022 		return false;
5023 
5024 	m_script->player_event(playersao, "hud_changed");
5025 	return true;
5026 }
5027 
hudSetHotbarItemcount(Player * player,s32 hotbar_itemcount)5028 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
5029 	if (!player)
5030 		return false;
5031 	if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
5032 		return false;
5033 
5034 	std::ostringstream os(std::ios::binary);
5035 	writeS32(os, hotbar_itemcount);
5036 	SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
5037 	return true;
5038 }
5039 
hudSetHotbarImage(Player * player,std::string name)5040 void Server::hudSetHotbarImage(Player *player, std::string name) {
5041 	if (!player)
5042 		return;
5043 
5044 	SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
5045 }
5046 
hudSetHotbarSelectedImage(Player * player,std::string name)5047 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
5048 	if (!player)
5049 		return;
5050 
5051 	SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
5052 }
5053 
setLocalPlayerAnimations(Player * player,v2s32 animation_frames[4],f32 frame_speed)5054 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
5055 {
5056 	if (!player)
5057 		return false;
5058 
5059 	SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
5060 	return true;
5061 }
5062 
setPlayerEyeOffset(Player * player,v3f first,v3f third)5063 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
5064 {
5065 	if (!player)
5066 		return false;
5067 
5068 	SendEyeOffset(player->peer_id, first, third);
5069 	return true;
5070 }
5071 
setSky(Player * player,const video::SColor & bgcolor,const std::string & type,const std::vector<std::string> & params)5072 bool Server::setSky(Player *player, const video::SColor &bgcolor,
5073 		const std::string &type, const std::vector<std::string> &params)
5074 {
5075 	if (!player)
5076 		return false;
5077 
5078 	SendSetSky(player->peer_id, bgcolor, type, params);
5079 	return true;
5080 }
5081 
overrideDayNightRatio(Player * player,bool do_override,float ratio)5082 bool Server::overrideDayNightRatio(Player *player, bool do_override,
5083 		float ratio)
5084 {
5085 	if (!player)
5086 		return false;
5087 
5088 	SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
5089 	return true;
5090 }
5091 
notifyPlayers(const std::wstring & msg)5092 void Server::notifyPlayers(const std::wstring &msg)
5093 {
5094 	SendChatMessage(PEER_ID_INEXISTENT,msg);
5095 }
5096 
spawnParticle(const char * playername,v3f pos,v3f velocity,v3f acceleration,float expirationtime,float size,bool collisiondetection,bool vertical,std::string texture)5097 void Server::spawnParticle(const char *playername, v3f pos,
5098 		v3f velocity, v3f acceleration,
5099 		float expirationtime, float size, bool
5100 		collisiondetection, bool vertical, std::string texture)
5101 {
5102 	Player *player = m_env->getPlayer(playername);
5103 	if(!player)
5104 		return;
5105 	SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
5106 			expirationtime, size, collisiondetection, vertical, texture);
5107 }
5108 
spawnParticleAll(v3f pos,v3f velocity,v3f acceleration,float expirationtime,float size,bool collisiondetection,bool vertical,std::string texture)5109 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
5110 		float expirationtime, float size,
5111 		bool collisiondetection, bool vertical, std::string texture)
5112 {
5113 	SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
5114 			expirationtime, size, collisiondetection, vertical, texture);
5115 }
5116 
addParticleSpawner(const char * playername,u16 amount,float spawntime,v3f minpos,v3f maxpos,v3f minvel,v3f maxvel,v3f minacc,v3f maxacc,float minexptime,float maxexptime,float minsize,float maxsize,bool collisiondetection,bool vertical,std::string texture)5117 u32 Server::addParticleSpawner(const char *playername,
5118 		u16 amount, float spawntime,
5119 		v3f minpos, v3f maxpos,
5120 		v3f minvel, v3f maxvel,
5121 		v3f minacc, v3f maxacc,
5122 		float minexptime, float maxexptime,
5123 		float minsize, float maxsize,
5124 		bool collisiondetection, bool vertical, std::string texture)
5125 {
5126 	Player *player = m_env->getPlayer(playername);
5127 	if(!player)
5128 		return -1;
5129 
5130 	u32 id = 0;
5131 	for(;;) // look for unused particlespawner id
5132 	{
5133 		id++;
5134 		if (std::find(m_particlespawner_ids.begin(),
5135 				m_particlespawner_ids.end(), id)
5136 				== m_particlespawner_ids.end())
5137 		{
5138 			m_particlespawner_ids.push_back(id);
5139 			break;
5140 		}
5141 	}
5142 
5143 	SendAddParticleSpawner(player->peer_id, amount, spawntime,
5144 		minpos, maxpos, minvel, maxvel, minacc, maxacc,
5145 		minexptime, maxexptime, minsize, maxsize,
5146 		collisiondetection, vertical, texture, id);
5147 
5148 	return id;
5149 }
5150 
addParticleSpawnerAll(u16 amount,float spawntime,v3f minpos,v3f maxpos,v3f minvel,v3f maxvel,v3f minacc,v3f maxacc,float minexptime,float maxexptime,float minsize,float maxsize,bool collisiondetection,bool vertical,std::string texture)5151 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
5152 		v3f minpos, v3f maxpos,
5153 		v3f minvel, v3f maxvel,
5154 		v3f minacc, v3f maxacc,
5155 		float minexptime, float maxexptime,
5156 		float minsize, float maxsize,
5157 		bool collisiondetection, bool vertical, std::string texture)
5158 {
5159 	u32 id = 0;
5160 	for(;;) // look for unused particlespawner id
5161 	{
5162 		id++;
5163 		if (std::find(m_particlespawner_ids.begin(),
5164 				m_particlespawner_ids.end(), id)
5165 				== m_particlespawner_ids.end())
5166 		{
5167 			m_particlespawner_ids.push_back(id);
5168 			break;
5169 		}
5170 	}
5171 
5172 	SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
5173 		minpos, maxpos, minvel, maxvel, minacc, maxacc,
5174 		minexptime, maxexptime, minsize, maxsize,
5175 		collisiondetection, vertical, texture, id);
5176 
5177 	return id;
5178 }
5179 
deleteParticleSpawner(const char * playername,u32 id)5180 void Server::deleteParticleSpawner(const char *playername, u32 id)
5181 {
5182 	Player *player = m_env->getPlayer(playername);
5183 	if(!player)
5184 		return;
5185 
5186 	m_particlespawner_ids.erase(
5187 			std::remove(m_particlespawner_ids.begin(),
5188 			m_particlespawner_ids.end(), id),
5189 			m_particlespawner_ids.end());
5190 	SendDeleteParticleSpawner(player->peer_id, id);
5191 }
5192 
deleteParticleSpawnerAll(u32 id)5193 void Server::deleteParticleSpawnerAll(u32 id)
5194 {
5195 	m_particlespawner_ids.erase(
5196 			std::remove(m_particlespawner_ids.begin(),
5197 			m_particlespawner_ids.end(), id),
5198 			m_particlespawner_ids.end());
5199 	SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
5200 }
5201 
createDetachedInventory(const std::string & name)5202 Inventory* Server::createDetachedInventory(const std::string &name)
5203 {
5204 	if(m_detached_inventories.count(name) > 0){
5205 		infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
5206 		delete m_detached_inventories[name];
5207 	} else {
5208 		infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
5209 	}
5210 	Inventory *inv = new Inventory(m_itemdef);
5211 	assert(inv);
5212 	m_detached_inventories[name] = inv;
5213 	//TODO find a better way to do this
5214 	sendDetachedInventory(name,PEER_ID_INEXISTENT);
5215 	return inv;
5216 }
5217 
5218 class BoolScopeSet
5219 {
5220 public:
BoolScopeSet(bool * dst,bool val)5221 	BoolScopeSet(bool *dst, bool val):
5222 		m_dst(dst)
5223 	{
5224 		m_orig_state = *m_dst;
5225 		*m_dst = val;
5226 	}
~BoolScopeSet()5227 	~BoolScopeSet()
5228 	{
5229 		*m_dst = m_orig_state;
5230 	}
5231 private:
5232 	bool *m_dst;
5233 	bool m_orig_state;
5234 };
5235 
5236 // actions: time-reversed list
5237 // Return value: success/failure
rollbackRevertActions(const std::list<RollbackAction> & actions,std::list<std::string> * log)5238 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
5239 		std::list<std::string> *log)
5240 {
5241 	infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
5242 	ServerMap *map = (ServerMap*)(&m_env->getMap());
5243 
5244 	// Fail if no actions to handle
5245 	if(actions.empty()){
5246 		log->push_back("Nothing to do.");
5247 		return false;
5248 	}
5249 
5250 	int num_tried = 0;
5251 	int num_failed = 0;
5252 
5253 	for(std::list<RollbackAction>::const_iterator
5254 			i = actions.begin();
5255 			i != actions.end(); i++)
5256 	{
5257 		const RollbackAction &action = *i;
5258 		num_tried++;
5259 		bool success = action.applyRevert(map, this, this);
5260 		if(!success){
5261 			num_failed++;
5262 			std::ostringstream os;
5263 			os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
5264 			infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
5265 			if(log)
5266 				log->push_back(os.str());
5267 		}else{
5268 			std::ostringstream os;
5269 			os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
5270 			infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
5271 			if(log)
5272 				log->push_back(os.str());
5273 		}
5274 	}
5275 
5276 	infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
5277 			<<" failed"<<std::endl;
5278 
5279 	// Call it done if less than half failed
5280 	return num_failed <= num_tried/2;
5281 }
5282 
5283 // IGameDef interface
5284 // Under envlock
getItemDefManager()5285 IItemDefManager* Server::getItemDefManager()
5286 {
5287 	return m_itemdef;
5288 }
getNodeDefManager()5289 INodeDefManager* Server::getNodeDefManager()
5290 {
5291 	return m_nodedef;
5292 }
getCraftDefManager()5293 ICraftDefManager* Server::getCraftDefManager()
5294 {
5295 	return m_craftdef;
5296 }
getTextureSource()5297 ITextureSource* Server::getTextureSource()
5298 {
5299 	return NULL;
5300 }
getShaderSource()5301 IShaderSource* Server::getShaderSource()
5302 {
5303 	return NULL;
5304 }
getSceneManager()5305 scene::ISceneManager* Server::getSceneManager()
5306 {
5307 	return NULL;
5308 }
5309 
allocateUnknownNodeId(const std::string & name)5310 u16 Server::allocateUnknownNodeId(const std::string &name)
5311 {
5312 	return m_nodedef->allocateDummy(name);
5313 }
getSoundManager()5314 ISoundManager* Server::getSoundManager()
5315 {
5316 	return &dummySoundManager;
5317 }
getEventManager()5318 MtEventManager* Server::getEventManager()
5319 {
5320 	return m_event;
5321 }
5322 
getWritableItemDefManager()5323 IWritableItemDefManager* Server::getWritableItemDefManager()
5324 {
5325 	return m_itemdef;
5326 }
getWritableNodeDefManager()5327 IWritableNodeDefManager* Server::getWritableNodeDefManager()
5328 {
5329 	return m_nodedef;
5330 }
getWritableCraftDefManager()5331 IWritableCraftDefManager* Server::getWritableCraftDefManager()
5332 {
5333 	return m_craftdef;
5334 }
5335 
getModSpec(const std::string & modname)5336 const ModSpec* Server::getModSpec(const std::string &modname)
5337 {
5338 	for(std::vector<ModSpec>::iterator i = m_mods.begin();
5339 			i != m_mods.end(); i++){
5340 		const ModSpec &mod = *i;
5341 		if(mod.name == modname)
5342 			return &mod;
5343 	}
5344 	return NULL;
5345 }
getModNames(std::list<std::string> & modlist)5346 void Server::getModNames(std::list<std::string> &modlist)
5347 {
5348 	for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
5349 	{
5350 		modlist.push_back(i->name);
5351 	}
5352 }
getBuiltinLuaPath()5353 std::string Server::getBuiltinLuaPath()
5354 {
5355 	return porting::path_share + DIR_DELIM + "builtin";
5356 }
5357 
findSpawnPos(ServerMap & map)5358 v3f findSpawnPos(ServerMap &map)
5359 {
5360 	//return v3f(50,50,50)*BS;
5361 
5362 	v3s16 nodepos;
5363 
5364 #if 0
5365 	nodepos = v2s16(0,0);
5366 	groundheight = 20;
5367 #endif
5368 
5369 #if 1
5370 	s16 water_level = map.getWaterLevel();
5371 
5372 	// Try to find a good place a few times
5373 	for(s32 i=0; i<1000; i++)
5374 	{
5375 		s32 range = 1 + i;
5376 		// We're going to try to throw the player to this position
5377 		v2s16 nodepos2d = v2s16(
5378 				-range + (myrand() % (range * 2)),
5379 				-range + (myrand() % (range * 2)));
5380 
5381 		// Get ground height at point
5382 		s16 groundheight = map.findGroundLevel(nodepos2d, g_settings->getBool("cache_block_before_spawn"));
5383 		if (groundheight <= water_level) // Don't go underwater
5384 			continue;
5385 		if (groundheight > water_level + g_settings->getS16("max_spawn_height")) // Don't go to high places
5386 			continue;
5387 
5388 		nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
5389 		bool is_good = false;
5390 		s32 air_count = 0;
5391 		for (s32 i = 0; i < 10; i++) {
5392 			v3s16 blockpos = getNodeBlockPos(nodepos);
5393 			map.emergeBlock(blockpos, true);
5394 			content_t c = map.getNodeNoEx(nodepos).getContent();
5395 			if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
5396 				air_count++;
5397 				if (air_count >= 2){
5398 					is_good = true;
5399 					break;
5400 				}
5401 			}
5402 			nodepos.Y++;
5403 		}
5404 		if(is_good){
5405 			// Found a good place
5406 			//infostream<<"Searched through "<<i<<" places."<<std::endl;
5407 			break;
5408 		}
5409 	}
5410 #endif
5411 
5412 	return intToFloat(nodepos, BS);
5413 }
5414 
emergePlayer(const char * name,u16 peer_id)5415 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
5416 {
5417 	RemotePlayer *player = NULL;
5418 	bool newplayer = false;
5419 
5420 	/*
5421 		Try to get an existing player
5422 	*/
5423 	player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
5424 
5425 	// If player is already connected, cancel
5426 	if(player != NULL && player->peer_id != 0)
5427 	{
5428 		infostream<<"emergePlayer(): Player already connected"<<std::endl;
5429 		return NULL;
5430 	}
5431 
5432 	/*
5433 		If player with the wanted peer_id already exists, cancel.
5434 	*/
5435 	if(m_env->getPlayer(peer_id) != NULL)
5436 	{
5437 		infostream<<"emergePlayer(): Player with wrong name but same"
5438 				" peer_id already exists"<<std::endl;
5439 		return NULL;
5440 	}
5441 
5442 	if (!player && maintenance_status) {
5443 		infostream<<"emergePlayer(): Maintenance in progress, disallowing loading player"<<std::endl;
5444 		return nullptr;
5445 	}
5446 
5447 	// Load player if it isn't already loaded
5448 	if (!player) {
5449 		player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
5450 	}
5451 
5452 	// Create player if it doesn't exist
5453 	if (!player) {
5454 		newplayer = true;
5455 		player = new RemotePlayer(this, name);
5456 		// Set player position
5457 		infostream<<"Server: Finding spawn place for player \""
5458 				<<name<<"\""<<std::endl;
5459 		v3f pos = findSpawnPos(m_env->getServerMap());
5460 		player->setPosition(pos);
5461 
5462 		// Add player to environment
5463 		m_env->addPlayer(player);
5464 	}
5465 
5466 	// Create a new player active object
5467 	PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
5468 			getPlayerEffectivePrivs(player->getName()),
5469 			isSingleplayer());
5470 
5471 	/* Clean up old HUD elements from previous sessions */
5472 	player->clearHud();
5473 
5474 	/* Add object to environment */
5475 	m_env->addActiveObject(playersao);
5476 
5477 	/* Run scripts */
5478 	if (newplayer) {
5479 		m_script->on_newplayer(playersao);
5480 	}
5481 
5482 	return playersao;
5483 }
5484 
dedicated_server_loop(Server & server,bool & kill)5485 void dedicated_server_loop(Server &server, bool &kill)
5486 {
5487 	DSTACK(__FUNCTION_NAME);
5488 
5489 	IntervalLimiter m_profiler_interval;
5490 
5491 	int errors = 0;
5492 	float steplen = g_settings->getFloat("dedicated_server_step");
5493 	for(;;)
5494 	{
5495 		// This is kind of a hack but can be done like this
5496 		// because server.step() is very light
5497 		{
5498 /*
5499 			ScopeProfiler sp(g_profiler, "dedicated server sleep");
5500 */
5501 			sleep_ms((int)(steplen*1000.0));
5502 		}
5503 		try {
5504 		server.step(steplen);
5505 		}
5506 		//TODO: more errors here
5507 		catch(std::exception &e) {
5508 			if (!errors++ || !(errors % (int)(60/steplen)))
5509 				errorstream<<"Fatal error n="<<errors<< " : "<<e.what()<<std::endl;
5510 		}
5511 		catch (...){
5512 			if (!errors++ || !(errors % (int)(60/steplen)))
5513 				errorstream<<"Fatal error unknown "<<errors<<std::endl;
5514 		}
5515 		if(server.getShutdownRequested() || kill)
5516 		{
5517 			infostream<<"Dedicated server quitting"<<std::endl;
5518 #if USE_CURL
5519 			if(g_settings->getBool("server_announce") == true)
5520 				ServerList::sendAnnounce("delete");
5521 #endif
5522 			break;
5523 		}
5524 
5525 		/*
5526 			Profiler
5527 		*/
5528 		float profiler_print_interval =
5529 				g_settings->getFloat("profiler_print_interval");
5530 		if(server.m_clients.getClientList().size() && profiler_print_interval != 0)
5531 		{
5532 			if(m_profiler_interval.step(steplen, profiler_print_interval))
5533 			{
5534 				infostream<<"Profiler:"<<std::endl;
5535 				g_profiler->print(infostream);
5536 				g_profiler->clear();
5537 			}
5538 		}
5539 	}
5540 }
5541 
5542 
5543 
5544 
5545 
5546 
5547 //freeminer:
5548 
deleteDetachedInventory(const std::string & name)5549 void Server::deleteDetachedInventory(const std::string &name)
5550 {
5551 	if(m_detached_inventories.count(name) > 0){
5552 		infostream<<"Server deleting detached inventory \""<<name<<"\""<<std::endl;
5553 		delete m_detached_inventories[name];
5554 		m_detached_inventories.erase(name);
5555 	}
5556 }
5557 
maintenance_start()5558 void Server::maintenance_start() {
5559 	infostream<<"Server: Starting maintenance: saving..."<<std::endl;
5560 	m_emerge->stopThreads();
5561 	save(0.1);
5562 	m_env->getServerMap().m_map_saving_enabled = false;
5563 	m_env->getServerMap().m_map_loading_enabled = false;
5564 	m_env->getServerMap().dbase->close();
5565 	m_env->m_key_value_storage->close();
5566 	m_env->m_players_storage->close();
5567 	stat.close();
5568 	actionstream<<"Server: Starting maintenance: bases closed now."<<std::endl;
5569 
5570 };
5571 
maintenance_end()5572 void Server::maintenance_end() {
5573 	m_env->getServerMap().dbase->open();
5574 	m_env->m_key_value_storage->open();
5575 	m_env->m_players_storage->open();
5576 	stat.open();
5577 	m_env->getServerMap().m_map_saving_enabled = true;
5578 	m_env->getServerMap().m_map_loading_enabled = true;
5579 	m_emerge->startThreads();
5580 	actionstream<<"Server: Starting maintenance: ended."<<std::endl;
5581 };
5582