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 
28 
29 
30 
32 // cServerListenCallbacks:
33 
36 {
39 
40  virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override
41  {
42  return m_Server.OnConnectionAccepted(a_RemoteIPAddress);
43  }
44 
45  virtual void OnAccepted(cTCPLink & a_Link) override {}
46 
47  virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
48  {
49  LOGWARNING("Cannot listen on port %d: %d (%s).", m_Port, a_ErrorCode, a_ErrorMsg.c_str());
50  }
51 
52 public:
53  cServerListenCallbacks(cServer & a_Server, UInt16 a_Port):
54  m_Server(a_Server),
55  m_Port(a_Port)
56  {
57  }
58 };
59 
60 
61 
62 
63 
65 // cServer::cTickThread:
66 
68  Super("Server Ticker"),
69  m_Server(a_Server)
70 {
71 }
72 
73 
74 
75 
76 
78 {
79  auto LastTime = std::chrono::steady_clock::now();
80  static const auto msPerTick = std::chrono::milliseconds(50);
81 
82  while (!m_ShouldTerminate)
83  {
84  auto NowTime = std::chrono::steady_clock::now();
85  auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(NowTime - LastTime).count();
86  m_Server.Tick(static_cast<float>(msec));
87  auto TickTime = std::chrono::steady_clock::now() - NowTime;
88 
89  if (TickTime < msPerTick)
90  {
91  // Stretch tick time until it's at least msPerTick
92  std::this_thread::sleep_for(msPerTick - TickTime);
93  }
94 
95  LastTime = NowTime;
96  }
97 }
98 
99 
100 
101 
102 
104 // cServer:
105 
107  m_PlayerCount(0),
109  m_bIsConnected(false),
110  m_RCONServer(*this),
111  m_MaxPlayers(0),
112  m_bIsHardcore(false),
113  m_TickThread(*this),
114  m_ShouldAuthenticate(false),
115  m_UpTime(0)
116 {
117  // Initialize the LuaStateTracker singleton before the app goes multithreaded:
119 }
120 
121 
122 
123 
124 
126 {
127  cCSLock Lock(m_CSClients);
128  m_ClientsToRemove.push_back(const_cast<cClientHandle *>(a_Client));
129 }
130 
131 
132 
133 
134 
136 {
137  m_PlayerCount++;
138 }
139 
140 
141 
142 
143 
145 {
146  m_PlayerCount--;
147 }
148 
149 
150 
151 
152 
153 bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_ShouldAuth)
154 {
155  m_Description = a_Settings.GetValueSet("Server", "Description", "Cuberite - in C++!");
156  m_ShutdownMessage = a_Settings.GetValueSet("Server", "ShutdownMessage", "Server shutdown");
157  m_MaxPlayers = static_cast<size_t>(a_Settings.GetValueSetI("Server", "MaxPlayers", 100));
158  m_bIsHardcore = a_Settings.GetValueSetB("Server", "HardcoreEnabled", false);
159  m_bAllowMultiLogin = a_Settings.GetValueSetB("Server", "AllowMultiLogin", false);
160  m_RequireResourcePack = a_Settings.GetValueSetB("Server", "RequireResourcePack", false);
161  m_ResourcePackUrl = a_Settings.GetValueSet("Server", "ResourcePackUrl", "");
162  m_CustomRedirectUrl = a_Settings.GetValueSet("Server", "CustomRedirectUrl", "https://youtu.be/dQw4w9WgXcQ");
163 
164  m_FaviconData = Base64Encode(cFile::ReadWholeFile(AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind
165 
166  if (m_bIsConnected)
167  {
168  LOGERROR("ERROR: Trying to initialize server while server is already running!");
169  return false;
170  }
171 
172  LOGINFO("Compatible clients: %s", MCS_CLIENT_VERSIONS);
173  LOGD("Compatible protocol versions %s", MCS_PROTOCOL_VERSIONS);
174 
175  m_Ports = ReadUpgradeIniPorts(a_Settings, "Server", "Ports", "Port", "PortsIPv6", "25565");
176 
177  m_RCONServer.Initialize(a_Settings);
178 
179  m_bIsConnected = true;
180 
181  m_ServerID = "-";
182  m_ShouldAuthenticate = a_ShouldAuth;
184  {
185  auto & rand = GetRandomProvider();
186  unsigned int r1 = rand.RandInt<unsigned int>(1000000000U, 0x7fffffffU);
187  unsigned int r2 = rand.RandInt<unsigned int>(1000000000U, 0x7fffffffU);
188  std::ostringstream sid;
189  sid << std::hex << r1;
190  sid << std::hex << r2;
191  m_ServerID = sid.str();
192  m_ServerID.resize(16, '0');
193  }
194 
195  // Check if both BungeeCord and online mode are on, if so, warn the admin:
196  m_ShouldAllowBungeeCord = a_Settings.GetValueSetB("Authentication", "AllowBungeeCord", false);
197  m_OnlyAllowBungeeCord = a_Settings.GetValueSetB("Authentication", "OnlyAllowBungeeCord", false);
198  m_ProxySharedSecret = a_Settings.GetValueSet("Authentication", "ProxySharedSecret", "");
199 
201  {
202  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.");
203  }
204 
206  {
207  LOGWARNING("WARNING: There is not a Proxy Forward Secret set up, and any proxy server can forward a player to this server unless closed from the internet.");
208  }
209 
210  m_ShouldAllowMultiWorldTabCompletion = a_Settings.GetValueSetB("Server", "AllowMultiWorldTabCompletion", true);
211  m_ShouldLimitPlayerBlockChanges = a_Settings.GetValueSetB("AntiCheat", "LimitPlayerBlockChanges", true);
212 
213  const auto ClientViewDistance = a_Settings.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE);
214  if (ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE)
215  {
217  LOGINFO("Setting default view distance to the minimum of %d", m_ClientViewDistance);
218  }
219  else if (ClientViewDistance > cClientHandle::MAX_VIEW_DISTANCE)
220  {
222  LOGINFO("Setting default view distance to the maximum of %d", m_ClientViewDistance);
223  }
224  else
225  {
226  m_ClientViewDistance = 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 
291 bool cServer::IsPlayerInQueue(const AString & a_Username)
292 {
293  cCSLock Lock(m_CSClients);
294  for (const 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  cCSLock Lock(m_CSClients);
324  m_Clients.push_back(NewHandle);
325  return NewHandle;
326 }
327 
328 
329 
330 
331 
332 void cServer::Tick(float a_Dt)
333 {
334  // Update server uptime
335  m_UpTime++;
336 
337  // Send the tick to the plugins, as well as let the plugin manager reload, if asked to (issue #102):
338  cPluginManager::Get()->Tick(a_Dt);
339 
340  // Process all the queued commands:
341  TickCommands();
342 
343  // Tick all clients not yet assigned to a world:
344  TickClients(a_Dt);
345 
346  // Process all queued tasks
347  TickQueuedTasks();
348 }
349 
350 
351 
352 
353 
354 void cServer::TickClients(float a_Dt)
355 {
356  cClientHandlePtrs RemoveClients;
357  {
358  cCSLock Lock(m_CSClients);
359 
360  // Remove clients that have moved to a world (the world will be ticking them from now on)
361  for (auto itr = m_ClientsToRemove.begin(), end = m_ClientsToRemove.end(); itr != end; ++itr)
362  {
363  for (auto itrC = m_Clients.begin(), endC = m_Clients.end(); itrC != endC; ++itrC)
364  {
365  if (itrC->get() == *itr)
366  {
367  m_Clients.erase(itrC);
368  break;
369  }
370  }
371  } // for itr - m_ClientsToRemove[]
372  m_ClientsToRemove.clear();
373 
374  // Tick the remaining clients, take out those that have been destroyed into RemoveClients
375  for (auto itr = m_Clients.begin(); itr != m_Clients.end();)
376  {
377  auto & Client = *itr;
378 
379  Client->ServerTick(a_Dt);
380  if (Client->IsDestroyed())
381  {
382  // Delete the client later, when CS is not held, to avoid deadlock: https://forum.cuberite.org/thread-374.html
383  RemoveClients.push_back(std::move(Client));
384  itr = m_Clients.erase(itr);
385  continue;
386  }
387 
388  ++itr;
389  } // for itr - m_Clients[]
390  }
391 
392  // Delete the clients that have been destroyed
393  RemoveClients.clear();
394 }
395 
396 
397 
398 
399 
400 bool cServer::Start(void)
401 {
402  for (const auto & port: m_Ports)
403  {
404  UInt16 PortNum;
405  if (!StringToInteger(port, PortNum))
406  {
407  LOGWARNING("Invalid port specified for server: \"%s\". Ignoring.", port.c_str());
408  continue;
409  }
410  auto Handle = cNetwork::Listen(PortNum, std::make_shared<cServerListenCallbacks>(*this, PortNum));
411  if (Handle->IsListening())
412  {
413  m_ServerHandles.push_back(Handle);
414  }
415  } // for port - Ports[]
416  if (m_ServerHandles.empty())
417  {
418  LOGERROR("Couldn't open any ports. Aborting the server");
419  return false;
420  }
422  return true;
423 }
424 
425 
426 
427 
428 
429 bool cServer::Command(cClientHandle & a_Client, AString & a_Cmd)
430 {
431  bool Res = cRoot::Get()->DoWithPlayerByUUID(
432  a_Client.GetUUID(),
433  [&](cPlayer & a_Player)
434  {
435  return cRoot::Get()->GetPluginManager()->CallHookChat(a_Player, a_Cmd);
436  }
437  );
438  return Res;
439 }
440 
441 
442 
443 
444 
446 {
447  // Put the command into a queue (Alleviates FS #363):
449  m_PendingCommands.emplace_back(a_Cmd, &a_Output);
450 }
451 
452 
453 
454 
455 
456 void cServer::ScheduleTask(cTickTime a_DelayTicks, std::function<void(cServer &)> a_Task)
457 {
458  const auto TargetTick = a_DelayTicks + m_UpTime;
459  // Insert the task into the list of scheduled tasks
460  {
461  cCSLock Lock(m_CSTasks);
462  m_Tasks.emplace_back(TargetTick, std::move(a_Task));
463  }
464 }
465 
466 
467 
468 
469 
471 {
472  AStringVector split = StringSplit(a_Cmd, " ");
473  if (split.empty())
474  {
475  return;
476  }
477 
478  // "stop" and "restart" are handled in cRoot::ExecuteConsoleCommand, our caller, due to its access to controlling variables
479 
480  // "help" and "reload" are to be handled by Cuberite, so that they work no matter what
481  if (split[0] == "help")
482  {
483  PrintHelp(split, a_Output);
484  a_Output.Finished();
485  return;
486  }
487  else if (split[0] == "reload")
488  {
489  if (split.size() > 1)
490  {
491  cPluginManager::Get()->ReloadPlugin(split[1]);
492  a_Output.OutLn("Plugin reload scheduled");
493  }
494  else
495  {
497  }
498  a_Output.Finished();
499  return;
500  }
501  else if (split[0] == "reloadplugins")
502  {
504  a_Output.OutLn("Plugins reloaded");
505  a_Output.Finished();
506  return;
507  }
508  else if (split[0] == "reloadweb")
509  {
510  cRoot::Get()->GetWebAdmin()->Reload();
511  a_Output.OutLn("WebAdmin configuration reloaded");
512  a_Output.Finished();
513  return;
514  }
515  else if (split[0] == "load")
516  {
517  if (split.size() > 1)
518  {
519  cPluginManager::Get()->RefreshPluginList(); // Refresh the plugin list, so that if the plugin was added just now, it is loadable
520  a_Output.OutLn(cPluginManager::Get()->LoadPlugin(split[1]) ? "Plugin loaded" : "Error occurred loading plugin");
521  }
522  else
523  {
524  a_Output.OutLn("Usage: load <PluginFolder>");
525  }
526  a_Output.Finished();
527  return;
528  }
529  else if (split[0] == "unload")
530  {
531  if (split.size() > 1)
532  {
533  cPluginManager::Get()->UnloadPlugin(split[1]);
534  a_Output.OutLn("Plugin unload scheduled");
535  }
536  else
537  {
538  a_Output.OutLn("Usage: unload <PluginFolder>");
539  }
540  a_Output.Finished();
541  return;
542  }
543  if (split[0] == "destroyentities")
544  {
545  cRoot::Get()->ForEachWorld([](cWorld & a_World)
546  {
547  a_World.ForEachEntity([](cEntity & a_Entity)
548  {
549  if (!a_Entity.IsPlayer())
550  {
551  a_Entity.Destroy();
552  }
553  return false;
554  }
555  );
556  return false;
557  }
558  );
559  a_Output.OutLn("Destroyed all entities");
560  a_Output.Finished();
561  return;
562  }
563 
564  // There is currently no way a plugin can do these (and probably won't ever be):
565  else if (split[0].compare("chunkstats") == 0)
566  {
567  cRoot::Get()->LogChunkStats(a_Output);
568  a_Output.Finished();
569  return;
570  }
571 
572  else if (split[0].compare("luastats") == 0)
573  {
574  a_Output.OutLn(cLuaStateTracker::GetStats());
575  a_Output.Finished();
576  return;
577  }
578  else if (cPluginManager::Get()->ExecuteConsoleCommand(split, a_Output, a_Cmd))
579  {
580  a_Output.Finished();
581  return;
582  }
583 
584  a_Output.OutLn("Unknown command, type 'help' for all commands.");
585  a_Output.Finished();
586 }
587 
588 
589 
590 
591 
592 void cServer::PrintHelp(const AStringVector & a_Split, cCommandOutputCallback & a_Output)
593 {
594  UNUSED(a_Split);
595  typedef std::pair<AString, AString> AStringPair;
596  typedef std::vector<AStringPair> AStringPairs;
597 
598  class cCallback :
600  {
601  public:
602  cCallback(void) : m_MaxLen(0) {}
603 
604  virtual bool Command(const AString & a_Command, const cPlugin * a_Plugin, const AString & a_Permission, const AString & a_HelpString) override
605  {
606  UNUSED(a_Plugin);
607  UNUSED(a_Permission);
608  if (!a_HelpString.empty())
609  {
610  m_Commands.push_back(AStringPair(a_Command, a_HelpString));
611  if (m_MaxLen < a_Command.length())
612  {
613  m_MaxLen = a_Command.length();
614  }
615  }
616  return false;
617  }
618 
619  AStringPairs m_Commands;
620  size_t m_MaxLen;
621  } Callback;
623  std::sort(Callback.m_Commands.begin(), Callback.m_Commands.end());
624  for (AStringPairs::const_iterator itr = Callback.m_Commands.begin(), end = Callback.m_Commands.end(); itr != end; ++itr)
625  {
626  const AStringPair & cmd = *itr;
627  // Output the commands and their help strings, with all the commands aligned to the same width
628  a_Output.OutLn(fmt::format(FMT_STRING("{1:{0}s} - {2}"), Callback.m_MaxLen, cmd.first, cmd.second));
629  } // for itr - Callback.m_Commands[]
630 }
631 
632 
633 
634 
635 
637 {
638  // Create an empty handler - the actual handling for the commands is performed before they are handed off to cPluginManager
639  class cEmptyHandler:
641  {
642  virtual bool ExecuteCommand(
643  const AStringVector & a_Split,
644  cPlayer * a_Player,
645  const AString & a_Command,
646  cCommandOutputCallback * a_Output = nullptr
647  ) override
648  {
649  return false;
650  }
651  };
652  auto handler = std::make_shared<cEmptyHandler>();
653 
654  // Register internal commands:
655  cPluginManager * PlgMgr = cPluginManager::Get();
656  PlgMgr->BindConsoleCommand("help", nullptr, handler, "Shows the available commands");
657  PlgMgr->BindConsoleCommand("reload", nullptr, handler, "Reloads all plugins");
658  PlgMgr->BindConsoleCommand("reloadweb", nullptr, handler, "Reloads the webadmin configuration");
659  PlgMgr->BindConsoleCommand("restart", nullptr, handler, "Restarts the server cleanly");
660  PlgMgr->BindConsoleCommand("stop", nullptr, handler, "Stops the server cleanly");
661  PlgMgr->BindConsoleCommand("chunkstats", nullptr, handler, "Displays detailed chunk memory statistics");
662  PlgMgr->BindConsoleCommand("load", nullptr, handler, "Adds and enables the specified plugin");
663  PlgMgr->BindConsoleCommand("unload", nullptr, handler, "Disables the specified plugin");
664  PlgMgr->BindConsoleCommand("destroyentities", nullptr, handler, "Destroys all entities in all worlds");
665 }
666 
667 
668 
669 
670 
672 {
673  // Stop listening on all sockets:
674  for (const auto & srv: m_ServerHandles)
675  {
676  srv->Close();
677  }
678  m_ServerHandles.clear();
679 
680  // Notify the tick thread and wait for it to terminate:
681  m_TickThread.Stop();
682 
683  // Save all chunks in all worlds, wait for chunks to be sent to the ChunkStorage queue for each world:
685 
686  // Remove all clients:
687  cCSLock Lock(m_CSClients);
688  for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr)
689  {
690  (*itr)->Destroy();
691  }
692  m_Clients.clear();
693 }
694 
695 
696 
697 
698 
699 void cServer::KickUser(int a_ClientID, const AString & a_Reason)
700 {
701  cCSLock Lock(m_CSClients);
702  for (auto itr = m_Clients.begin(); itr != m_Clients.end(); ++itr)
703  {
704  if ((*itr)->GetUniqueID() == a_ClientID)
705  {
706  (*itr)->Kick(a_Reason);
707  }
708  } // for itr - m_Clients[]
709 }
710 
711 
712 
713 
714 
715 void cServer::AuthenticateUser(int a_ClientID, AString && a_Username, const cUUID & a_UUID, Json::Value && a_Properties)
716 {
717  cCSLock Lock(m_CSClients);
718 
719  // Check max players condition within lock (expect server and authenticator thread to both call here)
720  if (GetNumPlayers() >= GetMaxPlayers())
721  {
722  KickUser(a_ClientID, "The server is currently full :(" "\n" "Try again later?");
723  return;
724  }
725 
726  for (const auto & Client : m_Clients)
727  {
728  if (Client->GetUniqueID() == a_ClientID)
729  {
730  Client->Authenticate(std::move(a_Username), a_UUID, std::move(a_Properties));
731  return;
732  }
733  }
734 }
735 
736 
737 
738 
739 
741 {
742  decltype(m_PendingCommands) PendingCommands;
743  {
745  std::swap(PendingCommands, m_PendingCommands);
746  }
747 
748  // Execute any pending commands:
749  for (const auto & Command : PendingCommands)
750  {
751  ExecuteConsoleCommand(Command.first, *Command.second);
752  }
753 }
754 
755 
756 
757 
758 
760 {
761  // Move the tasks to be executed to a seperate vector to avoid deadlocks on
762  // accessing m_Tasks
763  decltype(m_Tasks) Tasks;
764  {
765  cCSLock Lock(m_CSTasks);
766  if (m_Tasks.empty())
767  {
768  return;
769  }
770 
771  // Partition everything to be executed by returning false to move to end
772  // of list if time reached
773  auto MoveBeginIterator = std::partition(
774  m_Tasks.begin(), m_Tasks.end(),
775  [this](const decltype(m_Tasks)::value_type & a_Task)
776  {
777  return a_Task.first >= m_UpTime;
778  });
779 
780  // Cut all the due tasks from m_Tasks into Tasks:
781  Tasks.insert(
782  Tasks.end(), std::make_move_iterator(MoveBeginIterator),
783  std::make_move_iterator(m_Tasks.end()));
784  m_Tasks.erase(MoveBeginIterator, m_Tasks.end());
785  }
786 
787  // Execute each task:
788  for (const auto & Task : Tasks)
789  {
790  Task.second(*this);
791  } // for itr - m_Tasks[]
792 }
std::shared_ptr< cClientHandle > cClientHandlePtr
Definition: ClientHandle.h:41
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
#define VERIFY(x)
Definition: Globals.h:280
unsigned int UInt32
Definition: Globals.h:157
std::chrono::duration< signed int, std::ratio_multiply< std::chrono::milliseconds::period, std::ratio< 50 > >> cTickTime
Definition: Globals.h:364
unsigned short UInt16
Definition: Globals.h:158
#define UNUSED
Definition: Globals.h:72
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:923
void LOGERROR(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:73
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
#define LOGD
Definition: LoggerSimple.h:83
void LOGINFO(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:61
#define MCS_CLIENT_VERSIONS
#define MCS_PROTOCOL_VERSIONS
std::list< cClientHandlePtr > cClientHandlePtrs
Definition: Server.h:38
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:55
AString Base64Encode(const AString &a_Input)
Encodes a string into Base64.
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
bool StringToInteger(const AString &a_str, T &a_Num)
Parses any integer type.
Definition: StringUtils.h:143
std::map< AString, AString > AStringMap
A string dictionary, used for key-value pairs.
Definition: StringUtils.h:16
static AString GetStats(void)
Returns the statistics for all the registered LuaStates.
Definition: LuaState.cpp:154
Definition: Plugin.h:20
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
void RefreshPluginList()
Refreshes the m_Plugins list based on the current contents of the Plugins folder.
void UnloadPlugin(const AString &a_PluginFolder)
Queues the specified plugin to be unloaded in the next call to Tick().
bool ForEachConsoleCommand(cCommandEnumCallback &a_Callback)
Calls a_Callback for each bound console command, returns true if all commands were enumerated.
void Tick(float a_Dt)
Called each tick, calls the plugins' OnTick hook, as well as processes plugin events (addition,...
void ReloadPlugins()
Schedules a reload of the plugins to happen within the next call to Tick().
void ReloadPlugin(const AString &a_PluginFolder)
Queues the specified plugin to be reloaded in the next call to Tick().
bool BindConsoleCommand(const AString &a_Command, cPlugin *a_Plugin, cCommandHandlerPtr a_Handler, const AString &a_HelpString)
Binds a console command to the specified handler.
Used as a callback for enumerating bound commands.
Interface that must be provided by any class that implements a command handler, either in-game or con...
static const int MAX_VIEW_DISTANCE
Definition: ClientHandle.h:59
const cUUID & GetUUID(void) const
Returns the player's UUID, as used by the protocol.
Definition: ClientHandle.h:81
static const int MIN_VIEW_DISTANCE
Definition: ClientHandle.h:60
static const int DEFAULT_VIEW_DISTANCE
Definition: ClientHandle.h:57
Interface for a callback that receives command output The Out() function is called for any output the...
Definition: CommandOutput.h:16
virtual void Finished()
Called when the command processing has been finished.
Definition: CommandOutput.h:31
void OutLn(const AString &aText)
Outputs the specified text, plus a newline.
Definition: CommandOutput.h:24
Definition: Entity.h:76
bool IsPlayer(void) const
Definition: Entity.h:160
Definition: Player.h:29
ContiguousByteBuffer GetPubKeyDER(void)
Returns the public key part encoded in ASN1 DER encoding.
bool Generate(unsigned a_KeySizeBits=1024)
Generates a new key within this object, with the specified size in bits.
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
static AString ReadWholeFile(const AString &a_FileName)
Returns the entire contents of the specified file as a string.
Definition: File.cpp:573
void Stop(void)
Signals the thread to terminate and waits until it's finished.
Definition: IsThread.cpp:48
void Start(void)
Starts the thread; returns without waiting for the actual start.
Definition: IsThread.cpp:35
Interface that provides the methods available on a single TCP connection.
Definition: Network.h:42
std::shared_ptr< cCallbacks > cCallbacksPtr
Definition: Network.h:71
static cServerHandlePtr Listen(UInt16 a_Port, cListenCallbacksPtr a_ListenCallbacks)
Opens up the specified port for incoming connections.
Callbacks used when listening for incoming connections as a server.
Definition: Network.h:254
void Initialize(cSettingsRepositoryInterface &a_Settings)
Definition: RCONServer.cpp:137
static cRoot * Get()
Definition: Root.h:52
bool ForEachWorld(cWorldListCallback a_Callback)
Calls the callback for each world; returns true if the callback didn't abort (return true)
Definition: Root.cpp:480
void SaveAllChunksNow(void)
Saves all chunks in all worlds synchronously (waits until dirty chunks have been sent to the ChunkSto...
Definition: Root.cpp:585
bool DoWithPlayerByUUID(const cUUID &a_PlayerUUID, cPlayerListCallback a_Callback)
Finds the player over his uuid and calls the callback.
Definition: Root.cpp:747
cWebAdmin * GetWebAdmin(void)
Definition: Root.h:110
void LogChunkStats(cCommandOutputCallback &a_Output)
Writes chunkstats, for each world and totals, to the output callback.
Definition: Root.cpp:923
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:40
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:47
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:45
cServer & m_Server
Definition: Server.cpp:37
cServerListenCallbacks(cServer &a_Server, UInt16 a_Port)
Definition: Server.cpp:53
Definition: Server.h:56
AString m_CustomRedirectUrl
Definition: Server.h:231
cRCONServer m_RCONServer
Definition: Server.h:222
void TickClients(float a_Dt)
Ticks the clients in m_Clients, manages the list in respect to removing clients.
Definition: Server.cpp:354
void PlayerCreated()
Notifies the server that a player was created; the server uses this to adjust the number of players.
Definition: Server.cpp:135
void ExecuteConsoleCommand(const AString &a_Cmd, cCommandOutputCallback &a_Output)
Executes the console command, sends output through the specified callback.
Definition: Server.cpp:470
bool m_ShouldLimitPlayerBlockChanges
True if limit for number of block changes per tick by a player should be enabled.
Definition: Server.h:249
int m_ClientViewDistance
Definition: Server.h:212
size_t GetMaxPlayers(void) const
Definition: Server.h:70
void PrepareKeys(void)
Loads, or generates, if missing, RSA keys for protocol encryption.
Definition: Server.cpp:308
cTCPLink::cCallbacksPtr OnConnectionAccepted(const AString &a_RemoteIPAddress)
Creates a new cClientHandle instance and adds it to the list of clients.
Definition: Server.cpp:319
void PrintHelp(const AStringVector &a_Split, cCommandOutputCallback &a_Output)
Lists all available console commands and their helpstrings.
Definition: Server.cpp:592
bool m_bAllowMultiLogin
True - allow same username to login more than once False - only once.
Definition: Server.h:237
void TickCommands(void)
Executes commands queued in the command queue.
Definition: Server.cpp:740
void UnregisterForgeMod(const AString &a_ModName, UInt32 a_ProtocolVersionNumber)
Remove a Forge mod to the server ping list.
Definition: Server.cpp:249
cServer(void)
Definition: Server.cpp:106
void Tick(float a_Dt)
Definition: Server.cpp:332
ContiguousByteBuffer m_PublicKeyDER
Public key for m_PrivateKey, ASN1-DER-encoded.
Definition: Server.h:220
bool IsPlayerInQueue(const AString &a_Username)
Check if the player is queued to be transferred to a World.
Definition: Server.cpp:291
std::vector< std::pair< std::chrono::milliseconds, std::function< void(class cServer &)> > > m_Tasks
Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the futur...
Definition: Server.h:277
bool m_ShouldAllowBungeeCord
True if BungeeCord handshake packets (with player UUID) should be accepted.
Definition: Server.h:252
cServerHandlePtrs m_ServerHandles
The network sockets listening for client connections.
Definition: Server.h:195
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
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 Command(cClientHandle &a_Client, AString &a_Cmd)
Definition: Server.cpp:429
bool m_bIsHardcore
Definition: Server.h:228
AString m_ServerID
The server ID used for client authentication.
Definition: Server.h:242
std::atomic_size_t m_PlayerCount
Number of players currently playing in the server.
Definition: Server.h:207
bool m_ShouldAuthenticate
If true, players will be online-authenticated agains Mojang servers.
Definition: Server.h:246
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:204
void TickQueuedTasks(void)
Executes all tasks queued onto the tick thread.
Definition: Server.cpp:759
cTickThread m_TickThread
Definition: Server.h:239
bool Start(void)
Definition: Server.cpp:400
AString m_ResourcePackUrl
Definition: Server.h:230
size_t m_MaxPlayers
Definition: Server.h:227
cCriticalSection m_CSTasks
Guards the m_Tasks.
Definition: Server.h:273
std::vector< std::pair< AString, cCommandOutputCallback * > > m_PendingCommands
Definition: Server.h:210
void ClientMovedToWorld(const cClientHandle *a_Client)
Don't tick a_Client anymore, it will be ticked from its cPlayer instead.
Definition: Server.cpp:125
cCriticalSection m_CSClients
Protects m_Clients and m_ClientsToRemove against multithreaded access.
Definition: Server.h:198
bool InitServer(cSettingsRepositoryInterface &a_Settings, bool a_ShouldAuth)
Definition: Server.cpp:153
static void BindBuiltInConsoleCommands(void)
Binds the built-in console commands with the plugin manager.
Definition: Server.cpp:636
bool m_RequireResourcePack
Definition: Server.h:229
void QueueExecuteConsoleCommand(const AString &a_Cmd, cCommandOutputCallback &a_Output)
Queues a console command for execution through the cServer class.
Definition: Server.cpp:445
size_t GetNumPlayers(void) const
Definition: Server.h:71
std::map< UInt32, AStringMap > m_ForgeModsByVersion
Map of protocol version to Forge mods (map of ModName -> ModVersionString)
Definition: Server.h:234
bool m_ShouldAllowMultiWorldTabCompletion
True if usernames should be completed across worlds.
Definition: Server.h:261
AString m_Description
Definition: Server.h:224
cRsaPrivateKey m_PrivateKey
The private key used for the assymetric encryption start in the protocols.
Definition: Server.h:217
void Shutdown(void)
Definition: Server.cpp:671
AStringVector m_Ports
The list of ports on which the server should listen for connections.
Definition: Server.h:265
AString m_ProxySharedSecret
Security string that the proxy server should send, compatible with BungeeGuard.
Definition: Server.h:258
void KickUser(int a_ClientID, const AString &a_Reason)
Definition: Server.cpp:699
bool m_bIsConnected
Definition: Server.h:214
void PlayerDestroyed()
Notifies the server that a player is being destroyed; the server uses this to adjust the number of pl...
Definition: Server.cpp:144
cClientHandlePtrs m_Clients
Clients that are connected to the server and not yet assigned to a cWorld.
Definition: Server.h:201
AStringMap & RegisteredForgeMods(const UInt32 a_Protocol)
Get the Forge mods registered for a given protocol, for modification.
Definition: Server.cpp:264
AString m_FaviconData
Definition: Server.h:226
void AuthenticateUser(int a_ClientID, AString &&a_Username, const cUUID &a_UUID, Json::Value &&a_Properties)
Authenticates the specified user, called by cAuthenticator supplying player details from Mojang.
Definition: Server.cpp:715
cCriticalSection m_CSPendingCommands
Definition: Server.h:209
AString m_ShutdownMessage
Definition: Server.h:225
void ScheduleTask(cTickTime a_DelayTicks, std::function< void(class cServer &)> a_Task)
Queues a lambda task onto the server tick thread, with the specified delay in ticks.
Definition: Server.cpp:456
bool m_OnlyAllowBungeeCord
True if BungeeCord handshake packets should be the only ones accepted.
Definition: Server.h:255
cTickTimeLong m_UpTime
Time, in ticks, since the server started Not persistent across server restarts.
Definition: Server.h:270
cTickThread(cServer &a_Server)
Definition: Server.cpp:67
virtual void Execute(void) override
This function, overloaded by the descendants, is called in the new thread.
Definition: Server.cpp:77
virtual bool GetValueSetB(const AString &keyname, const AString &valuename, const bool defValue=false)=0
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.
virtual int GetValueSetI(const AString &keyname, const AString &valuename, const int defValue=0)=0
Definition: UUID.h:11
void Reload(void)
Reloads m_IniFile, m_LoginPage and m_TemplateScript.
Definition: WebAdmin.cpp:182
Definition: World.h:53
bool ForEachEntity(cEntityCallback a_Callback)
Calls the callback for each entity in the entire world; returns true if all entities processed,...
Definition: World.cpp:2427