summaryrefslogtreecommitdiff
path: root/src/progs/dyecmd/client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/progs/dyecmd/client.cpp')
-rw-r--r--src/progs/dyecmd/client.cpp813
1 files changed, 813 insertions, 0 deletions
diff --git a/src/progs/dyecmd/client.cpp b/src/progs/dyecmd/client.cpp
new file mode 100644
index 000000000..42b570a6b
--- /dev/null
+++ b/src/progs/dyecmd/client.cpp
@@ -0,0 +1,813 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "client.h"
+
+#include "configmanager.h"
+#include "dirs.h"
+#include "eventsmanager.h"
+#include "graphicsmanager.h"
+#include "main.h"
+#include "settings.h"
+#include "soundmanager.h"
+
+#include "fs/virtfs/fs.h"
+#include "fs/virtfs/tools.h"
+
+#include "gui/dialogsmanager.h"
+#include "gui/gui.h"
+#include "gui/skin.h"
+#include "gui/popupmanager.h"
+#include "gui/windowmanager.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/createwidget.h"
+#include "gui/widgets/desktop.h"
+#include "gui/widgets/window.h"
+#include "gui/widgets/windowcontainer.h"
+
+#include "input/inputmanager.h"
+#include "input/joystick.h"
+#include "input/keyboardconfig.h"
+
+#include "input/touch/touchmanager.h"
+
+#include "resources/imagehelper.h"
+
+#include "resources/dye/dyepalette.h"
+
+#include "resources/resourcemanager/resourcemanager.h"
+
+#include "utils/cpu.h"
+#include "utils/delete2.h"
+#include "utils/env.h"
+#include "utils/fuzzer.h"
+#include "utils/gettext.h"
+#include "utils/gettexthelper.h"
+#include "utils/mrand.h"
+#ifdef ANDROID
+#include "fs/paths.h"
+#endif // ANDROID
+
+#include "utils/sdlcheckutils.h"
+#include "utils/timer.h"
+
+#include "utils/translation/translationmanager.h"
+
+#include "configuration.h"
+
+#include "net/ipc.h"
+
+#ifdef WIN32
+PRAGMA48(GCC diagnostic push)
+PRAGMA48(GCC diagnostic ignored "-Wshadow")
+#include <SDL_syswm.h>
+PRAGMA48(GCC diagnostic pop)
+#include <sys/time.h>
+#include "fs/specialfolder.h"
+#undef ERROR
+#endif // WIN32
+
+#ifdef ANDROID
+#ifndef USE_SDL2
+PRAGMA48(GCC diagnostic push)
+PRAGMA48(GCC diagnostic ignored "-Wshadow")
+#include <SDL_screenkeyboard.h>
+PRAGMA48(GCC diagnostic pop)
+#include <fstream>
+#endif // USE_SDL2
+#endif // ANDROID
+
+PRAGMA48(GCC diagnostic push)
+PRAGMA48(GCC diagnostic ignored "-Wshadow")
+#ifdef USE_SDL2
+#include <SDL2_framerate.h>
+#else // USE_SDL2
+#include <SDL_framerate.h>
+#endif // USE_SDL2
+PRAGMA48(GCC diagnostic pop)
+
+#include "debug.h"
+
+std::string errorMessage;
+
+Client *client = nullptr;
+
+extern FPSmanager fpsManager;
+
+volatile bool runCounters;
+bool isSafeMode = false;
+int serverVersion = 0;
+int packetVersion = 0;
+unsigned int tmwServerVersion = 0;
+time_t start_time;
+unsigned int mLastHost = 0;
+unsigned long mSearchHash = 0;
+int textures_count = 0;
+
+Client::Client() :
+ ActionListener(),
+ mCurrentDialog(nullptr),
+ mSetupButton(nullptr),
+ mVideoButton(nullptr),
+ mHelpButton(nullptr),
+ mAboutButton(nullptr),
+ mThemesButton(nullptr),
+ mPerfomanceButton(nullptr),
+#ifdef ANDROID
+ mCloseButton(nullptr),
+#endif // ANDROID
+ mState(State::GAME),
+ mOldState(State::START),
+ mSkin(nullptr),
+ mButtonPadding(1),
+ mButtonSpacing(3)
+{
+ WindowManager::init();
+}
+
+void Client::testsInit()
+{
+}
+
+void Client::testsClear()
+{
+}
+
+// +++ need remove duplicate from here
+void Client::gameInit()
+{
+ logger = new Logger;
+
+ initRand();
+
+ // Load branding information
+ if (!settings.options.brandingPath.empty())
+ branding.init(settings.options.brandingPath);
+ setBrandingDefaults(branding);
+
+ Dirs::initRootDir();
+ Dirs::initHomeDir();
+
+ // Configure logger
+ if (!settings.options.logFileName.empty())
+ {
+ settings.logFileName = settings.options.logFileName;
+ }
+ else
+ {
+ settings.logFileName = pathJoin(settings.localDataDir,
+ "manaplus.log");
+ }
+ logger->setLogFile(settings.logFileName);
+
+#ifdef USE_FUZZER
+ Fuzzer::init();
+#endif // USE_FUZZER
+
+ if (settings.options.test.empty())
+ ConfigManager::backupConfig("config.xml");
+ ConfigManager::initConfiguration();
+ setPathsDefaults(paths);
+ initPaths();
+ logger->log("init 4");
+ logger->setDebugLog(config.getBoolValue("debugLog"));
+ logger->setReportUnimplemented(config.getBoolValue("unimplimentedLog"));
+
+ config.incValue("runcount");
+
+#ifndef ANDROID
+ if (settings.options.test.empty())
+ ConfigManager::storeSafeParameters();
+#endif // ANDROID
+
+ if (!VirtFs::setWriteDir(settings.localDataDir))
+ {
+ logger->error(strprintf("%s couldn't be set as home directory! "
+ "Exiting.", settings.localDataDir.c_str()));
+ }
+
+ GettextHelper::initLang();
+
+/*
+ chatLogger = new ChatLogger;
+ if (settings.options.chatLogDir.empty())
+ {
+ chatLogger->setBaseLogDir(settings.localDataDir
+ + std::string("/logs/"));
+ }
+ else
+ {
+ chatLogger->setBaseLogDir(settings.options.chatLogDir);
+ }
+*/
+ logger->setLogToStandardOut(config.getBoolValue("logToStandardOut"));
+
+ // Log the client version
+ logger->log1(FULL_VERSION);
+ logger->log("Start configPath: " + config.getConfigPath());
+
+ Dirs::initScreenshotDir();
+
+ // Initialize SDL
+ logger->log1("Initializing SDL...");
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
+ {
+ logger->safeError(strprintf("Could not initialize SDL: %s",
+ SDL_GetError()));
+ }
+ atexit(SDL_Quit);
+
+#ifndef USE_SDL2
+ SDL_EnableUNICODE(1);
+#endif // USE_SDL2
+
+ WindowManager::applyKeyRepeat();
+
+ // disable unused SDL events
+#ifndef USE_SDL2
+ SDL_EventState(SDL_VIDEOEXPOSE, SDL_IGNORE);
+#endif // USE_SDL2
+
+ SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
+ SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
+
+#ifdef WIN32
+ Dirs::extractDataDir();
+ Dirs::mountDataDir();
+#endif // WIN32
+
+ WindowManager::setIcon();
+ ConfigManager::checkConfigVersion();
+ logVars();
+ Cpu::detect();
+ DyePalette::initFunctions();
+#if defined(USE_OPENGL)
+#if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__)
+ if (!settings.options.safeMode && settings.options.test.empty()
+ && !config.getBoolValue("videodetected"))
+ {
+ graphicsManager.detectVideoSettings();
+ }
+#endif // !defined(ANDROID) && !defined(__APPLE__) &&
+ // !defined(__native_client__)
+#endif // defined(USE_OPENGL)
+
+ updateEnv();
+ initGraphics();
+
+#ifndef WIN32
+ Dirs::extractDataDir();
+ Dirs::mountDataDir();
+#endif // WIN32
+
+ Dirs::updateDataPath();
+
+ // Add the main data directories to our PhysicsFS search path
+ if (!settings.options.dataPath.empty())
+ {
+ VirtFs::mountDir(settings.options.dataPath,
+ Append_false);
+ }
+
+ // Add the local data directory to PhysicsFS search path
+ VirtFs::mountDir(settings.localDataDir,
+ Append_false);
+ TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
+#ifdef ENABLE_CUSTOMNLS
+ TranslationManager::loadGettextLang();
+#endif // ENABLE_CUSTOMNLS
+
+ WindowManager::initTitle();
+
+ mainGraphics->postInit();
+
+ theme = new Theme;
+ Theme::selectSkin();
+ touchManager.init();
+
+ // Initialize the item and emote shortcuts.
+// for (size_t f = 0; f < SHORTCUT_TABS; f ++)
+// itemShortcut[f] = new ItemShortcut(f);
+// emoteShortcut = new EmoteShortcut;
+// dropShortcut = new DropShortcut;
+
+ gui = new Gui;
+ gui->postInit(mainGraphics);
+ dialogsManager = new DialogsManager;
+ popupManager = new PopupManager;
+
+ initSoundManager();
+ eventsManager.init();
+
+ // Initialize keyboard
+ keyboard.init();
+ inputManager.init();
+
+ // Initialise player relations
+ Joystick::init();
+ WindowManager::createWindows();
+
+ keyboard.update();
+ if (joystick != nullptr)
+ joystick->update();
+
+// if (mState != State::ERROR)
+// mState = State::CHOOSE_SERVER;
+
+ startTimers();
+
+ const int fpsLimit = config.getIntValue("fpslimit");
+ settings.limitFps = fpsLimit > 0;
+
+ SDL_initFramerate(&fpsManager);
+ WindowManager::setFramerate(fpsLimit);
+
+ start_time = time(nullptr);
+
+// PlayerInfo::init();
+
+#ifdef ANDROID
+#ifndef USE_SDL2
+ WindowManager::updateScreenKeyboard(SDL_GetScreenKeyboardHeight(nullptr));
+#endif // USE_SDL2
+#endif // ANDROID
+
+ mSkin = theme->load("windowmenu.xml", "");
+ if (mSkin != nullptr)
+ {
+ mButtonPadding = mSkin->getPadding();
+ mButtonSpacing = mSkin->getOption("spacing", 3);
+ }
+}
+
+Client::~Client()
+{
+ if (!settings.options.testMode)
+ gameClear();
+ else
+ testsClear();
+}
+
+void Client::initSoundManager()
+{
+ // Initialize sound engine
+ try
+ {
+ if (config.getBoolValue("sound"))
+ soundManager.init();
+
+ soundManager.setSfxVolume(config.getIntValue("sfxVolume"));
+ soundManager.setMusicVolume(config.getIntValue("musicVolume"));
+ }
+ catch (const char *const err)
+ {
+ mState = State::ERROR;
+ errorMessage = err;
+ logger->log("Warning: %s", err);
+ }
+ soundManager.playMusic(branding.getValue(
+ "loginMusic",
+ "Magick - Real.ogg"),
+ SkipError_true);
+}
+
+void Client::initGraphics()
+{
+ WindowManager::applyVSync();
+ runCounters = config.getBoolValue("packetcounters");
+
+ graphicsManager.initGraphics();
+
+ imageHelper->postInit();
+ setConfigDefaults2(config);
+ WindowManager::applyGrabMode();
+ WindowManager::applyGamma();
+
+ mainGraphics->beginDraw();
+}
+
+void Client::gameClear()
+{
+ if (logger != nullptr)
+ logger->log1("Quitting1");
+
+ eventsManager.shutdown();
+ WindowManager::deleteWindows();
+ if (windowContainer != nullptr)
+ windowContainer->slowLogic();
+
+ stopTimers();
+
+ delete2(ipc);
+
+ if (logger != nullptr)
+ logger->log1("Quitting2");
+
+ delete2(mCurrentDialog);
+ delete2(popupManager);
+ delete2(dialogsManager);
+ delete2(gui);
+
+ if (logger != nullptr)
+ logger->log1("Quitting3");
+
+ GraphicsManager::deleteRenderers();
+
+ if (logger != nullptr)
+ logger->log1("Quitting4");
+
+ XML::cleanupXML();
+
+ if (logger != nullptr)
+ logger->log1("Quitting5");
+
+ // Shutdown sound
+ soundManager.close();
+
+ if (logger != nullptr)
+ logger->log1("Quitting6");
+
+ touchManager.clear();
+ ResourceManager::deleteInstance();
+
+ if (logger != nullptr)
+ logger->log1("Quitting8");
+
+ WindowManager::deleteIcon();
+
+ if (logger != nullptr)
+ logger->log1("Quitting9");
+
+ delete2(joystick);
+
+ keyboard.deinit();
+
+ if (logger != nullptr)
+ logger->log1("Quitting10");
+
+ soundManager.shutdown();
+ touchManager.shutdown();
+
+#ifdef DEBUG_CONFIG
+ config.enableKeyLogging();
+#endif // DEBUG_CONFIG
+
+ config.removeOldKeys();
+ config.write();
+ serverConfig.write();
+
+ config.clear();
+ serverConfig.clear();
+
+ if (logger != nullptr)
+ logger->log1("Quitting11");
+
+#ifdef USE_PROFILER
+ Perfomance::clear();
+#endif // USE_PROFILER
+
+#ifdef DEBUG_OPENGL_LEAKS
+ if (logger)
+ logger->log("textures left: %d", textures_count);
+#endif // DEBUG_OPENGL_LEAKS
+
+ Graphics::cleanUp();
+
+ if (logger != nullptr)
+ logger->log1("Quitting12");
+
+// delete2(chatLogger);
+ TranslationManager::close();
+ VirtFs::deinit();
+}
+
+#define ADDBUTTON(var, object) var = object; \
+ x -= var->getWidth() + mButtonSpacing; \
+ var->setPosition(x, mButtonPadding); \
+ top->add(var);
+
+void Client::stateGame()
+{
+ if (gui == nullptr)
+ return;
+
+ BasicContainer2 *const top = static_cast<BasicContainer2*>(
+ gui->getTop());
+
+ if (top == nullptr)
+ return;
+
+ CREATEWIDGETV(desktop, Desktop, nullptr);
+ top->add(desktop);
+ int x = top->getWidth() - mButtonPadding;
+ ADDBUTTON(mSetupButton, new Button(desktop,
+ // TRANSLATORS: setup tab quick button
+ _("Setup"), "Setup", this))
+ ADDBUTTON(mPerfomanceButton, new Button(desktop,
+ // TRANSLATORS: perfoamance tab quick button
+ _("Performance"), "Perfomance", this))
+ ADDBUTTON(mVideoButton, new Button(desktop,
+ // TRANSLATORS: video tab quick button
+ _("Video"), "Video", this))
+ ADDBUTTON(mThemesButton, new Button(desktop,
+ // TRANSLATORS: theme tab quick button
+ _("Theme"), "Themes", this))
+ ADDBUTTON(mAboutButton, new Button(desktop,
+ // TRANSLATORS: theme tab quick button
+ _("About"), "about", this))
+ ADDBUTTON(mHelpButton, new Button(desktop,
+ // TRANSLATORS: theme tab quick button
+ _("Help"), "help", this))
+#ifdef ANDROID
+ ADDBUTTON(mCloseButton, new Button(desktop,
+ // TRANSLATORS: close quick button
+ _("Close"), "close", this))
+#endif // ANDROID
+
+ desktop->setSize(mainGraphics->getWidth(),
+ mainGraphics->getHeight());
+}
+
+int Client::gameExec()
+{
+ int lastTickTime = tick_time;
+
+ while (mState != State::EXIT)
+ {
+ PROFILER_START();
+ if (eventsManager.handleEvents())
+ continue;
+
+ BLOCK_START("Client::gameExec 4")
+ if (gui != nullptr)
+ gui->logic();
+ cur_time = time(nullptr);
+ int k = 0;
+ while (lastTickTime != tick_time && k < 40)
+ {
+// if (mGame)
+// mGame->logic();
+// else
+ if (gui != nullptr)
+ gui->handleInput();
+
+ ++lastTickTime;
+ k ++;
+ }
+ soundManager.logic();
+
+ logic_count += k;
+ if (gui != nullptr)
+ gui->slowLogic();
+// if (mGame)
+// mGame->slowLogic();
+ slowLogic();
+ BLOCK_END("Client::gameExec 4")
+
+ // This is done because at some point tick_time will wrap.
+ lastTickTime = tick_time;
+
+ // Update the screen when application is visible, delay otherwise.
+ if (!WindowManager::getIsMinimized())
+ {
+ frame_count++;
+ if (gui != nullptr)
+ gui->draw();
+ mainGraphics->updateScreen();
+ }
+ else
+ {
+ SDL_Delay(100);
+ }
+
+ BLOCK_START("~Client::SDL_framerateDelay")
+ if (settings.limitFps)
+ SDL_framerateDelay(&fpsManager);
+ BLOCK_END("~Client::SDL_framerateDelay")
+
+ BLOCK_START("Client::gameExec 6")
+/*
+ if (mState == State::CONNECT_GAME)
+ {
+ stateConnectGame1();
+ }
+*/
+ BLOCK_END("Client::gameExec 6")
+
+ if (mState != mOldState)
+ {
+ BLOCK_START("Client::gameExec 7")
+
+ mOldState = mState;
+
+ // Get rid of the dialog of the previous state
+ delete2(mCurrentDialog);
+
+ // State has changed, while the quitDialog was active, it might
+ // not be correct anymore
+/*
+ if (mQuitDialog)
+ {
+ mQuitDialog->scheduleDelete();
+ mQuitDialog = nullptr;
+ }
+*/
+ BLOCK_END("Client::gameExec 7")
+
+ BLOCK_START("Client::gameExec 8")
+ PRAGMA45(GCC diagnostic push)
+ PRAGMA45(GCC diagnostic ignored "-Wswitch-enum")
+ switch (mState)
+ {
+ case State::GAME:
+ stateGame();
+ break;
+
+ case State::LOAD_DATA:
+ {
+ BLOCK_START("Client::gameExec State::LOAD_DATA")
+ logger->log1("State: LOAD DATA");
+
+ // If another data path has been set,
+ // we don't load any other files...
+ if (settings.options.dataPath.empty())
+ {
+ // Add customdata directory
+ VirtFs::searchAndAddArchives(
+ "customdata/",
+ "zip",
+ Append_false);
+ }
+
+ if (!settings.options.skipUpdate)
+ {
+ VirtFs::searchAndAddArchives(pathJoin(
+ settings.updatesDir, "local/"),
+ "zip",
+ Append_false);
+
+ VirtFs::mountDir(pathJoin(
+ settings.localDataDir,
+ settings.updatesDir,
+ "local/"),
+ Append_false);
+ }
+
+ logger->log("Init paths");
+ paths.init("paths.xml", UseVirtFs_true);
+ setPathsDefaults(paths);
+ initPaths();
+ TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
+
+ if (desktop != nullptr)
+ desktop->reloadWallpaper();
+
+ mState = State::GET_CHARACTERS;
+ BLOCK_END("Client::gameExec State::LOAD_DATA")
+ break;
+ }
+ case State::START:
+ default:
+ mState = State::FORCE_QUIT;
+ break;
+ }
+ PRAGMA45(GCC diagnostic pop)
+ BLOCK_END("Client::gameExec 8")
+ }
+ PROFILER_END();
+ }
+
+ return 0;
+}
+
+void Client::action(const ActionEvent &event)
+{
+ std::string tab;
+ const std::string &eventId = event.getId();
+
+ if (eventId == "close")
+ {
+ setState(State::FORCE_QUIT);
+ return;
+ }
+ if (eventId == "Setup")
+ {
+ tab.clear();
+ }
+ else if (eventId == "help")
+ {
+ inputManager.executeAction(InputAction::WINDOW_HELP);
+ return;
+ }
+ else if (eventId == "about")
+ {
+ inputManager.executeAction(InputAction::WINDOW_ABOUT);
+ return;
+ }
+ else if (eventId == "Video")
+ {
+ tab = "Video";
+ }
+ else if (eventId == "Themes")
+ {
+ tab = "Theme";
+ }
+ else if (eventId == "Perfomance")
+ {
+ tab = "Perfomance";
+ }
+ else
+ {
+ return;
+ }
+}
+
+void Client::moveButtons(const int width)
+{
+ if (mSetupButton != nullptr)
+ {
+ int x = width - mSetupButton->getWidth() - mButtonPadding;
+ mSetupButton->setPosition(x, mButtonPadding);
+#ifndef WIN32
+ x -= mPerfomanceButton->getWidth() + mButtonSpacing;
+ mPerfomanceButton->setPosition(x, mButtonPadding);
+
+ x -= mVideoButton->getWidth() + mButtonSpacing;
+ mVideoButton->setPosition(x, mButtonPadding);
+
+ x -= mThemesButton->getWidth() + mButtonSpacing;
+ mThemesButton->setPosition(x, mButtonPadding);
+
+ x -= mAboutButton->getWidth() + mButtonSpacing;
+ mAboutButton->setPosition(x, mButtonPadding);
+
+ x -= mHelpButton->getWidth() + mButtonSpacing;
+ mHelpButton->setPosition(x, mButtonPadding);
+#ifdef ANDROID
+ x -= mCloseButton->getWidth() + mButtonSpacing;
+ mCloseButton->setPosition(x, mButtonPadding);
+#endif // ANDROID
+#endif // WIN32
+ }
+}
+
+void Client::windowRemoved(const Window *const window)
+{
+ if (mCurrentDialog == window)
+ mCurrentDialog = nullptr;
+}
+
+void Client::logVars()
+{
+#ifdef ANDROID
+ logger->log("APPDIR: %s", getenv("APPDIR"));
+ logger->log("DATADIR2: %s", getSdStoragePath().c_str());
+#endif // ANDROID
+}
+
+void Client::slowLogic()
+{
+}
+
+int Client::testsExec()
+{
+ return 0;
+}
+
+bool Client::isTmw()
+{
+ const std::string &name = settings.serverName;
+ if (name == "server.themanaworld.org"
+ || name == "themanaworld.org"
+ || name == "167.114.185.71")
+ {
+ return true;
+ }
+ return false;
+}
+
+void Client::initPaths()
+{
+}