aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/MinecraftServer.h
blob: 1ed5db9d7c3386e8b4da37d1b37468e5caf48438 (plain)
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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#pragma once
#include "ConsoleInputSource.h"
#include "..\Minecraft.World\ArrayWithLength.h"
#include "..\Minecraft.World\SharedConstants.h"
#include "..\Minecraft.World\C4JThread.h"

class ServerConnection;
class Settings;
class PlayerList;
class EntityTracker;
class ConsoleInput;
class ConsoleCommands;
class LevelStorageSource;
class ChunkSource;
class INetworkPlayer;
class LevelRuleset;
class LevelType;
class ProgressRenderer;
class CommandDispatcher;

#if defined(_WINDOWS64)
#define MINECRAFT_SERVER_SLOW_QUEUE_DELAY 0 // Removed slow queue because at large player counts, chunks stopped appearing
#else
#define MINECRAFT_SERVER_SLOW_QUEUE_DELAY 250
#endif

#if defined _XBOX_ONE || defined _XBOX || defined __ORBIS__ || defined __PS3__ || defined __PSVITA__
#define _ACK_CHUNK_SEND_THROTTLING
#endif

typedef struct _LoadSaveDataThreadParam
{
	LPVOID data;
	int64_t fileSize;
	const wstring saveName;
	_LoadSaveDataThreadParam(LPVOID data, int64_t filesize, const wstring &saveName) : data( data ), fileSize( filesize ), saveName( saveName ) {}
} LoadSaveDataThreadParam;

typedef struct _NetworkGameInitData
{
	int64_t seed;
	LoadSaveDataThreadParam *saveData;
	DWORD settings;
	LevelGenerationOptions *levelGen;
	DWORD texturePackId;
	bool findSeed;
	bool dedicatedNoLocalHostPlayer;
	unsigned int xzSize;
	unsigned char hellScale;
	ESavePlatform savePlatform;
	wstring levelName;

	_NetworkGameInitData()
	{
		seed = 0;
		saveData = nullptr;
		settings = 0;
		levelGen = nullptr;
		texturePackId = 0;
		findSeed = false;
		dedicatedNoLocalHostPlayer = false;
		xzSize = LEVEL_LEGACY_WIDTH;
		hellScale = HELL_LEVEL_LEGACY_SCALE;
		savePlatform = SAVE_FILE_PLATFORM_LOCAL;
	}
} NetworkGameInitData;

using namespace std;

// 4J Stu - 1.0.1 updates the server to implement the ServerInterface class, but I don't think we will use any of the functions that defines so not implementing here
class MinecraftServer : public ConsoleInputSource
{
public:
	static const wstring VERSION;
	static const int TICK_STATS_SPAN = SharedConstants::TICKS_PER_SECOND * 5;

//    static Logger logger = Logger.getLogger("Minecraft");
    static unordered_map<wstring, int> ironTimers;

private:
	static const int DEFAULT_MINECRAFT_PORT = 25565;
	static const int MS_PER_TICK = 1000 / SharedConstants::TICKS_PER_SECOND;

	// 4J Stu - Added 1.0.1, Not needed
	//wstring localIp;
	//int port;
public:
	ServerConnection *connection;
    Settings *settings;
    ServerLevelArray levels;

private:
    PlayerList *players;

	// 4J Stu - Added 1.0.1, Not needed
	//long[] tickTimes = new long[TICK_STATS_SPAN];
	//long[][] levelTickTimes;
private:
	ConsoleCommands *commands;
    bool running;
	bool m_bLoaded;
public:
	bool stopped;
    int tickCount;

public:
	wstring progressStatus;
    int progress;
private:
//	vector<Tickable *> tickables = new ArrayList<Tickable>();	// 4J - removed
	CommandDispatcher *commandDispatcher;
    vector<ConsoleInput *> consoleInput;	// 4J - was synchronizedList - TODO - investigate
	CRITICAL_SECTION m_consoleInputCS;
public:
    bool onlineMode;
    bool animals;
	bool npcs;
    bool pvp;
    bool allowFlight;
	wstring motd;
	int maxBuildHeight;
	int playerIdleTimeout;
	bool forceGameType;
	int m_spawnProtectionRadius;

private:
	// 4J Added
	//int m_lastSentDifficulty;

public:
	// 4J Stu - This value should be incremented every time the list of players with friends-only UGC settings changes
	// It is sent with PreLoginPacket and compared when it comes back in the LoginPacket
	DWORD m_ugcPlayersVersion;

