Mana
Loading...
Searching...
No Matches
client.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "client.h"
23#include "main.h"
24
25#include "chatlogger.h"
26#include "configuration.h"
27#include "emoteshortcut.h"
28#include "event.h"
29#include "game.h"
30#include "itemshortcut.h"
31#include "keyboardconfig.h"
32#include "log.h"
33#include "playerrelations.h"
34#include "sound.h"
35
40#include "gui/gui.h"
41#include "gui/logindialog.h"
42#include "gui/okdialog.h"
43#include "gui/quitdialog.h"
44#include "gui/register.h"
45#include "gui/sdlinput.h"
46#include "gui/serverdialog.h"
47#include "gui/setup.h"
49#include "gui/updaterwindow.h"
51
52#include "gui/widgets/button.h"
53#include "gui/widgets/desktop.h"
54
55#include "net/charhandler.h"
56#include "net/gamehandler.h"
57#include "net/generalhandler.h"
58#include "net/logindata.h"
59#include "net/loginhandler.h"
60#include "net/net.h"
61#include "net/worldinfo.h"
62
63#include "resources/chardb.h"
64#include "resources/hairdb.h"
65#include "resources/image.h"
66#include "resources/itemdb.h"
68#include "resources/theme.h"
71
72#include "utils/filesystem.h"
73#include "utils/gettext.h"
74#include "utils/mkdir.h"
75#if defined(_WIN32) || defined(__APPLE__)
76#include "utils/specialfolder.h"
77#endif
78#include "utils/stringutils.h"
79#include "utils/time.h"
80
81#include <SDL_image.h>
82
83#ifdef _WIN32
84#include <SDL_syswm.h>
85#include <winuser.h>
86#endif
87
88#include <sys/stat.h>
89#include <cassert>
90
91#include <guichan/exception.hpp>
92
93// TODO: Get rid of these globals
94std::string errorMessage;
96
102
105
110
111volatile int fps = 0;
112volatile int frame_count = 0;
118static Uint32 nextSecond(Uint32 interval, void *param)
119{
121 frame_count = 0;
122
123 return interval;
124}
125
126bool isDoubleClick(int selected)
127{
128 static Timer timer;
129 static int lastSelected = -1;
130
131 if (selected == lastSelected && !timer.passed())
132 return true;
133
134 timer.set(500);
135 lastSelected = selected;
136 return false;
137}
138
143void FpsManager::limitFps(int fpsLimit)
144{
145 if (fpsLimit <= 0)
146 return;
147
148 const auto ticks = SDL_GetTicks();
149
150 // Need to reset if the FPS limit changes
151 if (mBaseTicks > 0 && mFpsLimit == fpsLimit)
152 {
153 ++mFrameCount;
154 const auto targetTicks = mBaseTicks + mFrameCount * 1000 / mFpsLimit;
155
156 // Make sure ticks hasn't wrapped
157 if (ticks > mBaseTicks && targetTicks > ticks)
158 {
159 SDL_Delay(targetTicks - ticks);
160 return;
161 }
162 }
163
164 mFpsLimit = fpsLimit;
165 mFrameCount = 0;
166 mBaseTicks = ticks;
167}
168
169
170Client *Client::mInstance = nullptr;
171
172Client::Client(const Options &options):
173 mOptions(options),
174 mStateAfterOkDialog(mState)
175{
176 assert(!mInstance);
177 mInstance = this;
178
179 // Set default values for configuration files
182
183 // Load branding information
184 if (!options.brandingPath.empty())
185 {
186 branding.init(options.brandingPath);
187 }
188
189 initRootDir();
190 initHomeDir();
192
193 // Configure logger
194 Log::init();
195 Log::setLogFile(mLocalDataDir + "/mana.log");
197 Log::info("%s", FULL_VERSION);
198
200 if (options.chatLogDir.empty())
202 else
204
206
207#if SDL_VERSION_ATLEAST(2, 24, 0)
208 SDL_SetHint(SDL_HINT_WINDOWS_DPI_AWARENESS, "permonitorv2");
209#endif
210
211 // Initialize SDL
212 Log::info("Initializing SDL...");
213 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
214 {
215 Log::critical(strprintf("Could not initialize SDL: %s",
216 SDL_GetError()));
217 }
218 atexit(SDL_Quit);
219
220 SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
221
223 {
224 Log::critical(strprintf("%s couldn't be set as write directory! "
225 "Exiting.", mLocalDataDir.c_str()));
226 }
227
228#if defined __APPLE__
229 mPackageDir = getResourcesLocation() + "/data";
230#else
231 mPackageDir = PKG_DATADIR "data";
232#endif
235
236 // Add branding/data to PhysFS search path
237 if (!options.brandingPath.empty())
238 {
239 std::string path = options.brandingPath;
240
241 // Strip blah.mana from the path
242#ifdef _WIN32
243 int loc1 = path.find_last_of('/');
244 int loc2 = path.find_last_of('\\');
245 int loc = std::max(loc1, loc2);
246#else
247 int loc = path.find_last_of('/');
248#endif
249 if (loc > 0)
250 ResourceManager::addToSearchPath(path.substr(0, loc + 1) + "data", false);
251 }
252
253 // Add the main data directories to our PhysicsFS search path
254 if (!options.dataPath.empty())
256
257 // Add the local data directory to PhysicsFS search path
259
260 bool useOpenGL = !mOptions.noOpenGL && config.opengl;
261
262 // Set up the transparency option for low CPU when not using OpenGL.
263 if (!useOpenGL && config.disableTransparency)
265
266 VideoSettings videoSettings;
267 videoSettings.windowMode = config.windowMode;
268 videoSettings.width = config.screenWidth;
269 videoSettings.height = config.screenHeight;
270 videoSettings.userScale = config.scale;
271 videoSettings.vsync = config.vsync;
272 videoSettings.openGL = useOpenGL;
273
274 // Try to set the desired video mode and create the graphics context
275 graphics = mVideo.initialize(videoSettings);
276
277 SDL_SetWindowTitle(mVideo.window(),
278 branding.getValue("appName", "Mana").c_str());
279
280 std::string iconFile = branding.getValue("appIcon", "icons/mana");
281#ifdef _WIN32
282 iconFile += ".ico";
283#else
284 iconFile += ".png";
285#endif
286 iconFile = ResourceManager::getPath(iconFile);
287 Log::info("Loading icon from file: %s", iconFile.c_str());
288#ifdef _WIN32
289 static SDL_SysWMinfo pInfo;
290 SDL_GetWindowWMInfo(mVideo.window(), &pInfo);
291 // Attempt to load icon from .ico file
292 HICON icon = (HICON) LoadImage(NULL,
293 iconFile.c_str(),
294 IMAGE_ICON, 64, 64, LR_LOADFROMFILE);
295 // If it's failing, we load the default resource file.
296 if (!icon)
297 icon = LoadIcon(GetModuleHandle(NULL), "A");
298
299 if (icon)
300 SetClassLongPtr(pInfo.info.win.window, GCLP_HICON, (LONG_PTR) icon);
301#else
302 mIcon = IMG_Load(iconFile.c_str());
303 if (mIcon)
304 {
305 SDL_SetWindowIcon(mVideo.window(), mIcon);
306 }
307#endif
308
309 // Initialize the item and emote shortcuts.
312
314
315 // Initialize sound engine
316 try
317 {
318 if (config.sound)
319 sound.init();
320
324 }
325 catch (const char *err)
326 {
328 errorMessage = err;
329 Log::warn("%s", err);
330 }
331
332 // Initialize keyboard
333 keyboard.init();
334
335 // Initialise player relations
337
339 setupWindow = new Setup;
340
341 sound.playMusic(branding.getStringValue("loginMusic"));
342
343 // Initialize default server
347 loginData.username = options.username;
348 loginData.password = options.password;
350 loginData.registerLogin = false;
351
353 {
355 }
356
358 {
360 branding.getValue("defaultServerType", "tmwathena"));
361 }
362
363 if (mCurrentServer.port == 0)
364 {
365 const uint16_t defaultPort = ServerInfo::defaultPortForServerType(mCurrentServer.type);
366 mCurrentServer.port = static_cast<uint16_t>(
367 branding.getValue("defaultPort", defaultPort));
368 }
369
370 const bool noServerList = branding.getValue("onlineServerList", std::string()).empty();
371 if (mCurrentServer.hostname.empty() && noServerList)
372 {
373 mCurrentServer.hostname = branding.getValue("defaultServer", std::string());
374 }
375
376 if (chatLogger)
378
379 if (loginData.username.empty() && loginData.remember)
381
382 if (mState != STATE_ERROR)
383 {
384 // If a server was passed on the command line, or branding
385 // provides a server and a blank server list, we skip the
386 // server selection dialog.
389 }
390
391 // Initialize seconds counter
392 mSecondsCounterId = SDL_AddTimer(1000, nextSecond, nullptr);
393
394 // Initialize PlayerInfo
396}
397
399{
400 SDL_RemoveTimer(mSecondsCounterId);
401
402 // Unload XML databases
405 delete itemDb;
406
408
409 // Before config.write() since it writes the shortcuts to the config
410 delete itemShortcut;
411 delete emoteShortcut;
412
413 delete gui;
414
415 // Shutdown libxml
416 xmlCleanupParser();
417
418 // Shutdown sound
419 sound.close();
420
422
423 SDL_FreeSurface(mIcon);
424
425 Log::info("Quitting");
426 delete userPalette;
427
428 XML::Writer writer(mConfigDir + "/config.xml");
429 if (writer.isValid())
430 serialize(writer, config);
431
432 mInstance = nullptr;
433}
434
436{
437 Time::beginFrame(); // Prevent startup lag influencing the first frame
438
439 while (mState != STATE_EXIT)
440 {
441 // Handle SDL events
442 SDL_Event event;
443 while (SDL_PollEvent(&event))
444 {
445 switch (event.type)
446 {
447 case SDL_QUIT:
449 break;
450
451 case SDL_WINDOWEVENT:
452 switch (event.window.event) {
453 case SDL_WINDOWEVENT_SIZE_CHANGED:
454 handleWindowSizeChanged(event.window.data1,
455 event.window.data2);
456 break;
457 }
458 break;
459
460 case SDL_KEYDOWN:
461 if (keyboard.isEnabled())
462 {
463 const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);
465 {
466 setupWindow->setVisible(!setupWindow->isVisible());
467 if (setupWindow->isVisible())
468 setupWindow->requestMoveToTop();
469 continue;
470 }
471 }
472
473 if (setupWindow->isVisible() &&
475 {
476 keyboard.setNewKey(event.key.keysym.sym);
479 continue;
480 }
481
482 // Check whether the game will handle the event
483 if (mGame && mGame->keyDownEvent(event.key))
484 continue;
485
486 break;
487 }
488
489 // Push input to GUI when not used
490 try
491 {
492 guiInput->pushInput(event);
493 }
494 catch (gcn::Exception e)
495 {
496 const char *err = e.getMessage().c_str();
497 Log::warn("Guichan input exception: %s", err);
498 }
499 }
500
501 update();
502 }
503
504 Net::unload();
505
506 return 0;
507}
508
510{
512
515
516 // Let the game handle continuous input while it is active
517 if (mGame)
519
522
523 gui->logic();
524 if (mGame)
525 mGame->logic();
526
527 sound.logic();
528
529 // Update the screen when application is active, delay otherwise.
530 if (isActive())
531 {
532 frame_count++;
533 gui->draw();
534 mVideo.present();
536 }
537 else
538 {
540 }
541
542 // TODO: Add connect timeouts
543 if (mState == STATE_CONNECT_GAME &&
544 Net::getGameHandler()->isConnected())
545 {
547 }
548 else if (mState == STATE_CONNECT_SERVER &&
550 Net::getLoginHandler()->isConnected())
551 {
553 }
555 {
556 if (Net::getLoginHandler()->getWorlds().size() < 2)
557 {
559 }
560 }
561 else if (mOldState == STATE_START ||
563 {
564 auto *top = static_cast<gcn::Container*>(gui->getTop());
565
566 mDesktop = new Desktop;
567 top->add(mDesktop);
568 mSetupButton = new Button("", "Setup", this);
570 mSetupButton->setButtonIcon("button-icon-setup.png");
571 mSetupButton->setPosition(top->getWidth() - mSetupButton->getWidth()
572 - 3, 3);
573 top->add(mSetupButton);
574
576 }
577
579 {
581 }
582
583 if (mState != mOldState)
584 {
585 {
587 event.setInt("oldState", mOldState);
588 event.setInt("newState", mState);
589 event.trigger(Event::ClientChannel);
590 }
591
592 if (mOldState == STATE_GAME)
593 {
594 delete mGame;
595 mGame = nullptr;
596 }
597
599
600 // Get rid of the dialog of the previous state
601 if (mCurrentDialog)
602 {
603 delete mCurrentDialog;
604 mCurrentDialog = nullptr;
605 }
606 // State has changed, while the quitDialog was active, it might
607 // not be correct anymore
608 if (mQuitDialog)
610
611 switch (mState)
612 {
614 Log::info("State: CHOOSE SERVER");
615
616 // Don't allow an alpha opacity
617 // lower than the default value
619
621 mConfigDir);
622 break;
623
625 Log::info("State: CONNECT SERVER");
626
628
630 _("Connecting to server"), STATE_SWITCH_SERVER);
631 break;
632
633 case STATE_LOGIN:
634 Log::info("State: LOGIN");
635 // Don't allow an alpha opacity
636 // lower than the default value
638
639 if (mOptions.username.empty() || mOptions.password.empty())
640 {
642 }
643 else
644 {
646 // Clear the password so that when login fails, the
647 // dialog will show up next time.
648 mOptions.password.clear();
649 }
650 break;
651
653 Log::info("State: LOGIN ATTEMPT");
656 _("Logging in"), STATE_SWITCH_SERVER);
657 break;
658
660 Log::info("State: WORLD SELECT");
661 {
663
664 if (worlds.empty())
665 {
666 // Trust that the netcode knows what it's doing
668 }
669 else if (worlds.size() == 1 || mOptions.chooseDefault)
670 {
673 }
674 else
675 {
676 mCurrentDialog = new WorldSelectDialog(std::move(worlds));
677 }
678 }
679 break;
680
682 Log::info("State: WORLD SELECT ATTEMPT");
684 _("Entering game world"), STATE_WORLD_SELECT);
685 break;
686
687 case STATE_UPDATE:
688 Log::info("State: UPDATE");
689
691 {
693 }
694 else if (initUpdatesDir())
695 {
698 mOptions.dataPath.empty());
699 }
700 break;
701
702 case STATE_LOAD_DATA:
703 Log::info("State: LOAD DATA");
704
705 // If another data path has been set,
706 // we don't load any other files...
707 if (mOptions.dataPath.empty())
708 {
709 // Add customdata directory
711 "customdata/",
712 "zip",
713 false);
714 }
715
716 // TODO remove this as soon as inventoryhandler stops using this event
718
719 // Load XML databases
720 CharDB::load();
721
722 delete itemDb;
723
724 switch (Net::getNetworkType())
725 {
728 break;
731 break;
732 default:
733 // Nothing
734 itemDb = nullptr;
735 break;
736 }
737 assert(itemDb);
738
739 // load settings.xml
741
743
745
747 break;
748
750 Log::info("State: GET CHARACTERS");
753 _("Requesting characters"),
755 break;
756
758 Log::info("State: CHAR SELECT");
759 // Don't allow an alpha opacity
760 // lower than the default value
762
764
765 if (!((CharSelectDialog*) mCurrentDialog)->selectByName(
767 {
768 ((CharSelectDialog*) mCurrentDialog)->selectByName(
773 }
774
775 // Choosing character on the command line should work only
776 // once, clear it so that 'switch character' works.
777 mOptions.character.clear();
778 mOptions.chooseDefault = false;
779
780 break;
781
783 Log::info("State: CONNECT GAME");
784
787 _("Connecting to the game server"),
790 break;
791
792 case STATE_CHANGE_MAP:
793 Log::info("State: CHANGE_MAP");
794
797 _("Changing game servers"),
799 break;
800
801 case STATE_GAME:
802 Log::info("Memorizing selected character %s",
803 local_player->getName().c_str());
805
806 // Fade out logon-music here too to give the desired effect
807 // of "flowing" into the game.
808 sound.fadeOutMusic(1000);
809
810 // Allow any alpha opacity
812
813 delete mSetupButton;
814 delete mDesktop;
815 mSetupButton = nullptr;
816 mDesktop = nullptr;
817
818 mCurrentDialog = nullptr;
819
820 Log::info("State: GAME");
821 mGame = new Game;
822 break;
823
825 Log::info("State: LOGIN ERROR");
827 break;
828
830 Log::info("State: ACCOUNT CHANGE ERROR");
832 break;
833
835 Log::info("State: REGISTER_PREP");
838 _("Requesting registration details"), STATE_LOGIN);
839 break;
840
841 case STATE_REGISTER:
842 Log::info("State: REGISTER");
844 break;
845
847 Log::info("Username is %s", loginData.username.c_str());
849 loginData.password.clear();
850 break;
851
853 Log::info("State: CHANGE PASSWORD");
855 break;
856
858 Log::info("State: CHANGE PASSWORD ATTEMPT");
862 break;
863
865 Log::info("State: CHANGE PASSWORD SUCCESS");
866 showOkDialog(_("Password Change"),
867 _("Password changed successfully!"),
869 loginData.password.clear();
870 loginData.newPassword.clear();
871 break;
872
874 Log::info("State: CHANGE EMAIL");
876 break;
877
879 Log::info("State: CHANGE EMAIL ATTEMPT");
881 break;
882
884 Log::info("State: CHANGE EMAIL SUCCESS");
885 showOkDialog(_("Email Change"),
886 _("Email changed successfully!"),
888 break;
889
890 case STATE_UNREGISTER:
891 Log::info("State: UNREGISTER");
893 break;
894
896 Log::info("State: UNREGISTER ATTEMPT");
899 break;
900
902 Log::info("State: UNREGISTER SUCCESS");
904
905 showOkDialog(_("Unregister Successful"),
906 _("Farewell, come back any time..."),
909 break;
910
912 Log::info("State: SWITCH SERVER");
913
916
917 mCurrentServer.hostname.clear();
919 break;
920
922 Log::info("State: SWITCH LOGIN");
923
925
927 break;
928
930 Log::info("State: SWITCH CHARACTER");
931
932 // Done with game
934
936 break;
937
939 Log::info("State: LOGOUT ATTEMPT");
940 // TODO
941 break;
942
943 case STATE_WAIT:
944 Log::info("State: WAIT");
945 break;
946
947 case STATE_EXIT:
948 Log::info("State: EXIT");
949 break;
950
951 case STATE_FORCE_QUIT:
952 Log::info("State: FORCE QUIT");
954 break;
955
956 case STATE_ERROR:
957 Log::info("State: ERROR");
958 Log::error("%s", errorMessage.c_str());
961 break;
962
963 default:
965 break;
966 }
967 }
968}
969
970void Client::showOkDialog(const std::string &title,
971 const std::string &message,
972 State state)
973{
974 auto *okDialog = new OkDialog(title, message);
975 okDialog->addActionListener(this);
976 mStateAfterOkDialog = state;
977}
978
979void Client::showErrorDialog(const std::string &message, State state)
980{
981 showOkDialog(_("Error"), message, state);
982}
983
984void Client::action(const gcn::ActionEvent &event)
985{
986 Window *window = nullptr;
987
988 if (event.getId() == "Setup")
989 window = setupWindow;
990
991 if (window)
992 {
993 window->setVisible(!window->isVisible());
994 if (window->isVisible())
995 window->requestMoveToTop();
996 }
997
998 // If this came from the OkDialog used by showOkDialog
999 if (event.getId() == "ok")
1001}
1002
1004{
1006#ifdef _WIN32
1007 std::string portableName = mRootDir + "portable.xml";
1008 struct stat statbuf;
1009
1010 if (!stat(portableName.c_str(), &statbuf) && S_ISREG(statbuf.st_mode))
1011 {
1012 std::string dir;
1013 Configuration portable;
1014 portable.init(portableName);
1015
1016 Log::info("Portable file: %s", portableName.c_str());
1017
1018 if (mOptions.localDataDir.empty())
1019 {
1020 dir = portable.getValue("dataDir", "");
1021 if (!dir.empty())
1022 {
1024 Log::info("Portable data dir: %s",
1025 mOptions.localDataDir.c_str());
1026 }
1027 }
1028
1029 if (mOptions.configDir.empty())
1030 {
1031 dir = portable.getValue("configDir", "");
1032 if (!dir.empty())
1033 {
1034 mOptions.configDir = mRootDir + dir;
1035 Log::info("Portable config dir: %s",
1036 mOptions.configDir.c_str());
1037 }
1038 }
1039
1040 if (mOptions.screenshotDir.empty())
1041 {
1042 dir = portable.getValue("screenshotDir", "");
1043 if (!dir.empty())
1044 {
1046 Log::info("Portable screenshot dir: %s",
1047 mOptions.screenshotDir.c_str());
1048 }
1049 }
1050 }
1051#endif
1052}
1053
1059{
1061
1062 if (mLocalDataDir.empty())
1063 {
1064#if defined __HAIKU__
1066 mLocalDataDir += "/config/data/Mana";
1067#elif defined _WIN32
1068 mLocalDataDir = getSpecialFolderLocation(FOLDERID_LocalAppData);
1069 if (mLocalDataDir.empty())
1071 mLocalDataDir += "/Mana";
1072#else
1073 mLocalDataDir = FS::getPrefDir("manasource.org", "mana");
1074#endif
1075 }
1076
1077 if (mkdir_r(mLocalDataDir.c_str()))
1078 {
1079 Log::critical(strprintf(_("%s doesn't exist and can't be created! "
1080 "Exiting."), mLocalDataDir.c_str()));
1081 }
1082
1084
1085 if (mConfigDir.empty())
1086 {
1087 const std::string app = branding.getValue("appShort", "manasource");
1088#ifdef __APPLE__
1089 mConfigDir = mLocalDataDir + "/" + app;
1090#elif defined __HAIKU__
1091 mConfigDir = FS::getPrefDir("manasource.org", "Mana");
1092 mConfigDir += app;
1093#elif defined _WIN32
1094 mConfigDir = FS::getPrefDir("Mana", app.c_str());
1095#else
1096 mConfigDir = std::string(FS::getUserDir()) + ".config/mana/" + app;
1097#endif
1098 }
1099
1100 if (mkdir_r(mConfigDir.c_str()))
1101 {
1102 Log::critical(strprintf(_("%s doesn't exist and can't be created! "
1103 "Exiting."), mConfigDir.c_str()));
1104 }
1105}
1106
1111{
1112 // Fill configuration with defaults
1113 config.updatehost = branding.getValue("defaultUpdateHost", std::string());
1114
1115 const std::string configPath = mConfigDir + "/config.xml";
1116 XML::Document doc(configPath, false);
1117
1118 if (doc.rootNode() && doc.rootNode().name() == "configuration")
1119 deserialize(doc.rootNode(), config);
1120 else
1121 Log::info("Couldn't read configuration file: %s", configPath.c_str());
1122}
1123
1129{
1130 // Determine which source to use for the update host
1131 if (!mOptions.updateHost.empty())
1133 else if (!loginData.updateHost.empty())
1135 else
1137
1138 // Remove any trailing slashes at the end of the URL
1139 while (!mUpdateHost.empty() && mUpdateHost.back() == '/')
1140 mUpdateHost.pop_back();
1141
1142 if (mUpdateHost.empty())
1143 {
1144 Log::info("No update host provided");
1145 mUpdatesDir.clear();
1147 return false;
1148 }
1149
1151
1152 Log::info("Update host: %s", mUpdateHost.c_str());
1153 Log::info("Updates dir: %s", mUpdatesDir.c_str());
1154
1155 // Verify that the updates directory exists. Create if necessary.
1157 {
1158 if (!FS::mkdir(mUpdatesDir))
1159 {
1160#if defined _WIN32
1161 std::string newDir = mLocalDataDir + "\\" + mUpdatesDir;
1162 std::string::size_type loc = newDir.find("/", 0);
1163
1164 while (loc != std::string::npos)
1165 {
1166 newDir.replace(loc, 1, "\\");
1167 loc = newDir.find("/", loc);
1168 }
1169
1170 if (!CreateDirectory(newDir.c_str(), 0) &&
1171 GetLastError() != ERROR_ALREADY_EXISTS)
1172 {
1173 Log::error("%s can't be made, but doesn't exist!",
1174 newDir.c_str());
1175 errorMessage =
1176 strprintf(_("Error creating updates directory!\n(%s)"),
1177 newDir.c_str());
1179 }
1180#else
1181 Log::error("%s/%s can't be made, but doesn't exist!",
1182 mLocalDataDir.c_str(), mUpdatesDir.c_str());
1183 errorMessage =
1184 strprintf(_("Error creating updates directory!\n(%s/%s)"),
1185 mLocalDataDir.c_str(), mUpdatesDir.c_str());
1187 return false;
1188#endif
1189 }
1190 }
1191
1192 return true;
1193}
1194
1196{
1197 if (!mOptions.screenshotDir.empty())
1198 {
1200 }
1201 else if (mScreenshotDir.empty())
1202 {
1203#ifdef _WIN32
1204 mScreenshotDir = getSpecialFolderLocation(FOLDERID_Pictures);
1205 if (mScreenshotDir.empty())
1206 mScreenshotDir = getSpecialFolderLocation(FOLDERID_Desktop);
1207#else
1208 mScreenshotDir = std::string(FS::getUserDir()) + "Desktop";
1209#endif
1210
1212 {
1213 std::string screenshotSuffix = config.screenshotDirectorySuffix;
1214 if (screenshotSuffix.empty())
1215 screenshotSuffix = branding.getValue("appShort", "Mana");
1216
1217 if (!screenshotSuffix.empty())
1218 {
1219 mScreenshotDir += "/" + screenshotSuffix;
1220 config.screenshotDirectorySuffix = screenshotSuffix;
1221 }
1222 }
1223 }
1224}
1225
1227{
1228 Log::info("Username is %s", loginData->username.c_str());
1229
1230 // Send login infos
1233 else
1235
1236 // Clear the password, avoids auto login when returning to login
1237 loginData->password.clear();
1238
1239 // TODO This is not the best place to save the config, but at least better
1240 // than the login gui window
1241 if (loginData->remember)
1244}
1245
1246void Client::handleWindowSizeChanged(int width, int height)
1247{
1248 // Store the new size in the configuration.
1249 config.screenWidth = width;
1250 config.screenHeight = height;
1251}
1252
1254{
1255 const int width = graphics->getWidth();
1256 const int height = graphics->getHeight();
1257
1258 if (!gui->videoResized(width, height))
1259 return;
1260
1261 if (mDesktop)
1262 mDesktop->setSize(width, height);
1263
1264 if (mSetupButton)
1265 mSetupButton->setPosition(width - mSetupButton->getWidth() - 3, 3);
1266
1267 if (mGame)
1268 mGame->videoResized(width, height);
1269}
1270
1272{
1273 return !(SDL_GetWindowFlags(getVideo().window()) & SDL_WINDOW_MINIMIZED);
1274}
1275
1277{
1278 return SDL_GetWindowFlags(getVideo().window()) & SDL_WINDOW_INPUT_FOCUS;
1279}
1280
1282{
1283 return SDL_GetWindowFlags(getVideo().window()) & SDL_WINDOW_MOUSE_FOCUS;
1284}
ChatLogger * chatLogger
Chat log object.
Definition client.cpp:100
static void load()
static void unload()
const std::string & getName() const
Returns the name of the being.
Definition being.h:190
Button widget.
Definition button.h:38
bool setButtonIcon(const std::string &iconFile)
Set the icons available next to the text.
Definition button.cpp:66
void setButtonPopupText(const std::string &text)
Set the button popup text when hovering it for a few seconds.
Definition button.h:78
The Change email dialog.
The Change password dialog.
Character selection dialog.
void setServerName(const std::string &serverName)
void setLogDir(const std::string &logDir)
The core part of the client.
Definition client.h:113
SDL_Surface * mIcon
Definition client.h:237
State mStateAfterOkDialog
Definition client.h:235
std::string mUpdatesDir
Definition client.h:220
Client(const Options &options)
Definition client.cpp:172
std::string mRootDir
Definition client.h:222
void initConfiguration()
Initialize configuration.
Definition client.cpp:1110
void showErrorDialog(const std::string &message, State state)
Pops up an error dialog with the given message, and switches to the given state when Ok is pressed.
Definition client.cpp:979
int exec()
Definition client.cpp:435
std::string mPackageDir
Definition client.h:216
void action(const gcn::ActionEvent &event) override
Definition client.cpp:984
Button * mSetupButton
Definition client.h:231
State mState
Definition client.h:233
void update()
Definition client.cpp:509
Game * mGame
Definition client.h:227
bool initUpdatesDir()
Parse the update host and determine the updates directory Then verify that the directory exists (crea...
Definition client.cpp:1128
void accountLogin(LoginData *loginData)
Definition client.cpp:1226
static bool isActive()
Definition client.cpp:1271
void initHomeDir()
Initializes the home directory.
Definition client.cpp:1058
static bool hasMouseFocus()
Definition client.cpp:1281
Video mVideo
Definition client.h:225
void checkGraphicsSize()
Definition client.cpp:1253
State mOldState
Definition client.h:234
std::string mLocalDataDir
Definition client.h:218
void initRootDir()
Definition client.cpp:1003
static bool hasInputFocus()
Definition client.cpp:1276
SDL_TimerID mSecondsCounterId
Definition client.h:239
static Video & getVideo()
Definition client.h:187
FpsManager mFpsManager
Definition client.h:240
void initScreenshotDir()
Definition client.cpp:1195
std::string mConfigDir
Definition client.h:217
void showOkDialog(const std::string &title, const std::string &message, State state)
Pops up an OkDialog with the given title and message, and switches to the given state when Ok is pres...
Definition client.cpp:970
std::string mScreenshotDir
Definition client.h:221
std::string mUpdateHost
Definition client.h:219
ServerInfo mCurrentServer
Definition client.h:224
static Client * mInstance
Definition client.h:212
QuitDialog * mQuitDialog
Definition client.h:229
void handleWindowSizeChanged(int width, int height)
Should be called after the window has been resized.
Definition client.cpp:1246
Desktop * mDesktop
Definition client.h:230
Options mOptions
Definition client.h:214
~Client() override
Definition client.cpp:398
Window * mCurrentDialog
Definition client.h:228
std::string getValue(const std::string &key, const std::string &deflt) const
Gets a value as string.
Configuration handler for reading (and writing).
std::string getStringValue(const std::string &key) const
void setDefaultValues(DefaultsData *defaultsData)
Set the default values for each keys.
void init(const std::string &filename, bool useResManager=false)
Reads config file and parse all options into memory.
The connection dialog.
Desktop widget, for drawing a background image and color.
Definition desktop.h:48
void reloadWallpaper()
Has to be called after updates have been loaded.
Definition desktop.cpp:57
The class which keeps track of the emote shortcuts.
Definition event.h:42
@ LoadingDatabases
Definition event.h:70
@ StateChange
Definition event.h:96
void trigger(Channel channel) const
Sends this event to all classes listening to the given channel.
Definition event.h:275
@ ClientChannel
Definition event.h:50
uint32_t mFrameCount
Definition client.h:101
uint32_t mBaseTicks
Definition client.h:102
int mFpsLimit
Definition client.h:100
void limitFps(int fpsLimit)
A simple but effective frame rate limiter.
Definition client.cpp:143
The main class responsible for running the game.
Definition game.h:37
void videoResized(int width, int height)
Definition game.cpp:933
void handleInput()
Continuous input handling.
Definition game.cpp:708
bool keyDownEvent(SDL_KeyboardEvent &event)
Handles an SDL_KEYDOWN event and returns whether it was consumed.
Definition game.cpp:400
void logic()
This method takes the game a small step further.
Definition game.cpp:349
A central point of control for graphics.
Definition graphics.h:78
int getHeight() const
Returns the logical height of the screen.
Definition graphics.h:226
int getWidth() const
Returns the logical width of the screen.
Definition graphics.h:221
Main GUI class.
Definition gui.h:80
bool videoResized(int width, int height)
Called when the application window has been resized.
Definition gui.cpp:196
Theme * getTheme() const
The global GUI theme.
Definition gui.h:138
void logic() override
Performs logic of the GUI.
Definition gui.cpp:167
Hair information database.
Definition hairdb.h:34
static void SDLdisableTransparency()
Disable the transparency handling (for low CPUs in SDL Mode)
Definition image.h:122
Item information database generic definition.
Definition itemdb.h:73
The class which keeps track of the item shortcuts.
void setNewKey(SDL_Keycode value)
Set the value of the new key.
int getNewKeyIndex() const
Get the index of the new key to be assigned.
void callbackNewKey()
Calls a function back so the key re-assignment(s) can be seen.
bool isEnabled() const
Get the enable flag, which will stop the user from doing actions.
int getKeyIndex(SDL_Keycode keyValue) const
Get the key function index by providing the keys value.
void init()
Initializes the keyboard config explicitly.
void setNewKeyIndex(int value)
Set the index of the new key to be assigned.
std::string email
Definition logindata.h:39
std::string updateHost
Definition logindata.h:37
std::string username
Definition logindata.h:33
void clear()
Definition logindata.h:57
std::string password
Definition logindata.h:34
std::string newPassword
Definition logindata.h:36
bool remember
Whether to store the username.
Definition logindata.h:44
bool registerLogin
Whether an account is being registered.
Definition logindata.h:45
The login dialog.
Definition logindialog.h:39
Item information database TmwAthena specific class.
Definition itemdb.h:191
virtual void requestCharacters()=0
virtual void disconnect()=0
virtual void connect()=0
virtual void flushNetwork()=0
virtual void changePassword(const std::string &username, const std::string &oldPassword, const std::string &newPassword)=0
virtual void registerAccount(LoginData *loginData)=0
virtual void disconnect()=0
virtual void changeEmail(const std::string &email)=0
virtual Worlds getWorlds() const =0
virtual void unregisterAccount(const std::string &username, const std::string &password)=0
virtual void chooseServer(unsigned int server)=0
virtual void getRegistrationDetails()=0
virtual void loginAccount(LoginData *loginData)=0
An 'Ok' button dialog.
Definition okdialog.h:34
void init()
Initialise player relations manager (load config file etc.)
The registration dialog.
Definition register.h:53
static std::string getPath(const std::string &file)
Returns the real path to a file.
static void deleteInstance()
Deletes the class instance if it exists.
static void searchAndAddArchives(const std::string &path, const std::string &ext, bool append)
Searches for zip files and adds them to the search path.
static bool addToSearchPath(const std::string &path, bool append)
Adds a directory or archive to the search path.
virtual void pushInput(SDL_Event event)
Pushes an SDL event.
Definition sdlinput.cpp:132
The server choice dialog.
std::string hostname
Definition serverinfo.h:42
static ServerType parseType(const std::string &type)
Definition serverinfo.h:73
uint16_t port
Definition serverinfo.h:43
bool isValid() const
Definition serverinfo.h:51
ServerType type
Definition serverinfo.h:40
static ServerType defaultServerTypeForPort(uint16_t port)
Definition serverinfo.h:99
static uint16_t defaultPortForServerType(ServerType type)
Definition serverinfo.h:85
The setup dialog.
Definition setup.h:48
Sound engine.
Definition sound.h:38
void playMusic(const std::string &fileName)
Starts background music.
Definition sound.cpp:166
void fadeOutMusic(int ms=1000)
Fades out currently running background music track.
Definition sound.cpp:197
void init()
Installs the sound engine.
Definition sound.cpp:61
void setMusicVolume(int volume)
Definition sound.cpp:139
void logic()
The sound logic.
Definition sound.cpp:224
void close()
Removes all sound functionalities.
Definition sound.cpp:296
void setSfxVolume(int volume)
Definition sound.cpp:147
void setNotificationsVolume(int volume)
Definition sound.cpp:158
static std::string prepareThemePath()
Definition theme.cpp:250
void setMinimumOpacity(float minimumOpacity)
Set the minimum opacity allowed to skins.
Definition theme.cpp:450
Simple timer that can be used to check if a certain amount of time has passed.
Definition time.h:62
bool passed() const
Returns whether the timer has passed.
Definition time.h:88
void set(uint32_t ms=0)
Sets the timer with an optional duration in milliseconds.
Definition time.h:69
Item information database TmwAthena specific class.
Definition itemdb.h:159
The Unregister dialog.
Update progress window GUI.
Class controlling the game's color palette.
Definition userpalette.h:33
SDL_Window * window() const
Definition video.h:78
void updateWindowSize()
Handles a change in window size, possibly adjusting the scale.
Definition video.cpp:250
void present()
Present the next frame.
Definition video.cpp:258
Graphics * initialize(const VideoSettings &settings)
Try to create a window with the given settings.
Definition video.cpp:66
A window.
Definition window.h:59
virtual void setVisible(bool visible)
Overloads window setVisible by Guichan to allow sticky window handling.
Definition window.cpp:282
void scheduleDelete()
Schedule this window for deletion.
Definition window.cpp:299
The server select dialog.
A helper class for parsing an XML document, which also cleans it up again (RAII).
Definition xml.h:190
Node rootNode() const
Returns the root node of the document (or NULL if there was a load error).
Definition xml.h:213
std::string_view name() const
Definition xml.h:46
Helper class for writing out XML data.
Definition xml.h:229
bool isValid() const
Definition xml.h:234
HairDB hairDB
Hair styles and colors info database.
Definition client.cpp:107
Config config
Global settings (config.xml)
Definition client.cpp:97
Configuration paths
XML default paths information reader.
Definition client.cpp:99
std::string errorMessage
Definition client.cpp:94
Graphics * graphics
Definition client.cpp:104
volatile int frame_count
Counts the frames during one second.
Definition client.cpp:112
bool isDoubleClick(int selected)
Returns whether this call and the last call were done for the same selected index and within a short ...
Definition client.cpp:126
UserPalette * userPalette
Definition client.cpp:103
ChatLogger * chatLogger
Chat log object.
Definition client.cpp:100
volatile int fps
Frames counted in the last second.
Definition client.cpp:111
Configuration branding
XML branding information reader.
Definition client.cpp:98
KeyboardConfig keyboard
Definition client.cpp:101
Sound sound
Definition client.cpp:109
LoginData loginData
Definition client.cpp:95
ItemDB * itemDb
Items info database.
Definition client.cpp:106
State
All client states.
Definition client.h:59
@ STATE_LOGIN_ERROR
Definition client.h:75
@ STATE_CONNECT_SERVER
Definition client.h:63
@ STATE_GET_CHARACTERS
Definition client.h:70
@ STATE_CHANGEPASSWORD_SUCCESS
Definition client.h:82
@ STATE_START
Definition client.h:61
@ STATE_CHOOSE_SERVER
Definition client.h:62
@ STATE_CHANGEEMAIL
Definition client.h:83
@ STATE_CONNECT_GAME
Definition client.h:72
@ STATE_CHANGEEMAIL_SUCCESS
Definition client.h:85
@ STATE_LOAD_DATA
Definition client.h:69
@ STATE_REGISTER
Definition client.h:78
@ STATE_UNREGISTER
Definition client.h:86
@ STATE_REGISTER_ATTEMPT
Definition client.h:79
@ STATE_REGISTER_PREP
Definition client.h:77
@ STATE_CHANGE_MAP
Definition client.h:74
@ STATE_LOGOUT_ATTEMPT
Definition client.h:92
@ STATE_UNREGISTER_ATTEMPT
Definition client.h:87
@ STATE_SWITCH_LOGIN
Definition client.h:90
@ STATE_SWITCH_SERVER
Definition client.h:89
@ STATE_WAIT
Definition client.h:93
@ STATE_EXIT
Definition client.h:94
@ STATE_ACCOUNTCHANGE_ERROR
Definition client.h:76
@ STATE_CHANGEPASSWORD
Definition client.h:80
@ STATE_UNREGISTER_SUCCESS
Definition client.h:88
@ STATE_LOGIN_ATTEMPT
Definition client.h:65
@ STATE_CHAR_SELECT
Definition client.h:71
@ STATE_CHANGEPASSWORD_ATTEMPT
Definition client.h:81
@ STATE_CHANGEEMAIL_ATTEMPT
Definition client.h:84
@ STATE_WORLD_SELECT
Definition client.h:66
@ STATE_ERROR
Definition client.h:60
@ STATE_UPDATE
Definition client.h:68
@ STATE_GAME
Definition client.h:73
@ STATE_FORCE_QUIT
Definition client.h:95
@ STATE_SWITCH_CHARACTER
Definition client.h:91
@ STATE_WORLD_SELECT_ATTEMPT
Definition client.h:67
@ STATE_LOGIN
Definition client.h:64
std::string errorMessage
Definition client.cpp:94
LoginData loginData
Definition client.cpp:95
void serialize(XML::Writer &writer, const Config &config)
void deserialize(XML::Node node, ItemShortcutEntry &itemShortcut)
DefaultsData * getBrandingDefaults()
Definition defaults.cpp:61
DefaultsData * getPathsDefaults()
Definition defaults.cpp:86
EmoteShortcut * emoteShortcut
#define _(s)
Definition gettext.h:38
SDLInput * guiInput
GUI input.
Definition gui.cpp:51
Gui * gui
The GUI system.
Definition gui.cpp:50
ItemShortcut * itemShortcut
LocalPlayer * local_player
#define PKG_DATADIR
Definition main.h:88
#define FULL_VERSION
Definition main.h:55
int mkdir_r(const char *pathname)
Create a directory, making leading components first if necessary.
Definition mkdir.cpp:36
void unload()
Definition chardb.cpp:87
void load()
Definition chardb.cpp:47
const char * getPrefDir(const char *org, const char *app)
Definition filesystem.h:62
bool setWriteDir(const std::string &path)
Sets the write directory.
Definition filesystem.h:73
bool mkdir(const std::string &path)
Creates a directory in the write path.
Definition filesystem.h:120
const char * getUserDir()
Definition filesystem.h:57
bool isDirectory(const std::string &path)
Checks whether the given path is a directory.
Definition filesystem.h:107
const char * getBaseDir()
Definition filesystem.h:52
void init()
Initializes the log system.
Definition log.cpp:84
void setLogToStandardOut(bool value)
Sets whether the log should be written to standard output.
Definition log.cpp:100
void warn(const char *log_text,...) LOG_PRINTF_ATTR
void setLogFile(const std::string &logFilename)
Sets the file to log to and opens it.
Definition log.cpp:89
void info(const char *log_text,...) LOG_PRINTF_ATTR
void error(const char *log_text,...) LOG_PRINTF_ATTR
LoginHandler * getLoginHandler()
Definition net.cpp:95
void connectToServer(ServerInfo &server)
Handles server detection and connection.
Definition net.cpp:130
ServerType getNetworkType()
Definition net.cpp:200
GameHandler * getGameHandler()
Definition net.cpp:75
CharHandler * getCharHandler()
Definition net.cpp:65
GeneralHandler * getGeneralHandler()
Definition net.cpp:80
void unload()
Definition net.cpp:177
void init()
Initializes some internals.
void beginFrame()
Called at the start of each frame, updates the above variables.
Definition time.cpp:54
PlayerRelationsManager player_relations
Setup * setupWindow
Definition setup.cpp:120
std::string getDirectoryFromURL(const std::string &url)
Derives a directory from the given URL, stripping the schema and replacing certain invalid characters...
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
A structure holding the values of various options that can be passed from the command line.
Definition client.h:120
std::string chatLogDir
Definition client.h:133
bool chooseDefault
Definition client.h:124
std::string dataPath
Definition client.h:132
ServerType serverType
Definition client.h:137
std::string screenshotDir
Definition client.h:136
std::string brandingPath
Definition client.h:130
std::string serverName
Definition client.h:139
uint16_t serverPort
Definition client.h:140
std::string updateHost
Definition client.h:131
std::string character
Definition client.h:129
std::string localDataDir
Definition client.h:135
bool skipUpdate
Definition client.h:123
std::string username
Definition client.h:127
std::string password
Definition client.h:128
std::string configDir
Definition client.h:134
bool logToStandardOut
bool opengl
int screenWidth
std::string lastCharacter
std::string updatehost
WindowMode windowMode
int screenHeight
int sfxVolume
int notificationsVolume
bool disableTransparency
bool useScreenshotDirectorySuffix
int musicVolume
std::string username
std::string screenshotDirectorySuffix
bool remember
WindowMode windowMode
Definition video.h:47
bool vsync
Definition video.h:52
int height
Definition video.h:49
bool openGL
Definition video.h:53
int width
Definition video.h:48
int userScale
Definition video.h:51
std::vector< WorldInfo * > Worlds
Definition worldinfo.h:35