summaryrefslogtreecommitdiffstats
path: root/src/Root.h
blob: f8318b8cd13157f19f0d7b6f8428fb4e1387706a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

#pragma once

#include "Defines.h"
#include "FunctionRef.h"
#include "HTTP/HTTPServer.h"
#include "Protocol/Authenticator.h"
#include "Protocol/MojangAPI.h"
#include "RankManager.h"
#include "ChunkDef.h"




// fwd:
class cItem;
class cMonsterConfig;
class cBrewingRecipes;
class cCraftingRecipes;
class cRecipeMapper;
class cFurnaceRecipe;
class cWebAdmin;
class cPluginManager;
class cServer;
class cWorld;
class cPlayer;
class cCommandOutputCallback;
class cCompositeChat;
class cSettingsRepositoryInterface;
class cDeadlockDetect;
class cUUID;
class BlockTypePalette;
class ProtocolPalettes;

using cPlayerListCallback = cFunctionRef<bool(cPlayer &)>;
using cWorldListCallback = cFunctionRef<bool(cWorld &)>;

namespace Json
{
class Value;
}





/** The root of the object hierarchy */
// tolua_begin
class cRoot
{
  public:
	static cRoot * Get() { return s_Root; }
	// tolua_end

	/** which ini file to load settings from, default is settings.ini */
	AString m_SettingsFilename;

	cRoot(void);
	~cRoot();

	/** Run the server. Returns true if we should restart, false to quit. */
	bool Run(cSettingsRepositoryInterface & a_OverridesRepo);

	/** Interrupts the server and stops it, as if "/stop" typed in the console. */
	static void Stop();

	/** Interrupts the server and restarts it, as if "/restart" was typed in the console. */
	static void Restart();

	// tolua_begin
	cServer * GetServer(void) { return m_Server; }
	cWorld * GetDefaultWorld(void);

	/** Returns a pointer to the world specified. If no world of that name exists, returns a nullptr. */
	cWorld * GetWorld(const AString & a_WorldName);