	// This value is used to store the texture pack id for the currently loaded world
	DWORD m_texturePackId;

public:
	MinecraftServer();
	~MinecraftServer();
private:
	// 4J Added - LoadSaveDataThreadParam
	bool initServer(int64_t seed, NetworkGameInitData *initData, DWORD initSettings, bool findSeed);
	void postProcessTerminate(ProgressRenderer *mcprogress);
    bool loadLevel(LevelStorageSource *storageSource, const wstring& name, int64_t levelSeed, LevelType *pLevelType, NetworkGameInitData *initData);
    void setProgress(const wstring& status, int progress);
    void endProgress();
    void saveAllChunks();
	void saveGameRules();
    void stopServer(bool didInit);
#ifdef _LARGE_WORLDS
	void overwriteBordersForNewWorldSize(ServerLevel* level);
	void overwriteHellBordersForNewWorldSize(ServerLevel* level, int oldHellSize);

#endif
public:
	void setMaxBuildHeight(int maxBuildHeight);
	int getMaxBuildHeight();
	PlayerList *getPlayers();
	void setPlayers(PlayerList *players);
	ServerConnection *getConnection();
	bool isAnimals();
	void setAnimals(bool animals);
	bool isNpcsEnabled();
	void setNpcsEnabled(bool npcs);
	bool isPvpAllowed();
	void setPvpAllowed(bool pvp);
	bool isFlightAllowed();
	void setFlightAllowed(bool allowFlight);
	bool isCommandBlockEnabled();
	bool isNetherEnabled();
	bool isHardcore();
	int getOperatorUserPermissionLevel();
	CommandDispatcher *getCommandDispatcher();
	Pos *getCommandSenderWorldPosition();
	Level *getCommandSenderWorld();
	int getSpawnProtectionRadius();
	bool isUnderSpawnProtection(Level *level, int x, int y, int z, shared_ptr<Player> player);
	void setForceGameType(bool forceGameType);
	bool getForceGameType();
	static int64_t getCurrentTimeMillis();
	int getPlayerIdleTimeout();
	void setPlayerIdleTimeout(int playerIdleTimeout);

public:
	void halt();
    void run(int64_t seed, void *lpParameter);

	void broadcastStartSavingPacket();
	void broadcastStopSavingPacket();

private:
	void tick();
public:
	void handleConsoleInput(const wstring& msg, ConsoleInputSource *source);
    void handleConsoleInputs();
//    void addTickable(Tickable tickable);	// 4J removed
    static void main(int64_t seed, void *lpParameter);
	static void HaltServer(bool bPrimaryPlayerSignedOut=false);

    File *getFile(const wstring& name);
    void info(const wstring& string);
    void warn(const wstring& string);
    wstring getConsoleName();
    ServerLevel *getLevel(int dimension);
	void setLevel(int dimension, ServerLevel *level);	// 4J added
	static MinecraftServer *getInstance() { return server; }	// 4J added
	static bool serverHalted() { return s_bServerHalted; }
	static bool saveOnExitAnswered() { return s_bSaveOnExitAnswered; }
	static void resetFlags() { s_bServerHalted = false; s_bSaveOnExitAnswered = false; }

	bool flagEntitiesToBeRemoved(unsigned int *flags);	// 4J added
private:
	//4J Added
	static MinecraftServer *server;

	static bool setTimeOfDayAtEndOfTick;
	static int64_t setTimeOfDay;
	static bool setTimeAtEndOfTick;
	static int64_t setTime;

	static bool	m_bPrimaryPlayerSignedOut;	// 4J-PB added to tell the stopserver not to save the game - another player may have signed in in their place, so ProfileManager.IsSignedIn isn't enough
	static bool s_bServerHalted; // 4J Stu Added so that we can halt the server even before it's been created properly
	static bool s_bSaveOnExitAnswered; // 4J Stu Added so that we only ask this question once when we exit

	// 4J - added so that we can have a separate thread for post processing chunks on level creation
	static int runPostUpdate(void* lpParam);
	C4JThread*				m_postUpdateThread;
	bool					m_postUpdateTerminate;
	class postProcessRequest
	{
	public:
		int				x, z;
		ChunkSource		*chunkSource;
		postProcessRequest(int x, int z, ChunkSource *chunkSource) : x(x), z(z), chunkSource(chunkSource) {}
	};
	vector<postProcessRequest>	m_postProcessRequests;
	CRITICAL_SECTION		m_postProcessCS;
public:
	void					addPostProcessRequest(ChunkSource *chunkSource, int x, int z);

    static PlayerList *getPlayerList() { if( server != nullptr) return server->players; else return nullptr; }
	static void SetTimeOfDay(int64_t time) { setTimeOfDayAtEndOfTick = true; setTimeOfDay = time; }
	static void SetTime(int64_t time) { setTimeAtEndOfTick = true; setTime = time; }

	C4JThread::Event* m_serverPausedEvent;
private:
	// 4J Added
	bool m_isServerPaused;

	// 4J Added - A static that stores the QNet index of the player that is next allowed to send a packet in the slow queue
#ifdef _ACK_CHUNK_SEND_THROTTLING
	static bool s_hasSentEnoughPackets;
	static int64_t s_tickStartTime;
	static vector<INetworkPlayer *> s_sentTo;
	static const int MAX_TICK_TIME_FOR_PACKET_SENDS = 35;
#else
	static int s_slowQueuePlayerIndex;
	static int s_slowQueueLastTime;
	static bool s_slowQueuePacketSent;
#endif

	bool IsServerPaused() { return m_isServerPaused; }

private:
	// 4J Added
	bool m_saveOnExit;
	bool m_suspending;

public:
	static bool chunkPacketManagement_CanSendTo(INetworkPlayer *player);
	static void chunkPacketManagement_DidSendTo(INetworkPlayer *player);
#ifndef _ACK_CHUNK_SEND_THROTTLING
	static void cycleSlowQueueIndex();
#endif

	void chunkPacketManagement_PreTick();
	void chunkPacketManagement_PostTick();

	void setSaveOnExit(bool save) { m_saveOnExit = save; s_bSaveOnExitAnswered = true; }
	void Suspend();
	bool IsSuspending();

	// 4J Stu - A load of functions were all added in 1.0.1 in the ServerInterface, but I don't think we need any of them
};