Cuberite
A lightweight, fast and extensible game server for Minecraft
Server.cpp
Go to the documentation of this file.
1 // ReDucTor is an awesome guy who helped me a lot
2 
3 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
4 
5 #include "Server.h"
6 #include "ClientHandle.h"
7 #include "Mobs/Monster.h"
8 #include "Root.h"
9 #include "World.h"
10 #include "Bindings/PluginManager.h"
11 #include "ChatColor.h"
12 #include "Entities/Player.h"
13 #include "Inventory.h"
14 #include "Item.h"
15 #include "FurnaceRecipe.h"
16 #include "WebAdmin.h"
18 #include "CommandOutput.h"
19 #include "FastRandom.h"
20 
21 #include "IniFile.h"
22 
23 #include <fstream>
24 #include <sstream>
25 #include <iostream>
26 
27 extern "C"
28 {
29  #include "zlib/zlib.h"
30 }
31 
32 
33 
34 
35 
36 typedef std::list< cClientHandle* > ClientList;
37 
38 
39 
40 
41 
43 // cServerListenCallbacks:
44 
47 {
50 
51  virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override
52  {
53  return m_Server.OnConnectionAccepted(a_RemoteIPAddress);
54  }
55 
56  virtual void OnAccepted(cTCPLink & a_Link) override {}
57 
58  virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
59  {
60  LOGWARNING("Cannot listen on port %d: %d (%s).", m_Port, a_ErrorCode, a_ErrorMsg.c_str());
61  }
62 
63 public:
64  cServerListenCallbacks(cServer & a_Server, UInt16 a_Port):
65  m_Server(a_Server),
66  m_Port(a_Port)
67  {
68  }
69 };
70 
71 
72 
73 
74 
76 // cServer::cTickThread:
77 
79  super("ServerTickThread"),
80  m_Server(a_Server)
81 {
82 }
83 
84 
85 
86 
87 
89 {
90  auto LastTime = std::chrono::steady_clock::now();
91  static const auto msPerTick = std::chrono::milliseconds(50);
92 
93  while (!m_ShouldTerminate)
94  {
95  auto NowTime = std::chrono::steady_clock::now();
96  auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(NowTime - LastTime).count();
97  m_ShouldTerminate = !m_Server.Tick(static_cast<float>(msec));
98  auto TickTime = std::chrono::steady_clock::now() - NowTime;
99 
100  if (TickTime < msPerTick)
101  {
102  // Stretch tick time until it's at least msPerTick
103  std::this_thread::sleep_for(msPerTick - TickTime);
104  }
105 
106  LastTime = NowTime;
107  }
108 }
109 
110 
111 
112 
113 
115 // cServer:
116 
118  m_PlayerCount(0),
120  m_bIsConnected(false),
121  m_bRestarting(false),
122  m_RCONServer(*this),
123  m_MaxPlayers(0),
124  m_bIsHardcore(false),
125  m_TickThread(*this),
126  m_ShouldAuthenticate(false),
129 {
130  // Initialize the LuaStateTracker singleton before the app goes multithreaded:
132 }
133 
134 
135 
136 
137 
139 {
140  cCSLock Lock(m_CSClients);
141  m_ClientsToRemove.push_back(const_cast<cClientHandle *>(a_Client));
142 }
143 
144 
145 
146 
147 
149 {
150  m_PlayerCount++;
151 }
152 
153 
154 
155 
156 
158 {
159  m_PlayerCount--;
160 }
161 
162 
163 
164 
165 
166 bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth)
167 {
168  m_Description = a_Settings.GetValueSet("Server", "Description", "Cuberite - in C++!");
169  m_ShutdownMessage = a_Settings.GetValueSet("Server", "ShutdownMessage", "Server shutdown");
170  m_MaxPlayers = static_cast<size_t>(a_Settings.GetValueSetI("Server", "MaxPlayers", 100));
171  m_bIsHardcore = a_Settings.GetValueSetB("Server", "HardcoreEnabled", false);
172  m_bAllowMultiLogin = a_Settings.GetValueSetB("Server", "AllowMultiLogin", false);
173 
174  m_FaviconData = Base64Encode(cFile::ReadWholeFile(FILE_IO_PREFIX + AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind
175 
176  if (m_bIsConnected)
177  {
178  LOGERROR("ERROR: Trying to initialize server while server is already running!");
179  return false;
180  }
181 
182  LOGINFO("Compatible clients: %s", MCS_CLIENT_VERSIONS);
183  LOGINFO("Compatible protocol versions %s", MCS_PROTOCOL_VERSIONS);
184 
185  m_Ports = ReadUpgradeIniPorts(a_Settings, "Server", "Ports", "Port", "PortsIPv6", "25565");
186 
187  m_RCONServer.Initialize(a_Settings);
188 
189  m_bIsConnected = true;
190 
191  m_ServerID = "-";
192  m_ShouldAuthenticate = a_ShouldAuth;
194  {
195  auto & rand = GetRandomProvider();
196  unsigned int r1 = rand.RandInt<unsigned int>(1000000000U, 0x7fffffffU);
197  unsigned int r2 = rand.RandInt<unsigned int>(1000000000U, 0x7fffffffU);
198  std::ostringstream sid;
199  sid << std::hex << r1;
200  sid << std::hex << r2;
201  m_ServerID = sid.str();
202  m_ServerID.resize(16, '0');
203  }
204 
205  // Check if both BungeeCord and online mode are on, if so, warn the admin:
206  m_ShouldAllowBungeeCord = a_Settings.GetValueSetB("Authentication", "AllowBungeeCord", false);
208  {
209  LOGWARNING("WARNING: BungeeCord is allowed and server set to online mode. This is unsafe and will not work properly. Disable either authentication or BungeeCord in settings.ini.");
210  }
211 
212  m_ShouldAllowMultiWorldTabCompletion = a_Settings.GetValueSetB("Server", "AllowMultiWorldTabCompletion", true);
213  m_ShouldLimitPlayerBlockChanges = a_Settings.GetValueSetB("AntiCheat", "LimitPlayerBlockChanges", true);
214  m_ShouldLoadOfflinePlayerData = a_Settings.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false);
215  m_ShouldLoadNamedPlayerData = a_Settings.GetValueSetB("PlayerData", "LoadNamedPlayerData", true);
216 
217  m_ClientViewDistance = a_Settings.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE);
219  {
221  LOGINFO("Setting default viewdistance to the minimum of %d", m_ClientViewDistance);
222  }
224  {
226  LOGINFO("Setting default viewdistance to the maximum of %d", m_ClientViewDistance);
227  }
228 
229  PrepareKeys();
230 
231  return true;
232 }
233 
234 
235 
236 
237 
238 bool cServer::RegisterForgeMod(const AString & a_ModName, const AString & a_ModVersion, UInt32 a_ProtocolVersionNumber)
239 {
240  auto & Mods = RegisteredForgeMods(a_ProtocolVersionNumber);
241 
242  return Mods.insert({a_ModName, a_ModVersion}).second;
243 }
244 
245 
246 
247 
248 
249 void cServer::UnregisterForgeMod(const AString & a_ModName, UInt32 a_ProtocolVersionNumber)
250 {
251  auto & Mods = RegisteredForgeMods(a_ProtocolVersionNumber);
252 
253  auto it = Mods.find(a_ModName);
254  if (it != Mods.end())
255  {
256  Mods.erase(it);
257  }
258 }
259 
260 
261 
262 
263 
265 {
266  auto it = m_ForgeModsByVersion.find(a_Protocol);
267 
268  if (it == m_ForgeModsByVersion.end())
269  {
270  AStringMap mods;
271  m_ForgeModsByVersion.insert({a_Protocol, mods});
272  return m_ForgeModsByVersion.find(a_Protocol)->second;
273  }
274 
275  return it->second;
276 }
277 
278 
279 
280 
281 
283 {
284  return RegisteredForgeMods(a_Protocol);
285 }
286 
287 
288 
289 
290 
292 {
293  cCSLock Lock(m_CSClients);
294  for (auto client : m_Clients)
295  {
296  if ((client->GetUsername()).compare(a_Username) == 0)
297  {
298  return true;
299  }
300  }
301  return false;
302 }
303 
304 
305 
306 
307 
309 {
310  LOGD("Generating protocol encryption keypair...");
313 }
314 
315 
316 
317 
318 
320 {
321  LOGD("Client \"%s\" connected!", a_RemoteIPAddress.c_str());
322  cClientHandlePtr NewHandle = std::make_shared<cClientHandle>(a_RemoteIPAddress, m_ClientViewDistance);
323  NewHandle->SetSelf(NewHandle);
324  cCSLock Lock(m_CSClients);
325  m_Clients.push_back(NewHandle);
326  return std::move(NewHandle);
327 }
328 
329 
330 
331 
332 
333 bool cServer::Tick(float a_Dt)
334 {
335  // Send the tick to the plugins, as well as let the plugin manager reload, if asked to (issue #102):
336  cPluginManager::Get()->Tick(a_Dt);
337 
338  // Let the Root process all the queued commands:
340 
341  // Tick all clients not yet assigned to a world:
342  TickClients(a_Dt);
343 
344  if (!m_bRestarting)
345  {
346  return true;
347  }
348  else
349  {
350  m_bRestarting = false;
352  return false;
353  }
354 }
355 
356 
357 
358 
359 
360 void cServer::TickClients(float a_Dt)
361 {
362  cClientHandlePtrs RemoveClients;
363  {
364  cCSLock Lock(m_CSClients);
365 
366  // Remove clients that have moved to a world (the world will be ticking them from now on)
367  for (auto itr = m_ClientsToRemove.begin(), end = m_ClientsToRemove.end(); itr != end; ++itr)
368  {
369  for (auto itrC = m_Clients.begin(), endC = m_Clients.end(); itrC != endC; ++itrC)
370  {
371  if (itrC->get() == *itr)
372  {
373  m_Clients.erase(itrC);
374  break;
375  }
376  }
377  } // for itr - m_ClientsToRemove[]
378  m_ClientsToRemove.clear();
379 
380  // Tick the remaining clients, take out those that have been destroyed into RemoveClients
381  for (auto itr = m_Clients.begin(); itr != m_Clients.end();)
382  {
383  if ((*itr)->IsDestroyed())
384  {
385  // Delete the client later, when CS is not held, to avoid deadlock: https://forum.cuberite.org/thread-374.html
386  RemoveClients.push_back(*itr);
387  itr = m_Clients.erase(itr);
388  continue;
389  }
390  (*itr)->ServerTick(a_Dt);
391  ++itr;
392  } // for itr - m_Clients[]
393  }
394 
395  // Delete the clients that have been destroyed
396  RemoveClients.clear();
397 }
398 
399 
400 
401 
402 
403 bool cServer::Start(void)
404 {
405  for (auto port: m_Ports)
406  {
407  UInt16 PortNum;
408  if (!StringToInteger(port, PortNum))
409  {
410  LOGWARNING("Invalid port specified for server: \"%s\". Ignoring.", port.c_str());
411  continue;
412  }
413  auto Handle = cNetwork::Listen(PortNum, std::make_shared<cServerListenCallbacks>(*this, PortNum));
414  if (Handle->IsListening())
415  {
416  m_ServerHandles.push_back(Handle);
417  }
418  } // for port - Ports[]
419  if (m_ServerHandles.empty())
420  {
421  LOGERROR("Couldn't open any ports. Aborting the server");
422  return false;
423  }
424  if (!m_TickThread.Start())
425  {
426  return false;
427  }
428  return true;
429 }
430 
431 
432 
433 
434 
435 bool cServer::Command(cClientHandle & a_Client, AString & a_Cmd)
436 {
437  return cRoot::Get()->GetPluginManager()->CallHookChat(*(a_Client.GetPlayer()), a_Cmd);
438 }
439 
440 
441 
442 
443 
445 {
446  AStringVector split = StringSplit(a_Cmd, " ");
447  if (split.empty())
448  {
449  return;
450  }
451 
452  // "stop" and "restart" are handled in cRoot::ExecuteConsoleCommand, our caller, due to its access to controlling variables
453 
454  // "help" and "reload" are to be handled by MCS, so that they work no matter what
455  if (split[0] == "help")
456  {
457  PrintHelp(split, a_Output);
458  a_Output.Finished();
459  return;
460  }
461  else if (split[0] == "reload")
462  {
464  a_Output.Finished();
465  return;
466  }
467  else if (split[0] == "reloadplugins")
468  {
470  a_Output.Out("Plugins reloaded");
471  a_Output.Finished();
472  return;
473  }
474  else if (split[0] == "load")
475  {
476  if (split.size() > 1)
477  {
478  cPluginManager::Get()->RefreshPluginList(); // Refresh the plugin list, so that if the plugin was added just now, it is loadable
479  a_Output.Out(cPluginManager::Get()->LoadPlugin(split[1]) ? "Plugin loaded" : "Error occurred loading plugin");
480  }
481  else
482  {
483  a_Output.Out("Usage: load <PluginFolder>");
484  }
485  a_Output.Finished();
486  return;
487  }
488  else if (split[0] == "unload")
489  {
490  if (split.size() > 1)
491  {
492  cPluginManager::Get()->UnloadPlugin(split[1]);
493  a_Output.Out("Plugin unload scheduled");
494  }
495  else
496  {
497  a_Output.Out("Usage: unload <PluginFolder>");
498  }
499  a_Output.Finished();
500  return;
501  }
502  if (split[0] == "destroyentities")
503  {
504  cRoot::Get()->ForEachWorld([](cWorld & a_World)
505  {
506  a_World.ForEachEntity([](cEntity & a_Entity)
507  {
508  if (!a_Entity.IsPlayer())
509  {
510  a_Entity.Destroy();
511  }
512  return false;
513  }
514  );
515  return false;
516  }
517  );
518  a_Output.Out("Destroyed all entities");
519  a_Output.Finished();
520  return;
521  }
522 
523  // There is currently no way a plugin can do these (and probably won't ever be):
524  else if (split[0].compare("chunkstats") == 0)
525  {
526  cRoot::Get()->LogChunkStats(a_Output);
527  a_Output.Finished();
528  return;
529  }
530 
531  else if (split[0].compare("luastats") == 0)
532  {
533  a_Output.Out(cLuaStateTracker::GetStats());
534  a_Output.Finished();
535  return;
536  }
537  else if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output, a_Cmd))
538  {
539  a_Output.Finished();
540  return;
541  }
542 
543  a_Output.Out("Unknown command, type 'help' for all commands.");
544  a_Output.Finished();
545 }
546 
547 
548 
549 
550 
551 void cServer::PrintHelp(const AStringVector & a_Split, cCommandOutputCallback & a_Output)
552 {
553  UNUSED(a_Split);
554  typedef std::pair<AString, AString> AStringPair;
555  typedef std::vector<AStringPair> AStringPairs;
556 
557  class cCallback :
559  {
560  public:
561  cCallback(void) : m_MaxLen(0) {}
562 
563  virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
564  {
565  UNUSED(a_Plugin);
566  UNUSED(a_Permission);
567  if (!a_HelpString.empty())
568  {
569  m_Commands.push_back(AStringPair(a_Command, a_HelpString));
570  if (m_MaxLen < a_Command.length())
571  {
572  m_MaxLen = a_Command.length();
573  }
574  }
575  return false;
576  }
577 
578  AStringPairs m_Commands;
579  size_t m_MaxLen;
580  } Callback;
582  std::sort(Callback.m_Commands.begin(), Callback.m_Commands.end());
583  for (AStringPairs::const_iterator itr = Callback.m_Commands.begin(), end = Callback.m_Commands.end(); itr != end; ++itr)
584  {
585  const AStringPair & cmd = *itr;
586  a_Output.Out(Printf("%-*s - %s\n", static_cast<int>(Callback.m_MaxLen), cmd.first.c_str(), cmd.second.c_str()));
587  } // for itr - Callback.m_Commands[]
588 }
589 
590 
591 
592 
593 
595 {
596  // Create an empty handler - the actual handling for the commands is performed before they are handed off to cPluginManager
597  class cEmptyHandler:
599  {
600  virtual bool ExecuteCommand(
601  const AStringVector & a_Split,
602  cPlayer * a_Player,
603  const AString & a_Command,
604  cCommandOutputCallback * a_Output = nullptr
605  ) override
606  {
607  return false;
608  }
609  };
610  auto handler = std::make_shared<cEmptyHandler>();
611 
612  // Register internal commands:
613  cPluginManager * PlgMgr = cPluginManager::Get();
614  PlgMgr->BindConsoleCommand("help", nullptr, handler, "Shows the available commands");
615  PlgMgr->BindConsoleCommand("reload", nullptr, handler, "Reloads all plugins");
616  PlgMgr->BindConsoleCommand("restart", nullptr, handler, "Restarts the server cleanly");
617  PlgMgr->BindConsoleCommand("stop", nullptr, handler, "Stops the server cleanly");
618  PlgMgr->BindConsoleCommand("chunkstats", nullptr, handler, "Displays detailed chunk memory statistics");
619  PlgMgr->BindConsoleCommand("load", nullptr, handler, "Adds and enables the specified plugin");
620  PlgMgr->BindConsoleCommand("unload", nullptr, handler, "Disables the specified plugin");
621  PlgMgr->BindConsoleCommand("destroyentities", nullptr, handler, "Destroys all entities in all worlds");
622 }
623 
624 
625 
626 
627 
629 {
630  // Stop listening on all sockets:
631  for (auto srv: m_ServerHandles)
632  {
633  srv->Close();
634  }
635  m_ServerHandles.clear();
636 
637  // Notify the tick thread and wait for it to terminate:
638  m_bRestarting = true;
640 
642 
643  // Remove all clients:
644  cCSLock Lock(m_CSClients);
645  for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr)
646  {
647  (*itr)->Destroy();
648  }
649  m_Clients.clear();
650 }
651 
652 
653 
654 
655 
656 void cServer::KickUser(int a_ClientID, const AString & a_Reason)
657 {
658  cCSLock Lock(m_CSClients);
659  for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr)
660  {
661  if ((*itr)->GetUniqueID() == a_ClientID)
662  {
663  (*itr)->Kick(a_Reason);
664  }
665  } // for itr - m_Clients[]
666 }
667 
668 
669 
670 
671 
672 void cServer::AuthenticateUser(int a_ClientID, const AString & a_Name, const cUUID & a_UUID, const Json::Value & a_Properties)
673 {
674  cCSLock Lock(m_CSClients);
675 
676  // Check max players condition within lock (expect server and authenticator thread to both call here)
677  if (GetNumPlayers() >= GetMaxPlayers())
678  {
679  KickUser(a_ClientID, "The server is currently full :(" "\n" "Try again later?");
680  return;
681  }
682 
683  for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr)
684  {
685  if ((*itr)->GetUniqueID() == a_ClientID)
686  {
687  (*itr)->Authenticate(a_Name, a_UUID, a_Properties);
688  return;
689  }
690  } // for itr - m_Clients[]
691 }
692 
693 
694 
695 
696 
void Shutdown(void)
Definition: Server.cpp:628
void PrepareKeys(void)
Loads, or generates, if missing, RSA keys for protocol encryption.
Definition: Server.cpp:308
AStringMap & RegisteredForgeMods(const UInt32 a_Protocol)
Get the Forge mods registered for a given protocol, for modification.
Definition: Server.cpp:264
void RefreshPluginList()
Refreshes the m_Plugins list based on the current contents of the Plugins folder. ...
cServer(void)
Definition: Server.cpp:117
void Set(void)
Sets the event - releases one thread that has been waiting in Wait().
Definition: Event.cpp:53
cServerListenCallbacks(cServer &a_Server, UInt16 a_Port)
Definition: Server.cpp:64
cClientHandles m_ClientsToRemove
Clients that have just been moved into a world and are to be removed from m_Clients in the next Tick(...
Definition: Server.h:193
std::atomic< bool > m_ShouldTerminate
The overriden Execute() method should check this value periodically and terminate if this is true...
Definition: IsThread.h:32
static void BindBuiltInConsoleCommands(void)
Binds the built-in console commands with the plugin manager.
Definition: Server.cpp:594
std::list< cClientHandlePtr > cClientHandlePtrs
Definition: Server.h:38
void ExecuteConsoleCommand(const AString &a_Cmd, cCommandOutputCallback &a_Output)
Executes the console command, sends output through the specified callback.
Definition: Server.cpp:444
AStringVector m_Ports
The list of ports on which the server should listen for connections.
Definition: Server.h:255
void PlayerDestroyed()
Notifies the server that a player is being destroyed; the server uses this to adjust the number of pl...
Definition: Server.cpp:157
void LogChunkStats(cCommandOutputCallback &a_Output)
Writes chunkstats, for each world and totals, to the output callback.
Definition: Root.cpp:1070
AString m_FaviconData
Definition: Server.h:214
static AString GetStats(void)
Returns the statistics for all the registered LuaStates.
Definition: LuaState.cpp:157
std::atomic_size_t m_PlayerCount
Number of players currently playing in the server.
Definition: Server.h:196
bool RegisterForgeMod(const AString &a_ModName, const AString &a_ModVersion, UInt32 a_ProtocolVersionNumber)
Add a Forge mod to the server ping list.
Definition: Server.cpp:238
bool m_ShouldLoadOfflinePlayerData
True if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found...
Definition: Server.h:240
#define VERIFY(x)
Definition: Globals.h:339
bool StringToInteger(const AString &a_str, T &a_Num)
Parses any integer type.
Definition: StringUtils.h:161
bool Start(void)
Definition: Server.cpp:403
void UnloadPlugin(const AString &a_PluginFolder)
Queues the specified plugin to be unloaded in the next call to Tick().
const AStringMap & GetRegisteredForgeMods(const UInt32 a_Protocol)
Get the Forge mods (map of ModName -> ModVersionString) registered for a given protocol.
Definition: Server.cpp:282
bool m_ShouldLoadNamedPlayerData
True if old-style playernames should be used to load data for players whose regular datafiles cannot ...
Definition: Server.h:245
Interface that must be provided by any class that implements a command handler, either in-game or con...
cEvent m_RestartEvent
Definition: Server.h:225
bool m_bAllowMultiLogin
True - allow same username to login more than once False - only once.
Definition: Server.h:222
MTRand & GetRandomProvider()
Returns the current thread&#39;s random number source.
Definition: FastRandom.cpp:20
#define FILE_IO_PREFIX
Definition: Globals.h:196
bool ForEachWorld(cWorldListCallback a_Callback)
Calls the callback for each world; returns true if the callback didn&#39;t abort (return true) ...
Definition: Root.cpp:656
cTickThread m_TickThread
Definition: Server.h:224
void ReloadPlugins()
Schedules a reload of the plugins to happen within the next call to Tick().
bool m_bIsConnected
Definition: Server.h:200
Definition: Player.h:27
static AString ReadWholeFile(const AString &a_FileName)
Returns the entire contents of the specified file as a string.
Definition: File.cpp:573
bool m_ShouldAllowBungeeCord
True if BungeeCord handshake packets (with player UUID) should be accepted.
Definition: Server.h:248
AString m_ShutdownMessage
Definition: Server.h:213
cCriticalSection m_CSClients
Protects m_Clients and m_ClientsToRemove against multithreaded access.
Definition: Server.h:187
AString GetPubKeyDER(void)
Returns the public key part encoded in ASN1 DER encoding.
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
cRCONServer m_RCONServer
Definition: Server.h:210
void LOGERROR(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:183
void UnregisterForgeMod(const AString &a_ModName, UInt32 a_ProtocolVersionNumber)
Remove a Forge mod to the server ping list.
Definition: Server.cpp:249
static const int MIN_VIEW_DISTANCE
Definition: ClientHandle.h:57
virtual void Destroy(bool a_ShouldBroadcast=true)
Destroys the entity and schedules it for memory freeing; if a_ShouldBroadcast is set to true...
Definition: Entity.cpp:219
virtual void OnError(int a_ErrorCode, const AString &a_ErrorMsg) override
Called when the socket fails to listen on the specified port.
Definition: Server.cpp:58
virtual void Execute(void) override
This is the main thread entrypoint.
Definition: Server.cpp:88
void Tick(float a_Dt)
Called each tick, calls the plugins&#39; OnTick hook, as well as processes plugin events (addition...
bool m_ShouldAllowMultiWorldTabCompletion
True if usernames should be completed across worlds.
Definition: Server.h:251
cServerHandlePtrs m_ServerHandles
The network sockets listening for client connections.
Definition: Server.h:184
virtual void Finished(void)
Called when the command processing has been finished.
Definition: CommandOutput.h:26
void ClientMovedToWorld(const cClientHandle *a_Client)
Don&#39;t tick a_Client anymore, it will be ticked from its cPlayer instead.
Definition: Server.cpp:138
Definition: UUID.h:10
Definition: Server.h:55
std::vector< AString > AStringVector
Definition: StringUtils.h:14
cTickThread(cServer &a_Server)
Definition: Server.cpp:78
size_t GetMaxPlayers(void) const
Definition: Server.h:70
void PlayerCreated()
Notifies the server that a player was created; the server uses this to adjust the number of players...
Definition: Server.cpp:148
void Wait(void)
Waits until the event has been set.
Definition: Event.cpp:24
void Out(const char *a_Fmt, fmt::ArgList)
Syntax sugar function, calls Out() with Printf()-ed parameters; appends a newline".
void KickUser(int a_ClientID, const AString &a_Reason)
Definition: Server.cpp:656
virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString &a_RemoteIPAddress, UInt16 a_RemotePort) override
Called when the TCP server created with Listen() receives a new incoming connection.
Definition: Server.cpp:51
Definition: World.h:65
int m_ClientViewDistance
Definition: Server.h:198
std::map< UInt32, AStringMap > m_ForgeModsByVersion
Map of protocol version to Forge mods (map of ModName -> ModVersionString)
Definition: Server.h:219
cPlayer * GetPlayer(void)
Definition: ClientHandle.h:75
bool IsPlayerInQueue(AString a_Username)
Check if the player is queued to be transferred to a World.
Definition: Server.cpp:291
static const int DEFAULT_VIEW_DISTANCE
Definition: ClientHandle.h:54
bool m_ShouldLimitPlayerBlockChanges
True if limit for number of block changes per tick by a player should be enabled. ...
Definition: Server.h:235
void SaveAllChunks(void)
Saves all chunks in all worlds.
Definition: Root.cpp:770
bool ForEachEntity(cEntityCallback a_Callback)
Calls the callback for each entity in the entire world; returns true if all entities processed...
Definition: World.cpp:2711
void LOGINFO(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:165
AString & Printf(AString &str, const char *format, fmt::ArgList args)
Output the formatted text into the string.
Definition: StringUtils.cpp:55
std::atomic< bool > m_bRestarting
Definition: Server.h:202
cTCPLink::cCallbacksPtr OnConnectionAccepted(const AString &a_RemoteIPAddress)
Creates a new cClientHandle instance and adds it to the list of clients.
Definition: Server.cpp:319
#define MCS_CLIENT_VERSIONS
std::map< AString, AString > AStringMap
A string dictionary, used for key-value pairs.
Definition: StringUtils.h:18
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:174
#define LOGD(...)
Definition: LoggerSimple.h:40
#define MCS_PROTOCOL_VERSIONS
bool m_ShouldAuthenticate
If true, players will be online-authenticated agains Mojang servers.
Definition: Server.h:232
size_t GetNumPlayers(void) const
Definition: Server.h:71
virtual AString GetValueSet(const AString &keyname, const AString &valuename, const AString &defValue="")=0
Gets the value; if not found, write the default to the repository.
Definition: Plugin.h:19
void TickClients(float a_Dt)
Ticks the clients in m_Clients, manages the list in respect to removing clients.
Definition: Server.cpp:360
#define UNUSED
Definition: Globals.h:152
std::list< cClientHandle * > ClientList
Definition: Server.cpp:36
bool InitServer(cSettingsRepositoryInterface &a_Settings, bool a_ShouldAuth)
Definition: Server.cpp:166
unsigned short UInt16
Definition: Globals.h:114
std::shared_ptr< cCallbacks > cCallbacksPtr
Definition: Network.h:63
bool Command(cClientHandle &a_Client, AString &a_Cmd)
Definition: Server.cpp:435
Callbacks used when listening for incoming connections as a server.
Definition: Network.h:244
void TickCommands(void)
Executes commands queued in the command queue.
Definition: Root.cpp:675
std::string AString
Definition: StringUtils.h:13
virtual bool GetValueSetB(const AString &keyname, const AString &valuename, const bool defValue=false)=0
size_t m_MaxPlayers
Definition: Server.h:215
bool IsPlayer(void) const
Definition: Entity.h:171
void Initialize(cSettingsRepositoryInterface &a_Settings)
Definition: RCONServer.cpp:137
AString m_ServerID
The server ID used for client authentication.
Definition: Server.h:228
void PrintHelp(const AStringVector &a_Split, cCommandOutputCallback &a_Output)
Lists all available console commands and their helpstrings.
Definition: Server.cpp:551
static cRoot * Get()
Definition: Root.h:51
Definition: Entity.h:73
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:76
static cServerHandlePtr Listen(UInt16 a_Port, cListenCallbacksPtr a_ListenCallbacks)
Opens up the specified port for incoming connections.
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
Interface that provides the methods available on a single TCP connection.
Definition: Network.h:33
unsigned int UInt32
Definition: Globals.h:113
AString m_Description
Definition: Server.h:212
virtual void OnAccepted(cTCPLink &a_Link) override
Called when the TCP server created with Listen() creates a new link for an incoming connection...
Definition: Server.cpp:56
bool ForEachConsoleCommand(cCommandEnumCallback &a_Callback)
Calls a_Callback for each bound console command, returns true if all commands were enumerated...
AStringVector ReadUpgradeIniPorts(cSettingsRepositoryInterface &a_Settings, const AString &a_KeyName, const AString &a_PortsValueName, const AString &a_OldIPv4ValueName, const AString &a_OldIPv6ValueName, const AString &a_DefaultValue)
Reads the list of ports from the INI file, possibly upgrading from IPv4 / IPv6-specific values into n...
Definition: IniFile.cpp:924
cServer & m_Server
Definition: Server.cpp:48
cServer & m_Server
Definition: Server.h:176
Interface for a callback that receives command output The Out() function is called for any output the...
Definition: CommandOutput.h:13
cClientHandlePtrs m_Clients
Clients that are connected to the server and not yet assigned to a cWorld.
Definition: Server.h:190
static const int MAX_VIEW_DISTANCE
Definition: ClientHandle.h:56
Used as a callback for enumerating bound commands.
AString m_PublicKeyDER
Public key for m_PrivateKey, ASN1-DER-encoded.
Definition: Server.h:208
bool Tick(float a_Dt)
Definition: Server.cpp:333
bool m_bIsHardcore
Definition: Server.h:216
std::shared_ptr< cClientHandle > cClientHandlePtr
Definition: ClientHandle.h:39
bool CallHookChat(cPlayer &a_Player, AString &a_Message)
void AuthenticateUser(int a_ClientID, const AString &a_Name, const cUUID &a_UUID, const Json::Value &a_Properties)
Authenticates the specified user, called by cAuthenticator.
Definition: Server.cpp:672
virtual int GetValueSetI(const AString &keyname, const AString &valuename, const int defValue=0)=0
bool Start(void)
Starts the thread; returns without waiting for the actual start.
Definition: IsThread.cpp:80
cPluginManager * GetPluginManager(void)
Definition: Root.h:114
AString Base64Encode(const AString &a_Input)
Encodes a string into Base64.
cRsaPrivateKey m_PrivateKey
The private key used for the assymetric encryption start in the protocols.
Definition: Server.h:205
bool Generate(unsigned a_KeySizeBits=1024)
Generates a new key within this object, with the specified size in bits.