	/** Returns the up time of the server in seconds */
	int GetServerUpTime(void)
	{
		return static_cast<int>(
			std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - m_StartTime).count()
		);
	}
	// tolua_end

	/** Calls the callback for each world; returns true if the callback didn't abort (return true) */
	bool ForEachWorld(cWorldListCallback a_Callback);  // >> Exported in ManualBindings <<

	/** Writes chunkstats, for each world and totals, to the output callback */
	void LogChunkStats(cCommandOutputCallback & a_Output);

	cMonsterConfig * GetMonsterConfig(void) { return m_MonsterConfig; }

	cCraftingRecipes * GetCraftingRecipes(void) { return m_CraftingRecipes; }  // tolua_export
	cRecipeMapper * GetRecipeMapper(void) { return m_RecipeMapper.get(); }
	cFurnaceRecipe * GetFurnaceRecipe(void)
	{
		return m_FurnaceRecipe;
	}  // Exported in ManualBindings.cpp with quite a different signature
	cBrewingRecipes * GetBrewingRecipes(void) { return m_BrewingRecipes.get(); }  // Exported in ManualBindings.cpp

	/** Returns the (read-write) storage for registered block types. */
	// BlockTypeRegistry & GetBlockTypeRegistry() { return m_BlockTypeRegistry; }

	/** Returns the number of ticks for how long the item would fuel a furnace. Returns zero if not a fuel */
	static int GetFurnaceFuelBurnTime(const cItem & a_Fuel);  // tolua_export

	/** Returns the completions for a player name across all worlds. Returns an
	empty vector if none are found. */
	AStringVector GetPlayerTabCompletionMultiWorld(const AString & a_Text);

	/** The current time where the startup of the server has been completed */
	std::chrono::steady_clock::time_point m_StartTime;

	cWebAdmin * GetWebAdmin(void) { return m_WebAdmin; }  // tolua_export
	cPluginManager * GetPluginManager(void) { return m_PluginManager; }  // tolua_export
	cAuthenticator & GetAuthenticator(void) { return m_Authenticator; }
	cMojangAPI & GetMojangAPI(void) { return *m_MojangAPI; }
	cRankManager * GetRankManager(void) { return m_RankManager.get(); }

	/** Queues a console command for execution through the cServer class.
	The command will be executed in the tick thread
	The command's output will be written to the a_Output callback
	"stop" and "restart" commands have special handling.
	*/
	void QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output);

	/** Queues a console command for execution through the cServer class.
	The command will be executed in the tick thread
	The command's output will be sent to console
	"stop" and "restart" commands have special handling.
	*/
	void QueueExecuteConsoleCommand(const AString & a_Cmd);  // tolua_export

	/** Kicks the user, no matter in what world they are. Used from cAuthenticator */
	void KickUser(int a_ClientID, const AString & a_Reason);

	/** Returns the number of chunks loaded */
	size_t GetTotalChunkCount(void);  // tolua_export

	/** Saves all chunks in all worlds */
	void SaveAllChunks(void);  // tolua_export

	/** Saves all chunks in all worlds synchronously (waits until dirty chunks have been sent to the ChunkStorage queue
	 * before returning) */
	void SaveAllChunksNow(void);

	/** Sets whether saving chunks is enabled in all worlds (overrides however the worlds were already set) */
	void SetSavingEnabled(bool a_SavingEnabled);  // tolua_export

	/** Calls the callback for each player in all worlds */
	bool ForEachPlayer(cPlayerListCallback a_Callback);  // >> EXPORTED IN MANUALBINDINGS <<

	/** Finds a player from a partial or complete player name and calls the callback - case-insensitive */
	bool FindAndDoWithPlayer(
		const AString & a_PlayerName,
		cPlayerListCallback a_Callback
	);  // >> EXPORTED IN MANUALBINDINGS <<

	/** Finds the player over his uuid and calls the callback */
	bool DoWithPlayerByUUID(
		const cUUID & a_PlayerUUID,
		cPlayerListCallback a_Callback
	);  // >> EXPORTED IN MANUALBINDINGS <<

	/** Finds the player using it's complete username and calls the callback */
	bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback a_Callback);

	/** Send playerlist of all worlds to player */
	void SendPlayerLists(cPlayer * a_DestPlayer);

	/** Broadcast playerlist addition through all worlds */
	void BroadcastPlayerListsAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr);

	/** Broadcast playerlist removal through all worlds */
	void BroadcastPlayerListsRemovePlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr);

	/** Broadcast playerlist header and footer through all worlds */
	// tolua_begin
	void BroadcastPlayerListsHeaderFooter(const cCompositeChat & a_Header, const cCompositeChat & a_Footer);
	// tolua_end

	// tolua_begin

	/** Sends a chat message to all connected clients (in all worlds) */
	void BroadcastChat(const AString & a_Message, eMessageType a_ChatPrefix = mtCustom);
	void BroadcastChat(const cCompositeChat & a_Message);
	void BroadcastChatDeath(const AString & a_Message) { BroadcastChat(a_Message, mtDeath); }
	void BroadcastChatFailure(const AString & a_Message) { BroadcastChat(a_Message, mtFailure); }
	void BroadcastChatFatal(const AString & a_Message) { BroadcastChat(a_Message, mtFailure); }
	void BroadcastChatInfo(const AString & a_Message) { BroadcastChat(a_Message, mtInformation); }
	void BroadcastChatJoin(const AString & a_Message) { BroadcastChat(a_Message, mtJoin); }
	void BroadcastChatLeave(const AString & a_Message) { BroadcastChat(a_Message, mtLeave); }
	void BroadcastChatSuccess(const AString & a_Message) { BroadcastChat(a_Message, mtSuccess); }
	void BroadcastChatWarning(const AString & a_Message) { BroadcastChat(a_Message, mtWarning); }

	/** Returns the textual description of the protocol version: 49 -> "1.4.4". Provided specifically for Lua API */
	static AString GetProtocolVersionTextFromInt(int a_ProtocolVersionNum);

	/** Returns the amount of virtual RAM used, in KiB. Returns a negative number on error */
	static int GetVirtualRAMUsage(void);

	/** Returns the amount of virtual RAM used, in KiB. Returns a negative number on error */
	static int GetPhysicalRAMUsage(void);

	// tolua_end

  private:
	/** States that the global cRoot can be in.
	You can transition freely between Run and Restart, but the server unconditionally terminates in Stop. */
	enum class NextState
	{
		Run,
		Restart,
		Stop
	};

	typedef std::map<AString, cWorld> WorldMap;

	/** Blocking reads and processes console input. */
	void HandleInput();

	/** Performs run state transition, enforcing guarantees about state transitions. */
	static void TransitionNextState(NextState a_NextState);

	cWorld * m_pDefaultWorld;
	WorldMap m_WorldsByName;

	static cEvent s_StopEvent;

	cServer * m_Server;
	cMonsterConfig * m_MonsterConfig;

	cCraftingRecipes * m_CraftingRecipes;
	std::unique_ptr<cRecipeMapper> m_RecipeMapper;
	cFurnaceRecipe * m_FurnaceRecipe;
	std::unique_ptr<cBrewingRecipes> m_BrewingRecipes;
	cWebAdmin * m_WebAdmin;
	cPluginManager * m_PluginManager;
	cAuthenticator m_Authenticator;
	cMojangAPI * m_MojangAPI;

	std::unique_ptr<cRankManager> m_RankManager;

	cHTTPServer m_HTTPServer;

	/** The storage for all registered block types. */
	// BlockTypeRegistry m_BlockTypeRegistry;


	void LoadGlobalSettings();

	/** Loads the worlds from settings.ini, creates the worldmap */
	void LoadWorlds(cDeadlockDetect & a_dd, cSettingsRepositoryInterface & a_Settings, bool a_IsNewIniFile);

	/** Starts each world's life */
	void StartWorlds(cDeadlockDetect & a_DeadlockDetect);

	/** Stops each world's threads, so that it's safe to unload them */
	void StopWorlds(cDeadlockDetect & a_DeadlockDetect);

	static cRoot * s_Root;

	/** Indicates the next action of cRoot, whether to run, stop or restart. */
	static std::atomic<NextState> s_NextState;
};  // tolua_export