1 |
|
|
/* |
2 |
|
|
* The ManaPlus Client |
3 |
|
|
* Copyright (C) 2004-2009 The Mana World Development Team |
4 |
|
|
* Copyright (C) 2009-2010 The Mana Developers |
5 |
|
|
* Copyright (C) 2011-2019 The ManaPlus Developers |
6 |
|
|
* Copyright (C) 2019-2021 Andrei Karas |
7 |
|
|
* |
8 |
|
|
* This file is part of The ManaPlus Client. |
9 |
|
|
* |
10 |
|
|
* This program is free software; you can redistribute it and/or modify |
11 |
|
|
* it under the terms of the GNU General Public License as published by |
12 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
13 |
|
|
* any later version. |
14 |
|
|
* |
15 |
|
|
* This program is distributed in the hope that it will be useful, |
16 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 |
|
|
* GNU General Public License for more details. |
19 |
|
|
* |
20 |
|
|
* You should have received a copy of the GNU General Public License |
21 |
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include "progs/manaplus/client.h" |
25 |
|
|
|
26 |
|
|
#include "chatlogger.h" |
27 |
|
|
#include "configmanager.h" |
28 |
|
|
#include "dirs.h" |
29 |
|
|
#include "eventsmanager.h" |
30 |
|
|
#include "game.h" |
31 |
|
|
#include "graphicsmanager.h" |
32 |
|
|
#include "main.h" |
33 |
|
|
#include "party.h" |
34 |
|
|
#include "pincodemanager.h" |
35 |
|
|
#include "settings.h" |
36 |
|
|
#include "soundmanager.h" |
37 |
|
|
#include "spellmanager.h" |
38 |
|
|
|
39 |
|
|
#include "being/localclan.h" |
40 |
|
|
#include "being/localplayer.h" |
41 |
|
|
#include "being/playerinfo.h" |
42 |
|
|
#include "being/playerrelations.h" |
43 |
|
|
|
44 |
|
|
#include "const/net/net.h" |
45 |
|
|
|
46 |
|
|
#include "enums/being/attributesstrings.h" |
47 |
|
|
|
48 |
|
|
#include "fs/virtfs/fs.h" |
49 |
|
|
#include "fs/virtfs/tools.h" |
50 |
|
|
|
51 |
|
|
#include "gui/dialogsmanager.h" |
52 |
|
|
#include "gui/gui.h" |
53 |
|
|
#include "gui/skin.h" |
54 |
|
|
#include "gui/popupmanager.h" |
55 |
|
|
#include "gui/windowmanager.h" |
56 |
|
|
|
57 |
|
|
#include "gui/shortcut/dropshortcut.h" |
58 |
|
|
#include "gui/shortcut/emoteshortcut.h" |
59 |
|
|
#include "gui/shortcut/itemshortcut.h" |
60 |
|
|
#include "gui/shortcut/spellshortcut.h" |
61 |
|
|
|
62 |
|
|
#include "gui/windows/changeemaildialog.h" |
63 |
|
|
#include "gui/windows/changepassworddialog.h" |
64 |
|
|
#include "gui/windows/charselectdialog.h" |
65 |
|
|
#include "gui/windows/connectiondialog.h" |
66 |
|
|
#include "gui/windows/equipmentwindow.h" |
67 |
|
|
#include "gui/windows/logindialog.h" |
68 |
|
|
#include "gui/windows/npcdialog.h" |
69 |
|
|
#include "gui/windows/okdialog.h" |
70 |
|
|
#include "gui/windows/registerdialog.h" |
71 |
|
|
#include "gui/windows/serverdialog.h" |
72 |
|
|
#include "gui/windows/setupwindow.h" |
73 |
|
|
#include "gui/windows/updaterwindow.h" |
74 |
|
|
#include "gui/windows/quitdialog.h" |
75 |
|
|
#include "gui/windows/worldselectdialog.h" |
76 |
|
|
|
77 |
|
|
#include "gui/widgets/button.h" |
78 |
|
|
#include "gui/widgets/createwidget.h" |
79 |
|
|
#include "gui/widgets/desktop.h" |
80 |
|
|
#include "gui/widgets/windowcontainer.h" |
81 |
|
|
|
82 |
|
|
#include "input/inputmanager.h" |
83 |
|
|
#include "input/joystick.h" |
84 |
|
|
#include "input/keyboardconfig.h" |
85 |
|
|
|
86 |
|
|
#include "input/touch/touchmanager.h" |
87 |
|
|
|
88 |
|
|
#include "net/charserverhandler.h" |
89 |
|
|
#include "net/chathandler.h" |
90 |
|
|
#include "net/download.h" |
91 |
|
|
#include "net/gamehandler.h" |
92 |
|
|
#include "net/generalhandler.h" |
93 |
|
|
#include "net/guildhandler.h" |
94 |
|
|
#include "net/inventoryhandler.h" |
95 |
|
|
#include "net/ipc.h" |
96 |
|
|
#include "net/loginhandler.h" |
97 |
|
|
#include "net/net.h" |
98 |
|
|
#include "net/updatetypeoperators.h" |
99 |
|
|
#include "net/useragent.h" |
100 |
|
|
#include "net/packetlimiter.h" |
101 |
|
|
#include "net/partyhandler.h" |
102 |
|
|
|
103 |
|
|
#ifdef TMWA_SUPPORT |
104 |
|
|
#include "net/tmwa/guildmanager.h" |
105 |
|
|
#endif // TMWA_SUPPORT |
106 |
|
|
|
107 |
|
|
#include "particle/particleengine.h" |
108 |
|
|
|
109 |
|
|
#include "resources/dbmanager.h" |
110 |
|
|
#include "resources/imagehelper.h" |
111 |
|
|
|
112 |
|
|
#include "resources/dye/dyepalette.h" |
113 |
|
|
|
114 |
|
|
#include "resources/resourcemanager/resourcemanager.h" |
115 |
|
|
|
116 |
|
|
#include "resources/sprite/spritereference.h" |
117 |
|
|
|
118 |
|
|
#include "utils/checkutils.h" |
119 |
|
|
#include "utils/cpu.h" |
120 |
|
|
#include "utils/delete2.h" |
121 |
|
|
#include "utils/dumplibs.h" |
122 |
|
|
#include "utils/dumpsizes.h" |
123 |
|
|
#include "utils/env.h" |
124 |
|
|
#include "utils/fuzzer.h" |
125 |
|
|
#include "utils/gettext.h" |
126 |
|
|
#include "utils/gettexthelper.h" |
127 |
|
|
#include "utils/mrand.h" |
128 |
|
|
#ifdef ANDROID |
129 |
|
|
#include "fs/paths.h" |
130 |
|
|
#endif // ANDROID |
131 |
|
|
#include "utils/perfstat.h" |
132 |
|
|
#include "utils/sdlcheckutils.h" |
133 |
|
|
#include "utils/sdlhelper.h" |
134 |
|
|
#include "utils/timer.h" |
135 |
|
|
|
136 |
|
|
#include "utils/translation/translationmanager.h" |
137 |
|
|
|
138 |
|
|
#include "listeners/assertlistener.h" |
139 |
|
|
#include "listeners/errorlistener.h" |
140 |
|
|
|
141 |
|
|
#ifdef USE_OPENGL |
142 |
|
|
#include "test/testlauncher.h" |
143 |
|
|
#include "test/testmain.h" |
144 |
|
|
#else // USE_OPENGL |
145 |
|
|
#include "configuration.h" |
146 |
|
|
#endif // USE_OPENGL |
147 |
|
|
|
148 |
|
|
#ifdef WIN32 |
149 |
|
|
PRAGMA48(GCC diagnostic push) |
150 |
|
|
PRAGMA48(GCC diagnostic ignored "-Wshadow") |
151 |
|
|
#include <SDL_syswm.h> |
152 |
|
|
PRAGMA48(GCC diagnostic pop) |
153 |
|
|
#include "fs/specialfolder.h" |
154 |
|
|
#undef ERROR |
155 |
|
|
#endif // WIN32 |
156 |
|
|
|
157 |
|
|
#ifdef ANDROID |
158 |
|
|
#ifndef USE_SDL2 |
159 |
|
|
PRAGMA48(GCC diagnostic push) |
160 |
|
|
PRAGMA48(GCC diagnostic ignored "-Wshadow") |
161 |
|
|
#include <SDL_screenkeyboard.h> |
162 |
|
|
PRAGMA48(GCC diagnostic pop) |
163 |
|
|
#include <fstream> |
164 |
|
|
#endif // USE_SDL2 |
165 |
|
|
#endif // ANDROID |
166 |
|
|
|
167 |
|
|
#include <sys/stat.h> |
168 |
|
|
|
169 |
|
|
#ifdef USE_MUMBLE |
170 |
|
|
#include "mumblemanager.h" |
171 |
|
|
#endif // USE_MUMBLE |
172 |
|
|
|
173 |
|
|
PRAGMA48(GCC diagnostic push) |
174 |
|
|
PRAGMA48(GCC diagnostic ignored "-Wshadow") |
175 |
|
|
#ifdef USE_SDL2 |
176 |
|
|
#include <SDL2_framerate.h> |
177 |
|
|
#else // USE_SDL2 |
178 |
|
|
#include <SDL_framerate.h> |
179 |
|
|
#endif // USE_SDL2 |
180 |
|
|
PRAGMA48(GCC diagnostic pop) |
181 |
|
|
|
182 |
|
|
#include "debug.h" |
183 |
|
|
|
184 |
|
1 |
std::string errorMessage; |
185 |
|
1 |
LoginData loginData; |
186 |
|
|
|
187 |
|
|
Client *client = nullptr; |
188 |
|
|
|
189 |
|
|
extern FPSmanager fpsManager; |
190 |
|
|
extern int evolPacketOffset; |
191 |
|
|
|
192 |
|
|
volatile bool runCounters; |
193 |
|
|
bool isSafeMode = false; |
194 |
|
|
int serverVersion = 0; |
195 |
|
|
int packetVersion = 0; |
196 |
|
|
int packetVersionMain = 0; |
197 |
|
|
int packetVersionRe = 0; |
198 |
|
|
int packetVersionZero = 0; |
199 |
|
|
int packetsType = 0; |
200 |
|
|
int itemIdLen = 2; |
201 |
|
|
bool packets_main = true; |
202 |
|
|
bool packets_re = false; |
203 |
|
|
bool packets_zero = false; |
204 |
|
|
unsigned int tmwServerVersion = 0; |
205 |
|
|
time_t start_time; |
206 |
|
|
unsigned int mLastHost = 0; |
207 |
|
|
unsigned long mSearchHash = 0; |
208 |
|
|
int textures_count = 0; |
209 |
|
|
volatile bool isTerminate = false; |
210 |
|
|
|
211 |
|
|
namespace |
212 |
|
|
{ |
213 |
|
1 |
class AccountListener final : public ActionListener |
214 |
|
|
{ |
215 |
|
|
public: |
216 |
|
|
AccountListener() |
217 |
|
2 |
{ } |
218 |
|
|
|
219 |
|
|
A_DELETE_COPY(AccountListener) |
220 |
|
|
|
221 |
|
|
void action(const ActionEvent &event A_UNUSED) override final |
222 |
|
|
{ |
223 |
|
|
client->setState(State::CHAR_SELECT); |
224 |
|
|
} |
225 |
|
1 |
} accountListener; |
226 |
|
|
|
227 |
|
1 |
class LoginListener final : public ActionListener |
228 |
|
|
{ |
229 |
|
|
public: |
230 |
|
|
LoginListener() |
231 |
|
2 |
{ } |
232 |
|
|
|
233 |
|
|
A_DELETE_COPY(LoginListener) |
234 |
|
|
|
235 |
|
|
void action(const ActionEvent &event A_UNUSED) override final |
236 |
|
|
{ |
237 |
|
|
client->setState(State::PRE_LOGIN); |
238 |
|
|
} |
239 |
|
1 |
} loginListener; |
240 |
|
|
} // namespace |
241 |
|
|
|
242 |
|
215 |
Client::Client() : |
243 |
|
|
ActionListener(), |
244 |
|
|
mCurrentServer(), |
245 |
|
|
mGame(nullptr), |
246 |
|
|
mCurrentDialog(nullptr), |
247 |
|
|
mQuitDialog(nullptr), |
248 |
|
|
mSetupButton(nullptr), |
249 |
|
|
mVideoButton(nullptr), |
250 |
|
|
mHelpButton(nullptr), |
251 |
|
|
mAboutButton(nullptr), |
252 |
|
|
mThemesButton(nullptr), |
253 |
|
|
mPerfomanceButton(nullptr), |
254 |
|
|
#ifdef ANDROID |
255 |
|
|
mCloseButton(nullptr), |
256 |
|
|
#endif // ANDROID |
257 |
|
|
mState(State::CHOOSE_SERVER), |
258 |
|
|
mOldState(State::START), |
259 |
|
|
mSkin(nullptr), |
260 |
|
|
mButtonPadding(1), |
261 |
|
|
mButtonSpacing(3), |
262 |
|
|
mPing(0), |
263 |
|
645 |
mConfigAutoSaved(false) |
264 |
|
|
{ |
265 |
✓✗ |
215 |
WindowManager::init(); |
266 |
|
215 |
} |
267 |
|
|
|
268 |
|
|
void Client::testsInit() |
269 |
|
|
{ |
270 |
|
|
if (!settings.options.test.empty() && |
271 |
|
|
settings.options.test != "99") |
272 |
|
|
{ |
273 |
|
|
gameInit(); |
274 |
|
|
} |
275 |
|
|
else |
276 |
|
|
{ |
277 |
|
|
initRand(); |
278 |
|
|
logger = new Logger; |
279 |
|
|
SDL::initLogger(); |
280 |
|
|
Dirs::initLocalDataDir(); |
281 |
|
|
Dirs::initTempDir(); |
282 |
|
|
Dirs::initConfigDir(); |
283 |
|
|
GettextHelper::initLang(); |
284 |
|
|
} |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
void Client::gameInit() |
288 |
|
|
{ |
289 |
|
|
logger = new Logger; |
290 |
|
|
SDL::initLogger(); |
291 |
|
|
|
292 |
|
|
initRand(); |
293 |
|
|
|
294 |
|
|
assertListener = new AssertListener; |
295 |
|
|
// Load branding information |
296 |
|
|
if (!settings.options.brandingPath.empty()) |
297 |
|
|
{ |
298 |
|
|
branding.init(settings.options.brandingPath, |
299 |
|
|
UseVirtFs_false, |
300 |
|
|
SkipError_false); |
301 |
|
|
} |
302 |
|
|
setBrandingDefaults(branding); |
303 |
|
|
|
304 |
|
|
Dirs::initRootDir(); |
305 |
|
|
Dirs::initHomeDir(); |
306 |
|
|
|
307 |
|
|
#ifndef ENABLE_COMMANDLINEPASSWORD |
308 |
|
|
if (!settings.options.password.empty()) |
309 |
|
|
{ |
310 |
|
|
settings.options.password.clear(); |
311 |
|
|
logger->log("Command line password parameter disabled."); |
312 |
|
|
} |
313 |
|
|
#endif |
314 |
|
|
|
315 |
|
|
// Configure logger |
316 |
|
|
if (!settings.options.logFileName.empty()) |
317 |
|
|
{ |
318 |
|
|
settings.logFileName = settings.options.logFileName; |
319 |
|
|
} |
320 |
|
|
else |
321 |
|
|
{ |
322 |
|
|
settings.logFileName = pathJoin(settings.localDataDir, |
323 |
|
|
"manaplus.log"); |
324 |
|
|
} |
325 |
|
|
logger->log("Log file: " + settings.logFileName); |
326 |
|
|
logger->setLogFile(settings.logFileName); |
327 |
|
|
|
328 |
|
|
#ifdef USE_FUZZER |
329 |
|
|
Fuzzer::init(); |
330 |
|
|
#endif // USE_FUZZER |
331 |
|
|
|
332 |
|
|
if (settings.options.ipc == true) |
333 |
|
|
IPC::start(); |
334 |
|
|
if (settings.options.test.empty()) |
335 |
|
|
ConfigManager::backupConfig("config.xml"); |
336 |
|
|
ConfigManager::initConfiguration(); |
337 |
|
|
SDL::setLogLevel(config.getIntValue("sdlLogLevel")); |
338 |
|
|
settings.init(); |
339 |
|
|
Net::loadIgnorePackets(); |
340 |
|
|
setPathsDefaults(paths); |
341 |
|
|
initFeatures(); |
342 |
|
|
initPaths(); |
343 |
|
|
logger->log("init 4"); |
344 |
|
|
logger->setDebugLog(config.getBoolValue("debugLog")); |
345 |
|
|
logger->setReportUnimplemented(config.getBoolValue("unimplimentedLog")); |
346 |
|
|
|
347 |
|
|
config.incValue("runcount"); |
348 |
|
|
|
349 |
|
|
#ifndef ANDROID |
350 |
|
|
if (settings.options.test.empty()) |
351 |
|
|
ConfigManager::storeSafeParameters(); |
352 |
|
|
#endif // ANDROID |
353 |
|
|
|
354 |
|
|
if (!VirtFs::setWriteDir(settings.localDataDir)) |
355 |
|
|
{ |
356 |
|
|
logger->error(strprintf("%s couldn't be set as home directory! " |
357 |
|
|
"Exiting.", settings.localDataDir.c_str())); |
358 |
|
|
} |
359 |
|
|
|
360 |
|
|
GettextHelper::initLang(); |
361 |
|
|
|
362 |
|
|
chatLogger = new ChatLogger; |
363 |
|
|
if (settings.options.chatLogDir.empty()) |
364 |
|
|
{ |
365 |
|
|
chatLogger->setBaseLogDir(settings.localDataDir |
366 |
|
|
+ std::string("/logs/")); |
367 |
|
|
} |
368 |
|
|
else |
369 |
|
|
{ |
370 |
|
|
chatLogger->setBaseLogDir(settings.options.chatLogDir); |
371 |
|
|
} |
372 |
|
|
|
373 |
|
|
// Log the client version |
374 |
|
|
logger->log1(FULL_VERSION); |
375 |
|
|
logger->log("Start configPath: " + config.getConfigPath()); |
376 |
|
|
|
377 |
|
|
Dirs::initScreenshotDir(); |
378 |
|
|
|
379 |
|
|
updateEnv(); |
380 |
|
|
SDL::allowScreenSaver(config.getBoolValue("allowscreensaver")); |
381 |
|
|
dumpLibs(); |
382 |
|
|
dumpSizes(); |
383 |
|
|
|
384 |
|
|
// Initialize SDL |
385 |
|
|
logger->log1("Initializing SDL..."); |
386 |
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) |
387 |
|
|
{ |
388 |
|
|
logger->safeError(strprintf("Could not initialize SDL: %s", |
389 |
|
|
SDL_GetError())); |
390 |
|
|
} |
391 |
|
|
#ifndef __SWITCH__ |
392 |
|
|
atexit(SDL_Quit); |
393 |
|
|
#endif |
394 |
|
|
PacketLimiter::initPacketLimiter(); |
395 |
|
|
#ifndef USE_SDL2 |
396 |
|
|
SDL_EnableUNICODE(1); |
397 |
|
|
#endif // USE_SDL2 |
398 |
|
|
|
399 |
|
|
WindowManager::applyKeyRepeat(); |
400 |
|
|
eventsManager.init(); |
401 |
|
|
eventsManager.enableEvents(); |
402 |
|
|
|
403 |
|
|
#ifdef WIN32 |
404 |
|
|
Dirs::mountDataDir(); |
405 |
|
|
#endif // WIN32 |
406 |
|
|
#ifndef USE_SDL2 |
407 |
|
|
WindowManager::setIcon(); |
408 |
|
|
#endif // USE_SDL2 |
409 |
|
|
|
410 |
|
|
ConfigManager::checkConfigVersion(); |
411 |
|
|
logVars(); |
412 |
|
|
Cpu::detect(); |
413 |
|
|
DyePalette::initFunctions(); |
414 |
|
|
#if defined(USE_OPENGL) |
415 |
|
|
#if !defined(ANDROID) && !defined(__APPLE__) |
416 |
|
|
#if !defined(__native_client__) && !defined(__SWITCH__) && !defined(UNITTESTS) |
417 |
|
|
if (!settings.options.safeMode && |
418 |
|
|
settings.options.renderer < 0 && |
419 |
|
|
settings.options.test.empty() && |
420 |
|
|
!settings.options.validate && |
421 |
|
|
!config.getBoolValue("videodetected")) |
422 |
|
|
{ |
423 |
|
|
graphicsManager.detectVideoSettings(); |
424 |
|
|
} |
425 |
|
|
#endif // !defined(__native_client__) && !defined(__SWITCH__) && |
426 |
|
|
// !defined(UNITTESTS) |
427 |
|
|
#endif // !defined(ANDROID) && !defined(__APPLE__) && |
428 |
|
|
#endif // defined(USE_OPENGL) |
429 |
|
|
|
430 |
|
|
initGraphics(); |
431 |
|
|
UserAgent::update(); |
432 |
|
|
|
433 |
|
|
touchManager.init(); |
434 |
|
|
|
435 |
|
|
#ifndef WIN32 |
436 |
|
|
Dirs::extractDataDir(); |
437 |
|
|
Dirs::mountDataDir(); |
438 |
|
|
#endif // WIN32 |
439 |
|
|
|
440 |
|
|
Dirs::updateDataPath(); |
441 |
|
|
|
442 |
|
|
// Add the main data directories to our VirtFs search path |
443 |
|
|
if (!settings.options.dataPath.empty()) |
444 |
|
|
{ |
445 |
|
|
VirtFs::mountDir(settings.options.dataPath, |
446 |
|
|
Append_false); |
447 |
|
|
} |
448 |
|
|
|
449 |
|
|
// Add the local data directory to VirtFs search path |
450 |
|
|
VirtFs::mountDir(settings.localDataDir, |
451 |
|
|
Append_false); |
452 |
|
|
TranslationManager::loadCurrentLang(); |
453 |
|
|
TranslationManager::loadDictionaryLang(); |
454 |
|
|
#ifdef ENABLE_CUSTOMNLS |
455 |
|
|
TranslationManager::loadGettextLang(); |
456 |
|
|
#endif // ENABLE_CUSTOMNLS |
457 |
|
|
|
458 |
|
|
#ifdef USE_SDL2 |
459 |
|
|
WindowManager::setIcon(); |
460 |
|
|
#endif // USE_SDL2 |
461 |
|
|
WindowManager::initTitle(); |
462 |
|
|
|
463 |
|
|
mainGraphics->postInit(); |
464 |
|
|
|
465 |
|
|
theme = new Theme; |
466 |
|
|
Theme::selectSkin(); |
467 |
|
|
ActorSprite::load(); |
468 |
|
|
touchManager.init(); |
469 |
|
|
|
470 |
|
|
// Initialize the item and emote shortcuts. |
471 |
|
|
for (size_t f = 0; f < SHORTCUT_TABS; f ++) |
472 |
|
|
itemShortcut[f] = new ItemShortcut(f); |
473 |
|
|
emoteShortcut = new EmoteShortcut; |
474 |
|
|
dropShortcut = new DropShortcut; |
475 |
|
|
|
476 |
|
|
gui = new Gui; |
477 |
|
|
gui->postInit(mainGraphics); |
478 |
|
|
dialogsManager = new DialogsManager; |
479 |
|
|
popupManager = new PopupManager; |
480 |
|
|
|
481 |
|
|
initSoundManager(); |
482 |
|
|
|
483 |
|
|
// Initialize keyboard |
484 |
|
|
keyboard.init(); |
485 |
|
|
inputManager.init(); |
486 |
|
|
|
487 |
|
|
// Initialise player relations |
488 |
|
|
playerRelations.init(); |
489 |
|
|
Joystick::init(); |
490 |
|
|
WindowManager::createWindows(); |
491 |
|
|
|
492 |
|
|
keyboard.update(); |
493 |
|
|
if (joystick != nullptr) |
494 |
|
|
joystick->update(); |
495 |
|
|
|
496 |
|
|
// Initialize default server |
497 |
|
|
mCurrentServer.hostname = settings.options.serverName; |
498 |
|
|
mCurrentServer.port = settings.options.serverPort; |
499 |
|
|
if (!settings.options.serverType.empty()) |
500 |
|
|
{ |
501 |
|
|
mCurrentServer.type = ServerInfo::parseType( |
502 |
|
|
settings.options.serverType); |
503 |
|
|
} |
504 |
|
|
|
505 |
|
|
loginData.username = settings.options.username; |
506 |
|
|
loginData.password = settings.options.password; |
507 |
|
|
LoginDialog::savedPassword = settings.options.password; |
508 |
|
|
loginData.remember = (serverConfig.getValue("remember", 1) != 0); |
509 |
|
|
loginData.registerLogin = false; |
510 |
|
|
|
511 |
|
|
if (mCurrentServer.hostname.empty()) |
512 |
|
|
{ |
513 |
|
|
mCurrentServer.hostname = branding.getValue("defaultServer", ""); |
514 |
|
|
settings.options.serverName = mCurrentServer.hostname; |
515 |
|
|
} |
516 |
|
|
|
517 |
|
|
if (mCurrentServer.port == 0) |
518 |
|
|
{ |
519 |
|
|
mCurrentServer.port = CAST_U16(branding.getValue( |
520 |
|
|
"defaultPort", CAST_S32(DEFAULT_PORT))); |
521 |
|
|
mCurrentServer.type = ServerInfo::parseType( |
522 |
|
|
branding.getValue("defaultServerType", "tmwathena")); |
523 |
|
|
} |
524 |
|
|
|
525 |
|
|
chatLogger->setServerName(mCurrentServer.hostname); |
526 |
|
|
|
527 |
|
|
if (loginData.username.empty() && loginData.remember) |
528 |
|
|
loginData.username = serverConfig.getValue("username", ""); |
529 |
|
|
|
530 |
|
|
if (mState != State::ERROR) |
531 |
|
|
mState = State::CHOOSE_SERVER; |
532 |
|
|
|
533 |
|
|
startTimers(); |
534 |
|
|
|
535 |
|
|
const int fpsLimit = config.getIntValue("fpslimit"); |
536 |
|
|
settings.limitFps = fpsLimit > 0; |
537 |
|
|
|
538 |
|
|
SDL_initFramerate(&fpsManager); |
539 |
|
|
WindowManager::setFramerate(fpsLimit); |
540 |
|
|
initConfigListeners(); |
541 |
|
|
|
542 |
|
|
settings.guiAlpha = config.getFloatValue("guialpha"); |
543 |
|
|
optionChanged("fpslimit"); |
544 |
|
|
|
545 |
|
|
start_time = time(nullptr); |
546 |
|
|
|
547 |
|
|
PlayerInfo::init(); |
548 |
|
|
|
549 |
|
|
#ifdef ANDROID |
550 |
|
|
#ifndef USE_SDL2 |
551 |
|
|
WindowManager::updateScreenKeyboard(SDL_GetScreenKeyboardHeight(nullptr)); |
552 |
|
|
#endif // USE_SDL2 |
553 |
|
|
#endif // ANDROID |
554 |
|
|
|
555 |
|
|
#ifdef USE_MUMBLE |
556 |
|
|
if (!mumbleManager) |
557 |
|
|
mumbleManager = new MumbleManager; |
558 |
|
|
#endif // USE_MUMBLE |
559 |
|
|
|
560 |
|
|
mSkin = theme->load("windowmenu.xml", |
561 |
|
|
"", |
562 |
|
|
true, |
563 |
|
|
Theme::getThemePath()); |
564 |
|
|
if (mSkin != nullptr) |
565 |
|
|
{ |
566 |
|
|
mButtonPadding = mSkin->getPadding(); |
567 |
|
|
mButtonSpacing = mSkin->getOption("spacing", 3); |
568 |
|
|
} |
569 |
|
|
if (settings.options.error) |
570 |
|
|
inputManager.executeAction(InputAction::ERROR); |
571 |
|
|
|
572 |
|
|
if (settings.options.validate == true) |
573 |
|
|
runValidate(); |
574 |
|
|
} |
575 |
|
|
|
576 |
|
645 |
Client::~Client() |
577 |
|
|
{ |
578 |
✓✗ |
215 |
if (!settings.options.testMode) |
579 |
|
215 |
gameClear(); |
580 |
|
|
else |
581 |
|
|
testsClear(); |
582 |
|
|
CHECKLISTENERS |
583 |
|
430 |
} |
584 |
|
|
|
585 |
|
|
void Client::initConfigListeners() |
586 |
|
|
{ |
587 |
|
|
config.addListener("fpslimit", this); |
588 |
|
|
config.addListener("guialpha", this); |
589 |
|
|
config.addListener("gamma", this); |
590 |
|
|
config.addListener("enableGamma", this); |
591 |
|
|
config.addListener("particleEmitterSkip", this); |
592 |
|
|
config.addListener("vsync", this); |
593 |
|
|
config.addListener("repeateDelay", this); |
594 |
|
|
config.addListener("repeateInterval", this); |
595 |
|
|
config.addListener("logInput", this); |
596 |
|
|
} |
597 |
|
|
|
598 |
|
|
void Client::initSoundManager() |
599 |
|
|
{ |
600 |
|
|
// Initialize sound engine |
601 |
|
|
try |
602 |
|
|
{ |
603 |
|
|
if (config.getBoolValue("sound")) |
604 |
|
|
soundManager.init(); |
605 |
|
|
|
606 |
|
|
soundManager.setSfxVolume(config.getIntValue("sfxVolume")); |
607 |
|
|
soundManager.setMusicVolume(config.getIntValue("musicVolume")); |
608 |
|
|
} |
609 |
|
|
catch (const char *const err) |
610 |
|
|
{ |
611 |
|
|
mState = State::ERROR; |
612 |
|
|
errorMessage = err; |
613 |
|
|
logger->log("Warning: %s", err); |
614 |
|
|
} |
615 |
|
|
soundManager.playMusic(branding.getValue( |
616 |
|
|
"loginMusic", |
617 |
|
|
"keprohm.ogg"), |
618 |
|
|
SkipError_true); |
619 |
|
|
} |
620 |
|
|
|
621 |
|
|
void Client::initGraphics() |
622 |
|
|
{ |
623 |
|
|
#ifndef USE_SDL2 |
624 |
|
|
WindowManager::applyVSync(); |
625 |
|
|
#endif // USE_SDL2 |
626 |
|
|
|
627 |
|
|
runCounters = config.getBoolValue("packetcounters"); |
628 |
|
|
|
629 |
|
|
graphicsManager.initGraphics(); |
630 |
|
|
#ifdef USE_SDL2 |
631 |
|
|
WindowManager::applyVSync(); |
632 |
|
|
#endif // USE_SDL2 |
633 |
|
|
|
634 |
|
|
imageHelper->postInit(); |
635 |
|
|
setConfigDefaults2(config); |
636 |
|
|
WindowManager::applyGrabMode(); |
637 |
|
|
WindowManager::applyGamma(); |
638 |
|
|
|
639 |
|
|
mainGraphics->beginDraw(); |
640 |
|
|
} |
641 |
|
|
|
642 |
|
|
void Client::testsClear() |
643 |
|
|
{ |
644 |
|
|
if (!settings.options.test.empty()) |
645 |
|
|
gameClear(); |
646 |
|
|
else |
647 |
|
|
BeingInfo::clear(); |
648 |
|
|
} |
649 |
|
|
|
650 |
|
215 |
void Client::gameClear() |
651 |
|
|
{ |
652 |
✓✗ |
215 |
if (logger != nullptr) |
653 |
|
215 |
logger->log1("Quitting1"); |
654 |
|
215 |
isTerminate = true; |
655 |
|
215 |
config.removeListeners(this); |
656 |
|
|
|
657 |
✗✓ |
215 |
delete2(assertListener) |
658 |
|
|
|
659 |
|
215 |
IPC::stop(); |
660 |
|
215 |
eventsManager.shutdown(); |
661 |
|
215 |
WindowManager::deleteWindows(); |
662 |
✓✓ |
215 |
if (windowContainer != nullptr) |
663 |
|
127 |
windowContainer->slowLogic(); |
664 |
|
|
|
665 |
|
215 |
stopTimers(); |
666 |
|
215 |
DbManager::unloadDb(); |
667 |
|
|
|
668 |
✗✓ |
215 |
if (loginHandler != nullptr) |
669 |
|
|
loginHandler->clearWorlds(); |
670 |
|
|
|
671 |
✗✓ |
215 |
if (chatHandler != nullptr) |
672 |
|
|
chatHandler->clear(); |
673 |
|
|
|
674 |
✓✓ |
215 |
if (charServerHandler != nullptr) |
675 |
|
77 |
charServerHandler->clear(); |
676 |
|
|
|
677 |
✗✓ |
215 |
delete2(ipc) |
678 |
|
|
|
679 |
|
|
#ifdef USE_MUMBLE |
680 |
✗✓ |
215 |
delete2(mumbleManager) |
681 |
|
|
#endif // USE_MUMBLE |
682 |
|
|
|
683 |
|
215 |
PlayerInfo::deinit(); |
684 |
|
|
|
685 |
|
|
// Before config.write() since it writes the shortcuts to the config |
686 |
✓✓ |
1290 |
for (unsigned f = 0; f < SHORTCUT_TABS; f ++) |
687 |
✗✓ |
1075 |
delete2(itemShortcut[f]) |
688 |
✗✓ |
215 |
delete2(emoteShortcut) |
689 |
✗✓ |
215 |
delete2(dropShortcut) |
690 |
|
|
|
691 |
|
215 |
playerRelations.store(); |
692 |
|
|
|
693 |
✓✗ |
215 |
if (logger != nullptr) |
694 |
|
215 |
logger->log1("Quitting2"); |
695 |
|
|
|
696 |
✗✓ |
215 |
delete2(mCurrentDialog) |
697 |
✗✓ |
215 |
delete2(popupManager) |
698 |
✗✓ |
215 |
delete2(dialogsManager) |
699 |
✓✓ |
215 |
delete2(gui) |
700 |
|
|
|
701 |
✓✓ |
215 |
if (inventoryHandler != nullptr) |
702 |
|
77 |
inventoryHandler->clear(); |
703 |
|
|
|
704 |
✓✗ |
215 |
if (logger != nullptr) |
705 |
|
215 |
logger->log1("Quitting3"); |
706 |
|
|
|
707 |
|
215 |
touchManager.clear(); |
708 |
|
|
|
709 |
|
215 |
GraphicsManager::deleteRenderers(); |
710 |
|
|
|
711 |
✓✗ |
215 |
if (logger != nullptr) |
712 |
|
215 |
logger->log1("Quitting4"); |
713 |
|
|
|
714 |
|
215 |
XML::cleanupXML(); |
715 |
|
|
|
716 |
✓✗ |
215 |
if (logger != nullptr) |
717 |
|
215 |
logger->log1("Quitting5"); |
718 |
|
|
|
719 |
|
215 |
BeingInfo::clear(); |
720 |
|
|
|
721 |
|
|
// Shutdown sound |
722 |
|
215 |
soundManager.close(); |
723 |
|
|
|
724 |
✓✗ |
215 |
if (logger != nullptr) |
725 |
|
215 |
logger->log1("Quitting6"); |
726 |
|
|
|
727 |
|
215 |
ActorSprite::unload(); |
728 |
|
|
|
729 |
|
215 |
ResourceManager::deleteInstance(); |
730 |
|
|
|
731 |
|
215 |
soundManager.shutdown(); |
732 |
|
|
|
733 |
✓✗ |
215 |
if (logger != nullptr) |
734 |
|
215 |
logger->log1("Quitting8"); |
735 |
|
|
|
736 |
|
215 |
WindowManager::deleteIcon(); |
737 |
|
|
|
738 |
✓✗ |
215 |
if (logger != nullptr) |
739 |
|
215 |
logger->log1("Quitting9"); |
740 |
|
|
|
741 |
✗✓ |
215 |
delete2(joystick) |
742 |
|
|
|
743 |
|
215 |
keyboard.deinit(); |
744 |
|
|
|
745 |
✓✗ |
215 |
if (logger != nullptr) |
746 |
|
215 |
logger->log1("Quitting10"); |
747 |
|
|
|
748 |
|
215 |
touchManager.shutdown(); |
749 |
|
|
|
750 |
|
|
#ifdef DEBUG_CONFIG |
751 |
|
|
config.enableKeyLogging(); |
752 |
|
|
#endif // DEBUG_CONFIG |
753 |
|
|
|
754 |
|
215 |
config.removeOldKeys(); |
755 |
|
215 |
config.write(); |
756 |
|
215 |
serverConfig.write(); |
757 |
|
|
|
758 |
|
215 |
config.clear(); |
759 |
|
215 |
serverConfig.clear(); |
760 |
|
|
|
761 |
✓✗ |
215 |
if (logger != nullptr) |
762 |
|
215 |
logger->log1("Quitting11"); |
763 |
|
|
|
764 |
|
|
#ifdef USE_PROFILER |
765 |
|
|
Perfomance::clear(); |
766 |
|
|
#endif // USE_PROFILER |
767 |
|
|
|
768 |
|
|
#ifdef DEBUG_OPENGL_LEAKS |
769 |
|
|
if (logger) |
770 |
|
|
logger->log("textures left: %d", textures_count); |
771 |
|
|
#endif // DEBUG_OPENGL_LEAKS |
772 |
|
|
|
773 |
|
215 |
Graphics::cleanUp(); |
774 |
|
|
|
775 |
✓✗ |
215 |
if (logger != nullptr) |
776 |
|
215 |
logger->log1("Quitting12"); |
777 |
|
|
|
778 |
✗✓ |
215 |
delete2(chatLogger) |
779 |
|
215 |
TranslationManager::close(); |
780 |
|
215 |
} |
781 |
|
|
|
782 |
|
|
int Client::testsExec() |
783 |
|
|
{ |
784 |
|
|
#ifdef USE_OPENGL |
785 |
|
|
if (settings.options.test.empty()) |
786 |
|
|
{ |
787 |
|
|
TestMain test; |
788 |
|
|
return test.exec(); |
789 |
|
|
} |
790 |
|
|
else |
791 |
|
|
{ |
792 |
|
|
TestLauncher launcher(settings.options.test); |
793 |
|
|
return launcher.exec(); |
794 |
|
|
} |
795 |
|
|
#else // USE_OPENGL |
796 |
|
|
|
797 |
|
|
return 0; |
798 |
|
|
#endif // USE_OPENGL |
799 |
|
|
} |
800 |
|
|
|
801 |
|
|
#define ADDBUTTON(var, object) var = object; \ |
802 |
|
|
x -= var->getWidth() + mButtonSpacing; \ |
803 |
|
|
var->setPosition(x, mButtonPadding); \ |
804 |
|
|
top->add(var); |
805 |
|
|
|
806 |
|
|
void Client::stateConnectGame1() |
807 |
|
|
{ |
808 |
|
|
if ((gameHandler != nullptr) && |
809 |
|
|
(loginHandler != nullptr) && |
810 |
|
|
gameHandler->isConnected()) |
811 |
|
|
{ |
812 |
|
|
loginHandler->disconnect(); |
813 |
|
|
} |
814 |
|
|
} |
815 |
|
|
|
816 |
|
|
void Client::stateConnectServer1() |
817 |
|
|
{ |
818 |
|
|
if (mOldState == State::CHOOSE_SERVER) |
819 |
|
|
{ |
820 |
|
|
settings.serverName = mCurrentServer.hostname; |
821 |
|
|
ConfigManager::initServerConfig(mCurrentServer.hostname); |
822 |
|
|
PacketLimiter::initPacketLimiter(); |
823 |
|
|
initTradeFilter(); |
824 |
|
|
Dirs::initUsersDir(); |
825 |
|
|
playerRelations.init(); |
826 |
|
|
|
827 |
|
|
// Initialize the item and emote shortcuts. |
828 |
|
|
for (unsigned f = 0; f < SHORTCUT_TABS; f ++) |
829 |
|
|
{ |
830 |
|
|
delete itemShortcut[f]; |
831 |
|
|
itemShortcut[f] = new ItemShortcut(f); |
832 |
|
|
} |
833 |
|
|
delete emoteShortcut; |
834 |
|
|
emoteShortcut = new EmoteShortcut; |
835 |
|
|
|
836 |
|
|
// Initialize the drop shortcuts. |
837 |
|
|
delete dropShortcut; |
838 |
|
|
dropShortcut = new DropShortcut; |
839 |
|
|
|
840 |
|
|
initFeatures(); |
841 |
|
|
PlayerInfo::loadData(); |
842 |
|
|
loginData.registerUrl = mCurrentServer.registerUrl; |
843 |
|
|
loginData.packetVersion = mCurrentServer.packetVersion; |
844 |
|
|
if (!mCurrentServer.onlineListUrl.empty()) |
845 |
|
|
settings.onlineListUrl = mCurrentServer.onlineListUrl; |
846 |
|
|
else |
847 |
|
|
settings.onlineListUrl = settings.serverName; |
848 |
|
|
settings.persistentIp = mCurrentServer.persistentIp; |
849 |
|
|
settings.supportUrl = mCurrentServer.supportUrl; |
850 |
|
|
settings.updateMirrors = mCurrentServer.updateMirrors; |
851 |
|
|
settings.enableRemoteCommands = (serverConfig.getValue( |
852 |
|
|
"enableRemoteCommands", 1) != 0); |
853 |
|
|
|
854 |
|
|
if (settings.options.username.empty()) |
855 |
|
|
{ |
856 |
|
|
if (loginData.remember) |
857 |
|
|
loginData.username = serverConfig.getValue("username", ""); |
858 |
|
|
else |
859 |
|
|
loginData.username.clear(); |
860 |
|
|
} |
861 |
|
|
else |
862 |
|
|
{ |
863 |
|
|
loginData.username = settings.options.username; |
864 |
|
|
} |
865 |
|
|
#ifdef SAVE_PASSWORD |
866 |
|
|
LoginDialog::savedPassword = loginData.remember ? |
867 |
|
|
serverConfig.getValue("password", "") : ""; |
868 |
|
|
loginData.password = LoginDialog::savedPassword; |
869 |
|
|
settings.options.password = LoginDialog::savedPassword; |
870 |
|
|
#endif |
871 |
|
|
settings.login = loginData.username; |
872 |
|
|
WindowManager::updateTitle(); |
873 |
|
|
|
874 |
|
|
loginData.remember = (serverConfig.getValue("remember", 1) != 0); |
875 |
|
|
Net::connectToServer(mCurrentServer); |
876 |
|
|
|
877 |
|
|
#ifdef USE_MUMBLE |
878 |
|
|
if (mumbleManager) |
879 |
|
|
mumbleManager->setServer(mCurrentServer.hostname); |
880 |
|
|
#endif // USE_MUMBLE |
881 |
|
|
|
882 |
|
|
#ifdef TMWA_SUPPORT |
883 |
|
|
GuildManager::init(); |
884 |
|
|
#endif // TMWA_SUPPORT |
885 |
|
|
|
886 |
|
|
if (!mConfigAutoSaved) |
887 |
|
|
{ |
888 |
|
|
mConfigAutoSaved = true; |
889 |
|
|
config.write(); |
890 |
|
|
} |
891 |
|
|
} |
892 |
|
|
else if (loginHandler != nullptr && |
893 |
|
|
loginHandler->isConnected()) |
894 |
|
|
{ |
895 |
|
|
mState = State::PRE_LOGIN; |
896 |
|
|
} |
897 |
|
|
} |
898 |
|
|
|
899 |
|
|
void Client::stateWorldSelect1() |
900 |
|
|
{ |
901 |
|
|
if (mOldState == State::UPDATE && |
902 |
|
|
(loginHandler != nullptr)) |
903 |
|
|
{ |
904 |
|
|
if (loginHandler->getWorlds().size() < 2) |
905 |
|
|
mState = State::PRE_LOGIN; |
906 |
|
|
} |
907 |
|
|
} |
908 |
|
|
|
909 |
|
|
void Client::stateGame1() |
910 |
|
|
{ |
911 |
|
|
if (gui == nullptr) |
912 |
|
|
return; |
913 |
|
|
|
914 |
|
|
BasicContainer2 *const top = static_cast<BasicContainer2*>( |
915 |
|
|
gui->getTop()); |
916 |
|
|
|
917 |
|
|
if (top == nullptr) |
918 |
|
|
return; |
919 |
|
|
|
920 |
|
|
CREATEWIDGETV(desktop, Desktop, nullptr); |
921 |
|
|
top->add(desktop); |
922 |
|
|
int x = top->getWidth() - mButtonPadding; |
923 |
|
|
ADDBUTTON(mSetupButton, new Button(desktop, |
924 |
|
|
// TRANSLATORS: setup tab quick button |
925 |
|
|
_("Setup"), "Setup", BUTTON_SKIN, this)) |
926 |
|
|
ADDBUTTON(mPerfomanceButton, new Button(desktop, |
927 |
|
|
// TRANSLATORS: perfoamance tab quick button |
928 |
|
|
_("Performance"), "Perfomance", BUTTON_SKIN, this)) |
929 |
|
|
ADDBUTTON(mVideoButton, new Button(desktop, |
930 |
|
|
// TRANSLATORS: video tab quick button |
931 |
|
|
_("Video"), "Video", BUTTON_SKIN, this)) |
932 |
|
|
ADDBUTTON(mThemesButton, new Button(desktop, |
933 |
|
|
// TRANSLATORS: theme tab quick button |
934 |
|
|
_("Theme"), "Themes", BUTTON_SKIN, this)) |
935 |
|
|
ADDBUTTON(mAboutButton, new Button(desktop, |
936 |
|
|
// TRANSLATORS: theme tab quick button |
937 |
|
|
_("About"), "about", BUTTON_SKIN, this)) |
938 |
|
|
ADDBUTTON(mHelpButton, new Button(desktop, |
939 |
|
|
// TRANSLATORS: theme tab quick button |
940 |
|
|
_("Help"), "help", BUTTON_SKIN, this)) |
941 |
|
|
#ifdef ANDROID |
942 |
|
|
ADDBUTTON(mCloseButton, new Button(desktop, |
943 |
|
|
// TRANSLATORS: close quick button |
944 |
|
|
_("Close"), "close", BUTTON_SKIN, this)) |
945 |
|
|
#endif // ANDROID |
946 |
|
|
|
947 |
|
|
desktop->setSize(mainGraphics->getWidth(), |
948 |
|
|
mainGraphics->getHeight()); |
949 |
|
|
} |
950 |
|
|
|
951 |
|
|
void Client::stateSwitchLogin1() |
952 |
|
|
{ |
953 |
|
|
if (mOldState == State::GAME && |
954 |
|
|
(gameHandler != nullptr)) |
955 |
|
|
{ |
956 |
|
|
gameHandler->disconnect(); |
957 |
|
|
} |
958 |
|
|
} |
959 |
|
|
|
960 |
|
|
int Client::gameExec() |
961 |
|
|
{ |
962 |
|
|
int lastTickTime = tick_time; |
963 |
|
|
|
964 |
|
|
Perf::init(); |
965 |
|
|
|
966 |
|
|
while (mState != State::EXIT) |
967 |
|
|
{ |
968 |
|
|
PROFILER_START(); |
969 |
|
|
PERF_STAT(0); |
970 |
|
|
if (eventsManager.handleEvents()) |
971 |
|
|
continue; |
972 |
|
|
|
973 |
|
|
PERF_STAT(1); |
974 |
|
|
|
975 |
|
|
BLOCK_START("Client::gameExec 3") |
976 |
|
|
if (generalHandler != nullptr) |
977 |
|
|
generalHandler->flushNetwork(); |
978 |
|
|
BLOCK_END("Client::gameExec 3") |
979 |
|
|
|
980 |
|
|
PERF_STAT(2); |
981 |
|
|
|
982 |
|
|
BLOCK_START("Client::gameExec 4") |
983 |
|
|
if (gui != nullptr) |
984 |
|
|
gui->logic(); |
985 |
|
|
|
986 |
|
|
PERF_STAT(3); |
987 |
|
|
|
988 |
|
|
cur_time = time(nullptr); |
989 |
|
|
int k = 0; |
990 |
|
|
while (lastTickTime != tick_time && |
991 |
|
|
k < 40) |
992 |
|
|
{ |
993 |
|
|
if (mGame != nullptr) |
994 |
|
|
mGame->logic(); |
995 |
|
|
else if (gui != nullptr) |
996 |
|
|
gui->handleInput(); |
997 |
|
|
|
998 |
|
|
++lastTickTime; |
999 |
|
|
k ++; |
1000 |
|
|
} |
1001 |
|
|
|
1002 |
|
|
PERF_STAT(4); |
1003 |
|
|
|
1004 |
|
|
soundManager.logic(); |
1005 |
|
|
|
1006 |
|
|
PERF_STAT(5); |
1007 |
|
|
|
1008 |
|
|
logic_count = logic_count + k; |
1009 |
|
|
if (gui != nullptr) |
1010 |
|
|
gui->slowLogic(); |
1011 |
|
|
|
1012 |
|
|
PERF_STAT(6); |
1013 |
|
|
|
1014 |
|
|
if (mGame != nullptr) |
1015 |
|
|
mGame->slowLogic(); |
1016 |
|
|
|
1017 |
|
|
PERF_STAT(7); |
1018 |
|
|
|
1019 |
|
|
slowLogic(); |
1020 |
|
|
|
1021 |
|
|
PERF_STAT(8); |
1022 |
|
|
|
1023 |
|
|
BLOCK_END("Client::gameExec 4") |
1024 |
|
|
|
1025 |
|
|
// This is done because at some point tick_time will wrap. |
1026 |
|
|
lastTickTime = tick_time; |
1027 |
|
|
|
1028 |
|
|
BLOCK_START("Client::gameExec 6") |
1029 |
|
|
if (mState == State::CONNECT_GAME) |
1030 |
|
|
{ |
1031 |
|
|
stateConnectGame1(); |
1032 |
|
|
} |
1033 |
|
|
else if (mState == State::CONNECT_SERVER) |
1034 |
|
|
{ |
1035 |
|
|
stateConnectServer1(); |
1036 |
|
|
} |
1037 |
|
|
else if (mState == State::WORLD_SELECT) |
1038 |
|
|
{ |
1039 |
|
|
stateWorldSelect1(); |
1040 |
|
|
} |
1041 |
|
|
else if (mOldState == State::START || |
1042 |
|
|
(mOldState == State::GAME && mState != State::GAME)) |
1043 |
|
|
{ |
1044 |
|
|
stateGame1(); |
1045 |
|
|
} |
1046 |
|
|
else if (mState == State::SWITCH_LOGIN) |
1047 |
|
|
{ |
1048 |
|
|
stateSwitchLogin1(); |
1049 |
|
|
} |
1050 |
|
|
BLOCK_END("Client::gameExec 6") |
1051 |
|
|
|
1052 |
|
|
PERF_STAT(9); |
1053 |
|
|
|
1054 |
|
|
if (mState != mOldState) |
1055 |
|
|
{ |
1056 |
|
|
BLOCK_START("Client::gameExec 7") |
1057 |
|
|
PlayerInfo::stateChange(mState); |
1058 |
|
|
|
1059 |
|
|
if (mOldState == State::GAME) |
1060 |
|
|
{ |
1061 |
|
|
delete2(mGame) |
1062 |
|
|
assertListener = new AssertListener; |
1063 |
|
|
Game::clearInstance(); |
1064 |
|
|
ResourceManager::cleanOrphans(false); |
1065 |
|
|
Party::clearParties(); |
1066 |
|
|
Guild::clearGuilds(); |
1067 |
|
|
NpcDialog::clearDialogs(); |
1068 |
|
|
if (guildHandler != nullptr) |
1069 |
|
|
guildHandler->clear(); |
1070 |
|
|
if (partyHandler != nullptr) |
1071 |
|
|
partyHandler->clear(); |
1072 |
|
|
if (chatLogger != nullptr) |
1073 |
|
|
chatLogger->clear(); |
1074 |
|
|
if (!settings.options.dataPath.empty()) |
1075 |
|
|
UpdaterWindow::unloadMods(settings.options.dataPath); |
1076 |
|
|
else |
1077 |
|
|
UpdaterWindow::unloadMods(settings.oldUpdates); |
1078 |
|
|
if (!settings.options.skipUpdate) |
1079 |
|
|
UpdaterWindow::unloadMods(settings.oldUpdates + "/fix/"); |
1080 |
|
|
} |
1081 |
|
|
else if (mOldState == State::CHAR_SELECT) |
1082 |
|
|
{ |
1083 |
|
|
if (mState != State::CHANGEPASSWORD && |
1084 |
|
|
charServerHandler != nullptr) |
1085 |
|
|
{ |
1086 |
|
|
charServerHandler->clear(); |
1087 |
|
|
} |
1088 |
|
|
} |
1089 |
|
|
|
1090 |
|
|
mOldState = mState; |
1091 |
|
|
|
1092 |
|
|
// Get rid of the dialog of the previous state |
1093 |
|
|
delete2(mCurrentDialog) |
1094 |
|
|
|
1095 |
|
|
// State has changed, while the quitDialog was active, it might |
1096 |
|
|
// not be correct anymore |
1097 |
|
|
if (mQuitDialog != nullptr) |
1098 |
|
|
{ |
1099 |
|
|
mQuitDialog->scheduleDelete(); |
1100 |
|
|
mQuitDialog = nullptr; |
1101 |
|
|
} |
1102 |
|
|
BLOCK_END("Client::gameExec 7") |
1103 |
|
|
|
1104 |
|
|
BLOCK_START("Client::gameExec 8") |
1105 |
|
|
switch (mState) |
1106 |
|
|
{ |
1107 |
|
|
case State::CHOOSE_SERVER: |
1108 |
|
|
{ |
1109 |
|
|
BLOCK_START("Client::gameExec STATE_CHOOSE_SERVER") |
1110 |
|
|
logger->log1("State: CHOOSE SERVER"); |
1111 |
|
|
unloadData(); |
1112 |
|
|
pincodeManager.closeDialogs(); |
1113 |
|
|
|
1114 |
|
|
// Allow changing this using a server choice dialog |
1115 |
|
|
// We show the dialog box only if the command-line |
1116 |
|
|
// options weren't set. |
1117 |
|
|
if (settings.options.serverName.empty() && |
1118 |
|
|
settings.options.serverPort == 0 && |
1119 |
|
|
!branding.getValue("onlineServerList", "a").empty()) |
1120 |
|
|
{ |
1121 |
|
|
// Don't allow an alpha opacity |
1122 |
|
|
// lower than the default value |
1123 |
|
|
theme->setMinimumOpacity(0.8F); |
1124 |
|
|
|
1125 |
|
|
CREATEWIDGETV(mCurrentDialog, ServerDialog, |
1126 |
|
|
&mCurrentServer, |
1127 |
|
|
settings.configDir); |
1128 |
|
|
} |
1129 |
|
|
else |
1130 |
|
|
{ |
1131 |
|
|
mState = State::CONNECT_SERVER; |
1132 |
|
|
|
1133 |
|
|
// Reset options so that cancelling or connect |
1134 |
|
|
// timeout will show the server dialog. |
1135 |
|
|
settings.options.serverName.clear(); |
1136 |
|
|
settings.options.serverPort = 0; |
1137 |
|
|
} |
1138 |
|
|
BLOCK_END("Client::gameExec STATE_CHOOSE_SERVER") |
1139 |
|
|
break; |
1140 |
|
|
} |
1141 |
|
|
|
1142 |
|
|
case State::CONNECT_SERVER: |
1143 |
|
|
BLOCK_START("Client::gameExec State::CONNECT_SERVER") |
1144 |
|
|
logger->log1("State: CONNECT SERVER"); |
1145 |
|
|
loginData.updateHosts.clear(); |
1146 |
|
|
CREATEWIDGETV(mCurrentDialog, ConnectionDialog, |
1147 |
|
|
// TRANSLATORS: connection dialog header |
1148 |
|
|
_("Connecting to server"), |
1149 |
|
|
State::SWITCH_SERVER); |
1150 |
|
|
TranslationManager::loadCurrentLang(); |
1151 |
|
|
TranslationManager::loadDictionaryLang(); |
1152 |
|
|
pincodeManager.init(); |
1153 |
|
|
BLOCK_END("Client::gameExec State::CONNECT_SERVER") |
1154 |
|
|
break; |
1155 |
|
|
|
1156 |
|
|
case State::PRE_LOGIN: |
1157 |
|
|
logger->log1("State: PRE_LOGIN"); |
1158 |
|
|
break; |
1159 |
|
|
|
1160 |
|
|
case State::LOGIN: |
1161 |
|
|
BLOCK_START("Client::gameExec State::LOGIN") |
1162 |
|
|
logger->log1("State: LOGIN"); |
1163 |
|
|
// Don't allow an alpha opacity |
1164 |
|
|
// lower than the default value |
1165 |
|
|
theme->setMinimumOpacity(0.8F); |
1166 |
|
|
|
1167 |
|
|
if (packetVersion == 0) |
1168 |
|
|
{ |
1169 |
|
|
packetVersion = loginData.packetVersion; |
1170 |
|
|
if (packetVersion != 0) |
1171 |
|
|
{ |
1172 |
|
|
loginHandler->updatePacketVersion(); |
1173 |
|
|
logger->log("Preconfigured packet version: %d", |
1174 |
|
|
packetVersion); |
1175 |
|
|
} |
1176 |
|
|
} |
1177 |
|
|
|
1178 |
|
|
loginData.updateType = static_cast<UpdateTypeT>( |
1179 |
|
|
serverConfig.getValue("updateType", 0)); |
1180 |
|
|
|
1181 |
|
|
mSearchHash = Net::Download::adlerBuffer( |
1182 |
|
|
const_cast<char*>(mCurrentServer.hostname.c_str()), |
1183 |
|
|
CAST_S32(mCurrentServer.hostname.size())); |
1184 |
|
|
if (settings.options.username.empty() || |
1185 |
|
|
settings.options.password.empty()) |
1186 |
|
|
{ |
1187 |
|
|
CREATEWIDGETV(mCurrentDialog, LoginDialog, |
1188 |
|
|
loginData, |
1189 |
|
|
&mCurrentServer, |
1190 |
|
|
&settings.options.updateHost); |
1191 |
|
|
} |
1192 |
|
|
else |
1193 |
|
|
{ |
1194 |
|
|
mState = State::LOGIN_ATTEMPT; |
1195 |
|
|
// Clear the password so that when login fails, the |
1196 |
|
|
// dialog will show up next time. |
1197 |
|
|
settings.options.password.clear(); |
1198 |
|
|
} |
1199 |
|
|
BLOCK_END("Client::gameExec State::LOGIN") |
1200 |
|
|
break; |
1201 |
|
|
|
1202 |
|
|
case State::LOGIN_ATTEMPT: |
1203 |
|
|
BLOCK_START("Client::gameExec State::LOGIN_ATTEMPT") |
1204 |
|
|
logger->log1("State: LOGIN ATTEMPT"); |
1205 |
|
|
CREATEWIDGETV(mCurrentDialog, ConnectionDialog, |
1206 |
|
|
// TRANSLATORS: connection dialog header |
1207 |
|
|
_("Logging in"), |
1208 |
|
|
State::SWITCH_SERVER); |
1209 |
|
|
if (loginHandler != nullptr) |
1210 |
|
|
loginHandler->loginOrRegister(&loginData); |
1211 |
|
|
BLOCK_END("Client::gameExec State::LOGIN_ATTEMPT") |
1212 |
|
|
break; |
1213 |
|
|
|
1214 |
|
|
case State::WORLD_SELECT: |
1215 |
|
|
BLOCK_START("Client::gameExec State::WORLD_SELECT") |
1216 |
|
|
logger->log1("State: WORLD SELECT"); |
1217 |
|
|
{ |
1218 |
|
|
TranslationManager::loadCurrentLang(); |
1219 |
|
|
TranslationManager::loadDictionaryLang(); |
1220 |
|
|
if (loginHandler == nullptr) |
1221 |
|
|
{ |
1222 |
|
|
BLOCK_END("Client::gameExec State::WORLD_SELECT") |
1223 |
|
|
break; |
1224 |
|
|
} |
1225 |
|
|
Worlds worlds = loginHandler->getWorlds(); |
1226 |
|
|
|
1227 |
|
|
if (worlds.empty()) |
1228 |
|
|
{ |
1229 |
|
|
// Trust that the netcode knows what it's doing |
1230 |
|
|
mState = State::UPDATE; |
1231 |
|
|
} |
1232 |
|
|
else if (worlds.size() == 1) |
1233 |
|
|
{ |
1234 |
|
|
loginHandler->chooseServer( |
1235 |
|
|
0, mCurrentServer.persistentIp); |
1236 |
|
|
mState = State::UPDATE; |
1237 |
|
|
} |
1238 |
|
|
else |
1239 |
|
|
{ |
1240 |
|
|
CREATEWIDGETV(mCurrentDialog, WorldSelectDialog, |
1241 |
|
|
worlds); |
1242 |
|
|
if (settings.options.chooseDefault) |
1243 |
|
|
{ |
1244 |
|
|
static_cast<WorldSelectDialog*>(mCurrentDialog) |
1245 |
|
|
->action(ActionEvent(nullptr, "ok")); |
1246 |
|
|
} |
1247 |
|
|
} |
1248 |
|
|
} |
1249 |
|
|
BLOCK_END("Client::gameExec State::WORLD_SELECT") |
1250 |
|
|
break; |
1251 |
|
|
|
1252 |
|
|
case State::WORLD_SELECT_ATTEMPT: |
1253 |
|
|
BLOCK_START("Client::gameExec State::WORLD_SELECT_ATTEMPT") |
1254 |
|
|
logger->log1("State: WORLD SELECT ATTEMPT"); |
1255 |
|
|
CREATEWIDGETV(mCurrentDialog, ConnectionDialog, |
1256 |
|
|
// TRANSLATORS: connection dialog header |
1257 |
|
|
_("Entering game world"), |
1258 |
|
|
State::WORLD_SELECT); |
1259 |
|
|
BLOCK_END("Client::gameExec State::WORLD_SELECT_ATTEMPT") |
1260 |
|
|
break; |
1261 |
|
|
|
1262 |
|
|
case State::UPDATE: |
1263 |
|
|
BLOCK_START("Client::gameExec State::UPDATE") |
1264 |
|
|
logger->log1("State: UPDATE"); |
1265 |
|
|
|
1266 |
|
|
// Determine which source to use for the update host |
1267 |
|
|
if (!settings.options.updateHost.empty()) |
1268 |
|
|
settings.updateHost = settings.options.updateHost; |
1269 |
|
|
else |
1270 |
|
|
settings.updateHost = loginData.updateHost; |
1271 |
|
|
Dirs::initUpdatesDir(); |
1272 |
|
|
|
1273 |
|
|
if (!settings.oldUpdates.empty()) |
1274 |
|
|
UpdaterWindow::unloadUpdates(settings.oldUpdates); |
1275 |
|
|
|
1276 |
|
|
if (settings.options.skipUpdate) |
1277 |
|
|
{ |
1278 |
|
|
mState = State::LOAD_DATA; |
1279 |
|
|
settings.oldUpdates.clear(); |
1280 |
|
|
UpdaterWindow::loadDirMods(settings.options.dataPath); |
1281 |
|
|
} |
1282 |
|
|
else if ((loginData.updateType & UpdateType::Skip) != 0) |
1283 |
|
|
{ |
1284 |
|
|
settings.oldUpdates = pathJoin(settings.localDataDir, |
1285 |
|
|
settings.updatesDir); |
1286 |
|
|
UpdaterWindow::loadLocalUpdates(settings.oldUpdates); |
1287 |
|
|
mState = State::LOAD_DATA; |
1288 |
|
|
} |
1289 |
|
|
else |
1290 |
|
|
{ |
1291 |
|
|
settings.oldUpdates = pathJoin(settings.localDataDir, |
1292 |
|
|
settings.updatesDir); |
1293 |
|
|
CREATEWIDGETV(mCurrentDialog, UpdaterWindow, |
1294 |
|
|
settings.updateHost, |
1295 |
|
|
settings.oldUpdates, |
1296 |
|
|
settings.options.dataPath.empty(), |
1297 |
|
|
loginData.updateType); |
1298 |
|
|
} |
1299 |
|
|
BLOCK_END("Client::gameExec State::UPDATE") |
1300 |
|
|
break; |
1301 |
|
|
|
1302 |
|
|
case State::LOAD_DATA: |
1303 |
|
|
{ |
1304 |
|
|
BLOCK_START("Client::gameExec State::LOAD_DATA") |
1305 |
|
|
logger->log1("State: LOAD DATA"); |
1306 |
|
|
|
1307 |
|
|
loadData(); |
1308 |
|
|
|
1309 |
|
|
mState = State::GET_CHARACTERS; |
1310 |
|
|
BLOCK_END("Client::gameExec State::LOAD_DATA") |
1311 |
|
|
break; |
1312 |
|
|
} |
1313 |
|
|
case State::GET_CHARACTERS: |
1314 |
|
|
BLOCK_START("Client::gameExec State::GET_CHARACTERS") |
1315 |
|
|
logger->log1("State: GET CHARACTERS"); |
1316 |
|
|
CREATEWIDGETV(mCurrentDialog, ConnectionDialog, |
1317 |
|
|
// TRANSLATORS: connection dialog header |
1318 |
|
|
_("Requesting characters"), |
1319 |
|
|
State::SWITCH_SERVER); |
1320 |
|
|
if (charServerHandler != nullptr) |
1321 |
|
|
charServerHandler->requestCharacters(); |
1322 |
|
|
BLOCK_END("Client::gameExec State::GET_CHARACTERS") |
1323 |
|
|
break; |
1324 |
|
|
|
1325 |
|
|
case State::CHAR_SELECT: |
1326 |
|
|
BLOCK_START("Client::gameExec State::CHAR_SELECT") |
1327 |
|
|
logger->log1("State: CHAR SELECT"); |
1328 |
|
|
// Don't allow an alpha opacity |
1329 |
|
|
// lower than the default value |
1330 |
|
|
theme->setMinimumOpacity(0.8F); |
1331 |
|
|
|
1332 |
|
|
settings.login = loginData.username; |
1333 |
|
|
WindowManager::updateTitle(); |
1334 |
|
|
|
1335 |
|
|
CREATEWIDGETV(mCurrentDialog, CharSelectDialog, |
1336 |
|
|
loginData); |
1337 |
|
|
pincodeManager.updateState(); |
1338 |
|
|
|
1339 |
|
|
if (!(static_cast<CharSelectDialog*>(mCurrentDialog)) |
1340 |
|
|
->selectByName(settings.options.character, |
1341 |
|
|
CharSelectDialog::Choose)) |
1342 |
|
|
{ |
1343 |
|
|
(static_cast<CharSelectDialog*>(mCurrentDialog)) |
1344 |
|
|
->selectByName( |
1345 |
|
|
serverConfig.getValue("lastCharacter", ""), |
1346 |
|
|
settings.options.chooseDefault ? |
1347 |
|
|
CharSelectDialog::Choose : |
1348 |
|
|
CharSelectDialog::Focus); |
1349 |
|
|
} |
1350 |
|
|
|
1351 |
|
|
// Choosing character on the command line should work only |
1352 |
|
|
// once, clear it so that 'switch character' works. |
1353 |
|
|
settings.options.character.clear(); |
1354 |
|
|
BLOCK_END("Client::gameExec State::CHAR_SELECT") |
1355 |
|
|
break; |
1356 |
|
|
|
1357 |
|
|
case State::CONNECT_GAME: |
1358 |
|
|
BLOCK_START("Client::gameExec State::CONNECT_GAME") |
1359 |
|
|
logger->log1("State: CONNECT GAME"); |
1360 |
|
|
CREATEWIDGETV(mCurrentDialog, ConnectionDialog, |
1361 |
|
|
// TRANSLATORS: connection dialog header |
1362 |
|
|
_("Connecting to the game server"), |
1363 |
|
|
State::CHOOSE_SERVER); |
1364 |
|
|
if (gameHandler != nullptr) |
1365 |
|
|
gameHandler->connect(); |
1366 |
|
|
BLOCK_END("Client::gameExec State::CONNECT_GAME") |
1367 |
|
|
break; |
1368 |
|
|
|
1369 |
|
|
case State::CHANGE_MAP: |
1370 |
|
|
BLOCK_START("Client::gameExec State::CHANGE_MAP") |
1371 |
|
|
logger->log1("State: CHANGE_MAP"); |
1372 |
|
|
CREATEWIDGETV(mCurrentDialog, ConnectionDialog, |
1373 |
|
|
// TRANSLATORS: connection dialog header |
1374 |
|
|
_("Changing game servers"), |
1375 |
|
|
State::SWITCH_CHARACTER); |
1376 |
|
|
if (gameHandler != nullptr) |
1377 |
|
|
gameHandler->connect(); |
1378 |
|
|
BLOCK_END("Client::gameExec State::CHANGE_MAP") |
1379 |
|
|
break; |
1380 |
|
|
|
1381 |
|
|
case State::GAME: |
1382 |
|
|
BLOCK_START("Client::gameExec State::GAME") |
1383 |
|
|
if (localPlayer != nullptr) |
1384 |
|
|
{ |
1385 |
|
|
logger->log("Memorizing selected character %s", |
1386 |
|
|
localPlayer->getName().c_str()); |
1387 |
|
|
serverConfig.setValue("lastCharacter", |
1388 |
|
|
localPlayer->getName()); |
1389 |
|
|
#ifdef USE_MUMBLE |
1390 |
|
|
if (mumbleManager) |
1391 |
|
|
mumbleManager->setPlayer(localPlayer->getName()); |
1392 |
|
|
#endif // USE_MUMBLE |
1393 |
|
|
Perf::init(); |
1394 |
|
|
} |
1395 |
|
|
|
1396 |
|
|
// Fade out logon-music here too to give the desired effect |
1397 |
|
|
// of "flowing" into the game. |
1398 |
|
|
soundManager.fadeOutMusic(1000); |
1399 |
|
|
|
1400 |
|
|
// Allow any alpha opacity |
1401 |
|
|
theme->setMinimumOpacity(-1.0F); |
1402 |
|
|
|
1403 |
|
|
if (chatLogger != nullptr) |
1404 |
|
|
chatLogger->setServerName(settings.serverName); |
1405 |
|
|
|
1406 |
|
|
#ifdef ANDROID |
1407 |
|
|
delete2(mCloseButton) |
1408 |
|
|
#endif // ANDROID |
1409 |
|
|
|
1410 |
|
|
delete2(mSetupButton) |
1411 |
|
|
delete2(mVideoButton) |
1412 |
|
|
delete2(mThemesButton) |
1413 |
|
|
delete2(mAboutButton) |
1414 |
|
|
delete2(mHelpButton) |
1415 |
|
|
delete2(mPerfomanceButton) |
1416 |
|
|
delete2(desktop) |
1417 |
|
|
|
1418 |
|
|
mCurrentDialog = nullptr; |
1419 |
|
|
|
1420 |
|
|
logger->log1("State: GAME"); |
1421 |
|
|
if (generalHandler != nullptr) |
1422 |
|
|
generalHandler->reloadPartially(); |
1423 |
|
|
mGame = new Game; |
1424 |
|
|
BLOCK_END("Client::gameExec State::GAME") |
1425 |
|
|
break; |
1426 |
|
|
|
1427 |
|
|
case State::LOGIN_ERROR: |
1428 |
|
|
BLOCK_START("Client::gameExec State::LOGIN_ERROR") |
1429 |
|
|
logger->log1("State: LOGIN ERROR"); |
1430 |
|
|
CREATEWIDGETV(mCurrentDialog, OkDialog, |
1431 |
|
|
// TRANSLATORS: error dialog header |
1432 |
|
|
_("Error"), |
1433 |
|
|
errorMessage, |
1434 |
|
|
// TRANSLATORS: ok dialog button |
1435 |
|
|
_("Close"), |
1436 |
|
|
DialogType::ERROR, |
1437 |
|
|
Modal_true, |
1438 |
|
|
ShowCenter_true, |
1439 |
|
|
nullptr, |
1440 |
|
|
260); |
1441 |
|
|
mCurrentDialog->addActionListener(&loginListener); |
1442 |
|
|
mCurrentDialog = nullptr; // OkDialog deletes itself |
1443 |
|
|
BLOCK_END("Client::gameExec State::LOGIN_ERROR") |
1444 |
|
|
break; |
1445 |
|
|
|
1446 |
|
|
case State::ACCOUNTCHANGE_ERROR: |
1447 |
|
|
BLOCK_START("Client::gameExec State::ACCOUNTCHANGE_ERROR") |
1448 |
|
|
logger->log1("State: ACCOUNT CHANGE ERROR"); |
1449 |
|
|
CREATEWIDGETV(mCurrentDialog, OkDialog, |
1450 |
|
|
// TRANSLATORS: error dialog header |
1451 |
|
|
_("Error"), |
1452 |
|
|
errorMessage, |
1453 |
|
|
// TRANSLATORS: ok dialog button |
1454 |
|
|
_("Close"), |
1455 |
|
|
DialogType::ERROR, |
1456 |
|
|
Modal_true, |
1457 |
|
|
ShowCenter_true, |
1458 |
|
|
nullptr, |
1459 |
|
|
260); |
1460 |
|
|
mCurrentDialog->addActionListener(&accountListener); |
1461 |
|
|
mCurrentDialog = nullptr; // OkDialog deletes itself |
1462 |
|
|
BLOCK_END("Client::gameExec State::ACCOUNTCHANGE_ERROR") |
1463 |
|
|
break; |
1464 |
|
|
|
1465 |
|
|
case State::REGISTER_PREP: |
1466 |
|
|
BLOCK_START("Client::gameExec State::REGISTER_PREP") |
1467 |
|
|
logger->log1("State: REGISTER_PREP"); |
1468 |
|
|
CREATEWIDGETV(mCurrentDialog, ConnectionDialog, |
1469 |
|
|
// TRANSLATORS: connection dialog header |
1470 |
|
|
_("Requesting registration details"), |
1471 |
|
|
State::LOGIN); |
1472 |
|
|
loginHandler->getRegistrationDetails(); |
1473 |
|
|
BLOCK_END("Client::gameExec State::REGISTER_PREP") |
1474 |
|
|
break; |
1475 |
|
|
|
1476 |
|
|
case State::REGISTER: |
1477 |
|
|
logger->log1("State: REGISTER"); |
1478 |
|
|
CREATEWIDGETV(mCurrentDialog, RegisterDialog, |
1479 |
|
|
loginData); |
1480 |
|
|
break; |
1481 |
|
|
|
1482 |
|
|
case State::REGISTER_ATTEMPT: |
1483 |
|
|
BLOCK_START("Client::gameExec State::REGISTER_ATTEMPT") |
1484 |
|
|
logger->log("Username is %s", loginData.username.c_str()); |
1485 |
|
|
if (loginHandler != nullptr) |
1486 |
|
|
loginHandler->registerAccount(&loginData); |
1487 |
|
|
BLOCK_END("Client::gameExec State::REGISTER_ATTEMPT") |
1488 |
|
|
break; |
1489 |
|
|
|
1490 |
|
|
case State::CHANGEPASSWORD: |
1491 |
|
|
BLOCK_START("Client::gameExec State::CHANGEPASSWORD") |
1492 |
|
|
logger->log1("State: CHANGE PASSWORD"); |
1493 |
|
|
CREATEWIDGETV(mCurrentDialog, ChangePasswordDialog, |
1494 |
|
|
loginData); |
1495 |
|
|
mCurrentDialog->setVisible(Visible_true); |
1496 |
|
|
BLOCK_END("Client::gameExec State::CHANGEPASSWORD") |
1497 |
|
|
break; |
1498 |
|
|
|
1499 |
|
|
case State::CHANGEPASSWORD_ATTEMPT: |
1500 |
|
|
BLOCK_START("Client::gameExec " |
1501 |
|
|
"State::CHANGEPASSWORD_ATTEMPT") |
1502 |
|
|
logger->log1("State: CHANGE PASSWORD ATTEMPT"); |
1503 |
|
|
if (loginHandler != nullptr) |
1504 |
|
|
{ |
1505 |
|
|
loginHandler->changePassword(loginData.password, |
1506 |
|
|
loginData.newPassword); |
1507 |
|
|
} |
1508 |
|
|
BLOCK_END("Client::gameExec State::CHANGEPASSWORD_ATTEMPT") |
1509 |
|
|
break; |
1510 |
|
|
|
1511 |
|
|
case State::CHANGEPASSWORD_SUCCESS: |
1512 |
|
|
BLOCK_START("Client::gameExec " |
1513 |
|
|
"State::CHANGEPASSWORD_SUCCESS") |
1514 |
|
|
logger->log1("State: CHANGE PASSWORD SUCCESS"); |
1515 |
|
|
CREATEWIDGETV(mCurrentDialog, OkDialog, |
1516 |
|
|
// TRANSLATORS: password change message header |
1517 |
|
|
_("Password Change"), |
1518 |
|
|
// TRANSLATORS: password change message text |
1519 |
|
|
_("Password changed successfully!"), |
1520 |
|
|
// TRANSLATORS: ok dialog button |
1521 |
|
|
_("OK"), |
1522 |
|
|
DialogType::ERROR, |
1523 |
|
|
Modal_true, |
1524 |
|
|
ShowCenter_true, |
1525 |
|
|
nullptr, |
1526 |
|
|
260); |
1527 |
|
|
mCurrentDialog->addActionListener(&accountListener); |
1528 |
|
|
mCurrentDialog = nullptr; // OkDialog deletes itself |
1529 |
|
|
loginData.password = loginData.newPassword; |
1530 |
|
|
loginData.newPassword.clear(); |
1531 |
|
|
BLOCK_END("Client::gameExec State::CHANGEPASSWORD_SUCCESS") |
1532 |
|
|
break; |
1533 |
|
|
|
1534 |
|
|
case State::CHANGEEMAIL: |
1535 |
|
|
logger->log1("State: CHANGE EMAIL"); |
1536 |
|
|
CREATEWIDGETV(mCurrentDialog, |
1537 |
|
|
ChangeEmailDialog, |
1538 |
|
|
loginData); |
1539 |
|
|
mCurrentDialog->setVisible(Visible_true); |
1540 |
|
|
break; |
1541 |
|
|
|
1542 |
|
|
case State::CHANGEEMAIL_ATTEMPT: |
1543 |
|
|
logger->log1("State: CHANGE EMAIL ATTEMPT"); |
1544 |
|
|
if (loginHandler != nullptr) |
1545 |
|
|
loginHandler->changeEmail(loginData.email); |
1546 |
|
|
break; |
1547 |
|
|
|
1548 |
|
|
case State::CHANGEEMAIL_SUCCESS: |
1549 |
|
|
logger->log1("State: CHANGE EMAIL SUCCESS"); |
1550 |
|
|
CREATEWIDGETV(mCurrentDialog, OkDialog, |
1551 |
|
|
// TRANSLATORS: email change message header |
1552 |
|
|
_("Email Change"), |
1553 |
|
|
// TRANSLATORS: email change message text |
1554 |
|
|
_("Email changed successfully!"), |
1555 |
|
|
// TRANSLATORS: ok dialog button |
1556 |
|
|
_("OK"), |
1557 |
|
|
DialogType::ERROR, |
1558 |
|
|
Modal_true, |
1559 |
|
|
ShowCenter_true, |
1560 |
|
|
nullptr, |
1561 |
|
|
260); |
1562 |
|
|
mCurrentDialog->addActionListener(&accountListener); |
1563 |
|
|
mCurrentDialog = nullptr; // OkDialog deletes itself |
1564 |
|
|
break; |
1565 |
|
|
|
1566 |
|
|
case State::SWITCH_SERVER: |
1567 |
|
|
BLOCK_START("Client::gameExec State::SWITCH_SERVER") |
1568 |
|
|
logger->log1("State: SWITCH SERVER"); |
1569 |
|
|
|
1570 |
|
|
if (loginHandler != nullptr) |
1571 |
|
|
loginHandler->disconnect(); |
1572 |
|
|
if (gameHandler != nullptr) |
1573 |
|
|
{ |
1574 |
|
|
gameHandler->disconnect(); |
1575 |
|
|
gameHandler->clear(); |
1576 |
|
|
} |
1577 |
|
|
settings.serverName.clear(); |
1578 |
|
|
settings.login.clear(); |
1579 |
|
|
WindowManager::updateTitle(); |
1580 |
|
|
serverConfig.write(); |
1581 |
|
|
serverConfig.unload(); |
1582 |
|
|
if (setupWindow != nullptr) |
1583 |
|
|
setupWindow->externalUnload(); |
1584 |
|
|
|
1585 |
|
|
mState = State::CHOOSE_SERVER; |
1586 |
|
|
BLOCK_END("Client::gameExec State::SWITCH_SERVER") |
1587 |
|
|
break; |
1588 |
|
|
|
1589 |
|
|
case State::SWITCH_LOGIN: |
1590 |
|
|
BLOCK_START("Client::gameExec State::SWITCH_LOGIN") |
1591 |
|
|
logger->log1("State: SWITCH LOGIN"); |
1592 |
|
|
|
1593 |
|
|
if (loginHandler != nullptr) |
1594 |
|
|
{ |
1595 |
|
|
loginHandler->logout(); |
1596 |
|
|
loginHandler->disconnect(); |
1597 |
|
|
} |
1598 |
|
|
if (gameHandler != nullptr) |
1599 |
|
|
gameHandler->disconnect(); |
1600 |
|
|
if (loginHandler != nullptr) |
1601 |
|
|
loginHandler->connect(); |
1602 |
|
|
|
1603 |
|
|
settings.login.clear(); |
1604 |
|
|
WindowManager::updateTitle(); |
1605 |
|
|
mState = State::LOGIN; |
1606 |
|
|
BLOCK_END("Client::gameExec State::SWITCH_LOGIN") |
1607 |
|
|
break; |
1608 |
|
|
|
1609 |
|
|
case State::SWITCH_CHARACTER: |
1610 |
|
|
BLOCK_START("Client::gameExec State::SWITCH_CHARACTER") |
1611 |
|
|
logger->log1("State: SWITCH CHARACTER"); |
1612 |
|
|
|
1613 |
|
|
// Done with game |
1614 |
|
|
if (gameHandler != nullptr) |
1615 |
|
|
gameHandler->disconnect(); |
1616 |
|
|
|
1617 |
|
|
settings.login.clear(); |
1618 |
|
|
WindowManager::updateTitle(); |
1619 |
|
|
mState = State::GET_CHARACTERS; |
1620 |
|
|
BLOCK_END("Client::gameExec State::SWITCH_CHARACTER") |
1621 |
|
|
break; |
1622 |
|
|
|
1623 |
|
|
case State::LOGOUT_ATTEMPT: |
1624 |
|
|
logger->log1("State: LOGOUT ATTEMPT"); |
1625 |
|
|
break; |
1626 |
|
|
|
1627 |
|
|
case State::WAIT: |
1628 |
|
|
logger->log1("State: WAIT"); |
1629 |
|
|
break; |
1630 |
|
|
|
1631 |
|
|
case State::EXIT: |
1632 |
|
|
BLOCK_START("Client::gameExec State::EXIT") |
1633 |
|
|
logger->log1("State: EXIT"); |
1634 |
|
|
Net::unload(); |
1635 |
|
|
BLOCK_END("Client::gameExec State::EXIT") |
1636 |
|
|
break; |
1637 |
|
|
|
1638 |
|
|
case State::FORCE_QUIT: |
1639 |
|
|
BLOCK_START("Client::gameExec State::FORCE_QUIT") |
1640 |
|
|
logger->log1("State: FORCE QUIT"); |
1641 |
|
|
if (generalHandler != nullptr) |
1642 |
|
|
generalHandler->unload(); |
1643 |
|
|
mState = State::EXIT; |
1644 |
|
|
BLOCK_END("Client::gameExec State::FORCE_QUIT") |
1645 |
|
|
break; |
1646 |
|
|
|
1647 |
|
|
case State::ERROR: |
1648 |
|
|
BLOCK_START("Client::gameExec State::ERROR") |
1649 |
|
|
config.write(); |
1650 |
|
|
#ifdef SAVE_PASSWORD |
1651 |
|
|
if (errorMessage == "Wrong password.") |
1652 |
|
|
{ |
1653 |
|
|
serverConfig.setValue("password", ""); |
1654 |
|
|
serverConfig.write(); |
1655 |
|
|
} |
1656 |
|
|
#endif |
1657 |
|
|
if (mOldState == State::GAME) |
1658 |
|
|
serverConfig.write(); |
1659 |
|
|
logger->log1("State: ERROR"); |
1660 |
|
|
logger->log("Error: %s\n", errorMessage.c_str()); |
1661 |
|
|
pincodeManager.closeDialogs(); |
1662 |
|
|
mCurrentDialog = DialogsManager::openErrorDialog( |
1663 |
|
|
// TRANSLATORS: error message header |
1664 |
|
|
_("Error"), |
1665 |
|
|
errorMessage, |
1666 |
|
|
Modal_true); |
1667 |
|
|
mCurrentDialog->addActionListener(&errorListener); |
1668 |
|
|
mCurrentDialog = nullptr; // OkDialog deletes itself |
1669 |
|
|
gameHandler->disconnect(); |
1670 |
|
|
BLOCK_END("Client::gameExec State::ERROR") |
1671 |
|
|
break; |
1672 |
|
|
|
1673 |
|
|
case State::AUTORECONNECT_SERVER: |
1674 |
|
|
// ++++++ |
1675 |
|
|
break; |
1676 |
|
|
|
1677 |
|
|
case State::START: |
1678 |
|
|
default: |
1679 |
|
|
mState = State::FORCE_QUIT; |
1680 |
|
|
break; |
1681 |
|
|
} |
1682 |
|
|
BLOCK_END("Client::gameExec 8") |
1683 |
|
|
} |
1684 |
|
|
|
1685 |
|
|
PERF_STAT(10); |
1686 |
|
|
|
1687 |
|
|
// Update the screen when application is visible, delay otherwise. |
1688 |
|
|
if (!WindowManager::getIsMinimized()) |
1689 |
|
|
{ |
1690 |
|
|
frame_count = frame_count + 1; |
1691 |
|
|
if (gui != nullptr) |
1692 |
|
|
gui->draw(); |
1693 |
|
|
mainGraphics->updateScreen(); |
1694 |
|
|
} |
1695 |
|
|
else |
1696 |
|
|
{ |
1697 |
|
|
SDL_Delay(100); |
1698 |
|
|
} |
1699 |
|
|
|
1700 |
|
|
PERF_STAT(11); |
1701 |
|
|
|
1702 |
|
|
BLOCK_START("~Client::SDL_framerateDelay") |
1703 |
|
|
if (settings.limitFps) |
1704 |
|
|
SDL_framerateDelay(&fpsManager); |
1705 |
|
|
BLOCK_END("~Client::SDL_framerateDelay") |
1706 |
|
|
|
1707 |
|
|
PERF_STAT(12); |
1708 |
|
|
PERF_NEXTFRAME(); |
1709 |
|
|
PROFILER_END(); |
1710 |
|
|
} |
1711 |
|
|
|
1712 |
|
|
return 0; |
1713 |
|
|
} |
1714 |
|
|
|
1715 |
|
|
void Client::optionChanged(const std::string &name) |
1716 |
|
|
{ |
1717 |
|
|
if (name == "fpslimit") |
1718 |
|
|
{ |
1719 |
|
|
const int fpsLimit = config.getIntValue("fpslimit"); |
1720 |
|
|
settings.limitFps = fpsLimit > 0; |
1721 |
|
|
WindowManager::setFramerate(fpsLimit); |
1722 |
|
|
} |
1723 |
|
|
else if (name == "guialpha" || |
1724 |
|
|
name == "enableGuiOpacity") |
1725 |
|
|
{ |
1726 |
|
|
const float alpha = config.getFloatValue("guialpha"); |
1727 |
|
|
settings.guiAlpha = alpha; |
1728 |
|
|
ImageHelper::setEnableAlpha(alpha != 1.0F && |
1729 |
|
|
config.getBoolValue("enableGuiOpacity")); |
1730 |
|
|
} |
1731 |
|
|
else if (name == "gamma" || |
1732 |
|
|
name == "enableGamma") |
1733 |
|
|
{ |
1734 |
|
|
WindowManager::applyGamma(); |
1735 |
|
|
} |
1736 |
|
|
else if (name == "particleEmitterSkip") |
1737 |
|
|
{ |
1738 |
|
|
ParticleEngine::emitterSkip = |
1739 |
|
|
config.getIntValue("particleEmitterSkip") + 1; |
1740 |
|
|
} |
1741 |
|
|
else if (name == "vsync") |
1742 |
|
|
{ |
1743 |
|
|
WindowManager::applyVSync(); |
1744 |
|
|
} |
1745 |
|
|
else if (name == "repeateInterval" || |
1746 |
|
|
name == "repeateDelay") |
1747 |
|
|
{ |
1748 |
|
|
WindowManager::applyKeyRepeat(); |
1749 |
|
|
} |
1750 |
|
|
} |
1751 |
|
|
|
1752 |
|
|
void Client::action(const ActionEvent &event) |
1753 |
|
|
{ |
1754 |
|
|
std::string tab; |
1755 |
|
|
const std::string &eventId = event.getId(); |
1756 |
|
|
|
1757 |
|
|
if (eventId == "close") |
1758 |
|
|
{ |
1759 |
|
|
setState(State::FORCE_QUIT); |
1760 |
|
|
return; |
1761 |
|
|
} |
1762 |
|
|
if (eventId == "Setup") |
1763 |
|
|
{ |
1764 |
|
|
tab.clear(); |
1765 |
|
|
} |
1766 |
|
|
else if (eventId == "help") |
1767 |
|
|
{ |
1768 |
|
|
inputManager.executeAction(InputAction::WINDOW_HELP); |
1769 |
|
|
return; |
1770 |
|
|
} |
1771 |
|
|
else if (eventId == "about") |
1772 |
|
|
{ |
1773 |
|
|
inputManager.executeAction(InputAction::WINDOW_ABOUT); |
1774 |
|
|
return; |
1775 |
|
|
} |
1776 |
|
|
else if (eventId == "Video") |
1777 |
|
|
{ |
1778 |
|
|
tab = "Video"; |
1779 |
|
|
} |
1780 |
|
|
else if (eventId == "Themes") |
1781 |
|
|
{ |
1782 |
|
|
tab = "Theme"; |
1783 |
|
|
} |
1784 |
|
|
else if (eventId == "Perfomance") |
1785 |
|
|
{ |
1786 |
|
|
tab = "Perfomance"; |
1787 |
|
|
} |
1788 |
|
|
else |
1789 |
|
|
{ |
1790 |
|
|
return; |
1791 |
|
|
} |
1792 |
|
|
|
1793 |
|
|
if (setupWindow != nullptr) |
1794 |
|
|
{ |
1795 |
|
|
setupWindow->setVisible(fromBool( |
1796 |
|
|
!setupWindow->isWindowVisible(), Visible)); |
1797 |
|
|
if (setupWindow->isWindowVisible()) |
1798 |
|
|
{ |
1799 |
|
|
if (!tab.empty()) |
1800 |
|
|
setupWindow->activateTab(tab); |
1801 |
|
|
setupWindow->requestMoveToTop(); |
1802 |
|
|
} |
1803 |
|
|
} |
1804 |
|
|
} |
1805 |
|
|
|
1806 |
|
|
void Client::initFeatures() |
1807 |
|
|
{ |
1808 |
|
|
features.init(paths.getStringValue("featuresFile"), |
1809 |
|
|
UseVirtFs_true, |
1810 |
|
|
SkipError_true); |
1811 |
|
|
setFeaturesDefaults(features); |
1812 |
|
|
settings.fixDeadAnimation = features.getBoolValue("fixDeadAnimation"); |
1813 |
|
|
} |
1814 |
|
|
|
1815 |
|
|
void Client::initPaths() |
1816 |
|
|
{ |
1817 |
|
|
settings.gmCommandSymbol = paths.getStringValue("gmCommandSymbol"); |
1818 |
|
|
settings.gmCharCommandSymbol = paths.getStringValue("gmCharCommandSymbol"); |
1819 |
|
|
settings.linkCommandSymbol = paths.getStringValue("linkCommandSymbol"); |
1820 |
|
|
if (settings.linkCommandSymbol.empty()) |
1821 |
|
|
settings.linkCommandSymbol = "="; |
1822 |
|
|
settings.overweightPercent = paths.getIntValue("overweightPercent"); |
1823 |
|
|
settings.fixedInventorySize = paths.getIntValue("fixedInventorySize"); |
1824 |
|
|
settings.playerNameOffset = paths.getIntValue( |
1825 |
|
|
"playerNameOffset"); |
1826 |
|
|
settings.playerBadgeAtRightOffset = paths.getIntValue( |
1827 |
|
|
"playerBadgeAtRightOffset"); |
1828 |
|
|
settings.unknownSkillsAutoTab = paths.getBoolValue("unknownSkillsAutoTab"); |
1829 |
|
|
settings.enableNewMailSystem = paths.getBoolValue("enableNewMailSystem"); |
1830 |
|
|
} |
1831 |
|
|
|
1832 |
|
|
void Client::initTradeFilter() |
1833 |
|
|
{ |
1834 |
|
|
const std::string tradeListName = |
1835 |
|
|
settings.serverConfigDir + "/tradefilter.txt"; |
1836 |
|
|
|
1837 |
|
|
std::ofstream tradeFile; |
1838 |
|
|
struct stat statbuf; |
1839 |
|
|
|
1840 |
|
|
if ((stat(tradeListName.c_str(), &statbuf) != 0) || |
1841 |
|
|
!S_ISREG(statbuf.st_mode)) |
1842 |
|
|
{ |
1843 |
|
|
tradeFile.open(tradeListName.c_str(), |
1844 |
|
|
std::ios::out); |
1845 |
|
|
if (tradeFile.is_open()) |
1846 |
|
|
{ |
1847 |
|
|
tradeFile << ": sell" << std::endl; |
1848 |
|
|
tradeFile << ": buy" << std::endl; |
1849 |
|
|
tradeFile << ": trade" << std::endl; |
1850 |
|
|
tradeFile << "i sell" << std::endl; |
1851 |
|
|
tradeFile << "i buy" << std::endl; |
1852 |
|
|
tradeFile << "i trade" << std::endl; |
1853 |
|
|
tradeFile << "i trading" << std::endl; |
1854 |
|
|
tradeFile << "i am buy" << std::endl; |
1855 |
|
|
tradeFile << "i am sell" << std::endl; |
1856 |
|
|
tradeFile << "i am trade" << std::endl; |
1857 |
|
|
tradeFile << "i am trading" << std::endl; |
1858 |
|
|
tradeFile << "i'm buy" << std::endl; |
1859 |
|
|
tradeFile << "i'm sell" << std::endl; |
1860 |
|
|
tradeFile << "i'm trade" << std::endl; |
1861 |
|
|
tradeFile << "i'm trading" << std::endl; |
1862 |
|
|
} |
1863 |
|
|
else |
1864 |
|
|
{ |
1865 |
|
|
reportAlways("Error opening file for writing: %s", |
1866 |
|
|
tradeListName.c_str()) |
1867 |
|
|
} |
1868 |
|
|
tradeFile.close(); |
1869 |
|
|
} |
1870 |
|
|
} |
1871 |
|
|
|
1872 |
|
77 |
bool Client::isTmw() |
1873 |
|
|
{ |
1874 |
|
77 |
const std::string &name = settings.serverName; |
1875 |
✓✗✓✗
|
231 |
if (name == "server.themanaworld.org" || |
1876 |
✓✗✗✓
|
231 |
name == "themanaworld.org" || |
1877 |
|
77 |
name == "167.114.129.72") |
1878 |
|
|
{ |
1879 |
|
|
return true; |
1880 |
|
|
} |
1881 |
|
77 |
return false; |
1882 |
|
|
} |
1883 |
|
|
|
1884 |
|
|
void Client::moveButtons(const int width) |
1885 |
|
|
{ |
1886 |
|
|
if (mSetupButton != nullptr) |
1887 |
|
|
{ |
1888 |
|
|
int x = width - mSetupButton->getWidth() - mButtonPadding; |
1889 |
|
|
mSetupButton->setPosition(x, mButtonPadding); |
1890 |
|
|
#ifndef WIN32 |
1891 |
|
|
x -= mPerfomanceButton->getWidth() + mButtonSpacing; |
1892 |
|
|
mPerfomanceButton->setPosition(x, mButtonPadding); |
1893 |
|
|
|
1894 |
|
|
x -= mVideoButton->getWidth() + mButtonSpacing; |
1895 |
|
|
mVideoButton->setPosition(x, mButtonPadding); |
1896 |
|
|
|
1897 |
|
|
x -= mThemesButton->getWidth() + mButtonSpacing; |
1898 |
|
|
mThemesButton->setPosition(x, mButtonPadding); |
1899 |
|
|
|
1900 |
|
|
x -= mAboutButton->getWidth() + mButtonSpacing; |
1901 |
|
|
mAboutButton->setPosition(x, mButtonPadding); |
1902 |
|
|
|
1903 |
|
|
x -= mHelpButton->getWidth() + mButtonSpacing; |
1904 |
|
|
mHelpButton->setPosition(x, mButtonPadding); |
1905 |
|
|
#ifdef ANDROID |
1906 |
|
|
x -= mCloseButton->getWidth() + mButtonSpacing; |
1907 |
|
|
mCloseButton->setPosition(x, mButtonPadding); |
1908 |
|
|
#endif // ANDROID |
1909 |
|
|
#endif // WIN32 |
1910 |
|
|
} |
1911 |
|
|
} |
1912 |
|
|
|
1913 |
|
63 |
void Client::windowRemoved(const Window *const window) |
1914 |
|
|
{ |
1915 |
✗✓ |
63 |
if (mCurrentDialog == window) |
1916 |
|
|
mCurrentDialog = nullptr; |
1917 |
|
63 |
} |
1918 |
|
|
|
1919 |
|
|
void Client::focusWindow() |
1920 |
|
|
{ |
1921 |
|
|
if (mCurrentDialog != nullptr) |
1922 |
|
|
{ |
1923 |
|
|
mCurrentDialog->requestFocus(); |
1924 |
|
|
} |
1925 |
|
|
} |
1926 |
|
|
|
1927 |
|
|
void Client::updatePinState() |
1928 |
|
|
{ |
1929 |
|
|
if (mCurrentDialog == nullptr || |
1930 |
|
|
mState != State::CHAR_SELECT) |
1931 |
|
|
{ |
1932 |
|
|
return; |
1933 |
|
|
} |
1934 |
|
|
CharSelectDialog *const dialog = |
1935 |
|
|
dynamic_cast<CharSelectDialog*>(mCurrentDialog); |
1936 |
|
|
if (dialog != nullptr) |
1937 |
|
|
pincodeManager.updateState(); |
1938 |
|
|
} |
1939 |
|
|
|
1940 |
|
|
void Client::logVars() |
1941 |
|
|
{ |
1942 |
|
|
#ifdef ANDROID |
1943 |
|
|
logger->log("APPDIR: %s", getenv("APPDIR")); |
1944 |
|
|
logger->log("DATADIR2: %s", getSdStoragePath().c_str()); |
1945 |
|
|
#endif // ANDROID |
1946 |
|
|
} |
1947 |
|
|
|
1948 |
|
|
void Client::slowLogic() |
1949 |
|
|
{ |
1950 |
|
|
if ((gameHandler == nullptr) || |
1951 |
|
|
!gameHandler->mustPing()) |
1952 |
|
|
{ |
1953 |
|
|
return; |
1954 |
|
|
} |
1955 |
|
|
|
1956 |
|
|
if (get_elapsed_time1(mPing) > 1500) |
1957 |
|
|
{ |
1958 |
|
|
mPing = tick_time; |
1959 |
|
|
if (mState == State::UPDATE || |
1960 |
|
|
mState == State::LOGIN || |
1961 |
|
|
mState == State::LOGIN_ATTEMPT || |
1962 |
|
|
mState == State::REGISTER || |
1963 |
|
|
mState == State::REGISTER_ATTEMPT) |
1964 |
|
|
{ |
1965 |
|
|
if (loginHandler != nullptr) |
1966 |
|
|
loginHandler->ping(); |
1967 |
|
|
if (generalHandler != nullptr) |
1968 |
|
|
generalHandler->flushSend(); |
1969 |
|
|
} |
1970 |
|
|
else if (mState == State::CHAR_SELECT) |
1971 |
|
|
{ |
1972 |
|
|
if (charServerHandler != nullptr) |
1973 |
|
|
charServerHandler->ping(); |
1974 |
|
|
if (generalHandler != nullptr) |
1975 |
|
|
generalHandler->flushSend(); |
1976 |
|
|
} |
1977 |
|
|
} |
1978 |
|
|
} |
1979 |
|
|
|
1980 |
|
|
void Client::loadData() |
1981 |
|
|
{ |
1982 |
|
|
// If another data path has been set, |
1983 |
|
|
// we don't load any other files... |
1984 |
|
|
if (settings.options.dataPath.empty()) |
1985 |
|
|
{ |
1986 |
|
|
// Add customdata directory |
1987 |
|
|
VirtFs::searchAndAddArchives( |
1988 |
|
|
"customdata/", |
1989 |
|
|
"zip", |
1990 |
|
|
Append_false); |
1991 |
|
|
} |
1992 |
|
|
|
1993 |
|
|
if (!settings.options.skipUpdate) |
1994 |
|
|
{ |
1995 |
|
|
VirtFs::searchAndAddArchives( |
1996 |
|
|
settings.updatesDir + "/local/", |
1997 |
|
|
"zip", |
1998 |
|
|
Append_false); |
1999 |
|
|
|
2000 |
|
|
VirtFs::mountDir(pathJoin( |
2001 |
|
|
settings.localDataDir, |
2002 |
|
|
settings.updatesDir, |
2003 |
|
|
"local/"), |
2004 |
|
|
Append_false); |
2005 |
|
|
} |
2006 |
|
|
|
2007 |
|
|
logger->log("Init paths"); |
2008 |
|
|
paths.init("paths.xml", |
2009 |
|
|
UseVirtFs_true, |
2010 |
|
|
SkipError_false); |
2011 |
|
|
setPathsDefaults(paths); |
2012 |
|
|
initPaths(); |
2013 |
|
|
if (SpriteReference::Empty == nullptr) |
2014 |
|
|
{ |
2015 |
|
|
SpriteReference::Empty = new SpriteReference( |
2016 |
|
|
paths.getStringValue("spriteErrorFile"), |
2017 |
|
|
0); |
2018 |
|
|
} |
2019 |
|
|
|
2020 |
|
|
if (BeingInfo::unknown == nullptr) |
2021 |
|
|
BeingInfo::unknown = new BeingInfo; |
2022 |
|
|
|
2023 |
|
|
initFeatures(); |
2024 |
|
|
TranslationManager::loadCurrentLang(); |
2025 |
|
|
TranslationManager::loadDictionaryLang(); |
2026 |
|
|
PlayerInfo::stateChange(mState); |
2027 |
|
|
|
2028 |
|
|
AttributesEnum::init(); |
2029 |
|
|
DbManager::loadDb(); |
2030 |
|
|
|
2031 |
|
|
delete spellManager; |
2032 |
|
|
spellManager = new SpellManager; |
2033 |
|
|
delete spellShortcut; |
2034 |
|
|
spellShortcut = new SpellShortcut; |
2035 |
|
|
|
2036 |
|
|
EquipmentWindow::prepareSlotNames(); |
2037 |
|
|
|
2038 |
|
|
ActorSprite::load(); |
2039 |
|
|
|
2040 |
|
|
if (desktop != nullptr) |
2041 |
|
|
desktop->reloadWallpaper(); |
2042 |
|
|
} |
2043 |
|
|
|
2044 |
|
|
void Client::unloadData() |
2045 |
|
|
{ |
2046 |
|
|
DbManager::unloadDb(); |
2047 |
|
|
mCurrentServer.supportUrl.clear(); |
2048 |
|
|
settings.supportUrl.clear(); |
2049 |
|
|
if (settings.options.dataPath.empty()) |
2050 |
|
|
{ |
2051 |
|
|
// Add customdata directory |
2052 |
|
|
VirtFs::searchAndRemoveArchives( |
2053 |
|
|
"customdata/", |
2054 |
|
|
"zip"); |
2055 |
|
|
} |
2056 |
|
|
|
2057 |
|
|
if (!settings.oldUpdates.empty()) |
2058 |
|
|
{ |
2059 |
|
|
UpdaterWindow::unloadUpdates(settings.oldUpdates); |
2060 |
|
|
settings.oldUpdates.clear(); |
2061 |
|
|
} |
2062 |
|
|
|
2063 |
|
|
if (!settings.options.skipUpdate) |
2064 |
|
|
{ |
2065 |
|
|
VirtFs::searchAndRemoveArchives( |
2066 |
|
|
pathJoin(settings.updatesDir, "local/"), |
2067 |
|
|
"zip"); |
2068 |
|
|
|
2069 |
|
|
VirtFs::unmountDirSilent(pathJoin( |
2070 |
|
|
settings.localDataDir, |
2071 |
|
|
settings.updatesDir, |
2072 |
|
|
"local/")); |
2073 |
|
|
} |
2074 |
|
|
|
2075 |
|
|
ResourceManager::clearCache(); |
2076 |
|
|
|
2077 |
|
|
loginData.clearUpdateHost(); |
2078 |
|
|
localClan.clear(); |
2079 |
|
|
serverVersion = 0; |
2080 |
|
|
packetVersion = 0; |
2081 |
|
|
packetVersionMain = 0; |
2082 |
|
|
packetVersionRe = 0; |
2083 |
|
|
packetVersionZero = 0; |
2084 |
|
|
tmwServerVersion = 0; |
2085 |
|
|
evolPacketOffset = 0; |
2086 |
|
|
} |
2087 |
|
|
|
2088 |
|
|
void Client::runValidate() |
2089 |
|
|
{ |
2090 |
|
|
loadData(); |
2091 |
|
|
WindowManager::createValidateWindows(); |
2092 |
|
|
|
2093 |
|
|
WindowManager::deleteValidateWindows(); |
2094 |
|
|
unloadData(); |
2095 |
|
|
delete2(client) |
2096 |
|
|
VirtFs::deinit(); |
2097 |
|
|
exit(0); |
2098 |
✓✗✓✗
|
3 |
} |