From 72b4c83073467998a5c036c4d50b5b6031eda320 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 6 Sep 2017 02:15:05 +0300 Subject: Move manaplus game related files into progs/manaplus. --- src/CMakeLists.txt | 24 +- src/Makefile.am | 50 +- src/actions/actions.cpp | 1914 -------------------------- src/actions/chat.cpp | 808 ----------- src/actions/commands.cpp | 2156 ------------------------------ src/actions/move.cpp | 280 ---- src/actions/pets.cpp | 248 ---- src/actions/statusbar.cpp | 200 --- src/actions/tabs.cpp | 106 -- src/actions/target.cpp | 90 -- src/actions/windows.cpp | 383 ------ src/client.cpp | 1981 --------------------------- src/client.h | 146 +- src/gui/viewport.cpp | 1148 ---------------- src/gui/viewport.h | 229 +--- src/progs/dyecmd/client.cpp | 2 +- src/progs/manaplus/actions/actions.cpp | 1914 ++++++++++++++++++++++++++ src/progs/manaplus/actions/chat.cpp | 808 +++++++++++ src/progs/manaplus/actions/commands.cpp | 2156 ++++++++++++++++++++++++++++++ src/progs/manaplus/actions/move.cpp | 280 ++++ src/progs/manaplus/actions/pets.cpp | 248 ++++ src/progs/manaplus/actions/statusbar.cpp | 200 +++ src/progs/manaplus/actions/tabs.cpp | 106 ++ src/progs/manaplus/actions/target.cpp | 90 ++ src/progs/manaplus/actions/windows.cpp | 383 ++++++ src/progs/manaplus/client.cpp | 1981 +++++++++++++++++++++++++++ src/progs/manaplus/client.h | 167 +++ src/progs/manaplus/gui/viewport.cpp | 1148 ++++++++++++++++ src/progs/manaplus/gui/viewport.h | 249 ++++ 29 files changed, 9773 insertions(+), 9722 deletions(-) delete mode 100644 src/actions/actions.cpp delete mode 100644 src/actions/chat.cpp delete mode 100644 src/actions/commands.cpp delete mode 100644 src/actions/move.cpp delete mode 100644 src/actions/pets.cpp delete mode 100644 src/actions/statusbar.cpp delete mode 100644 src/actions/tabs.cpp delete mode 100644 src/actions/target.cpp delete mode 100644 src/actions/windows.cpp delete mode 100644 src/client.cpp delete mode 100644 src/gui/viewport.cpp create mode 100644 src/progs/manaplus/actions/actions.cpp create mode 100644 src/progs/manaplus/actions/chat.cpp create mode 100644 src/progs/manaplus/actions/commands.cpp create mode 100644 src/progs/manaplus/actions/move.cpp create mode 100644 src/progs/manaplus/actions/pets.cpp create mode 100644 src/progs/manaplus/actions/statusbar.cpp create mode 100644 src/progs/manaplus/actions/tabs.cpp create mode 100644 src/progs/manaplus/actions/target.cpp create mode 100644 src/progs/manaplus/actions/windows.cpp create mode 100644 src/progs/manaplus/client.cpp create mode 100644 src/progs/manaplus/client.h create mode 100644 src/progs/manaplus/gui/viewport.cpp create mode 100644 src/progs/manaplus/gui/viewport.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 62ba63ffd..37389a0c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -530,7 +530,8 @@ SET(SRCS gui/windows/updaterwindow.h gui/userpalette.cpp gui/userpalette.h - gui/viewport.cpp + progs/manaplus/gui/viewport.cpp + progs/manaplus/gui/viewport.h gui/viewport.h gui/windowmanager.cpp gui/windowmanager.h @@ -980,23 +981,23 @@ SET(SRCS test/testmain.h actions/actiondef.h actions/actionfuncptr.h - actions/actions.cpp + progs/manaplus/actions/actions.cpp actions/actions.h - actions/chat.cpp + progs/manaplus/actions/chat.cpp actions/chat.h - actions/commands.cpp + progs/manaplus/actions/commands.cpp actions/commands.h - actions/move.cpp + progs/manaplus/actions/move.cpp actions/move.h - actions/pets.cpp + progs/manaplus/actions/pets.cpp actions/pets.h - actions/statusbar.cpp + progs/manaplus/actions/statusbar.cpp actions/statusbar.h - actions/tabs.cpp + progs/manaplus/actions/tabs.cpp actions/tabs.h - actions/target.cpp + progs/manaplus/actions/target.cpp actions/target.h - actions/windows.cpp + progs/manaplus/actions/windows.cpp actions/windows.h being/actor.cpp being/actor.h @@ -1046,7 +1047,8 @@ SET(SRCS spellmanager.h chatlogger.cpp chatlogger.h - client.cpp + progs/manaplus/client.cpp + progs/manaplus/client.h client.h commandline.cpp commandline.h diff --git a/src/Makefile.am b/src/Makefile.am index f8b7cf8a6..9497c7943 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -182,7 +182,8 @@ manaplus_CXXFLAGS += -DUSE_SDL2 endif endif -BASE_SRC += events/actionevent.h \ +BASE_SRC += client.h \ + events/actionevent.h \ listeners/actionlistener.h \ listeners/attributelistener.cpp \ listeners/attributelistener.h \ @@ -251,6 +252,7 @@ BASE_SRC += events/actionevent.h \ listeners/widgetlistener.h \ listeners/wrongdatanoticelistener.cpp \ listeners/wrongdatanoticelistener.h \ + gui/viewport.h \ gui/widgets/basiccontainer2.h \ gui/widgets/basiccontainer.cpp \ gui/colorpair.h \ @@ -660,6 +662,15 @@ BASE_SRC += events/actionevent.h \ test/testmain.h \ actions/actiondef.h \ actions/actionfuncptr.h \ + actions/actions.h \ + actions/chat.h \ + actions/commands.h \ + actions/move.h \ + actions/pets.h \ + actions/statusbar.h \ + actions/tabs.h \ + actions/target.h \ + actions/windows.h \ listeners/baselistener.hpp \ commandline.cpp \ commandline.h \ @@ -944,26 +955,6 @@ SRC = ${BASE_SRC} \ resources/sprite/animatedsprite.h \ resources/sprite/animationdelayload.cpp \ resources/sprite/animationdelayload.h \ - actions/actions.cpp \ - actions/actions.h \ - actions/chat.cpp \ - actions/chat.h \ - actions/commands.cpp \ - actions/commands.h \ - actions/move.cpp \ - actions/move.h \ - actions/pets.cpp \ - actions/pets.h \ - actions/statusbar.cpp \ - actions/statusbar.h \ - actions/tabs.cpp \ - actions/tabs.h \ - actions/target.cpp \ - actions/target.h \ - actions/windows.cpp \ - actions/windows.h \ - client.cpp \ - client.h \ resources/dbmanager.cpp \ resources/dbmanager.h \ resources/sprite/imagesprite.cpp \ @@ -1083,8 +1074,6 @@ SRC = ${BASE_SRC} \ listeners/awaylistener.h \ listeners/charrenamelistener.cpp \ listeners/charrenamelistener.h \ - gui/viewport.cpp \ - gui/viewport.h \ gui/popups/itempopup.cpp \ gui/popups/itempopup.h \ gui/popups/spellpopup.cpp \ @@ -1643,7 +1632,20 @@ SRC = ${BASE_SRC} \ net/ea/tradehandler.cpp \ net/ea/tradehandler.h \ net/ea/traderecv.cpp \ - net/ea/traderecv.h + net/ea/traderecv.h \ + progs/manaplus/actions/actions.cpp \ + progs/manaplus/actions/chat.cpp \ + progs/manaplus/actions/commands.cpp \ + progs/manaplus/actions/move.cpp \ + progs/manaplus/actions/pets.cpp \ + progs/manaplus/actions/statusbar.cpp \ + progs/manaplus/actions/tabs.cpp \ + progs/manaplus/actions/target.cpp \ + progs/manaplus/actions/windows.cpp \ + progs/manaplus/client.cpp \ + progs/manaplus/client.h \ + progs/manaplus/gui/viewport.cpp \ + progs/manaplus/gui/viewport.h if ENABLE_TMWA manaplus_CXXFLAGS += -DTMWA_SUPPORT diff --git a/src/actions/actions.cpp b/src/actions/actions.cpp deleted file mode 100644 index b958f8f62..000000000 --- a/src/actions/actions.cpp +++ /dev/null @@ -1,1914 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/actions.h" - -#include "actormanager.h" -#include "configuration.h" -#include "game.h" -#ifdef USE_OPENGL -#include "graphicsmanager.h" -#endif // USE_OPENGL -#include "main.h" -#include "spellmanager.h" - -#include "actions/actiondef.h" - -#include "being/localplayer.h" -#include "being/playerinfo.h" - -#include "const/spells.h" - -#include "const/resources/skill.h" - -#include "fs/files.h" - -#include "gui/gui.h" -#include "gui/popupmanager.h" -#include "gui/sdlinput.h" -#include "gui/windowmanager.h" - -#include "gui/shortcut/dropshortcut.h" -#include "gui/shortcut/emoteshortcut.h" -#include "gui/shortcut/itemshortcut.h" - -#include "gui/popups/popupmenu.h" - -#include "gui/windows/buydialog.h" -#include "gui/windows/okdialog.h" -#include "gui/windows/tradewindow.h" -#include "gui/windows/quitdialog.h" -#include "gui/windows/buyselldialog.h" -#include "gui/windows/chatwindow.h" -#include "gui/windows/helpwindow.h" -#include "gui/windows/inventorywindow.h" -#include "gui/windows/itemamountwindow.h" -#include "gui/windows/npcdialog.h" -#include "gui/windows/outfitwindow.h" -#include "gui/windows/setupwindow.h" -#include "gui/windows/shopwindow.h" -#include "gui/windows/shortcutwindow.h" -#include "gui/windows/skilldialog.h" -#include "gui/windows/whoisonline.h" - -#include "gui/widgets/createwidget.h" - -#include "gui/widgets/tabs/chat/chattab.h" - -#include "input/inputactionoperators.h" - -#if defined USE_OPENGL -#include "render/normalopenglgraphics.h" -#endif // USE_OPENGL - -#include "net/adminhandler.h" -#include "net/beinghandler.h" -#include "net/buyingstorehandler.h" -#include "net/buysellhandler.h" -#include "net/chathandler.h" -#include "net/download.h" -#include "net/homunculushandler.h" -#include "net/gamehandler.h" -#include "net/inventoryhandler.h" -#include "net/ipc.h" -#include "net/mercenaryhandler.h" -#include "net/net.h" -#include "net/npchandler.h" -#include "net/playerhandler.h" -#include "net/serverfeatures.h" -#include "net/uploadcharinfo.h" -#include "net/tradehandler.h" -#include "net/vendinghandler.h" - -#include "resources/iteminfo.h" -#include "resources/memorymanager.h" - -#include "resources/resourcemanager/resourcemanager.h" - -#include "utils/chatutils.h" -#include "utils/delete2.h" -#include "utils/foreach.h" -#include "utils/gettext.h" -#include "utils/mathutils.h" -#include "utils/parameters.h" -#include "utils/timer.h" - -PRAGMA48(GCC diagnostic push) -PRAGMA48(GCC diagnostic ignored "-Wshadow") -#ifdef ANDROID -#ifndef USE_SDL2 -#include -#endif // USE_OPENGL -#endif // ANDROID -PRAGMA48(GCC diagnostic pop) - -#include - -#include "debug.h" - -extern std::string tradePartnerName; -extern QuitDialog *quitDialog; -extern time_t start_time; -extern char **environ; - -namespace Actions -{ - -static int uploadUpdate(void *ptr, - const DownloadStatusT status, - size_t total A_UNUSED, - const size_t remaining A_UNUSED) A_NONNULL(1); - -static int uploadUpdate(void *ptr, - const DownloadStatusT status, - size_t total A_UNUSED, - const size_t remaining A_UNUSED) -{ - if (status == DownloadStatus::Idle || status == DownloadStatus::Starting) - return 0; - - UploadChatInfo *const info = reinterpret_cast(ptr); - if (info == nullptr) - return 0; - - if (status == DownloadStatus::Complete) - { - std::string str = Net::Download::getUploadResponse(); - const size_t sz = str.size(); - if (sz > 0) - { - if (str[sz - 1] == '\n') - str = str.substr(0, sz - 1); - str.append(info->addStr); - ChatTab *const tab = info->tab; - if (chatWindow != nullptr && - (tab == nullptr || chatWindow->isTabPresent(tab))) - { - str = strprintf("%s [@@%s |%s@@]", - info->text.c_str(), str.c_str(), str.c_str()); - outStringNormal(tab, str, str); - } - else - { - CREATEWIDGET(OkDialog, - // TRANSLATORS: file uploaded message - _("File uploaded"), - str, - // TRANSLATORS: ok dialog button - _("OK"), - DialogType::OK, - Modal_true, - ShowCenter_false, - nullptr, - 260); - } - } - } - delete2(info->upload); - delete info; - return 0; -} - -static void uploadFile(const std::string &str, - const std::string &fileName, - const std::string &addStr, - ChatTab *const tab) -{ - UploadChatInfo *const info = new UploadChatInfo; - Net::Download *const upload = new Net::Download(info, - "http://sprunge.us", - &uploadUpdate, - false, true, false); - info->upload = upload; - info->text = str; - info->addStr = addStr; - info->tab = tab; - upload->setFile(fileName); - upload->start(); -} - -static Being *findBeing(const std::string &name, const bool npc) -{ - if ((localPlayer == nullptr) || (actorManager == nullptr)) - return nullptr; - - Being *being = nullptr; - - if (name.empty()) - { - being = localPlayer->getTarget(); - } - else - { - being = actorManager->findBeingByName( - name, ActorType::Unknown); - } - if ((being == nullptr) && npc) - { - being = actorManager->findNearestLivingBeing( - localPlayer, 1, ActorType::Npc, AllowSort_true); - if (being != nullptr) - { - if (abs(being->getTileX() - localPlayer->getTileX()) > 1 - || abs(being->getTileY() - localPlayer->getTileY()) > 1) - { - being = nullptr; - } - } - } - if ((being == nullptr) && npc) - { - being = actorManager->findNearestLivingBeing( - localPlayer, 1, ActorType::Player, AllowSort_true); - if (being != nullptr) - { - if (abs(being->getTileX() - localPlayer->getTileX()) > 1 - || abs(being->getTileY() - localPlayer->getTileY()) > 1) - { - being = nullptr; - } - } - } - return being; -} - -static Item *getItemByInvIndex(const int index, - const InventoryTypeT invType) -{ - const Inventory *inv = nullptr; - switch (invType) - { - case InventoryType::Storage: - inv = PlayerInfo::getStorageInventory(); - break; - - case InventoryType::Inventory: - inv = PlayerInfo::getInventory(); - break; - case InventoryType::Trade: - case InventoryType::Npc: - case InventoryType::Cart: - case InventoryType::Vending: - case InventoryType::MailEdit: - case InventoryType::MailView: - case InventoryType::Craft: - case InventoryType::TypeEnd: - default: - break; - } - if (inv != nullptr) - return inv->getItem(index); - return nullptr; -} - -static int getAmountFromEvent(const InputEvent &event, - Item *&item0, - const InventoryTypeT invType) -{ - Item *const item = getItemByInvIndex(atoi(event.args.c_str()), - invType); - item0 = item; - if (item == nullptr) - return 0; - - std::string str = event.args; - removeToken(str, " "); - - if (str.empty()) - return 0; - - int amount = 0; - if (str[0] == '-') - { - if (str.size() > 1) - { - amount = item->getQuantity() - atoi(str.substr(1).c_str()); - if (amount <= 0 || amount > item->getQuantity()) - amount = item->getQuantity(); - } - } - else if (str == "/") - { - amount = item->getQuantity() / 2; - } - else if (str == "all") - { - amount = item->getQuantity(); - } - else - { - amount = atoi(str.c_str()); - } - return amount; -} - -impHandler(emote) -{ - const int emotion = 1 + (event.action - InputAction::EMOTE_1); - if (emotion > 0) - { - if (emoteShortcut != nullptr) - emoteShortcut->useEmotePlayer(emotion); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - - return false; -} - -impHandler(outfit) -{ - if (inputManager.isActionActive(InputAction::WEAR_OUTFIT)) - { - const int num = event.action - InputAction::OUTFIT_1; - if ((outfitWindow != nullptr) && num >= 0) - { - outfitWindow->wearOutfit(num); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - } - else if (inputManager.isActionActive(InputAction::COPY_OUTFIT)) - { - const int num = event.action - InputAction::OUTFIT_1; - if ((outfitWindow != nullptr) && num >= 0) - { - outfitWindow->copyOutfit(num); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - } - - return false; -} - -impHandler0(mouseClick) -{ - if ((guiInput == nullptr) || (gui == nullptr)) - return false; - - int mouseX, mouseY; - Gui::getMouseState(mouseX, mouseY); - guiInput->simulateMouseClick(mouseX, mouseY, MouseButton::RIGHT); - return true; -} - -impHandler0(ok) -{ - // Close the Browser if opened - if ((helpWindow != nullptr) && helpWindow->isWindowVisible()) - { - helpWindow->setVisible(Visible_false); - return true; - } - // Close the config window, cancelling changes if opened - else if ((setupWindow != nullptr) && setupWindow->isWindowVisible()) - { - setupWindow->action(ActionEvent(nullptr, "cancel")); - return true; - } - else if (NpcDialog *const dialog = NpcDialog::getActive()) - { - dialog->action(ActionEvent(nullptr, "ok")); - return true; - } - else if (popupMenu->isPopupVisible()) - { - popupMenu->select(); - } - return false; -} - -impHandler(shortcut) -{ - if (itemShortcutWindow != nullptr) - { - const int num = itemShortcutWindow->getTabIndex(); - if (num >= 0 && num < CAST_S32(SHORTCUT_TABS)) - { - if (itemShortcut[num] != nullptr) - { - itemShortcut[num]->useItem(event.action - - InputAction::SHORTCUT_1); - } - } - return true; - } - return false; -} - -impHandler0(quit) -{ - if (Game::instance() == nullptr) - return false; - if (PopupManager::isPopupMenuVisible()) - { - PopupManager::closePopupMenu(); - return true; - } - else if (quitDialog == nullptr) - { - CREATEWIDGETV(quitDialog, QuitDialog, - &quitDialog); - quitDialog->requestMoveToTop(); - return true; - } - return false; -} - -impHandler0(dropItem0) -{ - if (dropShortcut != nullptr) - { - dropShortcut->dropFirst(); - return true; - } - return false; -} - -impHandler0(dropItem) -{ - if (dropShortcut != nullptr) - { - dropShortcut->dropItems(); - return true; - } - return false; -} - -impHandler(dropItemId) -{ - const Inventory *const inv = PlayerInfo::getInventory(); - if (inv == nullptr) - return false; - - // +++ ignoring item color for now - Item *const item = inv->findItem(atoi(event.args.c_str()), - ItemColor_one); - - if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) - { - ItemAmountWindow::showWindow(ItemAmountWindowUsage::ItemDrop, - inventoryWindow, item); - } - return true; -} - -impHandler(dropItemInv) -{ - Item *const item = getItemByInvIndex(atoi(event.args.c_str()), - InventoryType::Inventory); - if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) - { - ItemAmountWindow::showWindow(ItemAmountWindowUsage::ItemDrop, - inventoryWindow, item); - } - return true; -} - -impHandler(dropItemIdAll) -{ - const Inventory *const inv = PlayerInfo::getInventory(); - if (inv == nullptr) - return false; - - // +++ ignoring item color for now - Item *const item = inv->findItem(atoi(event.args.c_str()), - ItemColor_one); - - if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) - PlayerInfo::dropItem(item, item->getQuantity(), Sfx_true); - return true; -} - -impHandler(dropItemInvAll) -{ - Item *const item = getItemByInvIndex(atoi(event.args.c_str()), - InventoryType::Inventory); - if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) - PlayerInfo::dropItem(item, item->getQuantity(), Sfx_true); - return true; -} - -#ifdef TMWA_SUPPORT -impHandler(heal) -{ - if (Net::getNetworkType() != ServerType::TMWATHENA) - return false; - if (actorManager != nullptr && - localPlayer != nullptr) - { - std::string args = event.args; - - if (!args.empty()) - { - const Being *being = nullptr; - if (args[0] == ':') - { - being = actorManager->findBeing(fromInt(atoi( - args.substr(1).c_str()), BeingId)); - if (being != nullptr && being->getType() == ActorType::Monster) - being = nullptr; - } - else - { - being = actorManager->findBeingByName(args, ActorType::Player); - } - if (being != nullptr) - actorManager->heal(being); - } - else - { - Being *target = localPlayer->getTarget(); - if (inputManager.isActionActive(InputAction::STOP_ATTACK)) - { - if (target == nullptr || - target->getType() != ActorType::Player) - { - target = actorManager->findNearestLivingBeing( - localPlayer, 10, ActorType::Player, AllowSort_true); - } - } - else - { - if (target == nullptr) - target = localPlayer; - } - actorManager->heal(target); - } - - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - return false; -} -#else // TMWA_SUPPORT - -impHandler0(heal) -{ - return false; -} -#endif // TMWA_SUPPORT - -impHandler0(healmd) -{ -#ifdef TMWA_SUPPORT - if (Net::getNetworkType() != ServerType::TMWATHENA) - return false; - if (actorManager != nullptr) - { - const int matk = PlayerInfo::getStatEffective(Attributes::PLAYER_MATK); - int maxHealingRadius; - - // magic levels < 2 - if (PlayerInfo::getSkillLevel(340) < 2 - || PlayerInfo::getSkillLevel(341) < 2) - { - maxHealingRadius = matk / 100 + 1; - } - else - { - maxHealingRadius = (12 * fastSqrtInt(matk) + matk) / 100 + 1; - } - - Being *target = actorManager->findMostDamagedPlayer(maxHealingRadius); - if (target != nullptr) - actorManager->heal(target); - - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } -#endif // TMWA_SUPPORT - - return false; -} - -impHandler0(itenplz) -{ -#ifdef TMWA_SUPPORT - if (Net::getNetworkType() != ServerType::TMWATHENA) - return false; - if (actorManager != nullptr) - { - if (playerHandler != nullptr && - playerHandler->canUseMagic() && - PlayerInfo::getAttribute(Attributes::PLAYER_MP) >= 3) - { - actorManager->itenplz(); - } - return true; - } -#endif // TMWA_SUPPORT - - return false; -} - -impHandler0(setHome) -{ - if (localPlayer != nullptr) - { - localPlayer->setHome(); - return true; - } - return false; -} - -impHandler0(magicAttack) -{ -#ifdef TMWA_SUPPORT - if (Net::getNetworkType() != ServerType::TMWATHENA) - return false; - if (localPlayer != nullptr) - { - localPlayer->magicAttack(); - return true; - } -#endif // TMWA_SUPPORT - - return false; -} - -impHandler0(copyEquippedToOutfit) -{ - if (outfitWindow != nullptr) - { - outfitWindow->copyFromEquiped(); - return true; - } - return false; -} - -impHandler(pickup) -{ - if (localPlayer == nullptr) - return false; - - const std::string args = event.args; - if (args.empty()) - { - localPlayer->pickUpItems(); - } - else - { - FloorItem *const item = actorManager->findItem(fromInt( - atoi(args.c_str()), BeingId)); - if (item != nullptr) - localPlayer->pickUp(item); - } - return true; -} - -static void doSit() -{ - if (inputManager.isActionActive(InputAction::EMOTE)) - localPlayer->updateSit(); - else - localPlayer->toggleSit(); -} - -impHandler0(sit) -{ - if (localPlayer != nullptr) - { - doSit(); - return true; - } - return false; -} - -impHandler(screenshot) -{ - Game::createScreenshot(event.args); - return true; -} - -impHandler0(ignoreInput) -{ - return true; -} - -impHandler(buy) -{ - if (serverFeatures == nullptr) - return false; - const std::string args = event.args; - Being *being = findBeing(args, false); - if ((being == nullptr) && Net::getNetworkType() == ServerType::TMWATHENA) - { - if (whoIsOnline != nullptr) - { - const std::set &players = - whoIsOnline->getOnlineNicks(); - if (players.find(args) != players.end()) - { - if (buySellHandler != nullptr) - buySellHandler->requestSellList(args); - return true; - } - } - return false; - } - - if (being == nullptr) - being = findBeing(args, true); - - if (being == nullptr) - return false; - - if (being->getType() == ActorType::Npc) - { - if (npcHandler != nullptr) - npcHandler->buy(being); - return true; - } - else if (being->getType() == ActorType::Player) - { - if (vendingHandler != nullptr && - Net::getNetworkType() != ServerType::TMWATHENA) - { - vendingHandler->open(being); - } - else if (buySellHandler != nullptr) - { - buySellHandler->requestSellList(being->getName()); - } - return true; - } - return false; -} - -impHandler(sell) -{ - if (serverFeatures == nullptr) - return false; - - const std::string args = event.args; - Being *being = findBeing(args, false); - if (being == nullptr && - Net::getNetworkType() == ServerType::TMWATHENA) - { - if (whoIsOnline != nullptr) - { - const std::set &players = - whoIsOnline->getOnlineNicks(); - if (players.find(args) != players.end()) - { - if (buySellHandler != nullptr) - buySellHandler->requestBuyList(args); - return true; - } - } - return false; - } - - if (being == nullptr) - being = findBeing(args, true); - - if (being == nullptr) - return false; - - if (being->getType() == ActorType::Npc) - { - if (npcHandler != nullptr) - npcHandler->sell(being->getId()); - return true; - } - else if (being->getType() == ActorType::Player) - { - if ((buyingStoreHandler != nullptr) && - Net::getNetworkType() != ServerType::TMWATHENA) - { - buyingStoreHandler->open(being); - } - else if (buySellHandler != nullptr) - { - buySellHandler->requestBuyList(being->getName()); - } - return true; - } - return false; -} - -impHandler(talk) -{ - Being *being = findBeing(event.args, true); - if (being == nullptr) - return false; - - if (being->canTalk()) - { - being->talkTo(); - } - else if (being->getType() == ActorType::Player) - { - CREATEWIDGET(BuySellDialog, - being->getName()); - } - return true; -} - -impHandler0(stopAttack) -{ - if (localPlayer != nullptr) - { - localPlayer->stopAttack(); - // not consume if target attack key pressed - if (inputManager.isActionActive(InputAction::TARGET_ATTACK)) - return false; - return true; - } - return false; -} - -impHandler0(untarget) -{ - if (localPlayer != nullptr) - { - localPlayer->untarget(); - return true; - } - return false; -} - -impHandler(attack) -{ - if ((localPlayer == nullptr) || (actorManager == nullptr)) - return false; - - Being *target = nullptr; - std::string args = event.args; - if (!args.empty()) - { - if (args[0] != ':') - { - target = actorManager->findNearestByName(args); - } - else - { - target = actorManager->findBeing(fromInt(atoi( - args.substr(1).c_str()), BeingId)); - if (target != nullptr && - target->getType() != ActorType::Monster) - { - target = nullptr; - } - } - } - if (target == nullptr) - target = localPlayer->getTarget(); - else - localPlayer->setTarget(target); - if (target != nullptr) - localPlayer->attack(target, true); - return true; -} - -impHandler(targetAttack) -{ - if ((localPlayer != nullptr) && (actorManager != nullptr)) - { - Being *target = nullptr; - std::string args = event.args; - const bool newTarget = !inputManager.isActionActive( - InputAction::STOP_ATTACK); - - if (!args.empty()) - { - if (args[0] != ':') - { - target = actorManager->findNearestByName(args); - } - else - { - target = actorManager->findBeing(fromInt(atoi( - args.substr(1).c_str()), BeingId)); - if (target != nullptr && - target->getType() != ActorType::Monster) - { - target = nullptr; - } - } - } - - if ((target == nullptr) && (settings.targetingType == 0u)) - target = localPlayer->getTarget(); - - if (target == nullptr) - { - target = actorManager->findNearestLivingBeing( - localPlayer, 90, ActorType::Monster, AllowSort_true); - } - - localPlayer->attack2(target, newTarget); - return true; - } - return false; -} - -impHandler0(attackHuman) -{ - if ((actorManager == nullptr) || (localPlayer == nullptr)) - return false; - - Being *const target = actorManager->findNearestPvpPlayer(); - if (target != nullptr) - { - localPlayer->setTarget(target); - localPlayer->attack2(target, true); - } - return true; -} - -impHandler0(safeVideoMode) -{ - WindowManager::setFullScreen(false); - - return true; -} - -impHandler0(stopSit) -{ - if (localPlayer != nullptr) - { - localPlayer->stopAttack(); - // not consume if target attack key pressed - if (inputManager.isActionActive(InputAction::TARGET_ATTACK)) - return false; - if (localPlayer->getTarget() == nullptr) - { - doSit(); - return true; - } - return true; - } - return false; -} - -impHandler0(showKeyboard) -{ -#ifdef ANDROID -#ifdef USE_SDL2 - if (SDL_IsTextInputActive()) - SDL_StopTextInput(); - else - SDL_StartTextInput(); -#else // USE_SDL2 - - SDL_ANDROID_ToggleScreenKeyboardTextInput(nullptr); -#endif // USE_SDL2 - - return true; -#else // ANDROID - - return false; -#endif // ANDROID -} - -impHandler0(showWindows) -{ - if (popupMenu != nullptr) - { - popupMenu->showWindowsPopup(); - return true; - } - return false; -} - -impHandler0(openTrade) -{ - const Being *const being = localPlayer->getTarget(); - if ((being != nullptr) && being->getType() == ActorType::Player) - { - if (tradeHandler != nullptr) - tradeHandler->request(being); - tradePartnerName = being->getName(); - if (tradeWindow != nullptr) - tradeWindow->clear(); - return true; - } - return false; -} - -impHandler0(ipcToggle) -{ - if (ipc != nullptr) - { - IPC::stop(); - if (ipc == nullptr) - { - debugChatTab->chatLog("IPC service stopped.", - ChatMsgType::BY_SERVER); - } - else - { - debugChatTab->chatLog("Unable to stop IPC service.", - ChatMsgType::BY_SERVER); - } - } - else - { - IPC::start(); - if (ipc != nullptr) - { - debugChatTab->chatLog( - strprintf("IPC service available on port %d", ipc->getPort()), - ChatMsgType::BY_SERVER); - } - else - { - debugChatTab->chatLog("Unable to start IPC service", - ChatMsgType::BY_SERVER); - } - } - return true; -} - -impHandler(where) -{ - ChatTab *const tab = event.tab != nullptr ? event.tab : debugChatTab; - if (tab == nullptr) - return false; - std::ostringstream where; - where << Game::instance()->getCurrentMapName() << ", coordinates: " - << ((localPlayer->getPixelX() - mapTileSize / 2) / mapTileSize) - << ", " << ((localPlayer->getPixelY() - mapTileSize) / mapTileSize); - tab->chatLog(where.str(), ChatMsgType::BY_SERVER); - return true; -} - -impHandler0(who) -{ - if (chatHandler != nullptr) - chatHandler->who(); - return true; -} - -impHandler0(cleanGraphics) -{ - ResourceManager::clearCache(); - - if (debugChatTab != nullptr) - { - // TRANSLATORS: clear graphics command message - debugChatTab->chatLog(_("Cache cleaned"), - ChatMsgType::BY_SERVER); - } - return true; -} - -impHandler0(cleanFonts) -{ - if (gui != nullptr) - gui->clearFonts(); - if (debugChatTab != nullptr) - { - // TRANSLATORS: clear fonts cache message - debugChatTab->chatLog(_("Cache cleaned"), - ChatMsgType::BY_SERVER); - } - return true; -} - -impHandler(trade) -{ - if (actorManager == nullptr) - return false; - - const Being *being = actorManager->findBeingByName( - event.args, ActorType::Player); - if (being == nullptr) - being = localPlayer->getTarget(); - if (being != nullptr) - { - if (tradeHandler != nullptr) - tradeHandler->request(being); - tradePartnerName = being->getName(); - if (tradeWindow != nullptr) - tradeWindow->clear(); - } - return true; -} - -impHandler0(priceLoad) -{ - if (shopWindow != nullptr) - { - shopWindow->loadList(); - return true; - } - return false; -} - -impHandler0(priceSave) -{ - if (shopWindow != nullptr) - { - shopWindow->saveList(); - return true; - } - return false; -} - -impHandler0(cacheInfo) -{ - if ((chatWindow == nullptr) || (debugChatTab == nullptr)) - return false; - -/* - Font *const font = chatWindow->getFont(); - if (!font) - return; - - const TextChunkList *const cache = font->getCache(); - if (!cache) - return; - - unsigned int all = 0; - // TRANSLATORS: chat fonts message - debugChatTab->chatLog(_("font cache size"), ChatMsgType::BY_SERVER); - std::string str; - for (int f = 0; f < 256; f ++) - { - if (!cache[f].size) - { - const unsigned int sz = CAST_S32(cache[f].size); - all += sz; - str.append(strprintf("%d: %u, ", f, sz)); - } - } - debugChatTab->chatLog(str, ChatMsgType::BY_SERVER); - // TRANSLATORS: chat fonts message - debugChatTab->chatLog(strprintf("%s %d", _("Cache size:"), all), - ChatMsgType::BY_SERVER); -#ifdef DEBUG_FONT_COUNTERS - debugChatTab->chatLog("", ChatMsgType::BY_SERVER); - debugChatTab->chatLog(strprintf("%s %d", - // TRANSLATORS: chat fonts message - _("Created:"), font->getCreateCounter()), - ChatMsgType::BY_SERVER); - debugChatTab->chatLog(strprintf("%s %d", - // TRANSLATORS: chat fonts message - _("Deleted:"), font->getDeleteCounter()), - ChatMsgType::BY_SERVER); -#endif -*/ - return true; -} - -impHandler0(disconnect) -{ - if (gameHandler != nullptr) - gameHandler->disconnect2(); - return true; -} - -impHandler(undress) -{ - if ((actorManager == nullptr) || (localPlayer == nullptr)) - return false; - - const std::string args = event.args; - StringVect pars; - if (!splitParameters(pars, args, " ,", '\"')) - return false; - Being *target = nullptr; - const size_t sz = pars.size(); - if (sz == 0) - { - target = localPlayer->getTarget(); - } - else - { - if (pars[0][0] == ':') - { - target = actorManager->findBeing(fromInt(atoi( - pars[0].substr(1).c_str()), BeingId)); - if ((target != nullptr) && target->getType() == ActorType::Monster) - target = nullptr; - } - else - { - target = actorManager->findNearestByName(args); - } - } - - if (sz == 2) - { - const int itemId = atoi(pars[1].c_str()); - if (target != nullptr) - target->undressItemById(itemId); - } - else - { - if ((target != nullptr) && (beingHandler != nullptr)) - beingHandler->undress(target); - } - - return true; -} - -impHandler0(dirs) -{ - if (debugChatTab == nullptr) - return false; - - debugChatTab->chatLog("config directory: " - + settings.configDir, - ChatMsgType::BY_SERVER); - debugChatTab->chatLog("logs directory: " - + settings.localDataDir, - ChatMsgType::BY_SERVER); - debugChatTab->chatLog("screenshots directory: " - + settings.screenshotDir, - ChatMsgType::BY_SERVER); - debugChatTab->chatLog("temp directory: " - + settings.tempDir, - ChatMsgType::BY_SERVER); - return true; -} - -impHandler0(uptime) -{ - if (debugChatTab == nullptr) - return false; - - if (cur_time < start_time) - { - // TRANSLATORS: uptime command - debugChatTab->chatLog(strprintf(_("Client uptime: %s"), "unknown"), - ChatMsgType::BY_SERVER); - } - else - { - // TRANSLATORS: uptime command - debugChatTab->chatLog(strprintf(_("Client uptime: %s"), - timeDiffToString(CAST_S32(cur_time - start_time)).c_str()), - ChatMsgType::BY_SERVER); - } - return true; -} - -#ifdef DEBUG_DUMP_LEAKS1 -static void showRes(std::string str, ResourceManager::Resources *res) -{ - if (!res) - return; - - str.append(toString(res->size())); - if (debugChatTab) - debugChatTab->chatLog(str, ChatMsgType::BY_SERVER); - logger->log(str); - ResourceManager::ResourceIterator iter = res->begin(); - const ResourceManager::ResourceIterator iter_end = res->end(); - while (iter != iter_end) - { - if (iter->second && iter->second->mRefCount) - { - char type = ' '; - char isNew = 'N'; - if (iter->second->getDumped()) - isNew = 'O'; - else - iter->second->setDumped(true); - - SubImage *const subImage = dynamic_cast( - iter->second); - Image *const image = dynamic_cast(iter->second); - int id = 0; - if (subImage) - type = 'S'; - else if (image) - type = 'I'; - if (image) - id = image->getGLImage(); - logger->log("Resource %c%c: %s (%d) id=%d", type, - isNew, iter->second->getIdPath().c_str(), - iter->second->mRefCount, id); - } - ++ iter; - } -} - -impHandler(dump) -{ - if (!debugChatTab) - return false; - - if (!event.args.empty()) - { - ResourceManager::Resources *res = ResourceManager::getResources(); - // TRANSLATORS: dump command - showRes(_("Resource images:"), res); - res = ResourceManager::getOrphanedResources(); - // TRANSLATORS: dump command - showRes(_("Resource orphaned images:"), res); - } - else - { - ResourceManager::Resources *res = ResourceManager::getResources(); - // TRANSLATORS: dump command - debugChatTab->chatLog(_("Resource images:") + toString(res->size()), - ChatMsgType::BY_SERVER); - res = ResourceManager::getOrphanedResources(); - // TRANSLATORS: dump command - debugChatTab->chatLog(_("Resource orphaned images:") - + toString(res->size()), - ChatMsgType::BY_SERVER); - } - return true; -} - -#elif defined ENABLE_MEM_DEBUG -impHandler0(dump) -{ - nvwa::check_leaks(); - return true; -} -#else // DEBUG_DUMP_LEAKS1 - -impHandler0(dump) -{ - return true; -} -#endif // DEBUG_DUMP_LEAKS1 - -impHandler0(serverIgnoreAll) -{ - if (chatHandler != nullptr) - chatHandler->ignoreAll(); - return true; -} - -impHandler0(serverUnIgnoreAll) -{ - if (chatHandler != nullptr) - chatHandler->unIgnoreAll(); - return true; -} - -PRAGMA6(GCC diagnostic push) -PRAGMA6(GCC diagnostic ignored "-Wnull-dereference") -impHandler0(error) -{ - int *const ptr = nullptr; - *(ptr + 1) = 20; -// logger->log("test %d", *ptr); - exit(1); -} -PRAGMA6(GCC diagnostic pop) - -impHandler(dumpGraphics) -{ - std::string str = strprintf("%s,%s,%dX%dX%d,", PACKAGE_OS, SMALL_VERSION, - mainGraphics->getWidth(), mainGraphics->getHeight(), - mainGraphics->getBpp()); - - if (mainGraphics->getFullScreen()) - str.append("F"); - else - str.append("W"); - if (mainGraphics->getHWAccel()) - str.append("H"); - else - str.append("S"); - - if (mainGraphics->getDoubleBuffer()) - str.append("D"); - else - str.append("_"); - -#if defined USE_OPENGL - str.append(strprintf(",%d", mainGraphics->getOpenGL())); -#else // defined USE_OPENGL - - str.append(",0"); -#endif // defined USE_OPENGL - - str.append(strprintf(",%f,", static_cast(settings.guiAlpha))) - .append(config.getBoolValue("adjustPerfomance") ? "1" : "0") - .append(config.getBoolValue("alphaCache") ? "1" : "0") - .append(config.getBoolValue("enableMapReduce") ? "1" : "0") - .append(config.getBoolValue("beingopacity") ? "1" : "0") - .append(",") - .append(config.getBoolValue("enableAlphaFix") ? "1" : "0") - .append(config.getBoolValue("disableAdvBeingCaching") ? "1" : "0") - .append(config.getBoolValue("disableBeingCaching") ? "1" : "0") - .append(config.getBoolValue("particleeffects") ? "1" : "0") - .append(strprintf(",%d-%d", fps, config.getIntValue("fpslimit"))); - outStringNormal(event.tab, str, str); - return true; -} - -impHandler0(dumpEnvironment) -{ - logger->log1("Start environment variables"); - for (char **env = environ; *env != nullptr; ++ env) - logger->log1(*env); - logger->log1("End environment variables"); - if (debugChatTab != nullptr) - { - // TRANSLATORS: dump environment command - debugChatTab->chatLog(_("Environment variables dumped"), - ChatMsgType::BY_SERVER); - } - return true; -} - -impHandler(dumpTests) -{ - const std::string str = config.getStringValue("testInfo"); - outStringNormal(event.tab, str, str); - return true; -} - -impHandler0(dumpOGL) -{ -#if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__native_client__) - NormalOpenGLGraphics::dumpSettings(); -#endif // defined(USE_OPENGL) && !defined(ANDROID) && - // !defined(__native_client__) - - return true; -} - -#ifdef USE_OPENGL -impHandler(dumpGL) -{ - std::string str = graphicsManager.getGLVersion(); - outStringNormal(event.tab, str, str); - return true; -} -#else // USE_OPENGL - -impHandler0(dumpGL) -{ - return true; -} -#endif // USE_OPENGL - -impHandler(dumpMods) -{ - std::string str = "enabled mods: " + serverConfig.getValue("mods", ""); - outStringNormal(event.tab, str, str); - return true; -} - -#if defined USE_OPENGL && defined DEBUG_SDLFONT -impHandler0(testSdlFont) -{ - Font *font = new Font("fonts/dejavusans.ttf", 18); - timespec time1; - timespec time2; - NullOpenGLGraphics *nullGraphics = new NullOpenGLGraphics; - STD_VECTOR data; - volatile int width = 0; - - for (int f = 0; f < 300; f ++) - data.push_back("test " + toString(f) + "string"); - nullGraphics->beginDraw(); - - clock_gettime(CLOCK_MONOTONIC, &time1); - Color color(0, 0, 0, 255); - - for (int f = 0; f < 500; f ++) - { - FOR_EACH (STD_VECTOR::const_iterator, it, data) - { - width += font->getWidth(*it); - font->drawString(nullGraphics, color, color, *it, 10, 10); - } - FOR_EACH (STD_VECTOR::const_iterator, it, data) - font->drawString(nullGraphics, color, color, *it, 10, 10); - - font->doClean(); - } - - clock_gettime(CLOCK_MONOTONIC, &time2); - - delete nullGraphics; - delete font; - - int64_t diff = (static_cast( - time2.tv_sec) * 1000000000LL + static_cast( - time2.tv_nsec)) / 100000 - (static_cast( - time1.tv_sec) * 1000000000LL + static_cast( - time1.tv_nsec)) / 100000; - if (debugChatTab) - { - debugChatTab->chatLog("sdlfont time: " + toString(diff), - ChatMsgType::BY_SERVER); - } - return true; -} -#endif // defined USE_OPENGL && defined DEBUG_SDLFONT - -impHandler0(createItems) -{ - BuyDialog *const dialog = CREATEWIDGETR0(BuyDialog); - const ItemDB::ItemInfos &items = ItemDB::getItemInfos(); - FOR_EACH (ItemDB::ItemInfos::const_iterator, it, items) - { - const ItemInfo *const info = (*it).second; - if (info == nullptr) - continue; - const int id = info->getId(); - if (id <= 500) - continue; - - dialog->addItem(id, - ItemType::Unknown, - ItemColor_one, - 100, - 0); - } - dialog->sort(); - return true; -} - -impHandler(createItem) -{ - int id = 0; - int amount = 0; - - if (adminHandler == nullptr) - return false; - - if (parse2Int(event.args, id, amount)) - adminHandler->createItems(id, ItemColor_one, amount); - else - adminHandler->createItems(atoi(event.args.c_str()), ItemColor_one, 1); - return true; -} - -impHandler(uploadConfig) -{ - // TRANSLATORS: upload config chat message - uploadFile(_("Uploaded config into:"), - config.getFileName(), - "?xml", - event.tab); - return true; -} - -impHandler(uploadServerConfig) -{ - // TRANSLATORS: upload config chat message - uploadFile(_("Uploaded server config into:"), - serverConfig.getFileName(), - "?xml", - event.tab); - return true; -} - -impHandler(uploadLog) -{ - // TRANSLATORS: upload log chat message - uploadFile(_("Uploaded log into:"), - settings.logFileName, - "?txt", - event.tab); - return true; -} - -impHandler0(mercenaryFire) -{ - if (mercenaryHandler != nullptr) - mercenaryHandler->fire(); - return true; -} - -impHandler0(mercenaryToMaster) -{ - if (mercenaryHandler != nullptr) - mercenaryHandler->moveToMaster(); - return true; -} - -impHandler0(homunculusToMaster) -{ - if (homunculusHandler != nullptr) - homunculusHandler->moveToMaster(); - return true; -} - -impHandler0(homunculusFeed) -{ - if (homunculusHandler != nullptr) - homunculusHandler->feed(); - return true; -} - -impHandler(useItem) -{ - const int itemId = atoi(event.args.c_str()); - - if (itemId < SPELL_MIN_ID) - { - const Inventory *const inv = PlayerInfo::getInventory(); - if (inv != nullptr) - { - // +++ ignoring item color for now - const Item *const item = inv->findItem(itemId, - ItemColor_one); - PlayerInfo::useEquipItem(item, 0, Sfx_true); - } - } - else if (itemId < SKILL_MIN_ID && (spellManager != nullptr)) - { - spellManager->useItem(itemId); - } - else if (skillDialog != nullptr) - { - // +++ probably need get data parameter from args - skillDialog->useItem(itemId, - fromBool(config.getBoolValue("skillAutotarget"), AutoTarget), - 0, - std::string()); - } - return true; -} - -impHandler(useItemInv) -{ - int param1 = 0; - int param2 = 0; - const std::string args = event.args; - if (parse2Int(args, param1, param2)) - { - Item *const item = getItemByInvIndex(param1, - InventoryType::Inventory); - PlayerInfo::useEquipItem(item, CAST_S16(param2), Sfx_true); - } - else - { - Item *const item = getItemByInvIndex(atoi(event.args.c_str()), - InventoryType::Inventory); - PlayerInfo::useEquipItem(item, 0, Sfx_true); - } - return true; -} - -impHandler(invToStorage) -{ - Item *item = nullptr; - const int amount = getAmountFromEvent(event, item, - InventoryType::Inventory); - if (item == nullptr) - return true; - if (amount != 0) - { - if (inventoryHandler != nullptr) - { - inventoryHandler->moveItem2(InventoryType::Inventory, - item->getInvIndex(), - amount, - InventoryType::Storage); - } - } - else - { - ItemAmountWindow::showWindow(ItemAmountWindowUsage::StoreAdd, - inventoryWindow, item); - } - return true; -} - -impHandler(tradeAdd) -{ - Item *item = nullptr; - const int amount = getAmountFromEvent(event, item, - InventoryType::Inventory); - if ((item == nullptr) || PlayerInfo::isItemProtected(item->getId())) - return true; - - if (amount != 0) - { - if (tradeWindow != nullptr) - tradeWindow->tradeItem(item, amount, true); - } - else - { - ItemAmountWindow::showWindow(ItemAmountWindowUsage::TradeAdd, - tradeWindow, item); - } - return true; -} - -impHandler(storageToInv) -{ - Item *item = nullptr; - const int amount = getAmountFromEvent(event, item, InventoryType::Storage); - if (amount != 0) - { - if ((inventoryHandler != nullptr) && (item != nullptr)) - { - inventoryHandler->moveItem2(InventoryType::Storage, - item->getInvIndex(), - amount, - InventoryType::Inventory); - } - } - else - { - ItemAmountWindow::showWindow(ItemAmountWindowUsage::StoreRemove, - storageWindow, item); - } - return true; -} - -impHandler(protectItem) -{ - const int id = atoi(event.args.c_str()); - if (id > 0) - PlayerInfo::protectItem(id); - return true; -} - -impHandler(unprotectItem) -{ - const int id = atoi(event.args.c_str()); - if (id > 0) - PlayerInfo::unprotectItem(id); - return true; -} - -impHandler(kick) -{ - if ((localPlayer == nullptr) || (actorManager == nullptr)) - return false; - - Being *target = nullptr; - std::string args = event.args; - if (!args.empty()) - { - if (args[0] != ':') - { - target = actorManager->findNearestByName(args); - } - else - { - target = actorManager->findBeing(fromInt(atoi( - args.substr(1).c_str()), BeingId)); - } - } - if (target == nullptr) - target = localPlayer->getTarget(); - if ((target != nullptr) && (adminHandler != nullptr)) - adminHandler->kick(target->getId()); - return true; -} - -impHandler0(clearDrop) -{ - if (dropShortcut != nullptr) - dropShortcut->clear(); - return true; -} - -impHandler0(testInfo) -{ - if (actorManager != nullptr) - { - logger->log("actors count: %d", CAST_S32( - actorManager->size())); - return true; - } - return false; -} - -impHandler(craftKey) -{ - const int slot = (event.action - InputAction::CRAFT_1); - if (slot >= 0 && slot < 9) - { - if (inventoryWindow != nullptr) - inventoryWindow->moveItemToCraft(slot); - return true; - } - return false; -} - -impHandler0(resetGameModifiers) -{ - GameModifiers::resetModifiers(); - return true; -} - -impHandler(barToChat) -{ - if (chatWindow != nullptr) - { - chatWindow->addInputText(event.args); - return true; - } - return false; -} - -impHandler(seen) -{ - if (actorManager == nullptr) - return false; - - ChatTab *tab = event.tab; - if (tab == nullptr) - tab = localChatTab; - if (tab == nullptr) - return false; - - if (config.getBoolValue("enableIdCollecting") == false) - { - // TRANSLATORS: last seen disabled warning - tab->chatLog(_("Last seen disabled. " - "Enable in players / collect players id and seen log."), - ChatMsgType::BY_SERVER); - return true; - } - - const std::string name = event.args; - if (name.empty()) - return false; - - std::string dir = settings.usersDir; - dir.append(stringToHexPath(name)).append("/seen.txt"); - if (Files::existsLocal(dir)) - { - StringVect lines; - Files::loadTextFileLocal(dir, lines); - if (lines.size() < 3) - { - // TRANSLATORS: last seen error - tab->chatLog(_("You not saw this nick."), - ChatMsgType::BY_SERVER); - return true; - } - const std::string message = strprintf( - // TRANSLATORS: last seen message - _("Last seen for %s: %s"), - name.c_str(), - lines[2].c_str()); - tab->chatLog(message, ChatMsgType::BY_SERVER); - } - else - { - // TRANSLATORS: last seen error - tab->chatLog(_("You not saw this nick."), - ChatMsgType::BY_SERVER); - } - - return true; -} - -impHandler(dumpMemoryUsage) -{ - if (event.tab != nullptr) - memoryManager.printAllMemory(event.tab); - else - memoryManager.printAllMemory(localChatTab); - return true; -} - -impHandler(setEmoteType) -{ - const std::string &args = event.args; - if (args == "player" || args.empty()) - { - settings.emoteType = EmoteType::Player; - } - else if (args == "pet") - { - settings.emoteType = EmoteType::Pet; - } - else if (args == "homun" || args == "homunculus") - { - settings.emoteType = EmoteType::Homunculus; - } - else if (args == "merc" || args == "mercenary") - { - settings.emoteType = EmoteType::Mercenary; - } - return true; -} - -} // namespace Actions diff --git a/src/actions/chat.cpp b/src/actions/chat.cpp deleted file mode 100644 index 307e4556e..000000000 --- a/src/actions/chat.cpp +++ /dev/null @@ -1,808 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/chat.h" - -#include "configuration.h" - -#include "actions/actiondef.h" - -#include "const/gui/chat.h" - -#include "being/localplayer.h" - -#include "gui/sdlinput.h" - -#include "gui/windows/chatwindow.h" - -#include "listeners/inputactionreplaylistener.h" - -#include "net/charserverhandler.h" -#include "net/chathandler.h" -#include "net/guildhandler.h" -#include "net/net.h" -#include "net/partyhandler.h" - -#ifdef TMWA_SUPPORT -#include "net/tmwa/guildmanager.h" -#endif // TMWA_SUPPORT - -#include "resources/iteminfo.h" - -#include "resources/db/itemdb.h" - -#include "utils/booleanoptions.h" -#include "utils/chatutils.h" -#include "utils/parameters.h" - -#include "utils/translation/podict.h" - -#include "debug.h" - -const int DEFAULT_CHAT_WINDOW_SCROLL = 7; - -namespace Actions -{ - -static void outString(ChatTab *const tab, - const std::string &str, - const std::string &def) -{ - if (tab == nullptr) - { - if (chatHandler != nullptr) - chatHandler->talk(def, GENERAL_CHANNEL); - return; - } - - switch (tab->getType()) - { - case ChatTabType::PARTY: - { - if (partyHandler != nullptr) - partyHandler->chat(str); - break; - } - case ChatTabType::GUILD: - { - if ((guildHandler == nullptr) || (localPlayer == nullptr)) - return; - const Guild *const guild = localPlayer->getGuild(); - if (guild != nullptr) - { -#ifdef TMWA_SUPPORT - if (guild->getServerGuild()) - { - if (Net::getNetworkType() == ServerType::TMWATHENA) - return; - guildHandler->chat(str); - } - else if (guildManager != nullptr) - { - guildManager->chat(str); - } -#else // TMWA_SUPPORT - - if (guild->getServerGuild()) - guildHandler->chat(str); -#endif // TMWA_SUPPORT - } - break; - } - case ChatTabType::CHANNEL: - case ChatTabType::GM: - case ChatTabType::TRADE: - tab->chatInput(str); - break; - default: - case ChatTabType::UNKNOWN: - case ChatTabType::INPUT: - case ChatTabType::WHISPER: - case ChatTabType::DEBUG: - case ChatTabType::BATTLE: - case ChatTabType::LANG: - if (chatHandler != nullptr) - chatHandler->talk(str, GENERAL_CHANNEL); - break; - } -} - -impHandler0(toggleChat) -{ - return chatWindow != nullptr ? chatWindow->requestChatFocus() : false; -} - -impHandler0(prevChatTab) -{ - if (chatWindow != nullptr) - { - chatWindow->prevTab(); - return true; - } - return false; -} - -impHandler0(nextChatTab) -{ - if (chatWindow != nullptr) - { - chatWindow->nextTab(); - return true; - } - return false; -} - -impHandler0(closeChatTab) -{ - if (chatWindow != nullptr) - { - chatWindow->closeTab(); - return true; - } - return false; -} - -impHandler0(closeAllChatTabs) -{ - if (chatWindow != nullptr) - { - chatWindow->removeAllWhispers(); - chatWindow->saveState(); - return true; - } - return false; -} - -impHandler0(ignoreAllWhispers) -{ - if (chatWindow != nullptr) - { - chatWindow->ignoreAllWhispers(); - chatWindow->saveState(); - return true; - } - return false; -} - -impHandler0(scrollChatUp) -{ - if ((chatWindow != nullptr) && chatWindow->isWindowVisible()) - { - chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL); - return true; - } - return false; -} - -impHandler0(scrollChatDown) -{ - if ((chatWindow != nullptr) && chatWindow->isWindowVisible()) - { - chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL); - return true; - } - return false; -} - -static bool splitWhisper(const std::string &args, - std::string &recvnick, - std::string &message) -{ - if (args.substr(0, 1) == "\"") - { - const size_t pos = args.find('"', 1); - if (pos != std::string::npos) - { - recvnick = args.substr(1, pos - 1); - if (pos + 2 < args.length()) - message = args.substr(pos + 2, args.length()); - } - } - else - { - const size_t pos = args.find(' '); - if (pos != std::string::npos) - { - recvnick = args.substr(0, pos); - if (pos + 1 < args.length()) - message = args.substr(pos + 1, args.length()); - } - else - { - recvnick = std::string(args); - message.clear(); - } - } - - trim(message); - - if (message.length() > 0) - { - std::string playerName = localPlayer->getName(); - std::string tempNick = recvnick; - - toLower(playerName); - toLower(tempNick); - - if (tempNick == playerName || args.empty()) - return false; - - return true; - } - return false; -} - -impHandler(msg) -{ - std::string recvnick; - std::string message; - - if (splitWhisper(event.args, recvnick, message)) - { - if (chatWindow == nullptr) - return false; - ChatTab *const tab = chatWindow->addChatTab(recvnick, false, true); - if (tab != nullptr) - { - chatWindow->saveState(); - tab->chatInput(message); - } - } - else - { - if (event.tab != nullptr) - { - event.tab->chatLog( - // TRANSLATORS: whisper send - _("Cannot send empty whisper or channel message!"), - ChatMsgType::BY_SERVER); - } - } - return true; -} - -impHandler(msgText) -{ - if (chatWindow == nullptr) - return false; - - if (config.getBoolValue("whispertab")) - { - chatWindow->localChatInput("/q " + event.args); - } - else - { - chatWindow->addInputText(std::string("/w \"").append( - event.args).append("\" ")); - } - return true; -} - -impHandler(msg2) -{ - std::string recvnick; - std::string message; - - if (chatHandler != nullptr && - splitWhisper(event.args, recvnick, message)) - { - chatHandler->privateMessage(recvnick, message); - } - return true; -} - -impHandler(query) -{ - const std::string &args = event.args; - if (chatWindow != nullptr) - { - if (chatWindow->addChatTab(args, true, true) != nullptr) - { - chatWindow->saveState(); - return true; - } - } - - if (event.tab != nullptr) - { - // TRANSLATORS: new whisper or channel query - event.tab->chatLog(strprintf(_("Cannot create a whisper tab " - "\"%s\"! It probably already exists."), - args.c_str()), ChatMsgType::BY_SERVER); - } - return true; -} - -impHandler0(clearChatTab) -{ - if (chatWindow != nullptr) - { - chatWindow->clearTab(); - return true; - } - return false; -} - -impHandler(createParty) -{ - if (partyHandler == nullptr) - return false; - - if (event.args.empty()) - { - // TRANSLATORS: dialog header - inputActionReplayListener.openDialog(_("Create party"), - "", - InputAction::CREATE_PARTY); - } - else - { - partyHandler->create(event.args); - } - return true; -} - -impHandler(createGuild) -{ - if ((guildHandler == nullptr) || - Net::getNetworkType() == ServerType::TMWATHENA) - { - return false; - } - - if (event.args.empty()) - { - // TRANSLATORS: dialog header - inputActionReplayListener.openDialog(_("Create guild"), - "", - InputAction::CREATE_GUILD); - } - else - { - guildHandler->create(event.args); - } - return true; -} - -impHandler(party) -{ - if (!event.args.empty()) - { - if (partyHandler != nullptr) - partyHandler->invite(event.args); - } - else - { - if (event.tab != nullptr) - { - // TRANSLATORS: party invite message - event.tab->chatLog(_("Please specify a name."), - ChatMsgType::BY_SERVER); - } - } - return true; -} - -impHandler(guild) -{ - if ((guildHandler == nullptr) || (localPlayer == nullptr)) - return false; - - const std::string args = event.args; - if (!args.empty()) - { - const Guild *const guild = localPlayer->getGuild(); - if (guild != nullptr) - { -#ifdef TMWA_SUPPORT - if (guild->getServerGuild()) - guildHandler->invite(args); - else if (guildManager != nullptr) - GuildManager::invite(args); -#else // TMWA_SUPPORT - - guildHandler->invite(args); -#endif // TMWA_SUPPORT - } - } - else - { - if (event.tab != nullptr) - { - // TRANSLATORS: guild invite message - event.tab->chatLog(_("Please specify a name."), - ChatMsgType::BY_SERVER); - } - else if (localChatTab != nullptr) - { - // TRANSLATORS: guild invite message - localChatTab->chatLog(_("Please specify a name."), - ChatMsgType::BY_SERVER); - } - } - return true; -} - -impHandler(me) -{ - outString(event.tab, textToMe(event.args), event.args); - return true; -} - -impHandler(toggle) -{ - if (event.args.empty()) - { - if ((chatWindow != nullptr) && (event.tab != nullptr)) - { - event.tab->chatLog(chatWindow->getReturnTogglesChat() ? - // TRANSLATORS: message from toggle chat command - _("Return toggles chat.") : _("Message closes chat."), - ChatMsgType::BY_SERVER); - } - return true; - } - - switch (parseBoolean(event.args)) - { - case 1: - if (event.tab != nullptr) - { - // TRANSLATORS: message from toggle chat command - event.tab->chatLog(_("Return now toggles chat."), - ChatMsgType::BY_SERVER); - } - if (chatWindow != nullptr) - chatWindow->setReturnTogglesChat(true); - return true; - case 0: - if (event.tab != nullptr) - { - // TRANSLATORS: message from toggle chat command - event.tab->chatLog(_("Message now closes chat."), - ChatMsgType::BY_SERVER); - } - if (chatWindow != nullptr) - chatWindow->setReturnTogglesChat(false); - return true; - case -1: - if (event.tab != nullptr) - { - event.tab->chatLog(strprintf(BOOLEAN_OPTIONS, "toggle"), - ChatMsgType::BY_SERVER); - } - return true; - default: - return true; - } -} - -impHandler(kickParty) -{ - if (!event.args.empty()) - { - if (partyHandler != nullptr) - partyHandler->kick(event.args); - } - else - { - if (event.tab != nullptr) - { - // TRANSLATORS: party kick message - event.tab->chatLog(_("Please specify a name."), - ChatMsgType::BY_SERVER); - } - } - return true; -} - -impHandler(kickGuild) -{ - if (!event.args.empty()) - { - if (localPlayer != nullptr) - { - const Guild *const guild = localPlayer->getGuild(); - if (guild != nullptr) - { - if (guild->getServerGuild()) - { - if (guildHandler != nullptr) - guildHandler->kick(guild->getMember(event.args), ""); - } -#ifdef TMWA_SUPPORT - else if (guildManager != nullptr) - { - GuildManager::kick(event.args); - } -#endif // TMWA_SUPPORT - } - } - } - else - { - if (event.tab != nullptr) - { - // TRANSLATORS: party kick message - event.tab->chatLog(_("Please specify a name."), - ChatMsgType::BY_SERVER); - } - } - return true; -} - -impHandler(addText) -{ - if (chatWindow != nullptr) - chatWindow->addInputText(event.args); - return true; -} - -impHandler0(clearChat) -{ - if (chatWindow != nullptr) - chatWindow->clearTab(); - return true; -} - -impHandler0(chatGeneralTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::INPUT); - return true; -} - -impHandler0(chatDebugTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::DEBUG); - return true; -} - -impHandler0(chatBattleTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::BATTLE); - return true; -} - -impHandler0(chatTradeTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::TRADE); - return true; -} - -impHandler0(chatLangTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::LANG); - return true; -} - -impHandler0(chatGmTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::GM); - return true; -} - -impHandler0(chatPartyTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::PARTY); - return true; -} - -impHandler0(chatGuildTab) -{ - if (chatWindow != nullptr) - chatWindow->selectTabByType(ChatTabType::GUILD); - return true; -} - -impHandler(hat) -{ - if ((localPlayer == nullptr) || (charServerHandler == nullptr)) - return false; - - const int sprite = localPlayer->getSpriteID( - charServerHandler->hatSprite()); - std::string str; - if (sprite == 0) - { - // TRANSLATORS: equipped hat chat message - str = strprintf(_("no hat equipped.")); - } - else - { - const ItemInfo &info = ItemDB::get(sprite); - // TRANSLATORS: equipped hat chat message - str = strprintf(_("equipped hat %s."), - info.getName().c_str()); - } - outString(event.tab, str, str); - return true; -} - -impHandler(chatClipboard) -{ - int x = 0; - int y = 0; - - if ((chatWindow != nullptr) && parse2Int(event.args, x, y)) - { - chatWindow->copyToClipboard(x, y); - return true; - } - return false; -} - -impHandler(guildNotice) -{ - if (localPlayer == nullptr) - return false; - const std::string args = event.args; - if (args.empty()) - { - // TRANSLATORS: dialog header - inputActionReplayListener.openDialog(_("Guild notice"), - "", - InputAction::GUILD_NOTICE); - return true; - } - - std::string str2; - if (args.size() > 60) - str2 = args.substr(60); - const Guild *const guild = localPlayer->getGuild(); - if (guild != nullptr) - { - guildHandler->changeNotice(guild->getId(), - args.substr(0, 60), - str2); - } - return true; -} - -impHandler(translate) -{ - if (reverseDictionary == nullptr || - localPlayer == nullptr || - event.args.empty()) - { - return false; - } - - ChatTab *const tab = event.tab; - if (tab == nullptr) - return false; - - std::string srcStr = event.args; - std::string enStr; - toLower(srcStr); - if (localPlayer->getLanguageId() > 0) - { - if (reverseDictionary->haveStr(srcStr)) - enStr = reverseDictionary->getStr(srcStr); - else if (dictionary->haveStr(srcStr)) - enStr = srcStr; - } - else - { - if (dictionary->haveStr(srcStr)) - enStr = srcStr; - } - - if (enStr.empty()) - { - tab->chatLog( - // TRANSLATORS: translation error message - strprintf(_("No translation found for string: %s"), - srcStr.c_str()), - ChatMsgType::BY_SERVER); - return true; - } - - tab->chatInput(enStr); - return true; -} - -impHandler(sendGuiKey) -{ - if (guiInput == nullptr) - return false; - - const std::string args = event.args; - if (args.empty()) - return false; - StringVect pars; - if (!splitParameters(pars, args, " ,", '\"')) - return false; - const int sz = CAST_S32(pars.size()); - if (sz < 1) - return false; - - int keyValue = atoi(pars[0].c_str()); - if (keyValue == 0 && - pars[0].size() == 1) - { - keyValue = CAST_S32(pars[0][0]); - } - if (sz == 2) - { - const InputActionT actionId = inputManager.getActionByConfigField( - pars[1]); - guiInput->simulateKey(keyValue, actionId); - } - else - { - guiInput->simulateKey(keyValue, InputAction::NO_VALUE); - } - return true; -} - -impHandler(sendMouseKey) -{ - if (guiInput == nullptr) - return false; - const std::string args = event.args; - if (args.empty()) - return false; - StringVect pars; - if (!splitParameters(pars, args, " ,", '\"')) - return false; - const int sz = CAST_S32(pars.size()); - if (sz != 3) - return false; - - const int x = atoi(pars[0].c_str()); - const int y = atoi(pars[1].c_str()); - const int key1 = CAST_S32(MouseButton::LEFT); - const int key2 = CAST_S32(MouseButton::MIDDLE); - const int key = atoi(pars[2].c_str()); - if (key < key1 || key > key2) - return false; - guiInput->simulateMouseClick(x, - y, - static_cast(key)); - return true; -} - -impHandler(sendChars) -{ - if (guiInput == nullptr) - return false; - - const std::string args = event.args; - if (args.empty()) - return false; - - const size_t sz = args.size(); - for (size_t f = 0; f < sz; f ++) - { - guiInput->simulateKey(CAST_S32(args[f]), - InputAction::NO_VALUE); - } - - return true; -} - -} // namespace Actions diff --git a/src/actions/commands.cpp b/src/actions/commands.cpp deleted file mode 100644 index f2d49b13b..000000000 --- a/src/actions/commands.cpp +++ /dev/null @@ -1,2156 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/commands.h" - -#include "actormanager.h" -#include "configuration.h" -#include "game.h" -#include "party.h" - -#include "actions/actiondef.h" - -#include "being/flooritem.h" -#include "being/localplayer.h" -#include "being/playerrelations.h" -#include "being/homunculusinfo.h" -#include "being/playerinfo.h" - -#include "const/resources/skill.h" - -#include "gui/viewport.h" - -#include "gui/popups/popupmenu.h" - -#include "gui/shortcut/emoteshortcut.h" -#include "gui/shortcut/itemshortcut.h" - -#include "gui/windows/mailwindow.h" - -#include "gui/windows/chatwindow.h" -#include "gui/windows/inventorywindow.h" -#include "gui/windows/npcdialog.h" -#include "gui/windows/outfitwindow.h" -#include "gui/windows/shortcutwindow.h" -#include "gui/windows/skilldialog.h" -#include "gui/windows/socialwindow.h" - -#include "gui/widgets/tabs/chat/whispertab.h" - -#include "input/inputactionoperators.h" - -#include "listeners/inputactionreplaylistener.h" - -#include "net/adminhandler.h" -#include "net/chathandler.h" -#include "net/guildhandler.h" -#include "net/familyhandler.h" -#include "net/homunculushandler.h" -#include "net/mail2handler.h" -#include "net/mailhandler.h" -#include "net/net.h" -#include "net/npchandler.h" -#include "net/partyhandler.h" -#include "net/serverfeatures.h" - -#include "resources/chatobject.h" - -#include "resources/db/itemdb.h" - -#include "resources/map/map.h" - -#include "resources/skill/skillinfo.h" - -#include "utils/booleanoptions.h" -#include "utils/chatutils.h" -#include "utils/copynpaste.h" -#include "utils/gmfunctions.h" -#include "utils/parameters.h" -#include "utils/process.h" - -#include "debug.h" - -namespace Actions -{ - -static std::string getNick(const InputEvent &event) -{ - std::string args = event.args; - if (args.empty()) - { - if (event.tab == nullptr || - event.tab->getType() != ChatTabType::WHISPER) - { - return std::string(); - } - - WhisperTab *const whisper = static_cast(event.tab); - if (whisper->getNick().empty()) - { - // TRANSLATORS: change relation - event.tab->chatLog(_("Please specify a name."), - ChatMsgType::BY_SERVER); - return std::string(); - } - args = whisper->getNick(); - } - return args; -} - -static void reportRelation(const InputEvent &event, - const RelationT &rel, - const std::string &str1, - const std::string &str2) -{ - if (event.tab != nullptr) - { - if (playerRelations.getRelation(event.args) == rel) - { - // TRANSLATORS: unignore command - event.tab->chatLog(str1, ChatMsgType::BY_SERVER); - } - else - { - // TRANSLATORS: unignore command - event.tab->chatLog(str2, ChatMsgType::BY_SERVER); - } - } -} - -static void changeRelation(const InputEvent &event, - const RelationT relation, - const std::string &relationText) -{ - std::string args = getNick(event); - if (args.empty()) - return; - - if (playerRelations.getRelation(args) == relation) - { - if (event.tab != nullptr) - { - // TRANSLATORS: change relation - event.tab->chatLog(strprintf(_("Player already %s!"), - relationText.c_str()), ChatMsgType::BY_SERVER); - return; - } - } - else - { - playerRelations.setRelation(args, relation); - } - - reportRelation(event, - relation, - // TRANSLATORS: change relation - strprintf(_("Player successfully %s!"), relationText.c_str()), - // TRANSLATORS: change relation - strprintf(_("Player could not be %s!"), relationText.c_str())); -} - -impHandler(chatAnnounce) -{ - if (adminHandler != nullptr) - { - adminHandler->announce(event.args); - return true; - } - return false; -} - -impHandler(chatIgnore) -{ - changeRelation(event, Relation::IGNORED, "ignored"); - return true; -} - -impHandler(chatUnignore) -{ - std::string args = getNick(event); - if (args.empty()) - return false; - - const RelationT rel = playerRelations.getRelation(args); - if (rel != Relation::NEUTRAL && rel != Relation::FRIEND) - { - playerRelations.setRelation(args, Relation::NEUTRAL); - } - else - { - if (event.tab != nullptr) - { - // TRANSLATORS: unignore command - event.tab->chatLog(_("Player wasn't ignored!"), - ChatMsgType::BY_SERVER); - } - return true; - } - - reportRelation(event, - Relation::NEUTRAL, - // TRANSLATORS: unignore command - _("Player no longer ignored!"), - // TRANSLATORS: unignore command - _("Player could not be unignored!")); - return true; -} - -impHandler(chatErase) -{ - std::string args = getNick(event); - if (args.empty()) - return false; - - if (playerRelations.getRelation(args) == Relation::ERASED) - { - if (event.tab != nullptr) - { - // TRANSLATORS: erase command - event.tab->chatLog(_("Player already erased!"), - ChatMsgType::BY_SERVER); - } - return true; - } - playerRelations.setRelation(args, Relation::ERASED); - - reportRelation(event, - Relation::ERASED, - // TRANSLATORS: erase command - _("Player no longer erased!"), - // TRANSLATORS: erase command - _("Player could not be erased!")); - return true; -} - -impHandler(chatFriend) -{ - // TRANSLATORS: adding friend command - changeRelation(event, Relation::FRIEND, _("friend")); - return true; -} - -impHandler(chatDisregard) -{ - // TRANSLATORS: disregard command - changeRelation(event, Relation::DISREGARDED, _("disregarded")); - return true; -} - -impHandler(chatNeutral) -{ - // TRANSLATORS: neutral command - changeRelation(event, Relation::NEUTRAL, _("neutral")); - return true; -} - -impHandler(chatBlackList) -{ - // TRANSLATORS: blacklist command - changeRelation(event, Relation::BLACKLISTED, _("blacklisted")); - return true; -} - -impHandler(chatEnemy) -{ - // TRANSLATORS: enemy command - changeRelation(event, Relation::ENEMY2, _("enemy")); - return true; -} - -impHandler(chatNuke) -{ - if (actorManager == nullptr) - return false; - - const std::string nick = getNick(event); - Being *const being = actorManager->findBeingByName( - nick, ActorType::Player); - if (being == nullptr) - return true; - - actorManager->addBlock(being->getId()); - actorManager->destroy(being); - return true; -} - -impHandler(chatAdd) -{ - if (chatWindow == nullptr) - return false; - - if (event.args.empty()) - return true; - - STD_VECTOR str; - splitToIntVector(str, event.args, ','); - if (str.empty()) - return true; - - int id = str[0]; - if (id == 0) - return true; - - if (ItemDB::exists(id)) - { - const std::string names = ItemDB::getNamesStr(str); - if (!names.empty()) - chatWindow->addItemText(names); - return true; - } - - const FloorItem *const floorItem = actorManager->findItem( - fromInt(id, BeingId)); - - if (floorItem != nullptr) - { - str[0] = floorItem->getItemId(); - const std::string names = ItemDB::getNamesStr(str); - chatWindow->addItemText(names); - } - return true; -} - -impHandler0(present) -{ - if (chatWindow != nullptr) - { - chatWindow->doPresent(); - return true; - } - return false; -} - -impHandler0(printAll) -{ - if (actorManager != nullptr) - { - actorManager->printAllToChat(); - return true; - } - return false; -} - -impHandler(move) -{ - int x = 0; - int y = 0; - - if ((localPlayer != nullptr) && parse2Int(event.args, x, y)) - { - localPlayer->setDestination(x, y); - return true; - } - return false; -} - -impHandler(setTarget) -{ - if ((actorManager == nullptr) || (localPlayer == nullptr)) - return false; - - Being *const target = actorManager->findNearestByName(event.args); - if (target != nullptr) - localPlayer->setTarget(target); - return true; -} - -impHandler(commandOutfit) -{ - if (outfitWindow != nullptr) - { - if (!event.args.empty()) - { - const std::string op = event.args.substr(0, 1); - if (op == "n") - { - outfitWindow->wearNextOutfit(true); - } - else if (op == "p") - { - outfitWindow->wearPreviousOutfit(true); - } - else - { - outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1, - false, true); - } - } - else - { - outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1, - false, true); - } - return true; - } - return false; -} - -impHandler(commandEmote) -{ - LocalPlayer::emote(CAST_U8(atoi(event.args.c_str()))); - return true; -} - -impHandler(awayMessage) -{ - if (localPlayer != nullptr) - { - localPlayer->setAway(event.args); - return true; - } - return false; -} - -impHandler(pseudoAway) -{ - if (localPlayer != nullptr) - { - LocalPlayer::setPseudoAway(event.args); - localPlayer->updateStatus(); - return true; - } - return false; -} - -impHandler(follow) -{ - if (localPlayer == nullptr) - return false; - - if (!features.getBoolValue("allowFollow")) - return false; - - if (!event.args.empty()) - { - localPlayer->setFollow(event.args); - } - else if (event.tab != nullptr && - event.tab->getType() == ChatTabType::WHISPER) - { - localPlayer->setFollow(static_cast(event.tab)->getNick()); - } - else - { - const Being *const being = localPlayer->getTarget(); - if (being != nullptr) - localPlayer->setFollow(being->getName()); - } - return true; -} - -impHandler(navigate) -{ - if ((localPlayer == nullptr) || - !localPlayer->canMove()) - { - return false; - } - - int x = 0; - int y = 0; - - if (parse2Int(event.args, x, y)) - localPlayer->navigateTo(x, y); - else - localPlayer->navigateClean(); - return true; -} - -impHandler(navigateTo) -{ - if ((localPlayer == nullptr) || - !localPlayer->canMove()) - { - return false; - } - - const std::string args = event.args; - if (args.empty()) - return true; - - Being *const being = actorManager->findBeingByName(args); - if (being != nullptr) - { - localPlayer->navigateTo(being->getTileX(), being->getTileY()); - } - else if (localPlayer->isInParty()) - { - const Party *const party = localPlayer->getParty(); - if (party != nullptr) - { - const PartyMember *const m = party->getMember(args); - const PartyMember *const o = party->getMember( - localPlayer->getName()); - if (m != nullptr && - o != nullptr && - m->getMap() == o->getMap()) - { - localPlayer->navigateTo(m->getX(), m->getY()); - } - } - } - return true; -} - -impHandler(moveCamera) -{ - int x = 0; - int y = 0; - - if (viewport == nullptr) - return false; - - if (parse2Int(event.args, x, y)) - viewport->moveCameraToPosition(x * mapTileSize, y * mapTileSize); - return true; -} - -impHandler0(restoreCamera) -{ - if (viewport == nullptr) - return false; - - viewport->returnCamera(); - return true; -} - -impHandler(imitation) -{ - if (localPlayer == nullptr) - return false; - - if (!event.args.empty()) - { - localPlayer->setImitate(event.args); - } - else if (event.tab != nullptr && - event.tab->getType() == ChatTabType::WHISPER) - { - localPlayer->setImitate(static_cast( - event.tab)->getNick()); - } - else - { - localPlayer->setImitate(""); - } - return true; -} - -impHandler(sendMail) -{ -#ifdef TMWA_SUPPORT - const ServerTypeT type = Net::getNetworkType(); - if (type == ServerType::EATHENA || type == ServerType::EVOL2) -#endif // TMWA_SUPPORT - { - std::string name; - std::string text; - - if (parse2Str(event.args, name, text)) - { - if (settings.enableNewMailSystem) - { - mail2Handler->queueCheckName(MailQueueType::SendMail, - name, - // TRANSLATORS: quick mail message caption - _("Quick message"), - text, - 0); - } - else - { - // TRANSLATORS: quick mail message caption - mailHandler->send(name, _("Quick message"), text); - } - } - } -#ifdef TMWA_SUPPORT - else if (serverConfig.getBoolValue("enableManaMarketBot")) - { - chatHandler->privateMessage("ManaMarket", "!mail " + event.args); - return true; - } -#endif // TMWA_SUPPORT - - return false; -} - -impHandler(info) -{ - if (event.tab == nullptr || - localPlayer == nullptr || - Net::getNetworkType() == ServerType::TMWATHENA) - { - return false; - } - - if (guildHandler != nullptr && - event.tab->getType() == ChatTabType::GUILD) - { - const Guild *const guild = localPlayer->getGuild(); - if (guild != nullptr) - guildHandler->info(); - } - return true; -} - -impHandler(wait) -{ - if (localPlayer != nullptr) - { - localPlayer->waitFor(event.args); - return true; - } - return false; -} - -impHandler(addPriorityAttack) -{ - if ((actorManager == nullptr) || - actorManager->isInPriorityAttackList(event.args)) - { - return false; - } - - actorManager->removeAttackMob(event.args); - actorManager->addPriorityAttackMob(event.args); - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; -} - -impHandler(addAttack) -{ - if (actorManager == nullptr) - return false; - - actorManager->removeAttackMob(event.args); - actorManager->addAttackMob(event.args); - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; -} - -impHandler(removeAttack) -{ - if (actorManager == nullptr) - return false; - - if (event.args.empty()) - { - if (actorManager->isInAttackList(event.args)) - { - actorManager->removeAttackMob(event.args); - actorManager->addIgnoreAttackMob(event.args); - } - else - { - actorManager->removeAttackMob(event.args); - actorManager->addAttackMob(event.args); - } - } - else - { - actorManager->removeAttackMob(event.args); - } - - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; -} - -impHandler(addIgnoreAttack) -{ - if (actorManager == nullptr) - return false; - - actorManager->removeAttackMob(event.args); - actorManager->addIgnoreAttackMob(event.args); - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; -} - -impHandler(setDrop) -{ - GameModifiers::setQuickDropCounter(atoi(event.args.c_str())); - return true; -} - -impHandler(url) -{ - if (event.tab != nullptr) - { - std::string url1 = event.args; - if (!strStartWith(url1, "http") && !strStartWith(url1, "?")) - url1 = "http://" + url1; - std::string str(strprintf("[@@%s |%s@@]", - url1.c_str(), event.args.c_str())); - outStringNormal(event.tab, str, str); - return true; - } - return false; -} - -impHandler(openUrl) -{ - std::string url = event.args; - if (!strStartWith(url, "http")) - url = "http://" + url; - openBrowser(url); - return true; -} - -impHandler(execute) -{ - const size_t idx = event.args.find(' '); - std::string name; - std::string params; - if (idx == std::string::npos) - { - name = event.args; - } - else - { - name = event.args.substr(0, idx); - params = event.args.substr(idx + 1); - } - execFile(name, name, params, ""); - return true; -} - -impHandler(enableHighlight) -{ - if (event.tab != nullptr) - { - event.tab->setAllowHighlight(true); - if (chatWindow != nullptr) - { - chatWindow->saveState(); - return true; - } - } - return false; -} - -impHandler(disableHighlight) -{ - if (event.tab != nullptr) - { - event.tab->setAllowHighlight(false); - if (chatWindow != nullptr) - { - chatWindow->saveState(); - return true; - } - } - return false; -} - -impHandler(dontRemoveName) -{ - if (event.tab != nullptr) - { - event.tab->setRemoveNames(false); - if (chatWindow != nullptr) - { - chatWindow->saveState(); - return true; - } - } - return false; -} - -impHandler(removeName) -{ - if (event.tab != nullptr) - { - event.tab->setRemoveNames(true); - if (chatWindow != nullptr) - { - chatWindow->saveState(); - return true; - } - } - return false; -} - -impHandler(disableAway) -{ - if (event.tab != nullptr) - { - event.tab->setNoAway(true); - if (chatWindow != nullptr) - { - chatWindow->saveState(); - return true; - } - } - return false; -} - -impHandler(enableAway) -{ - if (event.tab != nullptr) - { - event.tab->setNoAway(false); - if (chatWindow != nullptr) - { - chatWindow->saveState(); - return true; - } - } - return false; -} - -impHandler(testParticle) -{ - if (localPlayer != nullptr) - { - localPlayer->setTestParticle(event.args); - return true; - } - return false; -} - -impHandler(talkRaw) -{ - if (chatHandler != nullptr) - { - chatHandler->talkRaw(event.args); - return true; - } - return false; -} - -impHandler(gm) -{ - if (chatHandler != nullptr) - { - Gm::runCommand("wgm", event.args); - return true; - } - return false; -} - -impHandler(hack) -{ - if (chatHandler != nullptr) - { - chatHandler->sendRaw(event.args); - return true; - } - return false; -} - -impHandler(debugSpawn) -{ - if (localPlayer == nullptr) - return false; - int cnt = atoi(event.args.c_str()); - if (cnt < 1) - cnt = 1; - const int half = cnt / 2; - const Map *const map = localPlayer->getMap(); - int x1 = -half; - if (x1 < 0) - x1 = 0; - int y1 = x1; - int x2 = cnt - half; - if (x2 > map->getWidth()) - x2 = map->getWidth(); - int y2 = x2; - - for (int x = x1; x < x2; x ++) - { - for (int y = y1; y < y2; y ++) - ActorManager::cloneBeing(localPlayer, x, y, cnt); - } - return true; -} - -impHandler(serverIgnoreWhisper) -{ - std::string args = getNick(event); - if (args.empty()) - return false; - - if (chatHandler != nullptr) - { - chatHandler->ignore(args); - return true; - } - return false; -} - -impHandler(serverUnIgnoreWhisper) -{ - std::string args = getNick(event); - if (args.empty()) - return false; - - if (chatHandler != nullptr) - { - chatHandler->unIgnore(args); - return true; - } - return false; -} - -impHandler(setHomunculusName) -{ - const std::string args = event.args; - if (args.empty()) - { - const HomunculusInfo *const info = PlayerInfo::getHomunculus(); - if (info != nullptr) - { - // TRANSLATORS: dialog header - inputActionReplayListener.openDialog(_("Rename your homun"), - info->name, - InputAction::HOMUNCULUS_SET_NAME); - } - return false; - } - - if (homunculusHandler != nullptr) - { - homunculusHandler->setName(args); - return true; - } - return false; -} - -impHandler0(fireHomunculus) -{ - if (homunculusHandler != nullptr) - { - homunculusHandler->fire(); - return true; - } - return false; -} - -impHandler0(leaveParty) -{ - if (partyHandler != nullptr) - { - partyHandler->leave(); - return true; - } - return false; -} - -impHandler0(leaveGuild) -{ - if ((guildHandler != nullptr) && (localPlayer != nullptr)) - { - const Guild *const guild = localPlayer->getGuild(); - if (guild != nullptr) - guildHandler->leave(guild->getId()); - return true; - } - return false; -} - -impHandler(warp) -{ - int x = 0; - int y = 0; - - if ((adminHandler != nullptr) && - (Game::instance() != nullptr) && - parse2Int(event.args, x, y)) - { - adminHandler->warp(Game::instance()->getCurrentMapName(), - x, y); - return true; - } - return false; -} - -impHandler(homunTalk) -{ - if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet()) - return false; - - std::string args = event.args; - if (findCutFirst(args, "/me ")) - args = textToMe(args); - if (homunculusHandler != nullptr) - { - homunculusHandler->talk(args); - return true; - } - return false; -} - -impHandler(homunEmote) -{ - if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet()) - return false; - - if ((homunculusHandler != nullptr) && - event.action >= InputAction::HOMUN_EMOTE_1 && - event.action <= InputAction::HOMUN_EMOTE_48) - { - const int emotion = event.action - InputAction::HOMUN_EMOTE_1; - if (emoteShortcut != nullptr) - homunculusHandler->emote(emoteShortcut->getEmote(emotion)); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - - return false; -} - -impHandler(commandHomunEmote) -{ - if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet()) - return false; - - if (homunculusHandler != nullptr) - { - homunculusHandler->emote(CAST_U8( - atoi(event.args.c_str()))); - return true; - } - return false; -} - -impHandler(createPublicChatRoom) -{ - if ((chatHandler == nullptr) || event.args.empty()) - return false; - chatHandler->createChatRoom(event.args, "", 100, true); - return true; -} - -impHandler(joinChatRoom) -{ - if (chatHandler == nullptr) - return false; - const std::string args = event.args; - if (args.empty()) - return false; - ChatObject *const chat = ChatObject::findByName(args); - if (chat == nullptr) - return false; - chatHandler->joinChat(chat, ""); - return true; -} - -impHandler0(leaveChatRoom) -{ - if (chatHandler != nullptr) - { - chatHandler->leaveChatRoom(); - return true; - } - return false; -} - -impHandler(confSet) -{ - std::string name; - std::string val; - - if (parse2Str(event.args, name, val)) - { - config.setValue(name, val); - return true; - } - return false; -} - -impHandler(serverConfSet) -{ - std::string name; - std::string val; - - if (parse2Str(event.args, name, val)) - { - serverConfig.setValue(name, val); - return true; - } - return false; -} - -impHandler(confGet) -{ - const std::string args = event.args; - if (args.empty()) - return false; - - // TRANSLATORS: result from command /confget - const std::string str = strprintf(_("Config value: %s"), - config.getStringValue(args).c_str()); - outStringNormal(event.tab, str, str); - return true; -} - -impHandler(serverConfGet) -{ - const std::string args = event.args; - if (args.empty()) - return false; - - // TRANSLATORS: result from command /serverconfget - const std::string str = strprintf(_("Server config value: %s"), - serverConfig.getStringValue(args).c_str()); - outStringNormal(event.tab, str, str); - return true; -} - -impHandler(slide) -{ - int x = 0; - int y = 0; - - if ((adminHandler != nullptr) && parse2Int(event.args, x, y)) - { - adminHandler->slide(x, y); - return true; - } - return false; -} - -impHandler(selectSkillLevel) -{ - int skill = 0; - int level = 0; - - if ((skillDialog != nullptr) && parse2Int(event.args, skill, level)) - { - skillDialog->selectSkillLevel(skill, level); - return true; - } - return false; -} - -impHandler(skill) -{ - StringVect vect; - splitToStringVector(vect, event.args, ' '); - const int sz = CAST_S32(vect.size()); - if (sz < 1) - return true; - const int skillId = atoi(vect[0].c_str()); - int level = 0; - std::string text; - if (sz > 1) - { - level = atoi(vect[1].c_str()); - if (sz > 2) - text = vect[2]; - } - // +++ add here also cast type and offsets - if (text.empty()) - { - SkillDialog::useSkill(skillId, - AutoTarget_true, - level, - false, - "", - CastType::Default, - 0, - 0); - } - else - { - SkillDialog::useSkill(skillId, - AutoTarget_true, - level, - true, - text, - CastType::Default, - 0, - 0); - } - return true; -} - -impHandler(craft) -{ - const std::string args = event.args; - if (args.empty() || (inventoryWindow == nullptr)) - return false; - - inventoryWindow->moveItemToCraft(atoi(args.c_str())); - return true; -} - -impHandler(npcClipboard) -{ - if (npcHandler != nullptr) - { - int x = 0; - int y = 0; - - NpcDialog *const dialog = npcHandler->getCurrentNpcDialog(); - - if ((dialog != nullptr) && parse2Int(event.args, x, y)) - { - dialog->copyToClipboard(x, y); - return true; - } - } - return false; -} - -impHandler(clipboardCopy) -{ - const std::string args = event.args; - if (args.empty()) - return false; - sendBuffer(args); - return true; -} - -impHandler(addPickup) -{ - if (actorManager != nullptr) - { - actorManager->removePickupItem(event.args); - actorManager->addPickupItem(event.args); - if (socialWindow != nullptr) - socialWindow->updatePickupFilter(); - return true; - } - return false; -} - -impHandler(removePickup) -{ - if (actorManager != nullptr) - { - if (event.args.empty()) - { // default pickup manipulation - if (actorManager->checkDefaultPickup()) - { - actorManager->removePickupItem(event.args); - actorManager->addIgnorePickupItem(event.args); - } - else - { - actorManager->removePickupItem(event.args); - actorManager->addPickupItem(event.args); - } - } - else - { // any other pickups - actorManager->removePickupItem(event.args); - } - if (socialWindow != nullptr) - socialWindow->updatePickupFilter(); - return true; - } - return false; -} - -impHandler(ignorePickup) -{ - if (actorManager != nullptr) - { - actorManager->removePickupItem(event.args); - actorManager->addIgnorePickupItem(event.args); - if (socialWindow != nullptr) - socialWindow->updatePickupFilter(); - return true; - } - return false; -} - -impHandler(monsterInfo) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->monsterInfo(args); - return true; -} - -impHandler(itemInfo) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->itemInfo(args); - return true; -} - -impHandler(whoDrops) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->whoDrops(args); - return true; -} - -impHandler(mobSearch) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->mobSearch(args); - return true; -} - -impHandler(mobSpawnSearch) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->mobSpawnSearch(args); - return true; -} - -impHandler(playerGmCommands) -{ - adminHandler->playerGmCommands(event.args); - return true; -} - -impHandler(playerCharGmCommands) -{ - adminHandler->playerCharGmCommands(event.args); - return true; -} - -impHandler(commandShowLevel) -{ - adminHandler->showLevel(event.args); - return true; -} - -impHandler(commandShowStats) -{ - adminHandler->showStats(event.args); - return true; -} - -impHandler(commandShowStorage) -{ - adminHandler->showStorageList(event.args); - return true; -} - -impHandler(commandShowCart) -{ - adminHandler->showCartList(event.args); - return true; -} - -impHandler(commandShowInventory) -{ - adminHandler->showInventoryList(event.args); - return true; -} - -impHandler(locatePlayer) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->locatePlayer(args); - return true; -} - -impHandler(commandShowAccountInfo) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->showAccountInfo(args); - return true; -} - -impHandler(commandSpawn) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->spawn(args); - return true; -} - -impHandler(commandSpawnSlave) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->spawnSlave(args); - return true; -} - -impHandler(commandSpawnClone) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->spawnClone(args); - return true; -} - -impHandler(commandSpawnSlaveClone) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->spawnSlaveClone(args); - return true; -} - -impHandler(commandSpawnEvilClone) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->spawnEvilClone(args); - return true; -} - -impHandler(commandSavePosition) -{ - adminHandler->savePosition(event.args); - return true; -} - -impHandler(commandLoadPosition) -{ - adminHandler->loadPosition(event.args); - return true; -} - -impHandler(commandRandomWarp) -{ - adminHandler->randomWarp(event.args); - return true; -} - -impHandler(commandGotoNpc) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->gotoNpc(args); - return true; -} - -impHandler(commandGotoPc) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->gotoName(args); - return true; -} - -impHandler(commandRecallPc) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->recallName(args); - return true; -} - -impHandler(commandIpCheck) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->ipcheckName(args); - return true; -} - -impHandler(commandKiller) -{ - adminHandler->killer(event.args); - return true; -} - -impHandler(commandKillable) -{ - adminHandler->killable(event.args); - return true; -} - -impHandler(commandHeal) -{ - adminHandler->heal(event.args); - return true; -} - -impHandler(commandAlive) -{ - adminHandler->alive(event.args); - return true; -} - -impHandler(commandDisguise) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->disguise(args); - return true; -} - -impHandler(commandImmortal) -{ - adminHandler->immortal(event.args); - return true; -} - -impHandler(commandHide) -{ - adminHandler->hide(event.args); - return true; -} - -impHandler(commandNuke) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->nuke(args); - return true; -} - -impHandler(commandKill) -{ - adminHandler->kill(event.args); - return true; -} - -impHandler(commandJail) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->jail(args); - return true; -} - -impHandler(commandUnjail) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->unjail(args); - return true; -} - -impHandler(commandNpcMove) -{ - const std::string args = event.args; - if (args.empty()) - return false; - StringVect pars; - if (!splitParameters(pars, args, " ,", '\"')) - return false; - - if (pars.size() != 3) - return false; - - adminHandler->npcMove(pars[0], - atoi(pars[1].c_str()), - atoi(pars[2].c_str())); - return true; -} - -impHandler(commandNpcHide) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->hideNpc(args); - return true; -} - -impHandler(commandNpcShow) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->showNpc(args); - return true; -} - -impHandler(commandChangePartyLeader) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->changePartyLeader(args); - return true; -} - -impHandler(commandPartyRecall) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->partyRecall(args); - return true; -} - -impHandler(commandBreakGuild) -{ - adminHandler->breakGuild(event.args); - return true; -} - -impHandler(commandGuildRecall) -{ - const std::string args = event.args; - if (args.empty()) - return false; - adminHandler->guildRecall(args); - return true; -} - -impHandler(mailTo) -{ - if (mailWindow == nullptr) - return false; - const std::string args = event.args; - if (settings.enableNewMailSystem) - { - mail2Handler->queueCheckName(MailQueueType::EditMail, - args, - std::string(), - std::string(), - 0); - } - else - { - mailWindow->createMail(args); - } - return true; -} - -impHandler(adoptChild) -{ - const std::string nick = getNick(event); - Being *const being = actorManager->findBeingByName( - nick, ActorType::Player); - if (being == nullptr) - return true; - familyHandler->askForChild(being); - return true; -} - -impHandler(showSkillLevels) -{ - const std::string args = event.args; - if (args.empty()) - return false; - const SkillInfo *restrict const skill = skillDialog->getSkill( - atoi(args.c_str())); - if (skill == nullptr) - return false; - popupMenu->showSkillLevelPopup(skill); - return true; -} - -impHandler(showSkillType) -{ - const std::string args = event.args; - if (args.empty()) - return false; - const SkillInfo *restrict const skill = skillDialog->getSkill( - atoi(args.c_str())); - if (skill == nullptr) - return false; - popupMenu->showSkillTypePopup(skill); - return true; -} - -impHandler(selectSkillType) -{ - int skill = 0; - int type = 0; - - if ((skillDialog != nullptr) && parse2Int(event.args, skill, type)) - { - skillDialog->selectSkillCastType(skill, - static_cast(type)); - return true; - } - return false; -} - -impHandler(showSkillOffsetX) -{ - const std::string args = event.args; - if (args.empty()) - return false; - const SkillInfo *restrict const skill = skillDialog->getSkill( - atoi(args.c_str())); - if (skill == nullptr) - return false; - popupMenu->showSkillOffsetPopup(skill, true); - return true; -} - -impHandler(showSkillOffsetY) -{ - const std::string args = event.args; - if (args.empty()) - return false; - const SkillInfo *restrict const skill = skillDialog->getSkill( - atoi(args.c_str())); - if (skill == nullptr) - return false; - popupMenu->showSkillOffsetPopup(skill, false); - return true; -} - -impHandler(setSkillOffsetX) -{ - int skill = 0; - int offset = 0; - - if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset)) - { - skillDialog->setSkillOffsetX(skill, offset); - return true; - } - return false; -} - -impHandler(setSkillOffsetY) -{ - int skill = 0; - int offset = 0; - - if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset)) - { - skillDialog->setSkillOffsetY(skill, offset); - return true; - } - return false; -} - -impHandler(partyItemShare) -{ - if (localPlayer == nullptr) - return false; - - if (localPlayer->isInParty() == false) - return true; - - ChatTab *tab = event.tab; - if (tab == nullptr) - tab = localChatTab; - if (tab == nullptr) - return true; - - const std::string args = event.args; - if (args.empty()) - { - switch (partyHandler->getShareItems()) - { - case PartyShare::YES: - // TRANSLATORS: chat message - tab->chatLog(_("Item sharing enabled."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::NO: - // TRANSLATORS: chat message - tab->chatLog(_("Item sharing disabled."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::NOT_POSSIBLE: - // TRANSLATORS: chat message - tab->chatLog(_("Item sharing not possible."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::UNKNOWN: - // TRANSLATORS: chat message - tab->chatLog(_("Item sharing unknown."), - ChatMsgType::BY_SERVER); - return true; - default: - break; - } - } - - const signed char opt = parseBoolean(args); - - switch (opt) - { - case 1: - partyHandler->setShareItems( - PartyShare::YES); - break; - case 0: - partyHandler->setShareItems( - PartyShare::NO); - break; - case -1: - tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"), - ChatMsgType::BY_SERVER); - break; - default: - break; - } - return true; -} - -impHandler(partyExpShare) -{ - if (localPlayer == nullptr) - return false; - - if (localPlayer->isInParty() == false) - return true; - - ChatTab *tab = event.tab; - if (tab == nullptr) - tab = localChatTab; - if (tab == nullptr) - return true; - - const std::string args = event.args; - if (args.empty()) - { - switch (partyHandler->getShareExperience()) - { - case PartyShare::YES: - // TRANSLATORS: chat message - tab->chatLog(_("Experience sharing enabled."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::NO: - // TRANSLATORS: chat message - tab->chatLog(_("Experience sharing disabled."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::NOT_POSSIBLE: - // TRANSLATORS: chat message - tab->chatLog(_("Experience sharing not possible."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::UNKNOWN: - // TRANSLATORS: chat message - tab->chatLog(_("Experience sharing unknown."), - ChatMsgType::BY_SERVER); - return true; - default: - break; - } - } - - const signed char opt = parseBoolean(args); - - switch (opt) - { - case 1: - partyHandler->setShareExperience( - PartyShare::YES); - break; - case 0: - partyHandler->setShareExperience( - PartyShare::NO); - break; - case -1: - tab->chatLog(strprintf(BOOLEAN_OPTIONS, "exp"), - ChatMsgType::BY_SERVER); - break; - default: - break; - } - return true; -} - -impHandler(partyAutoItemShare) -{ - if (localPlayer == nullptr) - return false; - - if (localPlayer->isInParty() == false) - return true; - - ChatTab *tab = event.tab; - if (tab == nullptr) - tab = localChatTab; - if (tab == nullptr) - return true; - - const std::string args = event.args; - if (args.empty()) - { - switch (partyHandler->getShareAutoItems()) - { - case PartyShare::YES: - // TRANSLATORS: chat message - tab->chatLog(_("Auto item sharing enabled."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::NO: - // TRANSLATORS: chat message - tab->chatLog(_("Auto item sharing disabled."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::NOT_POSSIBLE: - // TRANSLATORS: chat message - tab->chatLog(_("Auto item sharing not possible."), - ChatMsgType::BY_SERVER); - return true; - case PartyShare::UNKNOWN: - // TRANSLATORS: chat message - tab->chatLog(_("Auto item sharing unknown."), - ChatMsgType::BY_SERVER); - return true; - default: - break; - } - } - - const signed char opt = parseBoolean(args); - - switch (opt) - { - case 1: - partyHandler->setShareAutoItems( - PartyShare::YES); - break; - case 0: - partyHandler->setShareAutoItems( - PartyShare::NO); - break; - case -1: - tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"), - ChatMsgType::BY_SERVER); - break; - default: - break; - } - return true; -} - -impHandler0(outfitToChat) -{ - if ((outfitWindow == nullptr) || (chatWindow == nullptr)) - return false; - - const std::string str = outfitWindow->getOutfitString(); - if (!str.empty()) - chatWindow->addInputText(str); - return true; -} - -impHandler0(outfitClear) -{ - if (outfitWindow == nullptr) - return false; - - outfitWindow->clearCurrentOutfit(); - return true; -} - -impHandler(moveAttackUp) -{ - if (actorManager == nullptr) - return false; - const std::string args = event.args; - const int idx = actorManager->getAttackMobIndex(args); - if (idx > 0) - { - std::list mobs - = actorManager->getAttackMobs(); - std::list::iterator it = mobs.begin(); - std::list::iterator it2 = it; - while (it != mobs.end()) - { - if (*it == args) - { - -- it2; - mobs.splice(it2, mobs, it); - actorManager->setAttackMobs(mobs); - actorManager->rebuildAttackMobs(); - break; - } - ++ it; - ++ it2; - } - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; - } - return false; -} - -impHandler(moveAttackDown) -{ - if (actorManager == nullptr) - return false; - const std::string args = event.args; - const int idx = actorManager->getAttackMobIndex(args); - const int size = actorManager->getAttackMobsSize(); - if (idx + 1 < size) - { - std::list mobs - = actorManager->getAttackMobs(); - std::list::iterator it = mobs.begin(); - std::list::iterator it2 = it; - while (it != mobs.end()) - { - if (*it == args) - { - ++ it2; - if (it2 == mobs.end()) - break; - - mobs.splice(it, mobs, it2); - actorManager->setAttackMobs(mobs); - actorManager->rebuildAttackMobs(); - break; - } - ++ it; - ++ it2; - } - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; - } - return false; -} - -impHandler(movePriorityAttackUp) -{ - if (actorManager == nullptr) - return false; - const std::string args = event.args; - const int idx = actorManager-> - getPriorityAttackMobIndex(args); - if (idx > 0) - { - std::list mobs - = actorManager->getPriorityAttackMobs(); - std::list::iterator it = mobs.begin(); - std::list::iterator it2 = it; - while (it != mobs.end()) - { - if (*it == args) - { - -- it2; - mobs.splice(it2, mobs, it); - actorManager->setPriorityAttackMobs(mobs); - actorManager->rebuildPriorityAttackMobs(); - break; - } - ++ it; - ++ it2; - } - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; - } - return false; -} - -impHandler(movePriorityAttackDown) -{ - if (actorManager == nullptr) - return false; - const std::string args = event.args; - const int idx = actorManager - ->getPriorityAttackMobIndex(args); - const int size = actorManager->getPriorityAttackMobsSize(); - if (idx + 1 < size) - { - std::list mobs - = actorManager->getPriorityAttackMobs(); - std::list::iterator it = mobs.begin(); - std::list::iterator it2 = it; - while (it != mobs.end()) - { - if (*it == args) - { - ++ it2; - if (it2 == mobs.end()) - break; - - mobs.splice(it, mobs, it2); - actorManager->setPriorityAttackMobs(mobs); - actorManager->rebuildPriorityAttackMobs(); - break; - } - ++ it; - ++ it2; - } - - if (socialWindow != nullptr) - socialWindow->updateAttackFilter(); - return true; - } - return false; -} - -impHandler(addSkillShortcut) -{ - const std::string args = event.args; - if (args.empty() || - itemShortcutWindow == nullptr) - { - return false; - } - const SkillInfo *restrict const skill = skillDialog->getSkill( - atoi(args.c_str())); - if (skill == nullptr) - return false; - - const int num = itemShortcutWindow->getTabIndex(); - if (num < 0 || - num >= CAST_S32(SHORTCUT_TABS) || - num == CAST_S32(SHORTCUT_AUTO_TAB)) - { - return false; - } - - ItemShortcut *const selShortcut = itemShortcut[num]; - const size_t index = selShortcut->getFreeIndex(); - if (index == SHORTCUT_ITEMS) - return true; - - selShortcut->setItem(index, - skill->id + SKILL_MIN_ID, - fromInt(skill->customSelectedLevel, ItemColor)); - selShortcut->setItemData(index, - skill->toDataStr()); - -// popupMenu->showSkillLevelPopup(skill); - return true; -} - -} // namespace Actions diff --git a/src/actions/move.cpp b/src/actions/move.cpp deleted file mode 100644 index d2be4de7e..000000000 --- a/src/actions/move.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/move.h" - -#include "game.h" - -#include "actions/actiondef.h" -#include "actions/pets.h" - -#include "being/crazymoves.h" -#include "being/localplayer.h" - -#include "enums/being/beingdirection.h" - -#include "gui/windows/socialwindow.h" -#include "gui/windows/npcdialog.h" -#include "gui/windows/outfitwindow.h" - -#include "gui/popups/popupmenu.h" - -#include "input/inputactionoperators.h" - -#include "net/playerhandler.h" - -#include "debug.h" - -namespace Actions -{ - -static bool closeMoveNpcDialog(bool focus) -{ - NpcDialog *const dialog = NpcDialog::getActive(); - if (dialog != nullptr) - { - if (dialog->isCloseState() != 0) - { - dialog->closeDialog(); - return true; - } - else if (focus) - { - dialog->refocus(); - } - } - return false; -} - -impHandler(moveUp) -{ - if (inputManager.isActionActive(InputAction::EMOTE)) - return directUp(event); - else if (inputManager.isActionActive(InputAction::PET_EMOTE)) - return petDirectUp(event); - else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) - return petMoveUp(event); - else if (!localPlayer->canMove()) - return directUp(event); - if (popupMenu->isPopupVisible()) - { - popupMenu->moveUp(); - return true; - } - return closeMoveNpcDialog(false); -} - -impHandler(moveDown) -{ - if (inputManager.isActionActive(InputAction::EMOTE)) - return directDown(event); - else if (inputManager.isActionActive(InputAction::PET_EMOTE)) - return petDirectDown(event); - else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) - return petMoveDown(event); - else if (!localPlayer->canMove()) - return directDown(event); - if (popupMenu->isPopupVisible()) - { - popupMenu->moveDown(); - return true; - } - return closeMoveNpcDialog(false); -} - -impHandler(moveLeft) -{ - if (outfitWindow != nullptr && - inputManager.isActionActive(InputAction::WEAR_OUTFIT)) - { - outfitWindow->wearPreviousOutfit(); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - if (inputManager.isActionActive(InputAction::EMOTE)) - return directLeft(event); - else if (inputManager.isActionActive(InputAction::PET_EMOTE)) - return petDirectLeft(event); - else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) - return petMoveLeft(event); - else if (!localPlayer->canMove()) - return directLeft(event); - return closeMoveNpcDialog(false); -} - -impHandler(moveRight) -{ - if (outfitWindow != nullptr && - inputManager.isActionActive(InputAction::WEAR_OUTFIT)) - { - outfitWindow->wearNextOutfit(); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - if (inputManager.isActionActive(InputAction::EMOTE)) - return directRight(event); - else if (inputManager.isActionActive(InputAction::PET_EMOTE)) - return petDirectRight(event); - else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) - return petMoveRight(event); - else if (!localPlayer->canMove()) - return directRight(event); - return closeMoveNpcDialog(false); -} - -impHandler(moveForward) -{ - if (inputManager.isActionActive(InputAction::EMOTE)) - return directRight(event); - return closeMoveNpcDialog(false); -} - -impHandler(moveToPoint) -{ - const int num = event.action - InputAction::MOVE_TO_POINT_1; - if ((socialWindow != nullptr) && num >= 0) - { - socialWindow->selectPortal(num); - return true; - } - - return false; -} - -impHandler0(crazyMoves) -{ - if (localPlayer != nullptr) - { - ::crazyMoves->crazyMove(); - return true; - } - return false; -} - -impHandler0(moveToTarget) -{ - if (localPlayer != nullptr && - !inputManager.isActionActive(InputAction::TARGET_ATTACK) && - !inputManager.isActionActive(InputAction::ATTACK)) - { - localPlayer->moveToTarget(); - return true; - } - return false; -} - -impHandler0(moveToHome) -{ - if (localPlayer != nullptr && - !inputManager.isActionActive(InputAction::TARGET_ATTACK) && - !inputManager.isActionActive(InputAction::ATTACK)) - { - localPlayer->moveToHome(); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - return false; -} - -impHandler0(directUp) -{ - if (localPlayer != nullptr) - { - if (localPlayer->getDirection() != BeingDirection::UP) - { -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::UP); - if (playerHandler != nullptr) - playerHandler->setDirection(BeingDirection::UP); - } - } - return true; - } - return false; -} - -impHandler0(directDown) -{ - if (localPlayer != nullptr) - { - if (localPlayer->getDirection() != BeingDirection::DOWN) - { -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::DOWN); - if (playerHandler != nullptr) - { - playerHandler->setDirection( - BeingDirection::DOWN); - } - } - } - return true; - } - return false; -} - -impHandler0(directLeft) -{ - if (localPlayer != nullptr) - { - if (localPlayer->getDirection() != BeingDirection::LEFT) - { -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::LEFT); - if (playerHandler != nullptr) - { - playerHandler->setDirection( - BeingDirection::LEFT); - } - } - } - return true; - } - return false; -} - -impHandler0(directRight) -{ - if (localPlayer != nullptr) - { - if (localPlayer->getDirection() != BeingDirection::RIGHT) - { -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::RIGHT); - if (playerHandler != nullptr) - { - playerHandler->setDirection( - BeingDirection::RIGHT); - } - } - } - return true; - } - return false; -} - -} // namespace Actions diff --git a/src/actions/pets.cpp b/src/actions/pets.cpp deleted file mode 100644 index 25c5f1411..000000000 --- a/src/actions/pets.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/pets.h" - -#include "actormanager.h" -#include "game.h" - -#include "actions/actiondef.h" - -#include "being/localplayer.h" -#include "being/playerinfo.h" - -#include "enums/being/beingdirection.h" - -#include "const/gui/chat.h" - -#include "input/inputactionoperators.h" - -#include "listeners/inputactionreplaylistener.h" - -#include "gui/shortcut/emoteshortcut.h" - -#include "net/chathandler.h" -#include "net/pethandler.h" -#include "net/serverfeatures.h" - -#include "utils/chatutils.h" -#include "utils/gettext.h" -#include "utils/stringutils.h" - -#include "debug.h" - -namespace Actions -{ - -static const Being *getPet() -{ - const BeingId id = PlayerInfo::getPetBeingId(); - if (id == BeingId_zero) - return nullptr; - return actorManager->findBeing(id); -} - -impHandler(commandEmotePet) -{ - petHandler->emote(CAST_U8(atoi(event.args.c_str()))); - return true; -} - -impHandler(talkPet) -{ - if (!serverFeatures->haveTalkPet()) - return false; - - std::string args = event.args; - if (findCutFirst(args, "/me ")) - args = textToMe(args); - chatHandler->talkPet(args, GENERAL_CHANNEL); - return true; -} - -impHandler(setPetName) -{ - const std::string args = event.args; - if (args.empty()) - { - const Being *const pet = getPet(); - if (pet == nullptr) - return false; - // TRANSLATORS: dialog header - inputActionReplayListener.openDialog(_("Rename your pet"), - pet->getName(), - InputAction::PET_SET_NAME); - return false; - } - - petHandler->setName(args); - return true; -} - -impHandler(petEmote) -{ - if (!serverFeatures->haveTalkPet()) - return false; - - if (event.action >= InputAction::PET_EMOTE_1 - && event.action <= InputAction::PET_EMOTE_48) - { - const int emotion = event.action - InputAction::PET_EMOTE_1; - if (emoteShortcut != nullptr) - petHandler->emote(emoteShortcut->getEmote(emotion)); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - - return false; -} - -impHandler(catchPet) -{ - if ((localPlayer == nullptr) || (actorManager == nullptr)) - return false; - - Being *target = nullptr; - const std::string args = event.args; - if (!args.empty()) - { - if (args[0] == ':') - { - target = actorManager->findBeing(fromInt(atoi( - args.substr(1).c_str()), BeingId)); - } - else - { - target = actorManager->findNearestByName(args); - } - } - - if (target == nullptr) - target = localPlayer->getTarget(); - else - localPlayer->setTarget(target); - if (target != nullptr) - petHandler->catchPet(target); - return true; -} - -impHandler0(petMoveUp) -{ - const Being *const pet = getPet(); - if (pet == nullptr) - return false; - petHandler->move(pet->getTileX(), pet->getTileY() - 1); - return true; -} - -impHandler0(petMoveDown) -{ - const Being *const pet = getPet(); - if (pet == nullptr) - return false; - petHandler->move(pet->getTileX(), pet->getTileY() + 1); - return true; -} - -impHandler0(petMoveLeft) -{ - const Being *const pet = getPet(); - if (pet == nullptr) - return false; - petHandler->move(pet->getTileX() - 1, pet->getTileY()); - return true; -} - -impHandler0(petMoveRight) -{ - const Being *const pet = getPet(); - if (pet == nullptr) - return false; - petHandler->move(pet->getTileX() + 1, pet->getTileY()); - return true; -} - -impHandler0(petDirectUp) -{ - petHandler->setDirection(BeingDirection::UP); - return true; -} - -impHandler0(petDirectDown) -{ - petHandler->setDirection(BeingDirection::DOWN); - return true; -} - -impHandler0(petDirectLeft) -{ - petHandler->setDirection(BeingDirection::LEFT); - return true; -} - -impHandler0(petDirectRight) -{ - petHandler->setDirection(BeingDirection::RIGHT); - return true; -} - -impHandler(petMove) -{ - int x = 0; - int y = 0; - - if (parse2Int(event.args, x, y)) - { - petHandler->move(x, y); - return true; - } - return false; -} - -impHandler0(petFeed) -{ - if (petHandler != nullptr) - petHandler->feed(); - return true; -} - -impHandler0(petDropLoot) -{ - if (petHandler != nullptr) - petHandler->dropLoot(); - return true; -} - -impHandler0(petReturnToEgg) -{ - if (petHandler != nullptr) - petHandler->returnToEgg(); - return true; -} - -impHandler0(petUnequip) -{ - if (petHandler != nullptr) - petHandler->unequip(); - return true; -} - -} // namespace Actions diff --git a/src/actions/statusbar.cpp b/src/actions/statusbar.cpp deleted file mode 100644 index 0d5ba68cd..000000000 --- a/src/actions/statusbar.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/statusbar.h" - -#include "game.h" -#include "soundmanager.h" - -#include "actions/actiondef.h" - -#include "being/localplayer.h" -#include "being/playerrelation.h" -#include "being/playerrelations.h" - -#include "gui/viewport.h" - -#include "gui/widgets/tabs/chat/chattab.h" - -#include "listeners/updatestatuslistener.h" - -#include "resources/map/map.h" - -#include "utils/gettext.h" - -PRAGMA48(GCC diagnostic push) -PRAGMA48(GCC diagnostic ignored "-Wshadow") -#ifdef ANDROID -#ifndef USE_SDL2 -#include -#endif // USE_SDL2 -#endif // ANDROID -PRAGMA48(GCC diagnostic pop) - -#include "debug.h" - -namespace Actions -{ - -impHandler0(switchQuickDrop) -{ - callYellowBarCond(changeQuickDropCounter) -} - -impHandler0(changeCrazyMove) -{ - callYellowBar(changeCrazyMoveType); -} - -impHandler0(changePickupType) -{ - callYellowBar(changePickUpType); -} - -impHandler0(changeMoveType) -{ - callYellowBar(changeMoveType); -} - -impHandler0(changeAttackWeaponType) -{ - callYellowBar(changeAttackWeaponType); -} - -impHandler0(changeAttackType) -{ - callYellowBar(changeAttackType); -} - -impHandler0(changeTargetingType) -{ - callYellowBar(changeTargetingType); -} - -impHandler0(changeFollowMode) -{ - callYellowBar(changeFollowMode); -} - -impHandler0(changeImitationMode) -{ - callYellowBar(changeImitationMode); -} - -impHandler0(changeMagicAttackType) -{ - callYellowBar(changeMagicAttackType); -} - -impHandler0(changePvpMode) -{ - callYellowBar(changePvpAttackType); -} - -impHandler0(changeMoveToTarget) -{ - callYellowBar(changeMoveToTargetType); -} - -impHandler0(changeGameModifier) -{ - if (localPlayer != nullptr) - { - GameModifiers::changeGameModifiers(false); - return true; - } - return false; -} - -impHandler0(changeAudio) -{ - soundManager.changeAudio(); - if (localPlayer != nullptr) - localPlayer->updateMusic(); - return true; -} - -impHandler0(away) -{ - GameModifiers::changeAwayMode(true); - if (localPlayer != nullptr) - { - localPlayer->updateStatus(); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - return false; -} - -impHandler0(camera) -{ - if (viewport != nullptr) - { - viewport->toggleCameraMode(); - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - return true; - } - return false; -} - -impHandler0(changeMapMode) -{ - if (viewport != nullptr) - viewport->toggleMapDrawType(); - UpdateStatusListener::distributeEvent(); - if (Game::instance() != nullptr) - { - if (Map *const map = Game::instance()->getCurrentMap()) - map->redrawMap(); - } - return true; -} - -impHandler0(changeTrade) -{ - unsigned int deflt = playerRelations.getDefault(); - if ((deflt & PlayerRelation::TRADE) != 0u) - { - if (localChatTab != nullptr) - { - // TRANSLATORS: disable trades message - localChatTab->chatLog(_("Ignoring incoming trade requests"), - ChatMsgType::BY_SERVER); - } - deflt &= ~PlayerRelation::TRADE; - } - else - { - if (localChatTab != nullptr) - { - // TRANSLATORS: enable trades message - localChatTab->chatLog(_("Accepting incoming trade requests"), - ChatMsgType::BY_SERVER); - } - deflt |= PlayerRelation::TRADE; - } - - playerRelations.setDefault(deflt); - return true; -} - -} // namespace Actions diff --git a/src/actions/tabs.cpp b/src/actions/tabs.cpp deleted file mode 100644 index 99d964b40..000000000 --- a/src/actions/tabs.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/tabs.h" - -#include "actions/actiondef.h" - -#include "gui/windows/inventorywindow.h" -#include "gui/windows/socialwindow.h" -#include "gui/windows/shortcutwindow.h" - -#include "debug.h" - -namespace Actions -{ - -impHandler0(prevSocialTab) -{ - if (socialWindow != nullptr) - { - socialWindow->prevTab(); - return true; - } - return false; -} - -impHandler0(nextSocialTab) -{ - if (socialWindow != nullptr) - { - socialWindow->nextTab(); - return true; - } - return false; -} - -impHandler0(nextShortcutsTab) -{ - if (itemShortcutWindow != nullptr) - { - itemShortcutWindow->nextTab(); - return true; - } - return false; -} - -impHandler0(prevShortcutsTab) -{ - if (itemShortcutWindow != nullptr) - { - itemShortcutWindow->prevTab(); - return true; - } - return false; -} - -impHandler0(nextCommandsTab) -{ - if (spellShortcutWindow != nullptr) - { - spellShortcutWindow->nextTab(); - return true; - } - return false; -} - -impHandler0(prevCommandsTab) -{ - if (spellShortcutWindow != nullptr) - { - spellShortcutWindow->prevTab(); - return true; - } - return false; -} - -impHandler0(nextInvTab) -{ - InventoryWindow::nextTab(); - return true; -} - -impHandler0(prevInvTab) -{ - InventoryWindow::prevTab(); - return true; -} - -} // namespace Actions diff --git a/src/actions/target.cpp b/src/actions/target.cpp deleted file mode 100644 index a72cbe502..000000000 --- a/src/actions/target.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/target.h" - -#include "actions/actiondef.h" - -#include "being/localplayer.h" - -#include "gui/popups/popupmenu.h" - -#include "debug.h" - -namespace Actions -{ - -static bool setTarget(const ActorTypeT type, const AllowSort allowSort) -{ - if (localPlayer != nullptr) - return localPlayer->setNewTarget(type, allowSort) != nullptr; - return false; -} - -impHandler0(targetPlayer) -{ - return setTarget(ActorType::Player, AllowSort_true); -} - -impHandler0(targetMonster) -{ - return setTarget(ActorType::Monster, AllowSort_true); -} - -impHandler0(targetClosestMonster) -{ - return setTarget(ActorType::Monster, AllowSort_false); -} - -impHandler0(targetNPC) -{ - return setTarget(ActorType::Npc, AllowSort_true); -} - -impHandler0(targetMercenary) -{ - return setTarget(ActorType::Mercenary, AllowSort_true); -} - -impHandler0(targetSkillUnit) -{ - return setTarget(ActorType::SkillUnit, AllowSort_true); -} - -impHandler0(targetPet) -{ - return setTarget(ActorType::Pet, AllowSort_true); -} - -impHandler0(contextMenu) -{ - if (localPlayer == nullptr) - return false; - const Being *const target = localPlayer->getTarget(); - if (target == nullptr) - return true; - - popupMenu->showPopup(target->getPixelX(), - target->getPixelY(), - target); - return true; -} - -} // namespace Actions diff --git a/src/actions/windows.cpp b/src/actions/windows.cpp deleted file mode 100644 index 7c9b57d0a..000000000 --- a/src/actions/windows.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2012-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 . - */ - -#include "actions/windows.h" - -#include "actormanager.h" -#include "client.h" - -#include "actions/actiondef.h" - -#include "being/localplayer.h" - -#include "gui/dialogsmanager.h" - -#include "gui/windows/bankwindow.h" -#include "gui/windows/skilldialog.h" -#include "gui/windows/socialwindow.h" -#include "gui/windows/statuswindow.h" -#include "gui/windows/questswindow.h" -#include "gui/windows/whoisonline.h" -#include "gui/windows/chatwindow.h" -#include "gui/windows/debugwindow.h" -#include "gui/windows/didyouknowwindow.h" -#include "gui/windows/equipmentwindow.h" -#include "gui/windows/helpwindow.h" -#include "gui/windows/inventorywindow.h" -#include "gui/windows/killstats.h" -#include "gui/windows/mailwindow.h" -#include "gui/windows/minimap.h" -#include "gui/windows/outfitwindow.h" -#include "gui/windows/setupwindow.h" -#include "gui/windows/serverinfowindow.h" -#include "gui/windows/shopwindow.h" -#include "gui/windows/shortcutwindow.h" -#include "gui/windows/updaterwindow.h" - -#include "gui/widgets/createwidget.h" - -#include "gui/widgets/tabs/chat/chattab.h" - -#include "utils/gettext.h" - -#include "net/net.h" - -#include "debug.h" - -namespace Actions -{ - -impHandler0(setupWindowShow) -{ - if (setupWindow != nullptr) - { - if (setupWindow->isWindowVisible()) - { - setupWindow->doCancel(); - } - else - { - setupWindow->setVisible(Visible_true); - setupWindow->requestMoveToTop(); - } - return true; - } - return false; -} - -impHandler0(hideWindows) -{ - if (setupWindow != nullptr) - setupWindow->hideWindows(); - return true; -} - -static bool showHelpPage(const std::string &page, const bool showHide) -{ - if (helpWindow != nullptr) - { - if (showHide && helpWindow->isWindowVisible()) - { - helpWindow->setVisible(Visible_false); - } - else - { - helpWindow->loadHelp(page); - helpWindow->requestMoveToTop(); - } - return true; - } - return false; -} - -impHandler(helpWindowShow) -{ - if ((chatWindow == nullptr) || !chatWindow->isInputFocused()) - return showHelpPage("index", true); - if (event.tab == nullptr) - return showHelpPage("chatcommands", true); - switch (event.tab->getType()) - { - case ChatTabType::PARTY: - return showHelpPage("chatparty", true); - case ChatTabType::GUILD: - return showHelpPage("chatguild", true); - case ChatTabType::WHISPER: - return showHelpPage("chatwhisper", true); - case ChatTabType::DEBUG: - return showHelpPage("chatdebug", true); - case ChatTabType::TRADE: - return showHelpPage("chattrade", true); - case ChatTabType::BATTLE: - return showHelpPage("chatbattle", true); - case ChatTabType::LANG: - return showHelpPage("chatlang", true); - case ChatTabType::GM: - return showHelpPage("chatgm", true); - case ChatTabType::CHANNEL: - return showHelpPage("chatchannel", true); - default: - case ChatTabType::UNKNOWN: - case ChatTabType::INPUT: - return showHelpPage("chatcommands", true); - } -} - -impHandler0(aboutWindowShow) -{ - return showHelpPage("about", false); -} - -static void showHideWindow(Window *const window) -{ - if (window != nullptr) - { - window->setVisible(fromBool( - !window->isWindowVisible(), Visible)); - if (window->isWindowVisible()) - window->requestMoveToTop(); - } -} - -impHandler0(statusWindowShow) -{ - showHideWindow(statusWindow); - return true; -} - -impHandler0(inventoryWindowShow) -{ - showHideWindow(inventoryWindow); - return true; -} - -impHandler0(equipmentWindowShow) -{ - showHideWindow(equipmentWindow); - return true; -} - -impHandler0(skillDialogShow) -{ - showHideWindow(skillDialog); - return true; -} - -impHandler0(minimapWindowShow) -{ - if (minimap != nullptr) - { - minimap->toggle(); - return true; - } - return false; -} - -impHandler0(chatWindowShow) -{ - showHideWindow(chatWindow); - return true; -} - -impHandler0(shortcutWindowShow) -{ - showHideWindow(itemShortcutWindow); - return true; -} - -impHandler0(debugWindowShow) -{ - showHideWindow(debugWindow); - return true; -} - -impHandler0(socialWindowShow) -{ - showHideWindow(socialWindow); - return true; -} - -impHandler0(emoteShortcutWindowShow) -{ - showHideWindow(emoteShortcutWindow); - return true; -} - -impHandler0(outfitWindowShow) -{ - showHideWindow(outfitWindow); - return true; -} - -impHandler0(shopWindowShow) -{ - showHideWindow(shopWindow); - return true; -} - -impHandler0(dropShortcutWindowShow) -{ - showHideWindow(dropShortcutWindow); - return true; -} - -impHandler0(killStatsWindowShow) -{ - showHideWindow(killStats); - return true; -} - -impHandler0(spellShortcutWindowShow) -{ - showHideWindow(spellShortcutWindow); - return true; -} - -impHandler0(whoIsOnlineWindowShow) -{ - showHideWindow(whoIsOnline); - return true; -} - -impHandler0(didYouKnowWindowShow) -{ - showHideWindow(didYouKnowWindow); - return true; -} - -impHandler0(questsWindowShow) -{ - showHideWindow(questsWindow); - return true; -} - -impHandler0(bankWindowShow) -{ -#ifdef TMWA_SUPPORT - if (Net::getNetworkType() == ServerType::TMWATHENA) - return false; -#endif // TMWA_SUPPORT - - showHideWindow(bankWindow); - return true; -} - -impHandler0(cartWindowShow) -{ - if (Net::getNetworkType() == ServerType::TMWATHENA || - (localPlayer == nullptr) || - !localPlayer->getHaveCart()) - { - return false; - } - - showHideWindow(cartWindow); - if (inventoryWindow != nullptr) - inventoryWindow->updateDropButton(); - return true; -} - -impHandler0(updaterWindowShow) -{ - if (updaterWindow != nullptr) - updaterWindow->deleteSelf(); - else - DialogsManager::createUpdaterWindow(); - return true; -} - -impHandler0(quickWindowShow) -{ - if (setupWindow != nullptr) - { - if (setupWindow->isWindowVisible()) - setupWindow->doCancel(); - setupWindow->setVisible(Visible_true); - // TRANSLATORS: settings tab name - setupWindow->activateTab(_("Quick")); - setupWindow->requestMoveToTop(); - return true; - } - return false; -} - -impHandler0(mailWindowShow) -{ - showHideWindow(mailWindow); - return true; -} - -impHandler0(serverInfoWindowShow) -{ - if (serverInfoWindow != nullptr && - serverInfoWindow->isWindowVisible()) - { - serverInfoWindow->close(); - serverInfoWindow = nullptr; - } - else - { - serverInfoWindow = CREATEWIDGETR(ServerInfoWindow, - client->getCurrentServer()); - serverInfoWindow->requestMoveToTop(); - } - return true; -} - -impHandler(showItems) -{ - const std::string args = event.args; - if (args.empty()) - return false; - - Being *being = nullptr; - if (args[0] == ':') - { - being = actorManager->findBeing(fromInt(atoi( - args.substr(1).c_str()), BeingId)); - if ((being != nullptr) && being->getType() == ActorType::Monster) - being = nullptr; - } - else - { - being = actorManager->findBeingByName(args, ActorType::Player); - } - if (being == nullptr) - return true; - if (being == localPlayer) - { - if (equipmentWindow != nullptr && - !equipmentWindow->isWindowVisible()) - { - equipmentWindow->setVisible(Visible_true); - } - } - else - { - if (beingEquipmentWindow != nullptr) - { - beingEquipmentWindow->setBeing(being); - beingEquipmentWindow->setVisible(Visible_true); - } - } - return true; -} - -} // namespace Actions diff --git a/src/client.cpp b/src/client.cpp deleted file mode 100644 index c9c1ad976..000000000 --- a/src/client.cpp +++ /dev/null @@ -1,1981 +0,0 @@ -/* - * 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 . - */ - -#include "client.h" - -#include "chatlogger.h" -#include "configmanager.h" -#include "dirs.h" -#include "eventsmanager.h" -#include "game.h" -#include "graphicsmanager.h" -#include "main.h" -#include "party.h" -#include "settings.h" -#include "soundmanager.h" -#include "spellmanager.h" - -#include "being/localplayer.h" -#include "being/playerinfo.h" -#include "being/playerrelations.h" - -#include "const/net/net.h" - -#include "enums/being/attributesstrings.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/shortcut/dropshortcut.h" -#include "gui/shortcut/emoteshortcut.h" -#include "gui/shortcut/itemshortcut.h" -#include "gui/shortcut/spellshortcut.h" - -#include "gui/windows/changeemaildialog.h" -#include "gui/windows/changepassworddialog.h" -#include "gui/windows/charselectdialog.h" -#include "gui/windows/connectiondialog.h" -#include "gui/windows/equipmentwindow.h" -#include "gui/windows/logindialog.h" -#include "gui/windows/npcdialog.h" -#include "gui/windows/okdialog.h" -#include "gui/windows/registerdialog.h" -#include "gui/windows/serverdialog.h" -#include "gui/windows/setupwindow.h" -#include "gui/windows/updaterwindow.h" -#include "gui/windows/quitdialog.h" -#include "gui/windows/worldselectdialog.h" - -#include "gui/widgets/button.h" -#include "gui/widgets/createwidget.h" -#include "gui/widgets/desktop.h" -#include "gui/widgets/windowcontainer.h" - -#include "input/inputmanager.h" -#include "input/joystick.h" -#include "input/keyboardconfig.h" - -#include "input/touch/touchmanager.h" - -#include "net/charserverhandler.h" -#include "net/chathandler.h" -#include "net/download.h" -#include "net/gamehandler.h" -#include "net/generalhandler.h" -#include "net/guildhandler.h" -#include "net/inventoryhandler.h" -#include "net/ipc.h" -#include "net/loginhandler.h" -#include "net/net.h" -#include "net/updatetypeoperators.h" -#include "net/packetlimiter.h" -#include "net/partyhandler.h" - -#ifdef TMWA_SUPPORT -#include "net/tmwa/guildmanager.h" -#endif // TMWA_SUPPORT - -#include "particle/particleengine.h" - -#include "resources/dbmanager.h" -#include "resources/imagehelper.h" - -#include "resources/dye/dyepalette.h" - -#include "resources/resourcemanager/resourcemanager.h" - -#include "resources/sprite/spritereference.h" - -#include "utils/checkutils.h" -#include "utils/cpu.h" -#include "utils/delete2.h" -#include "utils/dumplibs.h" -#include "utils/dumpsizes.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 "listeners/assertlistener.h" -#include "listeners/errorlistener.h" - -#ifdef USE_OPENGL -#include "test/testlauncher.h" -#include "test/testmain.h" -#else // USE_OPENGL -#include "configuration.h" -#endif // USE_OPENGL - -#ifdef WIN32 -PRAGMA48(GCC diagnostic push) -PRAGMA48(GCC diagnostic ignored "-Wshadow") -#include -PRAGMA48(GCC diagnostic pop) -#include "fs/specialfolder.h" -#undef ERROR -#endif // WIN32 - -#ifdef ANDROID -#ifndef USE_SDL2 -PRAGMA48(GCC diagnostic push) -PRAGMA48(GCC diagnostic ignored "-Wshadow") -#include -PRAGMA48(GCC diagnostic pop) -#include -#endif // USE_SDL2 -#endif // ANDROID - -#include - -#ifdef USE_MUMBLE -#include "mumblemanager.h" -#endif // USE_MUMBLE - -PRAGMA48(GCC diagnostic push) -PRAGMA48(GCC diagnostic ignored "-Wshadow") -#ifdef USE_SDL2 -#include -#else // USE_SDL2 -#include -#endif // USE_SDL2 -PRAGMA48(GCC diagnostic pop) - -#include "debug.h" - -std::string errorMessage; -LoginData loginData; - -Client *client = nullptr; - -extern FPSmanager fpsManager; -extern int evolPacketOffset; - -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; -volatile bool isTerminate = false; - -namespace -{ - class AccountListener final : public ActionListener - { - public: - AccountListener() - { } - - A_DELETE_COPY(AccountListener) - - void action(const ActionEvent &event A_UNUSED) override final - { - client->setState(State::CHAR_SELECT); - } - } accountListener; - - class LoginListener final : public ActionListener - { - public: - LoginListener() - { } - - A_DELETE_COPY(LoginListener) - - void action(const ActionEvent &event A_UNUSED) override final - { - client->setState(State::PRE_LOGIN); - } - } loginListener; -} // namespace - -Client::Client() : - ActionListener(), - mCurrentServer(), - mGame(nullptr), - mCurrentDialog(nullptr), - mQuitDialog(nullptr), - mSetupButton(nullptr), - mVideoButton(nullptr), - mHelpButton(nullptr), - mAboutButton(nullptr), - mThemesButton(nullptr), - mPerfomanceButton(nullptr), -#ifdef ANDROID - mCloseButton(nullptr), -#endif // ANDROID - mState(State::CHOOSE_SERVER), - mOldState(State::START), - mSkin(nullptr), - mButtonPadding(1), - mButtonSpacing(3), - mPing(0), - mConfigAutoSaved(false) -{ - WindowManager::init(); -} - -void Client::testsInit() -{ - if (!settings.options.test.empty() && - settings.options.test != "99") - { - gameInit(); - } - else - { - initRand(); - logger = new Logger; - Dirs::initLocalDataDir(); - Dirs::initTempDir(); - Dirs::initConfigDir(); - GettextHelper::initLang(); - } -} - -void Client::gameInit() -{ - logger = new Logger; - - initRand(); - - assertListener = new AssertListener; - // 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->log("Log file: " + settings.logFileName); - logger->setLogFile(settings.logFileName); - -#ifdef USE_FUZZER - Fuzzer::init(); -#endif // USE_FUZZER - - if (settings.options.ipc == true) - IPC::start(); - if (settings.options.test.empty()) - ConfigManager::backupConfig("config.xml"); - ConfigManager::initConfiguration(); - settings.init(); - Net::loadIgnorePackets(); - setPathsDefaults(paths); - initFeatures(); - 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(); - - updateEnv(); - dumpLibs(); - dumpSizes(); - - // 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); - - PacketLimiter::initPacketLimiter(); -#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__) && !defined(UNITTESTS) - if (!settings.options.safeMode && - settings.options.renderer < 0 && - settings.options.test.empty() && - !settings.options.validate && - !config.getBoolValue("videodetected")) - { - graphicsManager.detectVideoSettings(); - } -#endif // !defined(ANDROID) && !defined(__APPLE__) && - // !defined(__native_client__) && !defined(UNITTESTS) -#endif // defined(USE_OPENGL) - - initGraphics(); - - touchManager.init(); - -#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(); - ActorSprite::load(); - 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 - playerRelations.init(); - Joystick::init(); - WindowManager::createWindows(); - - keyboard.update(); - if (joystick != nullptr) - joystick->update(); - - // Initialize default server - mCurrentServer.hostname = settings.options.serverName; - mCurrentServer.port = settings.options.serverPort; - if (!settings.options.serverType.empty()) - { - mCurrentServer.type = ServerInfo::parseType( - settings.options.serverType); - } - - loginData.username = settings.options.username; - loginData.password = settings.options.password; - LoginDialog::savedPassword = settings.options.password; - loginData.remember = (serverConfig.getValue("remember", 1) != 0); - loginData.registerLogin = false; - - if (mCurrentServer.hostname.empty()) - { - mCurrentServer.hostname = branding.getValue("defaultServer", ""); - settings.options.serverName = mCurrentServer.hostname; - } - - if (mCurrentServer.port == 0) - { - mCurrentServer.port = CAST_U16(branding.getValue( - "defaultPort", CAST_S32(DEFAULT_PORT))); - mCurrentServer.type = ServerInfo::parseType( - branding.getValue("defaultServerType", "tmwathena")); - } - - chatLogger->setServerName(mCurrentServer.hostname); - - if (loginData.username.empty() && loginData.remember) - loginData.username = serverConfig.getValue("username", ""); - - 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); - initConfigListeners(); - - settings.guiAlpha = config.getFloatValue("guialpha"); - optionChanged("fpslimit"); - - start_time = time(nullptr); - - PlayerInfo::init(); - -#ifdef ANDROID -#ifndef USE_SDL2 - WindowManager::updateScreenKeyboard(SDL_GetScreenKeyboardHeight(nullptr)); -#endif // USE_SDL2 -#endif // ANDROID - -#ifdef USE_MUMBLE - if (!mumbleManager) - mumbleManager = new MumbleManager; -#endif // USE_MUMBLE - - mSkin = theme->load("windowmenu.xml", ""); - if (mSkin != nullptr) - { - mButtonPadding = mSkin->getPadding(); - mButtonSpacing = mSkin->getOption("spacing", 3); - } - if (settings.options.error) - inputManager.executeAction(InputAction::ERROR); - - if (settings.options.validate == true) - runValidate(); -} - -Client::~Client() -{ - if (!settings.options.testMode) - gameClear(); - else - testsClear(); - CHECKLISTENERS -} - -void Client::initConfigListeners() -{ - config.addListener("fpslimit", this); - config.addListener("guialpha", this); - config.addListener("gamma", this); - config.addListener("enableGamma", this); - config.addListener("particleEmitterSkip", this); - config.addListener("vsync", this); - config.addListener("repeateDelay", this); - config.addListener("repeateInterval", this); - config.addListener("logInput", this); -} - -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", - "keprohm.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::testsClear() -{ - if (!settings.options.test.empty()) - gameClear(); - else - BeingInfo::clear(); -} - -void Client::gameClear() -{ - if (logger != nullptr) - logger->log1("Quitting1"); - isTerminate = true; - config.removeListeners(this); - - delete2(assertListener); - - IPC::stop(); - eventsManager.shutdown(); - WindowManager::deleteWindows(); - if (windowContainer != nullptr) - windowContainer->slowLogic(); - - stopTimers(); - DbManager::unloadDb(); - - if (loginHandler != nullptr) - loginHandler->clearWorlds(); - - if (chatHandler != nullptr) - chatHandler->clear(); - - if (charServerHandler != nullptr) - charServerHandler->clear(); - - delete2(ipc); - -#ifdef USE_MUMBLE - delete2(mumbleManager); -#endif // USE_MUMBLE - - PlayerInfo::deinit(); - - // Before config.write() since it writes the shortcuts to the config - for (unsigned f = 0; f < SHORTCUT_TABS; f ++) - delete2(itemShortcut[f]) - delete2(emoteShortcut); - delete2(dropShortcut); - - playerRelations.store(); - - if (logger != nullptr) - logger->log1("Quitting2"); - - delete2(mCurrentDialog); - delete2(popupManager); - delete2(dialogsManager); - delete2(gui); - - if (inventoryHandler != nullptr) - inventoryHandler->clear(); - - if (logger != nullptr) - logger->log1("Quitting3"); - - touchManager.clear(); - - GraphicsManager::deleteRenderers(); - - if (logger != nullptr) - logger->log1("Quitting4"); - - XML::cleanupXML(); - - if (logger != nullptr) - logger->log1("Quitting5"); - - BeingInfo::clear(); - - // Shutdown sound - soundManager.close(); - - if (logger != nullptr) - logger->log1("Quitting6"); - - ActorSprite::unload(); - - 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(); -} - -int Client::testsExec() -{ -#ifdef USE_OPENGL - if (settings.options.test.empty()) - { - TestMain test; - return test.exec(); - } - else - { - TestLauncher launcher(settings.options.test); - return launcher.exec(); - } -#else // USE_OPENGL - - return 0; -#endif // USE_OPENGL -} - -#define ADDBUTTON(var, object) var = object; \ - x -= var->getWidth() + mButtonSpacing; \ - var->setPosition(x, mButtonPadding); \ - top->add(var); - -void Client::stateConnectGame1() -{ - if ((gameHandler != nullptr) && - (loginHandler != nullptr) && - gameHandler->isConnected()) - { - loginHandler->disconnect(); - } -} - -void Client::stateConnectServer1() -{ - if (mOldState == State::CHOOSE_SERVER) - { - settings.serverName = mCurrentServer.hostname; - ConfigManager::initServerConfig(mCurrentServer.hostname); - PacketLimiter::initPacketLimiter(); - initTradeFilter(); - Dirs::initUsersDir(); - playerRelations.init(); - - // Initialize the item and emote shortcuts. - for (unsigned f = 0; f < SHORTCUT_TABS; f ++) - { - delete itemShortcut[f]; - itemShortcut[f] = new ItemShortcut(f); - } - delete emoteShortcut; - emoteShortcut = new EmoteShortcut; - - // Initialize the drop shortcuts. - delete dropShortcut; - dropShortcut = new DropShortcut; - - initFeatures(); - PlayerInfo::loadData(); - loginData.registerUrl = mCurrentServer.registerUrl; - loginData.packetVersion = mCurrentServer.packetVersion; - if (!mCurrentServer.onlineListUrl.empty()) - settings.onlineListUrl = mCurrentServer.onlineListUrl; - else - settings.onlineListUrl = settings.serverName; - settings.persistentIp = mCurrentServer.persistentIp; - settings.supportUrl = mCurrentServer.supportUrl; - settings.updateMirrors = mCurrentServer.updateMirrors; - settings.enableRemoteCommands = (serverConfig.getValue( - "enableRemoteCommands", 1) != 0); - - if (settings.options.username.empty()) - { - if (loginData.remember) - loginData.username = serverConfig.getValue("username", ""); - else - loginData.username.clear(); - } - else - { - loginData.username = settings.options.username; - } - settings.login = loginData.username; - WindowManager::updateTitle(); - - loginData.remember = (serverConfig.getValue("remember", 1) != 0); - Net::connectToServer(mCurrentServer); - -#ifdef USE_MUMBLE - if (mumbleManager) - mumbleManager->setServer(mCurrentServer.hostname); -#endif // USE_MUMBLE - -#ifdef TMWA_SUPPORT - GuildManager::init(); -#endif // TMWA_SUPPORT - - if (!mConfigAutoSaved) - { - mConfigAutoSaved = true; - config.write(); - } - } - else if (mOldState != State::CHOOSE_SERVER && - (loginHandler != nullptr) && - loginHandler->isConnected()) - { - mState = State::PRE_LOGIN; - } -} - -void Client::stateWorldSelect1() -{ - if (mOldState == State::UPDATE && - (loginHandler != nullptr)) - { - if (loginHandler->getWorlds().size() < 2) - mState = State::PRE_LOGIN; - } -} - -void Client::stateGame1() -{ - if (gui == nullptr) - return; - - BasicContainer2 *const top = static_cast( - 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()); -} - -void Client::stateSwitchLogin1() -{ - if (mOldState == State::GAME && - (gameHandler != nullptr)) - { - gameHandler->disconnect(); - } -} - -int Client::gameExec() -{ - int lastTickTime = tick_time; - - while (mState != State::EXIT) - { - PROFILER_START(); - if (eventsManager.handleEvents()) - continue; - - BLOCK_START("Client::gameExec 3") - if (generalHandler != nullptr) - generalHandler->flushNetwork(); - BLOCK_END("Client::gameExec 3") - - 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 != nullptr) - mGame->logic(); - else if (gui != nullptr) - gui->handleInput(); - - ++lastTickTime; - k ++; - } - soundManager.logic(); - - logic_count += k; - if (gui != nullptr) - gui->slowLogic(); - if (mGame != nullptr) - 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(); - } - else if (mState == State::CONNECT_SERVER) - { - stateConnectServer1(); - } - else if (mState == State::WORLD_SELECT) - { - stateWorldSelect1(); - } - else if (mOldState == State::START || - (mOldState == State::GAME && mState != State::GAME)) - { - stateGame1(); - } - else if (mState == State::SWITCH_LOGIN) - { - stateSwitchLogin1(); - } - BLOCK_END("Client::gameExec 6") - - if (mState != mOldState) - { - BLOCK_START("Client::gameExec 7") - PlayerInfo::stateChange(mState); - - if (mOldState == State::GAME) - { - delete2(mGame); - assertListener = new AssertListener; - Game::clearInstance(); - ResourceManager::cleanOrphans(); - Party::clearParties(); - Guild::clearGuilds(); - NpcDialog::clearDialogs(); - if (guildHandler != nullptr) - guildHandler->clear(); - if (partyHandler != nullptr) - partyHandler->clear(); - if (chatLogger != nullptr) - chatLogger->clear(); - if (!settings.options.dataPath.empty()) - UpdaterWindow::unloadMods(settings.options.dataPath); - else - UpdaterWindow::unloadMods(settings.oldUpdates); - if (!settings.options.skipUpdate) - UpdaterWindow::unloadMods(settings.oldUpdates + "/fix/"); - } - else if (mOldState == State::CHAR_SELECT) - { - if (mState != State::CHANGEPASSWORD && - charServerHandler != nullptr) - { - charServerHandler->clear(); - } - } - - 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 != nullptr) - { - mQuitDialog->scheduleDelete(); - mQuitDialog = nullptr; - } - BLOCK_END("Client::gameExec 7") - - BLOCK_START("Client::gameExec 8") - switch (mState) - { - case State::CHOOSE_SERVER: - { - BLOCK_START("Client::gameExec STATE_CHOOSE_SERVER") - logger->log1("State: CHOOSE SERVER"); - unloadData(); - - // Allow changing this using a server choice dialog - // We show the dialog box only if the command-line - // options weren't set. - if (settings.options.serverName.empty() && - settings.options.serverPort == 0 && - !branding.getValue("onlineServerList", "a").empty()) - { - // Don't allow an alpha opacity - // lower than the default value - theme->setMinimumOpacity(0.8F); - - CREATEWIDGETV(mCurrentDialog, ServerDialog, - &mCurrentServer, - settings.configDir); - } - else - { - mState = State::CONNECT_SERVER; - - // Reset options so that cancelling or connect - // timeout will show the server dialog. - settings.options.serverName.clear(); - settings.options.serverPort = 0; - } - BLOCK_END("Client::gameExec STATE_CHOOSE_SERVER") - break; - } - - case State::CONNECT_SERVER: - BLOCK_START("Client::gameExec State::CONNECT_SERVER") - logger->log1("State: CONNECT SERVER"); - loginData.updateHosts.clear(); - CREATEWIDGETV(mCurrentDialog, ConnectionDialog, - // TRANSLATORS: connection dialog header - _("Connecting to server"), - State::SWITCH_SERVER); - TranslationManager::loadCurrentLang(); - TranslationManager::loadDictionaryLang(); - BLOCK_END("Client::gameExec State::CONNECT_SERVER") - break; - - case State::PRE_LOGIN: - logger->log1("State: PRE_LOGIN"); - break; - - case State::LOGIN: - BLOCK_START("Client::gameExec State::LOGIN") - logger->log1("State: LOGIN"); - // Don't allow an alpha opacity - // lower than the default value - theme->setMinimumOpacity(0.8F); - - if (packetVersion == 0) - { - packetVersion = loginData.packetVersion; - if (packetVersion != 0) - { - loginHandler->updatePacketVersion(); - logger->log("Preconfigured packet version: %d", - packetVersion); - } - } - - loginData.updateType = static_cast( - serverConfig.getValue("updateType", 0)); - - mSearchHash = Net::Download::adlerBuffer( - const_cast(mCurrentServer.hostname.c_str()), - CAST_S32(mCurrentServer.hostname.size())); - if (settings.options.username.empty() || - settings.options.password.empty()) - { - CREATEWIDGETV(mCurrentDialog, LoginDialog, - loginData, - &mCurrentServer, - &settings.options.updateHost); - } - else - { - mState = State::LOGIN_ATTEMPT; - // Clear the password so that when login fails, the - // dialog will show up next time. - settings.options.password.clear(); - } - BLOCK_END("Client::gameExec State::LOGIN") - break; - - case State::LOGIN_ATTEMPT: - BLOCK_START("Client::gameExec State::LOGIN_ATTEMPT") - logger->log1("State: LOGIN ATTEMPT"); - CREATEWIDGETV(mCurrentDialog, ConnectionDialog, - // TRANSLATORS: connection dialog header - _("Logging in"), - State::SWITCH_SERVER); - if (loginHandler != nullptr) - loginHandler->loginOrRegister(&loginData); - BLOCK_END("Client::gameExec State::LOGIN_ATTEMPT") - break; - - case State::WORLD_SELECT: - BLOCK_START("Client::gameExec State::WORLD_SELECT") - logger->log1("State: WORLD SELECT"); - { - TranslationManager::loadCurrentLang(); - TranslationManager::loadDictionaryLang(); - if (loginHandler == nullptr) - { - BLOCK_END("Client::gameExec State::WORLD_SELECT") - break; - } - Worlds worlds = loginHandler->getWorlds(); - - if (worlds.empty()) - { - // Trust that the netcode knows what it's doing - mState = State::UPDATE; - } - else if (worlds.size() == 1) - { - loginHandler->chooseServer( - 0, mCurrentServer.persistentIp); - mState = State::UPDATE; - } - else - { - CREATEWIDGETV(mCurrentDialog, WorldSelectDialog, - worlds); - if (settings.options.chooseDefault) - { - static_cast(mCurrentDialog) - ->action(ActionEvent(nullptr, "ok")); - } - } - } - BLOCK_END("Client::gameExec State::WORLD_SELECT") - break; - - case State::WORLD_SELECT_ATTEMPT: - BLOCK_START("Client::gameExec State::WORLD_SELECT_ATTEMPT") - logger->log1("State: WORLD SELECT ATTEMPT"); - CREATEWIDGETV(mCurrentDialog, ConnectionDialog, - // TRANSLATORS: connection dialog header - _("Entering game world"), - State::WORLD_SELECT); - BLOCK_END("Client::gameExec State::WORLD_SELECT_ATTEMPT") - break; - - case State::UPDATE: - BLOCK_START("Client::gameExec State::UPDATE") - logger->log1("State: UPDATE"); - - // Determine which source to use for the update host - if (!settings.options.updateHost.empty()) - settings.updateHost = settings.options.updateHost; - else - settings.updateHost = loginData.updateHost; - Dirs::initUpdatesDir(); - - if (!settings.oldUpdates.empty()) - UpdaterWindow::unloadUpdates(settings.oldUpdates); - - if (settings.options.skipUpdate) - { - mState = State::LOAD_DATA; - settings.oldUpdates.clear(); - UpdaterWindow::loadDirMods(settings.options.dataPath); - } - else if ((loginData.updateType & UpdateType::Skip) != 0) - { - settings.oldUpdates = pathJoin(settings.localDataDir, - settings.updatesDir); - UpdaterWindow::loadLocalUpdates(settings.oldUpdates); - mState = State::LOAD_DATA; - } - else - { - settings.oldUpdates = pathJoin(settings.localDataDir, - settings.updatesDir); - CREATEWIDGETV(mCurrentDialog, UpdaterWindow, - settings.updateHost, - settings.oldUpdates, - settings.options.dataPath.empty(), - loginData.updateType); - } - BLOCK_END("Client::gameExec State::UPDATE") - break; - - case State::LOAD_DATA: - { - BLOCK_START("Client::gameExec State::LOAD_DATA") - logger->log1("State: LOAD DATA"); - - loadData(); - - mState = State::GET_CHARACTERS; - BLOCK_END("Client::gameExec State::LOAD_DATA") - break; - } - case State::GET_CHARACTERS: - BLOCK_START("Client::gameExec State::GET_CHARACTERS") - logger->log1("State: GET CHARACTERS"); - CREATEWIDGETV(mCurrentDialog, ConnectionDialog, - // TRANSLATORS: connection dialog header - _("Requesting characters"), - State::SWITCH_SERVER); - if (charServerHandler != nullptr) - charServerHandler->requestCharacters(); - BLOCK_END("Client::gameExec State::GET_CHARACTERS") - break; - - case State::CHAR_SELECT: - BLOCK_START("Client::gameExec State::CHAR_SELECT") - logger->log1("State: CHAR SELECT"); - // Don't allow an alpha opacity - // lower than the default value - theme->setMinimumOpacity(0.8F); - - settings.login = loginData.username; - WindowManager::updateTitle(); - - CREATEWIDGETV(mCurrentDialog, CharSelectDialog, - loginData); - - if (!(static_cast(mCurrentDialog)) - ->selectByName(settings.options.character, - CharSelectDialog::Choose)) - { - (static_cast(mCurrentDialog)) - ->selectByName( - serverConfig.getValue("lastCharacter", ""), - settings.options.chooseDefault ? - CharSelectDialog::Choose : - CharSelectDialog::Focus); - } - - // Choosing character on the command line should work only - // once, clear it so that 'switch character' works. - settings.options.character.clear(); - BLOCK_END("Client::gameExec State::CHAR_SELECT") - break; - - case State::CONNECT_GAME: - BLOCK_START("Client::gameExec State::CONNECT_GAME") - logger->log1("State: CONNECT GAME"); - CREATEWIDGETV(mCurrentDialog, ConnectionDialog, - // TRANSLATORS: connection dialog header - _("Connecting to the game server"), - State::CHOOSE_SERVER); - if (gameHandler != nullptr) - gameHandler->connect(); - BLOCK_END("Client::gameExec State::CONNECT_GAME") - break; - - case State::CHANGE_MAP: - BLOCK_START("Client::gameExec State::CHANGE_MAP") - logger->log1("State: CHANGE_MAP"); - CREATEWIDGETV(mCurrentDialog, ConnectionDialog, - // TRANSLATORS: connection dialog header - _("Changing game servers"), - State::SWITCH_CHARACTER); - if (gameHandler != nullptr) - gameHandler->connect(); - BLOCK_END("Client::gameExec State::CHANGE_MAP") - break; - - case State::GAME: - BLOCK_START("Client::gameExec State::GAME") - if (localPlayer != nullptr) - { - logger->log("Memorizing selected character %s", - localPlayer->getName().c_str()); - serverConfig.setValue("lastCharacter", - localPlayer->getName()); -#ifdef USE_MUMBLE - if (mumbleManager) - mumbleManager->setPlayer(localPlayer->getName()); -#endif // USE_MUMBLE - } - - // Fade out logon-music here too to give the desired effect - // of "flowing" into the game. - soundManager.fadeOutMusic(1000); - - // Allow any alpha opacity - theme->setMinimumOpacity(-1.0F); - - if (chatLogger != nullptr) - chatLogger->setServerName(settings.serverName); - -#ifdef ANDROID - delete2(mCloseButton); -#endif // ANDROID - - delete2(mSetupButton); - delete2(mVideoButton); - delete2(mThemesButton); - delete2(mAboutButton); - delete2(mHelpButton); - delete2(mPerfomanceButton); - delete2(desktop); - - mCurrentDialog = nullptr; - - logger->log1("State: GAME"); - if (generalHandler != nullptr) - generalHandler->reloadPartially(); - mGame = new Game; - BLOCK_END("Client::gameExec State::GAME") - break; - - case State::LOGIN_ERROR: - BLOCK_START("Client::gameExec State::LOGIN_ERROR") - logger->log1("State: LOGIN ERROR"); - CREATEWIDGETV(mCurrentDialog, OkDialog, - // TRANSLATORS: error dialog header - _("Error"), - errorMessage, - // TRANSLATORS: ok dialog button - _("Close"), - DialogType::ERROR, - Modal_true, - ShowCenter_true, - nullptr, - 260); - mCurrentDialog->addActionListener(&loginListener); - mCurrentDialog = nullptr; // OkDialog deletes itself - BLOCK_END("Client::gameExec State::LOGIN_ERROR") - break; - - case State::ACCOUNTCHANGE_ERROR: - BLOCK_START("Client::gameExec State::ACCOUNTCHANGE_ERROR") - logger->log1("State: ACCOUNT CHANGE ERROR"); - CREATEWIDGETV(mCurrentDialog, OkDialog, - // TRANSLATORS: error dialog header - _("Error"), - errorMessage, - // TRANSLATORS: ok dialog button - _("Close"), - DialogType::ERROR, - Modal_true, - ShowCenter_true, - nullptr, - 260); - mCurrentDialog->addActionListener(&accountListener); - mCurrentDialog = nullptr; // OkDialog deletes itself - BLOCK_END("Client::gameExec State::ACCOUNTCHANGE_ERROR") - break; - - case State::REGISTER_PREP: - BLOCK_START("Client::gameExec State::REGISTER_PREP") - logger->log1("State: REGISTER_PREP"); - CREATEWIDGETV(mCurrentDialog, ConnectionDialog, - // TRANSLATORS: connection dialog header - _("Requesting registration details"), - State::LOGIN); - loginHandler->getRegistrationDetails(); - BLOCK_END("Client::gameExec State::REGISTER_PREP") - break; - - case State::REGISTER: - logger->log1("State: REGISTER"); - CREATEWIDGETV(mCurrentDialog, RegisterDialog, - loginData); - break; - - case State::REGISTER_ATTEMPT: - BLOCK_START("Client::gameExec State::REGISTER_ATTEMPT") - logger->log("Username is %s", loginData.username.c_str()); - if (loginHandler != nullptr) - loginHandler->registerAccount(&loginData); - BLOCK_END("Client::gameExec State::REGISTER_ATTEMPT") - break; - - case State::CHANGEPASSWORD: - BLOCK_START("Client::gameExec State::CHANGEPASSWORD") - logger->log1("State: CHANGE PASSWORD"); - CREATEWIDGETV(mCurrentDialog, ChangePasswordDialog, - loginData); - mCurrentDialog->setVisible(Visible_true); - BLOCK_END("Client::gameExec State::CHANGEPASSWORD") - break; - - case State::CHANGEPASSWORD_ATTEMPT: - BLOCK_START("Client::gameExec " - "State::CHANGEPASSWORD_ATTEMPT") - logger->log1("State: CHANGE PASSWORD ATTEMPT"); - if (loginHandler != nullptr) - { - loginHandler->changePassword(loginData.password, - loginData.newPassword); - } - BLOCK_END("Client::gameExec State::CHANGEPASSWORD_ATTEMPT") - break; - - case State::CHANGEPASSWORD_SUCCESS: - BLOCK_START("Client::gameExec " - "State::CHANGEPASSWORD_SUCCESS") - logger->log1("State: CHANGE PASSWORD SUCCESS"); - CREATEWIDGETV(mCurrentDialog, OkDialog, - // TRANSLATORS: password change message header - _("Password Change"), - // TRANSLATORS: password change message text - _("Password changed successfully!"), - // TRANSLATORS: ok dialog button - _("OK"), - DialogType::ERROR, - Modal_true, - ShowCenter_true, - nullptr, - 260); - mCurrentDialog->addActionListener(&accountListener); - mCurrentDialog = nullptr; // OkDialog deletes itself - loginData.password = loginData.newPassword; - loginData.newPassword.clear(); - BLOCK_END("Client::gameExec State::CHANGEPASSWORD_SUCCESS") - break; - - case State::CHANGEEMAIL: - logger->log1("State: CHANGE EMAIL"); - CREATEWIDGETV(mCurrentDialog, - ChangeEmailDialog, - loginData); - mCurrentDialog->setVisible(Visible_true); - break; - - case State::CHANGEEMAIL_ATTEMPT: - logger->log1("State: CHANGE EMAIL ATTEMPT"); - if (loginHandler != nullptr) - loginHandler->changeEmail(loginData.email); - break; - - case State::CHANGEEMAIL_SUCCESS: - logger->log1("State: CHANGE EMAIL SUCCESS"); - CREATEWIDGETV(mCurrentDialog, OkDialog, - // TRANSLATORS: email change message header - _("Email Change"), - // TRANSLATORS: email change message text - _("Email changed successfully!"), - // TRANSLATORS: ok dialog button - _("OK"), - DialogType::ERROR, - Modal_true, - ShowCenter_true, - nullptr, - 260); - mCurrentDialog->addActionListener(&accountListener); - mCurrentDialog = nullptr; // OkDialog deletes itself - break; - - case State::SWITCH_SERVER: - BLOCK_START("Client::gameExec State::SWITCH_SERVER") - logger->log1("State: SWITCH SERVER"); - - if (loginHandler != nullptr) - loginHandler->disconnect(); - if (gameHandler != nullptr) - { - gameHandler->disconnect(); - gameHandler->clear(); - } - settings.serverName.clear(); - settings.login.clear(); - WindowManager::updateTitle(); - serverConfig.write(); - serverConfig.unload(); - if (setupWindow != nullptr) - setupWindow->externalUnload(); - - mState = State::CHOOSE_SERVER; - BLOCK_END("Client::gameExec State::SWITCH_SERVER") - break; - - case State::SWITCH_LOGIN: - BLOCK_START("Client::gameExec State::SWITCH_LOGIN") - logger->log1("State: SWITCH LOGIN"); - - if (loginHandler != nullptr) - { - loginHandler->logout(); - loginHandler->disconnect(); - } - if (gameHandler != nullptr) - gameHandler->disconnect(); - if (loginHandler != nullptr) - loginHandler->connect(); - - settings.login.clear(); - WindowManager::updateTitle(); - mState = State::LOGIN; - BLOCK_END("Client::gameExec State::SWITCH_LOGIN") - break; - - case State::SWITCH_CHARACTER: - BLOCK_START("Client::gameExec State::SWITCH_CHARACTER") - logger->log1("State: SWITCH CHARACTER"); - - // Done with game - if (gameHandler != nullptr) - gameHandler->disconnect(); - - settings.login.clear(); - WindowManager::updateTitle(); - mState = State::GET_CHARACTERS; - BLOCK_END("Client::gameExec State::SWITCH_CHARACTER") - break; - - case State::LOGOUT_ATTEMPT: - logger->log1("State: LOGOUT ATTEMPT"); - break; - - case State::WAIT: - logger->log1("State: WAIT"); - break; - - case State::EXIT: - BLOCK_START("Client::gameExec State::EXIT") - logger->log1("State: EXIT"); - Net::unload(); - BLOCK_END("Client::gameExec State::EXIT") - break; - - case State::FORCE_QUIT: - BLOCK_START("Client::gameExec State::FORCE_QUIT") - logger->log1("State: FORCE QUIT"); - if (generalHandler != nullptr) - generalHandler->unload(); - mState = State::EXIT; - BLOCK_END("Client::gameExec State::FORCE_QUIT") - break; - - case State::ERROR: - BLOCK_START("Client::gameExec State::ERROR") - config.write(); - if (mOldState == State::GAME) - serverConfig.write(); - logger->log1("State: ERROR"); - logger->log("Error: %s\n", errorMessage.c_str()); - mCurrentDialog = DialogsManager::openErrorDialog( - // TRANSLATORS: error message header - _("Error"), - errorMessage, - Modal_true); - mCurrentDialog->addActionListener(&errorListener); - mCurrentDialog = nullptr; // OkDialog deletes itself - gameHandler->disconnect(); - BLOCK_END("Client::gameExec State::ERROR") - break; - - case State::AUTORECONNECT_SERVER: - // ++++++ - break; - - case State::START: - default: - mState = State::FORCE_QUIT; - break; - } - BLOCK_END("Client::gameExec 8") - } - PROFILER_END(); - } - - return 0; -} - -void Client::optionChanged(const std::string &name) -{ - if (name == "fpslimit") - { - const int fpsLimit = config.getIntValue("fpslimit"); - settings.limitFps = fpsLimit > 0; - WindowManager::setFramerate(fpsLimit); - } - else if (name == "guialpha" || - name == "enableGuiOpacity") - { - const float alpha = config.getFloatValue("guialpha"); - settings.guiAlpha = alpha; - ImageHelper::setEnableAlpha(alpha != 1.0F && - config.getBoolValue("enableGuiOpacity")); - } - else if (name == "gamma" || - name == "enableGamma") - { - WindowManager::applyGamma(); - } - else if (name == "particleEmitterSkip") - { - ParticleEngine::emitterSkip = - config.getIntValue("particleEmitterSkip") + 1; - } - else if (name == "vsync") - { - WindowManager::applyVSync(); - } - else if (name == "repeateInterval" || - name == "repeateDelay") - { - WindowManager::applyKeyRepeat(); - } -} - -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; - } - - if (setupWindow != nullptr) - { - setupWindow->setVisible(fromBool( - !setupWindow->isWindowVisible(), Visible)); - if (setupWindow->isWindowVisible()) - { - if (!tab.empty()) - setupWindow->activateTab(tab); - setupWindow->requestMoveToTop(); - } - } -} - -void Client::initFeatures() -{ - features.init(paths.getStringValue("featuresFile"), - UseVirtFs_true, - SkipError_true); - setFeaturesDefaults(features); - settings.fixDeadAnimation = features.getBoolValue("fixDeadAnimation"); -} - -void Client::initPaths() -{ - settings.gmCommandSymbol = paths.getStringValue("gmCommandSymbol"); - settings.gmCharCommandSymbol = paths.getStringValue("gmCharCommandSymbol"); - settings.linkCommandSymbol = paths.getStringValue("linkCommandSymbol"); - if (settings.linkCommandSymbol.empty()) - settings.linkCommandSymbol = "="; - settings.overweightPercent = paths.getIntValue("overweightPercent"); - settings.playerNameOffset = paths.getIntValue( - "playerNameOffset"); - settings.playerBadgeAtRightOffset = paths.getIntValue( - "playerBadgeAtRightOffset"); - settings.unknownSkillsAutoTab = paths.getBoolValue("unknownSkillsAutoTab"); - settings.enableNewMailSystem = paths.getBoolValue("enableNewMailSystem"); -} - -void Client::initTradeFilter() -{ - const std::string tradeListName = - settings.serverConfigDir + "/tradefilter.txt"; - - std::ofstream tradeFile; - struct stat statbuf; - - if ((stat(tradeListName.c_str(), &statbuf) != 0) || - !S_ISREG(statbuf.st_mode)) - { - tradeFile.open(tradeListName.c_str(), - std::ios::out); - if (tradeFile.is_open()) - { - tradeFile << ": sell" << std::endl; - tradeFile << ": buy" << std::endl; - tradeFile << ": trade" << std::endl; - tradeFile << "i sell" << std::endl; - tradeFile << "i buy" << std::endl; - tradeFile << "i trade" << std::endl; - tradeFile << "i trading" << std::endl; - tradeFile << "i am buy" << std::endl; - tradeFile << "i am sell" << std::endl; - tradeFile << "i am trade" << std::endl; - tradeFile << "i am trading" << std::endl; - tradeFile << "i'm buy" << std::endl; - tradeFile << "i'm sell" << std::endl; - tradeFile << "i'm trade" << std::endl; - tradeFile << "i'm trading" << std::endl; - } - else - { - reportAlways("Error opening file for writing: %s", - tradeListName.c_str()); - } - tradeFile.close(); - } -} - -bool Client::isTmw() -{ - const std::string &name = settings.serverName; - if (name == "server.themanaworld.org" || - name == "themanaworld.org" || - name == "167.114.129.72") - { - return true; - } - return false; -} - -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() -{ - if ((gameHandler == nullptr) || - !gameHandler->mustPing()) - { - return; - } - - if (get_elapsed_time1(mPing) > 1500) - { - mPing = tick_time; - if (mState == State::UPDATE || - mState == State::LOGIN || - mState == State::LOGIN_ATTEMPT || - mState == State::REGISTER || - mState == State::REGISTER_ATTEMPT) - { - if (loginHandler != nullptr) - loginHandler->ping(); - if (generalHandler != nullptr) - generalHandler->flushSend(); - } - else if (mState == State::CHAR_SELECT) - { - if (charServerHandler != nullptr) - charServerHandler->ping(); - if (generalHandler != nullptr) - generalHandler->flushSend(); - } - } -} - -void Client::loadData() -{ - // 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( - 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(); - if (SpriteReference::Empty == nullptr) - { - SpriteReference::Empty = new SpriteReference( - paths.getStringValue("spriteErrorFile"), - 0); - } - - if (BeingInfo::unknown == nullptr) - BeingInfo::unknown = new BeingInfo; - - initFeatures(); - TranslationManager::loadCurrentLang(); - TranslationManager::loadDictionaryLang(); - PlayerInfo::stateChange(mState); - - delete spellManager; - spellManager = new SpellManager; - delete spellShortcut; - spellShortcut = new SpellShortcut; - - AttributesEnum::init(); - DbManager::loadDb(); - EquipmentWindow::prepareSlotNames(); - - ActorSprite::load(); - - if (desktop != nullptr) - desktop->reloadWallpaper(); -} - -void Client::unloadData() -{ - DbManager::unloadDb(); - mCurrentServer.supportUrl.clear(); - settings.supportUrl.clear(); - if (settings.options.dataPath.empty()) - { - // Add customdata directory - VirtFs::searchAndRemoveArchives( - "customdata/", - "zip"); - } - - if (!settings.oldUpdates.empty()) - { - UpdaterWindow::unloadUpdates(settings.oldUpdates); - settings.oldUpdates.clear(); - } - - if (!settings.options.skipUpdate) - { - VirtFs::searchAndRemoveArchives( - pathJoin(settings.updatesDir, "local/"), - "zip"); - - VirtFs::unmountDirSilent(pathJoin( - settings.localDataDir, - settings.updatesDir, - "local/")); - } - - ResourceManager::clearCache(); - - loginData.clearUpdateHost(); - serverVersion = 0; - packetVersion = 0; - tmwServerVersion = 0; - evolPacketOffset = 0; -} - -void Client::runValidate() -{ - loadData(); - WindowManager::createValidateWindows(); - - WindowManager::deleteValidateWindows(); - unloadData(); - delete2(client); - VirtFs::deinit(); - exit(0); -} diff --git a/src/client.h b/src/client.h index 6c6888f52..feead38e4 100644 --- a/src/client.h +++ b/src/client.h @@ -1,7 +1,5 @@ /* * 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. @@ -25,149 +23,7 @@ #ifdef DYECMD #include "progs/dyecmd/client.h" - #else // DYECMD - -#include "enums/state.h" - -#include "listeners/actionlistener.h" -#include "listeners/configlistener.h" - -#include "net/serverinfo.h" - -#include "localconsts.h" - -class Button; -class Game; -class LoginData; -class Skin; -class Window; -class QuitDialog; - -extern bool isSafeMode; -extern int serverVersion; -extern unsigned int tmwServerVersion; -extern time_t start_time; -extern int textures_count; - -extern std::string errorMessage; -extern LoginData loginData; - -/** - * The core part of the client. This class initializes all subsystems, runs - * the event loop, and shuts everything down again. - */ -class Client final : public ConfigListener, - public ActionListener -{ - public: - Client(); - - A_DELETE_COPY(Client) - - ~Client(); - - void gameInit(); - - void testsInit(); - - int gameExec(); - - static int testsExec(); - - void setState(const StateT state) - { mState = state; } - - StateT getState() const noexcept2 A_WARN_UNUSED - { return mState; } - - static bool isTmw() A_WARN_UNUSED; - - void optionChanged(const std::string &name) override final; - - void action(const ActionEvent &event) override final; - - static void initTradeFilter(); - - void moveButtons(const int width); - - void windowRemoved(const Window *const window); - - void slowLogic(); - - ServerInfo &getCurrentServer() - { return mCurrentServer; } - - private: - void initSoundManager(); - - void initConfigListeners(); - - static void initGraphics(); - - static void initFeatures(); - - static void initPaths(); - - void gameClear(); - - void testsClear(); - -#ifdef ANDROID - static void logVars(); -#else // ANDROID - - static void logVars() A_CONST; -#endif // ANDROID - - void stateConnectGame1(); - - void stateConnectServer1(); - - void stateWorldSelect1(); - - void stateGame1(); - - void stateSwitchLogin1(); - - void loadData(); - - void unloadData(); - - void runValidate() -#ifndef BAD_CILKPLUS - __attribute__ ((noreturn)) -#endif // BAD_CILKPLUS -; - - ServerInfo mCurrentServer; - - Game *mGame; - Window *mCurrentDialog; - QuitDialog *mQuitDialog; - Button *mSetupButton; - Button *mVideoButton; - Button *mHelpButton; - Button *mAboutButton; - Button *mThemesButton; - Button *mPerfomanceButton; -#ifdef ANDROID - Button *mCloseButton; -#endif // ANDROID - - StateT mState; - StateT mOldState; - - Skin *mSkin; - int mButtonPadding; - int mButtonSpacing; - int mPing; - bool mConfigAutoSaved; -}; - -extern Client *client; -extern unsigned int mLastHost; -extern unsigned long mSearchHash; - +#include "progs/manaplus/client.h" #endif // DYECMD #endif // CLIENT_H diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp deleted file mode 100644 index 5715eae3a..000000000 --- a/src/gui/viewport.cpp +++ /dev/null @@ -1,1148 +0,0 @@ -/* - * 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 . - */ - -#include "gui/viewport.h" - -#include "actormanager.h" -#include "configuration.h" -#include "game.h" -#include "settings.h" -#include "sdlshared.h" -#include "textmanager.h" - -#include "being/flooritem.h" -#include "being/localplayer.h" -#include "being/playerinfo.h" - -#include "enums/resources/map/blockmask.h" -#include "enums/resources/map/mapitemtype.h" - -#include "gui/gui.h" -#include "gui/popupmanager.h" -#include "gui/userpalette.h" - -#include "gui/fonts/font.h" - -#include "gui/popups/beingpopup.h" -#include "gui/popups/popupmenu.h" -#include "gui/popups/textpopup.h" - -#include "gui/windows/ministatuswindow.h" - -#include "input/inputmanager.h" - -#include "utils/checkutils.h" -#include "utils/foreach.h" - -#include "resources/map/map.h" -#include "resources/map/mapitem.h" -#include "resources/map/speciallayer.h" - -#include "debug.h" - -Viewport *viewport = nullptr; - -extern volatile int tick_time; - -Viewport::Viewport() : - WindowContainer(nullptr), - MouseListener(), - ConfigListener(), - mMouseX(0), - mMouseY(0), - mMap(nullptr), - mHoverBeing(nullptr), - mHoverItem(nullptr), - mHoverSign(nullptr), - mScrollRadius(config.getIntValue("ScrollRadius")), - mScrollLaziness(config.getIntValue("ScrollLaziness")), - mScrollCenterOffsetX(config.getIntValue("ScrollCenterOffsetX")), - mScrollCenterOffsetY(config.getIntValue("ScrollCenterOffsetY")), - mMousePressX(0), - mMousePressY(0), - mPixelViewX(0), - mPixelViewY(0), - mMidTileX(0), - mMidTileY(0), - mViewXmax(0), - mViewYmax(0), - mLocalWalkTime(-1), - mCameraRelativeX(0), - mCameraRelativeY(0), - mShowBeingPopup(config.getBoolValue("showBeingPopup")), - mSelfMouseHeal(config.getBoolValue("selfMouseHeal")), - mEnableLazyScrolling(config.getBoolValue("enableLazyScrolling")), - mMouseDirectionMove(config.getBoolValue("mouseDirectionMove")), - mLongMouseClick(config.getBoolValue("longmouseclick")), - mAllowMoveByMouse(config.getBoolValue("allowMoveByMouse")), - mMouseClicked(false), - mPlayerFollowMouse(false) -{ - setOpaque(Opaque_false); - addMouseListener(this); - - config.addListener("ScrollLaziness", this); - config.addListener("ScrollRadius", this); - config.addListener("showBeingPopup", this); - config.addListener("selfMouseHeal", this); - config.addListener("enableLazyScrolling", this); - config.addListener("mouseDirectionMove", this); - config.addListener("longmouseclick", this); - config.addListener("allowMoveByMouse", this); - - setFocusable(true); - updateMidVars(); -} - -Viewport::~Viewport() -{ - config.removeListeners(this); - CHECKLISTENERS -} - -void Viewport::setMap(Map *const map) -{ - if ((mMap != nullptr) && (map != nullptr)) - map->setDrawLayersFlags(mMap->getDrawLayersFlags()); - mMap = map; - updateMaxVars(); -} - -void Viewport::draw(Graphics *const graphics) -{ - BLOCK_START("Viewport::draw 1") - static int lastTick = tick_time; - - if ((mMap == nullptr) || (localPlayer == nullptr)) - { - graphics->setColor(Color(64, 64, 64)); - graphics->fillRectangle( - Rect(0, 0, getWidth(), getHeight())); - BLOCK_END("Viewport::draw 1") - return; - } - - // Avoid freaking out when tick_time overflows - if (tick_time < lastTick) - lastTick = tick_time; - - // Calculate viewpoint - - const int player_x = localPlayer->mPixelX - mMidTileX; - const int player_y = localPlayer->mPixelY - mMidTileY; - - if (mScrollLaziness < 1) - mScrollLaziness = 1; // Avoids division by zero - - if (mEnableLazyScrolling) - { - int cnt = 0; - - // Apply lazy scrolling - while (lastTick < tick_time && cnt < mapTileSize) - { - if (player_x > mPixelViewX + mScrollRadius) - { - mPixelViewX += CAST_S32( - static_cast(player_x - - mPixelViewX - mScrollRadius) / - static_cast(mScrollLaziness)); - } - if (player_x < mPixelViewX - mScrollRadius) - { - mPixelViewX += CAST_S32( - static_cast(player_x - - mPixelViewX + mScrollRadius) / - static_cast(mScrollLaziness)); - } - if (player_y > mPixelViewY + mScrollRadius) - { - mPixelViewY += CAST_S32( - static_cast(player_y - - mPixelViewY - mScrollRadius) / - static_cast(mScrollLaziness)); - } - if (player_y < mPixelViewY - mScrollRadius) - { - mPixelViewY += CAST_S32( - static_cast(player_y - - mPixelViewY + mScrollRadius) / - static_cast(mScrollLaziness)); - } - lastTick ++; - cnt ++; - } - - // Auto center when player is off screen - if (cnt > 30 || player_x - mPixelViewX - > graphics->mWidth / 2 || mPixelViewX - - player_x > graphics->mWidth / 2 || mPixelViewY - - player_y > graphics->getHeight() / 2 || player_y - - mPixelViewY > graphics->getHeight() / 2) - { - if (player_x <= 0 || player_y <= 0) - { - logger->log("incorrect player position: %d, %d, %d, %d", - player_x, player_y, mPixelViewX, mPixelViewY); - logger->log("tile position: %d, %d", - localPlayer->getTileX(), localPlayer->getTileY()); - } - mPixelViewX = player_x; - mPixelViewY = player_y; - } - } - else - { - mPixelViewX = player_x; - mPixelViewY = player_y; - } - - if (mPixelViewX < 0) - mPixelViewX = 0; - if (mPixelViewY < 0) - mPixelViewY = 0; - if (mPixelViewX > mViewXmax) - mPixelViewX = mViewXmax; - if (mPixelViewY > mViewYmax) - mPixelViewY = mViewYmax; - - // Draw tiles and sprites - mMap->draw(graphics, mPixelViewX, mPixelViewY); - - const MapTypeT drawType = settings.mapDrawType; - if (drawType != MapType::NORMAL) - { - if (drawType != MapType::SPECIAL4) - { - mMap->drawCollision(graphics, mPixelViewX, - mPixelViewY, drawType); - } - if (drawType == MapType::DEBUGTYPE) - drawDebugPath(graphics); - } - - if (localPlayer->getCheckNameSetting()) - { - localPlayer->setCheckNameSetting(false); - localPlayer->setName(localPlayer->getName()); - } - - // Draw text - if (textManager != nullptr) - textManager->draw(graphics, mPixelViewX, mPixelViewY); - - // Draw player names, speech, and emotion sprite as needed - const ActorSprites &actors = actorManager->getAll(); - FOR_EACH (ActorSpritesIterator, it, actors) - { - if ((*it)->getType() == ActorType::FloorItem) - continue; - Being *const b = static_cast(*it); - b->drawEmotion(graphics, mPixelViewX, mPixelViewY); - b->drawSpeech(mPixelViewX, mPixelViewY); - } - - if (miniStatusWindow != nullptr) - miniStatusWindow->drawIcons(graphics); - - // Draw contained widgets - WindowContainer::draw(graphics); - BLOCK_END("Viewport::draw 1") -} - -void Viewport::safeDraw(Graphics *const graphics) -{ - Viewport::draw(graphics); -} - -void Viewport::logic() -{ - BLOCK_START("Viewport::logic") - // Make the player follow the mouse position - // if the mouse is dragged elsewhere than in a window. - Gui::getMouseState(mMouseX, mMouseY); - BLOCK_END("Viewport::logic") -} - -void Viewport::followMouse() -{ - if (gui == nullptr) - return; - const MouseStateType button = Gui::getMouseState(mMouseX, mMouseY); - // If the left button is dragged - if (mPlayerFollowMouse && ((button & SDL_BUTTON(1)) != 0)) - { - // We create a mouse event and send it to mouseDragged. - const MouseEvent event(nullptr, - MouseEventType::DRAGGED, - MouseButton::LEFT, - mMouseX, - mMouseY, - 0); - - walkByMouse(event); - } -} - -void Viewport::drawDebugPath(Graphics *const graphics) -{ - if (localPlayer == nullptr || - userPalette == nullptr || - actorManager == nullptr || - mMap == nullptr || - gui == nullptr) - { - return; - } - - Gui::getMouseState(mMouseX, mMouseY); - - static Path debugPath; - static Vector lastMouseDestination = Vector(0.0F, 0.0F); - const int mousePosX = mMouseX + mPixelViewX; - const int mousePosY = mMouseY + mPixelViewY; - Vector mouseDestination(mousePosX, mousePosY); - - if (mouseDestination.x != lastMouseDestination.x - || mouseDestination.y != lastMouseDestination.y) - { - debugPath = mMap->findPath( - CAST_S32(localPlayer->mPixelX - mapTileSize / 2) / mapTileSize, - CAST_S32(localPlayer->mPixelY - mapTileSize) / mapTileSize, - mousePosX / mapTileSize, - mousePosY / mapTileSize, - localPlayer->getBlockWalkMask(), - 500); - lastMouseDestination = mouseDestination; - } - drawPath(graphics, debugPath, userPalette->getColorWithAlpha( - UserColorId::ROAD_POINT)); - - const ActorSprites &actors = actorManager->getAll(); - FOR_EACH (ActorSpritesConstIterator, it, actors) - { - const Being *const being = dynamic_cast(*it); - if ((being != nullptr) && being != localPlayer) - { - const Path &beingPath = being->getPath(); - drawPath(graphics, beingPath, userPalette->getColorWithAlpha( - UserColorId::ROAD_POINT)); - } - } -} - -void Viewport::drawPath(Graphics *const graphics, - const Path &path, - const Color &color) const -{ - graphics->setColor(color); - Font *const font = getFont(); - - int cnt = 1; - FOR_EACH (Path::const_iterator, i, path) - { - const int squareX = i->x * mapTileSize - mPixelViewX + 12; - const int squareY = i->y * mapTileSize - mPixelViewY + 12; - - graphics->fillRectangle(Rect(squareX, squareY, 8, 8)); - if (mMap != nullptr) - { - const std::string str = toString(cnt); - font->drawString(graphics, - color, color, - str, - squareX + 4 - font->getWidth(str) / 2, - squareY + 12); - } - cnt ++; - } -} - -bool Viewport::openContextMenu(const MouseEvent &event) -{ - mPlayerFollowMouse = false; - const int eventX = event.getX(); - const int eventY = event.getY(); - if (popupMenu == nullptr) - return false; - if (mHoverBeing != nullptr) - { - validateSpeed(); - if (actorManager != nullptr) - { - STD_VECTOR beings; - const int x = mMouseX + mPixelViewX; - const int y = mMouseY + mPixelViewY; - actorManager->findBeingsByPixel(beings, x, y, AllPlayers_true); - if (beings.size() > 1) - popupMenu->showPopup(eventX, eventY, beings); - else - popupMenu->showPopup(eventX, eventY, mHoverBeing); - return true; - } - } - else if (mHoverItem != nullptr) - { - validateSpeed(); - popupMenu->showPopup(eventX, eventY, mHoverItem); - return true; - } - else if (mHoverSign != nullptr) - { - validateSpeed(); - popupMenu->showPopup(eventX, eventY, mHoverSign); - return true; - } - else if (settings.cameraMode != 0u) - { - if (mMap == nullptr) - return false; - popupMenu->showMapPopup(eventX, eventY, - (mMouseX + mPixelViewX) / mMap->getTileWidth(), - (mMouseY + mPixelViewY) / mMap->getTileHeight(), - false); - return true; - } - return false; -} - -bool Viewport::leftMouseAction() -{ - const bool stopAttack = inputManager.isActionActive( - InputAction::STOP_ATTACK); - // Interact with some being - if (mHoverBeing != nullptr) - { - if (!mHoverBeing->isAlive()) - return true; - - if (mHoverBeing->canTalk()) - { - validateSpeed(); - mHoverBeing->talkTo(); - return true; - } - - const ActorTypeT type = mHoverBeing->getType(); - switch (type) - { - case ActorType::Player: - validateSpeed(); - if (actorManager != nullptr) - { -#ifdef TMWA_SUPPORT - if (localPlayer != mHoverBeing || mSelfMouseHeal) - actorManager->heal(mHoverBeing); -#endif // TMWA_SUPPORT - - if (localPlayer == mHoverBeing && - mHoverItem != nullptr) - { - localPlayer->pickUp(mHoverItem); - } - return true; - } - break; - case ActorType::Monster: - case ActorType::Npc: - case ActorType::SkillUnit: - if (!stopAttack) - { - if (localPlayer->withinAttackRange(mHoverBeing) || - inputManager.isActionActive(InputAction::ATTACK)) - { - validateSpeed(); - if (!mStatsReUpdated && localPlayer != mHoverBeing) - { - localPlayer->attack(mHoverBeing, - !inputManager.isActionActive( - InputAction::STOP_ATTACK)); - return true; - } - } - else if (!inputManager.isActionActive( - InputAction::ATTACK)) - { - validateSpeed(); - if (!mStatsReUpdated && localPlayer != mHoverBeing) - { - localPlayer->setGotoTarget(mHoverBeing); - return true; - } - } - } - break; - case ActorType::FloorItem: - case ActorType::Portal: - case ActorType::Pet: - case ActorType::Mercenary: - case ActorType::Homunculus: - case ActorType::Elemental: - break; - case ActorType::Unknown: - case ActorType::Avatar: - default: - reportAlways("Left click on unknown actor type: %d", - CAST_S32(type)); - break; - } - } - // Picks up a item if we clicked on one - if (mHoverItem != nullptr) - { - validateSpeed(); - localPlayer->pickUp(mHoverItem); - } - else if (stopAttack) - { - if (mMap != nullptr) - { - const int mouseTileX = (mMouseX + mPixelViewX) - / mMap->getTileWidth(); - const int mouseTileY = (mMouseY + mPixelViewY) - / mMap->getTileHeight(); - inputManager.executeChatCommand(InputAction::PET_MOVE, - strprintf("%d %d", mouseTileX, mouseTileY), - nullptr); - } - return true; - } - // Just walk around - else if (!inputManager.isActionActive(InputAction::ATTACK) && - localPlayer->canMove()) - { - validateSpeed(); - localPlayer->stopAttack(); - localPlayer->cancelFollow(); - mPlayerFollowMouse = mAllowMoveByMouse; - if (mPlayerFollowMouse) - { - // Make the player go to the mouse position - followMouse(); - } - } - return false; -} - -void Viewport::mousePressed(MouseEvent &event) -{ - if (event.getSource() != this || event.isConsumed()) - return; - - // Check if we are alive and kickin' - if ((mMap == nullptr) || (localPlayer == nullptr)) - return; - - // Check if we are busy - // if commented, allow context menu if npc dialog open - if (PlayerInfo::isTalking()) - { - mMouseClicked = false; - return; - } - - mMouseClicked = true; - - mMousePressX = event.getX(); - mMousePressY = event.getY(); - const MouseButtonT eventButton = event.getButton(); - const int pixelX = mMousePressX + mPixelViewX; - const int pixelY = mMousePressY + mPixelViewY; - - // Right click might open a popup - if (eventButton == MouseButton::RIGHT) - { - if (openContextMenu(event)) - return; - } - - // If a popup is active, just remove it - if (PopupManager::isPopupMenuVisible()) - { - mPlayerFollowMouse = false; - PopupManager::hidePopupMenu(); - return; - } - - // Left click can cause different actions - if (!mLongMouseClick && eventButton == MouseButton::LEFT) - { - if (leftMouseAction()) - { - mPlayerFollowMouse = false; - return; - } - } - else if (eventButton == MouseButton::MIDDLE) - { - mPlayerFollowMouse = false; - validateSpeed(); - // Find the being nearest to the clicked position - if (actorManager != nullptr) - { - Being *const target = actorManager->findNearestLivingBeing( - pixelX, pixelY, 20, ActorType::Monster, nullptr); - - if (target != nullptr) - localPlayer->setTarget(target); - } - } -} - -void Viewport::getMouseTile(int &destX, int &destY) const -{ - getMouseTile(mMouseX, mMouseY, destX, destY); -} - -void Viewport::getMouseTile(const int x, const int y, - int &destX, int &destY) const -{ - if (mMap == nullptr) - return; - const int tw = mMap->getTileWidth(); - const int th = mMap->getTileHeight(); - destX = CAST_S32(x + mPixelViewX) - / static_cast(tw); - - if (mMap->isHeightsPresent()) - { - const int th2 = th / 2; - const int clickY = y + mPixelViewY - th2; - destY = y + mPixelViewY; - int newDiffY = 1000000; - const int heightTiles = mainGraphics->mHeight / th; - const int tileViewY = mPixelViewY / th; - for (int f = tileViewY; f < tileViewY + heightTiles; f ++) - { - if (!mMap->getWalk(destX, - f, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - continue; - } - - const int offset = mMap->getHeightOffset( - destX, f) * th2; - const int pixelF = f * th; - const int diff = abs(clickY + offset - pixelF); - if (diff < newDiffY) - { - destY = pixelF; - newDiffY = diff; - } - } - destY /= 32; - } - else - { - destY = CAST_S32((y + mPixelViewY) / static_cast(th)); - } -} - -void Viewport::walkByMouse(const MouseEvent &event) -{ - if ((mMap == nullptr) || (localPlayer == nullptr)) - return; - if (mPlayerFollowMouse - && !inputManager.isActionActive(InputAction::STOP_ATTACK) - && !inputManager.isActionActive(InputAction::UNTARGET)) - { - if (!mMouseDirectionMove) - mPlayerFollowMouse = false; - if (mLocalWalkTime != localPlayer->getActionTime()) - { - mLocalWalkTime = cur_time; - localPlayer->unSetPickUpTarget(); - int playerX = localPlayer->getTileX(); - int playerY = localPlayer->getTileY(); - if (mMouseDirectionMove) - { - const int width = mainGraphics->mWidth / 2; - const int height = mainGraphics->mHeight / 2; - const float wh = static_cast(width) - / static_cast(height); - int x = event.getX() - width; - int y = event.getY() - height; - if ((x == 0) && (y == 0)) - return; - const int x2 = abs(x); - const int y2 = abs(y); - const float diff = 2; - int dx = 0; - int dy = 0; - if (x2 > y2) - { - if (y2 != 0 && - static_cast(x2) / static_cast(y2) / - wh > diff) - { - y = 0; - } - } - else - { - if ((x2 != 0) && y2 * wh / x2 > diff) - x = 0; - } - if (x > 0) - dx = 1; - else if (x < 0) - dx = -1; - if (y > 0) - dy = 1; - else if (y < 0) - dy = -1; - - if (mMap->getWalk(playerX + dx, - playerY + dy, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - localPlayer->navigateTo(playerX + dx, playerY + dy); - } - else - { - if ((dx != 0) && (dy != 0)) - { - // try avoid diagonal collision - if (x2 > y2) - { - if (mMap->getWalk(playerX + dx, - playerY, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - dy = 0; - } - else - { - dx = 0; - } - } - else - { - if (mMap->getWalk(playerX, - playerY + dy, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - dx = 0; - } - else - { - dy = 0; - } - } - } - else - { - // try avoid vertical or horisontal collision - if (dx == 0) - { - if (mMap->getWalk(playerX + 1, - playerY + dy, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - dx = 1; - } - if (mMap->getWalk(playerX - 1, - playerY + dy, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - dx = -1; - } - } - if (dy == 0) - { - if (mMap->getWalk(playerX + dx, - playerY + 1, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - dy = 1; - } - if (mMap->getWalk(playerX + dx, - playerY - 1, - BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL)) - { - dy = -1; - } - } - } - localPlayer->navigateTo(playerX + dx, playerY + dy); - } - } - else - { - int destX; - int destY; - getMouseTile(event.getX(), event.getY(), - destX, destY); - if (playerX != destX || playerY != destY) - { - if (!localPlayer->navigateTo(destX, destY)) - { - if (playerX > destX) - playerX --; - else if (playerX < destX) - playerX ++; - if (playerY > destY) - playerY --; - else if (playerY < destY) - playerY ++; - if (mMap->getWalk(playerX, playerY, 0)) - localPlayer->navigateTo(playerX, playerY); - } - } - } - } - } -} - -void Viewport::mouseDragged(MouseEvent &event) -{ - if (event.getSource() != this || event.isConsumed()) - { - mPlayerFollowMouse = false; - return; - } - if (mAllowMoveByMouse && - mMouseClicked && - (localPlayer != nullptr) && - localPlayer->canMove()) - { - if (abs(event.getX() - mMousePressX) > 32 - || abs(event.getY() - mMousePressY) > 32) - { - mPlayerFollowMouse = true; - } - - walkByMouse(event); - } -} - -void Viewport::mouseReleased(MouseEvent &event) -{ - mPlayerFollowMouse = false; - mLocalWalkTime = -1; - if (mLongMouseClick && mMouseClicked) - { - mMouseClicked = false; - if (event.getSource() != this || event.isConsumed()) - return; - const MouseButtonT eventButton = event.getButton(); - if (eventButton == MouseButton::LEFT) - { - // long button press - if ((gui != nullptr) && gui->isLongPress()) - { - if (openContextMenu(event)) - { - gui->resetClickCount(); - return; - } - } - else - { - if (leftMouseAction()) - return; - } - walkByMouse(event); - } - } -} - -void Viewport::optionChanged(const std::string &name) -{ - if (name == "ScrollLaziness") - mScrollLaziness = config.getIntValue("ScrollLaziness"); - else if (name == "ScrollRadius") - mScrollRadius = config.getIntValue("ScrollRadius"); - else if (name == "showBeingPopup") - mShowBeingPopup = config.getBoolValue("showBeingPopup"); - else if (name == "selfMouseHeal") - mSelfMouseHeal = config.getBoolValue("selfMouseHeal"); - else if (name == "enableLazyScrolling") - mEnableLazyScrolling = config.getBoolValue("enableLazyScrolling"); - else if (name == "mouseDirectionMove") - mMouseDirectionMove = config.getBoolValue("mouseDirectionMove"); - else if (name == "longmouseclick") - mLongMouseClick = config.getBoolValue("longmouseclick"); - else if (name == "allowMoveByMouse") - mAllowMoveByMouse = config.getBoolValue("allowMoveByMouse"); -} - -void Viewport::mouseMoved(MouseEvent &event) -{ - // Check if we are on the map - if (mMap == nullptr || - localPlayer == nullptr || - actorManager == nullptr) - { - return; - } - - if (mMouseDirectionMove) - mPlayerFollowMouse = false; - - const int x = mMouseX + mPixelViewX; - const int y = mMouseY + mPixelViewY; - - ActorTypeT type = ActorType::Unknown; - mHoverBeing = actorManager->findBeingByPixel(x, y, AllPlayers_true); - if (mHoverBeing != nullptr) - type = mHoverBeing->getType(); - if ((mHoverBeing != nullptr) - && (type == ActorType::Player - || type == ActorType::Npc - || type == ActorType::Homunculus - || type == ActorType::Mercenary - || type == ActorType::Pet)) - { - PopupManager::hideTextPopup(); - if (mShowBeingPopup && (beingPopup != nullptr)) - beingPopup->show(mMouseX, mMouseY, mHoverBeing); - } - else - { - PopupManager::hideBeingPopup(); - } - - mHoverItem = actorManager->findItem(x / mMap->getTileWidth(), - y / mMap->getTileHeight()); - - if ((mHoverBeing == nullptr) && (mHoverItem == nullptr)) - { - const SpecialLayer *const specialLayer = mMap->getSpecialLayer(); - if (specialLayer != nullptr) - { - const int mouseTileX = (mMouseX + mPixelViewX) - / mMap->getTileWidth(); - const int mouseTileY = (mMouseY + mPixelViewY) - / mMap->getTileHeight(); - - mHoverSign = specialLayer->getTile(mouseTileX, mouseTileY); - if (mHoverSign != nullptr && - mHoverSign->getType() != MapItemType::EMPTY) - { - if (!mHoverSign->getComment().empty()) - { - PopupManager::hideBeingPopup(); - if (textPopup != nullptr) - { - textPopup->show(mMouseX, mMouseY, - mHoverSign->getComment()); - } - } - else - { - if (PopupManager::isTextPopupVisible()) - PopupManager::hideTextPopup(); - } - gui->setCursorType(Cursor::CURSOR_UP); - return; - } - } - } - if (!event.isConsumed() && - PopupManager::isTextPopupVisible()) - { - PopupManager::hideTextPopup(); - } - - if (mHoverBeing != nullptr) - { - switch (type) - { - case ActorType::Npc: - case ActorType::Monster: - case ActorType::Portal: - case ActorType::Pet: - case ActorType::Mercenary: - case ActorType::Homunculus: - case ActorType::SkillUnit: - case ActorType::Elemental: - gui->setCursorType(mHoverBeing->getHoverCursor()); - break; - - case ActorType::Avatar: - case ActorType::FloorItem: - case ActorType::Unknown: - case ActorType::Player: - default: - gui->setCursorType(Cursor::CURSOR_POINTER); - break; - } - } - // Item mouseover - else if (mHoverItem != nullptr) - { - gui->setCursorType(mHoverItem->getHoverCursor()); - } - else - { - gui->setCursorType(Cursor::CURSOR_POINTER); - } -} - -void Viewport::toggleMapDrawType() -{ - settings.mapDrawType = static_cast( - CAST_S32(settings.mapDrawType) + 1); - if (settings.mapDrawType > MapType::BLACKWHITE) - settings.mapDrawType = MapType::NORMAL; - if (mMap != nullptr) - mMap->setDrawLayersFlags(settings.mapDrawType); -} - -void Viewport::toggleCameraMode() -{ - settings.cameraMode ++; - if (settings.cameraMode > 1) - settings.cameraMode = 0; - if (settings.cameraMode == 0u) - { - mCameraRelativeX = 0; - mCameraRelativeY = 0; - updateMidVars(); - } - UpdateStatusListener::distributeEvent(); -} - -void Viewport::clearHover(const ActorSprite *const actor) -{ - if (mHoverBeing == actor) - mHoverBeing = nullptr; - - if (mHoverItem == actor) - mHoverItem = nullptr; -} - -void Viewport::cleanHoverItems() -{ - mHoverBeing = nullptr; - mHoverItem = nullptr; - mHoverSign = nullptr; -} - -void Viewport::moveCamera(const int dx, const int dy) -{ - mCameraRelativeX += dx; - mCameraRelativeY += dy; - updateMidVars(); -} - -void Viewport::moveCameraToActor(const BeingId actorId, - const int x, const int y) -{ - if ((localPlayer == nullptr) || (actorManager == nullptr)) - return; - - const Actor *const actor = actorManager->findBeing(actorId); - if (actor == nullptr) - return; - settings.cameraMode = 1; - mCameraRelativeX = actor->mPixelX - localPlayer->mPixelX + x; - mCameraRelativeY = actor->mPixelY - localPlayer->mPixelY + y; - updateMidVars(); -} - -void Viewport::moveCameraToPosition(const int x, const int y) -{ - if (localPlayer == nullptr) - return; - - settings.cameraMode = 1; - mCameraRelativeX = x - localPlayer->mPixelX; - mCameraRelativeY = y - localPlayer->mPixelY; - updateMidVars(); -} - -void Viewport::moveCameraRelative(const int x, const int y) -{ - settings.cameraMode = 1; - mCameraRelativeX += x; - mCameraRelativeY += y; - updateMidVars(); -} - -void Viewport::returnCamera() -{ - settings.cameraMode = 0; - mCameraRelativeX = 0; - mCameraRelativeY = 0; - updateMidVars(); -} - -void Viewport::validateSpeed() -{ - if (!inputManager.isActionActive(InputAction::TARGET_ATTACK) && - !inputManager.isActionActive(InputAction::ATTACK)) - { - if (Game::instance() != nullptr) - Game::instance()->setValidSpeed(); - } -} - -void Viewport::updateMidVars() -{ - mMidTileX = (mainGraphics->mWidth + mScrollCenterOffsetX) / 2 - - mCameraRelativeX; - mMidTileY = (mainGraphics->mHeight + mScrollCenterOffsetY) / 2 - - mCameraRelativeY; -} - -void Viewport::updateMaxVars() -{ - if (mMap == nullptr) - return; - mViewXmax = mMap->getWidth() * mMap->getTileWidth() - - mainGraphics->mWidth; - mViewYmax = mMap->getHeight() * mMap->getTileHeight() - - mainGraphics->mHeight; -} - -void Viewport::videoResized() -{ - updateMidVars(); - updateMaxVars(); -} diff --git a/src/gui/viewport.h b/src/gui/viewport.h index f4e3d26be..70c918bf6 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -1,7 +1,5 @@ /* * 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. @@ -25,231 +23,8 @@ #ifdef DYECMD #include "progs/dyecmd/gui/viewport.h" - #else - -#include "position.h" - -#include "enums/simpletypes/beingid.h" - -#include "gui/widgets/windowcontainer.h" - -#include "listeners/mouselistener.h" - -class ActorSprite; -class Being; -class FloorItem; -class Graphics; -class Map; -class MapItem; - -/** - * The viewport on the map. Displays the current map and handles mouse input - * and the popup menu. - */ -class Viewport final : public WindowContainer, - public MouseListener, - public ConfigListener -{ - public: - /** - * Constructor. - */ - Viewport(); - - A_DELETE_COPY(Viewport) - - /** - * Destructor. - */ - ~Viewport(); - - /** - * Sets the map displayed by the viewport. - */ - void setMap(Map *const map); - - /** - * Draws the viewport. - */ - void draw(Graphics *const graphics) override final A_NONNULL(2); - - void safeDraw(Graphics *const graphics) override final A_NONNULL(2); - - /** - * Implements player to keep following mouse. - */ - void logic() override final; - - /** - * Toggles whether the path debug graphics are shown. normal, - * debug with all images and grid, debug with out big images - * and with out grid. - */ - void toggleMapDrawType(); - - void toggleCameraMode(); - - /** - * Handles mouse press on map. - */ - void mousePressed(MouseEvent &event) override final; - - /** - * Handles mouse move on map - */ - void mouseDragged(MouseEvent &event) override final; - - /** - * Handles mouse button release on map. - */ - void mouseReleased(MouseEvent &event) override final; - - /** - * Handles mouse move on map. - */ - void mouseMoved(MouseEvent &event) override final; - - /** - * A relevant config option changed. - */ - void optionChanged(const std::string &name) override final; - - /** - * Returns camera x offset in pixels. - */ - int getCameraX() const noexcept2 A_WARN_UNUSED - { return mPixelViewX; } - - /** - * Returns camera y offset in pixels. - */ - int getCameraY() const noexcept2 A_WARN_UNUSED - { return mPixelViewY; } - - /** - * Changes viewpoint by relative pixel coordinates. - */ - void scrollBy(const int x, const int y) - { mPixelViewX += x; mPixelViewY += y; } - - /** - * Clear all hover item, being etc - */ - void cleanHoverItems(); - - Map *getMap() const noexcept2 A_WARN_UNUSED - { return mMap; } - - void moveCamera(const int dx, const int dy); - - int getCameraRelativeX() const noexcept2 A_WARN_UNUSED - { return mCameraRelativeX; } - - int getCameraRelativeY() const noexcept2 A_WARN_UNUSED - { return mCameraRelativeY; } - - void setCameraRelativeX(const int n) - { mCameraRelativeX = n; updateMidVars(); } - - void setCameraRelativeY(const int n) - { mCameraRelativeY = n; updateMidVars(); } - - void moveCameraToActor(const BeingId actorId, - const int x = 0, - const int y = 0); - - void moveCameraToPosition(const int x, const int y); - - void moveCameraRelative(const int x, const int y); - - void returnCamera(); - - void getMouseTile(int &destX, int &destY) const; - - void videoResized(); - - int mMouseX; /**< Current mouse position in pixels. */ - int mMouseY; /**< Current mouse position in pixels. */ - - protected: - friend class ActorManager; - - /// Clears any matching hovers - void clearHover(const ActorSprite *const actor); - - void updateMidVars(); - - void updateMaxVars(); - - static void validateSpeed(); - - private: - /** - * Finds a path from the player to the mouse, and draws it. This is for - * debug purposes. - */ - void drawDebugPath(Graphics *const graphics) A_NONNULL(2); - - /** - * Draws the given path. - */ - void drawPath(Graphics *const graphics, - const Path &path, - const Color &color = Color(255, 0, 0)) - const A_NONNULL(2); - - bool leftMouseAction(); - - bool openContextMenu(const MouseEvent &event); - - void walkByMouse(const MouseEvent &event); - - void getMouseTile(const int x, - const int y, - int &destX, - int &destY) const; - - /** - * Make the player go to the mouse position. - */ - void followMouse(); - - Map *mMap; /**< The current map. */ - - Being *mHoverBeing; /**< Being mouse is currently over. */ - FloorItem *mHoverItem; /**< FloorItem mouse is currently over. */ - MapItem *mHoverSign; /**< Map sign mouse is currently over. */ - - int mScrollRadius; - int mScrollLaziness; - int mScrollCenterOffsetX; - int mScrollCenterOffsetY; - int mMousePressX; - int mMousePressY; - int mPixelViewX; /**< Current viewpoint in pixels. */ - int mPixelViewY; /**< Current viewpoint in pixels. */ - int mMidTileX; - int mMidTileY; - int mViewXmax; - int mViewYmax; - - time_t mLocalWalkTime; - - int mCameraRelativeX; - int mCameraRelativeY; - - bool mShowBeingPopup; - bool mSelfMouseHeal; - bool mEnableLazyScrolling; - bool mMouseDirectionMove; - bool mLongMouseClick; - bool mAllowMoveByMouse; - bool mMouseClicked; - bool mPlayerFollowMouse; -}; - -extern Viewport *viewport; /**< The viewport. */ - +#include "progs/manaplus/gui/viewport.h" #endif // DYECMD + #endif // GUI_VIEWPORT_H diff --git a/src/progs/dyecmd/client.cpp b/src/progs/dyecmd/client.cpp index 42b570a6b..7f75f4cd5 100644 --- a/src/progs/dyecmd/client.cpp +++ b/src/progs/dyecmd/client.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -#include "client.h" +#include "progs/dyecmd/client.h" #include "configmanager.h" #include "dirs.h" diff --git a/src/progs/manaplus/actions/actions.cpp b/src/progs/manaplus/actions/actions.cpp new file mode 100644 index 000000000..b958f8f62 --- /dev/null +++ b/src/progs/manaplus/actions/actions.cpp @@ -0,0 +1,1914 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/actions.h" + +#include "actormanager.h" +#include "configuration.h" +#include "game.h" +#ifdef USE_OPENGL +#include "graphicsmanager.h" +#endif // USE_OPENGL +#include "main.h" +#include "spellmanager.h" + +#include "actions/actiondef.h" + +#include "being/localplayer.h" +#include "being/playerinfo.h" + +#include "const/spells.h" + +#include "const/resources/skill.h" + +#include "fs/files.h" + +#include "gui/gui.h" +#include "gui/popupmanager.h" +#include "gui/sdlinput.h" +#include "gui/windowmanager.h" + +#include "gui/shortcut/dropshortcut.h" +#include "gui/shortcut/emoteshortcut.h" +#include "gui/shortcut/itemshortcut.h" + +#include "gui/popups/popupmenu.h" + +#include "gui/windows/buydialog.h" +#include "gui/windows/okdialog.h" +#include "gui/windows/tradewindow.h" +#include "gui/windows/quitdialog.h" +#include "gui/windows/buyselldialog.h" +#include "gui/windows/chatwindow.h" +#include "gui/windows/helpwindow.h" +#include "gui/windows/inventorywindow.h" +#include "gui/windows/itemamountwindow.h" +#include "gui/windows/npcdialog.h" +#include "gui/windows/outfitwindow.h" +#include "gui/windows/setupwindow.h" +#include "gui/windows/shopwindow.h" +#include "gui/windows/shortcutwindow.h" +#include "gui/windows/skilldialog.h" +#include "gui/windows/whoisonline.h" + +#include "gui/widgets/createwidget.h" + +#include "gui/widgets/tabs/chat/chattab.h" + +#include "input/inputactionoperators.h" + +#if defined USE_OPENGL +#include "render/normalopenglgraphics.h" +#endif // USE_OPENGL + +#include "net/adminhandler.h" +#include "net/beinghandler.h" +#include "net/buyingstorehandler.h" +#include "net/buysellhandler.h" +#include "net/chathandler.h" +#include "net/download.h" +#include "net/homunculushandler.h" +#include "net/gamehandler.h" +#include "net/inventoryhandler.h" +#include "net/ipc.h" +#include "net/mercenaryhandler.h" +#include "net/net.h" +#include "net/npchandler.h" +#include "net/playerhandler.h" +#include "net/serverfeatures.h" +#include "net/uploadcharinfo.h" +#include "net/tradehandler.h" +#include "net/vendinghandler.h" + +#include "resources/iteminfo.h" +#include "resources/memorymanager.h" + +#include "resources/resourcemanager/resourcemanager.h" + +#include "utils/chatutils.h" +#include "utils/delete2.h" +#include "utils/foreach.h" +#include "utils/gettext.h" +#include "utils/mathutils.h" +#include "utils/parameters.h" +#include "utils/timer.h" + +PRAGMA48(GCC diagnostic push) +PRAGMA48(GCC diagnostic ignored "-Wshadow") +#ifdef ANDROID +#ifndef USE_SDL2 +#include +#endif // USE_OPENGL +#endif // ANDROID +PRAGMA48(GCC diagnostic pop) + +#include + +#include "debug.h" + +extern std::string tradePartnerName; +extern QuitDialog *quitDialog; +extern time_t start_time; +extern char **environ; + +namespace Actions +{ + +static int uploadUpdate(void *ptr, + const DownloadStatusT status, + size_t total A_UNUSED, + const size_t remaining A_UNUSED) A_NONNULL(1); + +static int uploadUpdate(void *ptr, + const DownloadStatusT status, + size_t total A_UNUSED, + const size_t remaining A_UNUSED) +{ + if (status == DownloadStatus::Idle || status == DownloadStatus::Starting) + return 0; + + UploadChatInfo *const info = reinterpret_cast(ptr); + if (info == nullptr) + return 0; + + if (status == DownloadStatus::Complete) + { + std::string str = Net::Download::getUploadResponse(); + const size_t sz = str.size(); + if (sz > 0) + { + if (str[sz - 1] == '\n') + str = str.substr(0, sz - 1); + str.append(info->addStr); + ChatTab *const tab = info->tab; + if (chatWindow != nullptr && + (tab == nullptr || chatWindow->isTabPresent(tab))) + { + str = strprintf("%s [@@%s |%s@@]", + info->text.c_str(), str.c_str(), str.c_str()); + outStringNormal(tab, str, str); + } + else + { + CREATEWIDGET(OkDialog, + // TRANSLATORS: file uploaded message + _("File uploaded"), + str, + // TRANSLATORS: ok dialog button + _("OK"), + DialogType::OK, + Modal_true, + ShowCenter_false, + nullptr, + 260); + } + } + } + delete2(info->upload); + delete info; + return 0; +} + +static void uploadFile(const std::string &str, + const std::string &fileName, + const std::string &addStr, + ChatTab *const tab) +{ + UploadChatInfo *const info = new UploadChatInfo; + Net::Download *const upload = new Net::Download(info, + "http://sprunge.us", + &uploadUpdate, + false, true, false); + info->upload = upload; + info->text = str; + info->addStr = addStr; + info->tab = tab; + upload->setFile(fileName); + upload->start(); +} + +static Being *findBeing(const std::string &name, const bool npc) +{ + if ((localPlayer == nullptr) || (actorManager == nullptr)) + return nullptr; + + Being *being = nullptr; + + if (name.empty()) + { + being = localPlayer->getTarget(); + } + else + { + being = actorManager->findBeingByName( + name, ActorType::Unknown); + } + if ((being == nullptr) && npc) + { + being = actorManager->findNearestLivingBeing( + localPlayer, 1, ActorType::Npc, AllowSort_true); + if (being != nullptr) + { + if (abs(being->getTileX() - localPlayer->getTileX()) > 1 + || abs(being->getTileY() - localPlayer->getTileY()) > 1) + { + being = nullptr; + } + } + } + if ((being == nullptr) && npc) + { + being = actorManager->findNearestLivingBeing( + localPlayer, 1, ActorType::Player, AllowSort_true); + if (being != nullptr) + { + if (abs(being->getTileX() - localPlayer->getTileX()) > 1 + || abs(being->getTileY() - localPlayer->getTileY()) > 1) + { + being = nullptr; + } + } + } + return being; +} + +static Item *getItemByInvIndex(const int index, + const InventoryTypeT invType) +{ + const Inventory *inv = nullptr; + switch (invType) + { + case InventoryType::Storage: + inv = PlayerInfo::getStorageInventory(); + break; + + case InventoryType::Inventory: + inv = PlayerInfo::getInventory(); + break; + case InventoryType::Trade: + case InventoryType::Npc: + case InventoryType::Cart: + case InventoryType::Vending: + case InventoryType::MailEdit: + case InventoryType::MailView: + case InventoryType::Craft: + case InventoryType::TypeEnd: + default: + break; + } + if (inv != nullptr) + return inv->getItem(index); + return nullptr; +} + +static int getAmountFromEvent(const InputEvent &event, + Item *&item0, + const InventoryTypeT invType) +{ + Item *const item = getItemByInvIndex(atoi(event.args.c_str()), + invType); + item0 = item; + if (item == nullptr) + return 0; + + std::string str = event.args; + removeToken(str, " "); + + if (str.empty()) + return 0; + + int amount = 0; + if (str[0] == '-') + { + if (str.size() > 1) + { + amount = item->getQuantity() - atoi(str.substr(1).c_str()); + if (amount <= 0 || amount > item->getQuantity()) + amount = item->getQuantity(); + } + } + else if (str == "/") + { + amount = item->getQuantity() / 2; + } + else if (str == "all") + { + amount = item->getQuantity(); + } + else + { + amount = atoi(str.c_str()); + } + return amount; +} + +impHandler(emote) +{ + const int emotion = 1 + (event.action - InputAction::EMOTE_1); + if (emotion > 0) + { + if (emoteShortcut != nullptr) + emoteShortcut->useEmotePlayer(emotion); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + + return false; +} + +impHandler(outfit) +{ + if (inputManager.isActionActive(InputAction::WEAR_OUTFIT)) + { + const int num = event.action - InputAction::OUTFIT_1; + if ((outfitWindow != nullptr) && num >= 0) + { + outfitWindow->wearOutfit(num); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + } + else if (inputManager.isActionActive(InputAction::COPY_OUTFIT)) + { + const int num = event.action - InputAction::OUTFIT_1; + if ((outfitWindow != nullptr) && num >= 0) + { + outfitWindow->copyOutfit(num); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + } + + return false; +} + +impHandler0(mouseClick) +{ + if ((guiInput == nullptr) || (gui == nullptr)) + return false; + + int mouseX, mouseY; + Gui::getMouseState(mouseX, mouseY); + guiInput->simulateMouseClick(mouseX, mouseY, MouseButton::RIGHT); + return true; +} + +impHandler0(ok) +{ + // Close the Browser if opened + if ((helpWindow != nullptr) && helpWindow->isWindowVisible()) + { + helpWindow->setVisible(Visible_false); + return true; + } + // Close the config window, cancelling changes if opened + else if ((setupWindow != nullptr) && setupWindow->isWindowVisible()) + { + setupWindow->action(ActionEvent(nullptr, "cancel")); + return true; + } + else if (NpcDialog *const dialog = NpcDialog::getActive()) + { + dialog->action(ActionEvent(nullptr, "ok")); + return true; + } + else if (popupMenu->isPopupVisible()) + { + popupMenu->select(); + } + return false; +} + +impHandler(shortcut) +{ + if (itemShortcutWindow != nullptr) + { + const int num = itemShortcutWindow->getTabIndex(); + if (num >= 0 && num < CAST_S32(SHORTCUT_TABS)) + { + if (itemShortcut[num] != nullptr) + { + itemShortcut[num]->useItem(event.action + - InputAction::SHORTCUT_1); + } + } + return true; + } + return false; +} + +impHandler0(quit) +{ + if (Game::instance() == nullptr) + return false; + if (PopupManager::isPopupMenuVisible()) + { + PopupManager::closePopupMenu(); + return true; + } + else if (quitDialog == nullptr) + { + CREATEWIDGETV(quitDialog, QuitDialog, + &quitDialog); + quitDialog->requestMoveToTop(); + return true; + } + return false; +} + +impHandler0(dropItem0) +{ + if (dropShortcut != nullptr) + { + dropShortcut->dropFirst(); + return true; + } + return false; +} + +impHandler0(dropItem) +{ + if (dropShortcut != nullptr) + { + dropShortcut->dropItems(); + return true; + } + return false; +} + +impHandler(dropItemId) +{ + const Inventory *const inv = PlayerInfo::getInventory(); + if (inv == nullptr) + return false; + + // +++ ignoring item color for now + Item *const item = inv->findItem(atoi(event.args.c_str()), + ItemColor_one); + + if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) + { + ItemAmountWindow::showWindow(ItemAmountWindowUsage::ItemDrop, + inventoryWindow, item); + } + return true; +} + +impHandler(dropItemInv) +{ + Item *const item = getItemByInvIndex(atoi(event.args.c_str()), + InventoryType::Inventory); + if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) + { + ItemAmountWindow::showWindow(ItemAmountWindowUsage::ItemDrop, + inventoryWindow, item); + } + return true; +} + +impHandler(dropItemIdAll) +{ + const Inventory *const inv = PlayerInfo::getInventory(); + if (inv == nullptr) + return false; + + // +++ ignoring item color for now + Item *const item = inv->findItem(atoi(event.args.c_str()), + ItemColor_one); + + if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) + PlayerInfo::dropItem(item, item->getQuantity(), Sfx_true); + return true; +} + +impHandler(dropItemInvAll) +{ + Item *const item = getItemByInvIndex(atoi(event.args.c_str()), + InventoryType::Inventory); + if ((item != nullptr) && !PlayerInfo::isItemProtected(item->getId())) + PlayerInfo::dropItem(item, item->getQuantity(), Sfx_true); + return true; +} + +#ifdef TMWA_SUPPORT +impHandler(heal) +{ + if (Net::getNetworkType() != ServerType::TMWATHENA) + return false; + if (actorManager != nullptr && + localPlayer != nullptr) + { + std::string args = event.args; + + if (!args.empty()) + { + const Being *being = nullptr; + if (args[0] == ':') + { + being = actorManager->findBeing(fromInt(atoi( + args.substr(1).c_str()), BeingId)); + if (being != nullptr && being->getType() == ActorType::Monster) + being = nullptr; + } + else + { + being = actorManager->findBeingByName(args, ActorType::Player); + } + if (being != nullptr) + actorManager->heal(being); + } + else + { + Being *target = localPlayer->getTarget(); + if (inputManager.isActionActive(InputAction::STOP_ATTACK)) + { + if (target == nullptr || + target->getType() != ActorType::Player) + { + target = actorManager->findNearestLivingBeing( + localPlayer, 10, ActorType::Player, AllowSort_true); + } + } + else + { + if (target == nullptr) + target = localPlayer; + } + actorManager->heal(target); + } + + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + return false; +} +#else // TMWA_SUPPORT + +impHandler0(heal) +{ + return false; +} +#endif // TMWA_SUPPORT + +impHandler0(healmd) +{ +#ifdef TMWA_SUPPORT + if (Net::getNetworkType() != ServerType::TMWATHENA) + return false; + if (actorManager != nullptr) + { + const int matk = PlayerInfo::getStatEffective(Attributes::PLAYER_MATK); + int maxHealingRadius; + + // magic levels < 2 + if (PlayerInfo::getSkillLevel(340) < 2 + || PlayerInfo::getSkillLevel(341) < 2) + { + maxHealingRadius = matk / 100 + 1; + } + else + { + maxHealingRadius = (12 * fastSqrtInt(matk) + matk) / 100 + 1; + } + + Being *target = actorManager->findMostDamagedPlayer(maxHealingRadius); + if (target != nullptr) + actorManager->heal(target); + + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } +#endif // TMWA_SUPPORT + + return false; +} + +impHandler0(itenplz) +{ +#ifdef TMWA_SUPPORT + if (Net::getNetworkType() != ServerType::TMWATHENA) + return false; + if (actorManager != nullptr) + { + if (playerHandler != nullptr && + playerHandler->canUseMagic() && + PlayerInfo::getAttribute(Attributes::PLAYER_MP) >= 3) + { + actorManager->itenplz(); + } + return true; + } +#endif // TMWA_SUPPORT + + return false; +} + +impHandler0(setHome) +{ + if (localPlayer != nullptr) + { + localPlayer->setHome(); + return true; + } + return false; +} + +impHandler0(magicAttack) +{ +#ifdef TMWA_SUPPORT + if (Net::getNetworkType() != ServerType::TMWATHENA) + return false; + if (localPlayer != nullptr) + { + localPlayer->magicAttack(); + return true; + } +#endif // TMWA_SUPPORT + + return false; +} + +impHandler0(copyEquippedToOutfit) +{ + if (outfitWindow != nullptr) + { + outfitWindow->copyFromEquiped(); + return true; + } + return false; +} + +impHandler(pickup) +{ + if (localPlayer == nullptr) + return false; + + const std::string args = event.args; + if (args.empty()) + { + localPlayer->pickUpItems(); + } + else + { + FloorItem *const item = actorManager->findItem(fromInt( + atoi(args.c_str()), BeingId)); + if (item != nullptr) + localPlayer->pickUp(item); + } + return true; +} + +static void doSit() +{ + if (inputManager.isActionActive(InputAction::EMOTE)) + localPlayer->updateSit(); + else + localPlayer->toggleSit(); +} + +impHandler0(sit) +{ + if (localPlayer != nullptr) + { + doSit(); + return true; + } + return false; +} + +impHandler(screenshot) +{ + Game::createScreenshot(event.args); + return true; +} + +impHandler0(ignoreInput) +{ + return true; +} + +impHandler(buy) +{ + if (serverFeatures == nullptr) + return false; + const std::string args = event.args; + Being *being = findBeing(args, false); + if ((being == nullptr) && Net::getNetworkType() == ServerType::TMWATHENA) + { + if (whoIsOnline != nullptr) + { + const std::set &players = + whoIsOnline->getOnlineNicks(); + if (players.find(args) != players.end()) + { + if (buySellHandler != nullptr) + buySellHandler->requestSellList(args); + return true; + } + } + return false; + } + + if (being == nullptr) + being = findBeing(args, true); + + if (being == nullptr) + return false; + + if (being->getType() == ActorType::Npc) + { + if (npcHandler != nullptr) + npcHandler->buy(being); + return true; + } + else if (being->getType() == ActorType::Player) + { + if (vendingHandler != nullptr && + Net::getNetworkType() != ServerType::TMWATHENA) + { + vendingHandler->open(being); + } + else if (buySellHandler != nullptr) + { + buySellHandler->requestSellList(being->getName()); + } + return true; + } + return false; +} + +impHandler(sell) +{ + if (serverFeatures == nullptr) + return false; + + const std::string args = event.args; + Being *being = findBeing(args, false); + if (being == nullptr && + Net::getNetworkType() == ServerType::TMWATHENA) + { + if (whoIsOnline != nullptr) + { + const std::set &players = + whoIsOnline->getOnlineNicks(); + if (players.find(args) != players.end()) + { + if (buySellHandler != nullptr) + buySellHandler->requestBuyList(args); + return true; + } + } + return false; + } + + if (being == nullptr) + being = findBeing(args, true); + + if (being == nullptr) + return false; + + if (being->getType() == ActorType::Npc) + { + if (npcHandler != nullptr) + npcHandler->sell(being->getId()); + return true; + } + else if (being->getType() == ActorType::Player) + { + if ((buyingStoreHandler != nullptr) && + Net::getNetworkType() != ServerType::TMWATHENA) + { + buyingStoreHandler->open(being); + } + else if (buySellHandler != nullptr) + { + buySellHandler->requestBuyList(being->getName()); + } + return true; + } + return false; +} + +impHandler(talk) +{ + Being *being = findBeing(event.args, true); + if (being == nullptr) + return false; + + if (being->canTalk()) + { + being->talkTo(); + } + else if (being->getType() == ActorType::Player) + { + CREATEWIDGET(BuySellDialog, + being->getName()); + } + return true; +} + +impHandler0(stopAttack) +{ + if (localPlayer != nullptr) + { + localPlayer->stopAttack(); + // not consume if target attack key pressed + if (inputManager.isActionActive(InputAction::TARGET_ATTACK)) + return false; + return true; + } + return false; +} + +impHandler0(untarget) +{ + if (localPlayer != nullptr) + { + localPlayer->untarget(); + return true; + } + return false; +} + +impHandler(attack) +{ + if ((localPlayer == nullptr) || (actorManager == nullptr)) + return false; + + Being *target = nullptr; + std::string args = event.args; + if (!args.empty()) + { + if (args[0] != ':') + { + target = actorManager->findNearestByName(args); + } + else + { + target = actorManager->findBeing(fromInt(atoi( + args.substr(1).c_str()), BeingId)); + if (target != nullptr && + target->getType() != ActorType::Monster) + { + target = nullptr; + } + } + } + if (target == nullptr) + target = localPlayer->getTarget(); + else + localPlayer->setTarget(target); + if (target != nullptr) + localPlayer->attack(target, true); + return true; +} + +impHandler(targetAttack) +{ + if ((localPlayer != nullptr) && (actorManager != nullptr)) + { + Being *target = nullptr; + std::string args = event.args; + const bool newTarget = !inputManager.isActionActive( + InputAction::STOP_ATTACK); + + if (!args.empty()) + { + if (args[0] != ':') + { + target = actorManager->findNearestByName(args); + } + else + { + target = actorManager->findBeing(fromInt(atoi( + args.substr(1).c_str()), BeingId)); + if (target != nullptr && + target->getType() != ActorType::Monster) + { + target = nullptr; + } + } + } + + if ((target == nullptr) && (settings.targetingType == 0u)) + target = localPlayer->getTarget(); + + if (target == nullptr) + { + target = actorManager->findNearestLivingBeing( + localPlayer, 90, ActorType::Monster, AllowSort_true); + } + + localPlayer->attack2(target, newTarget); + return true; + } + return false; +} + +impHandler0(attackHuman) +{ + if ((actorManager == nullptr) || (localPlayer == nullptr)) + return false; + + Being *const target = actorManager->findNearestPvpPlayer(); + if (target != nullptr) + { + localPlayer->setTarget(target); + localPlayer->attack2(target, true); + } + return true; +} + +impHandler0(safeVideoMode) +{ + WindowManager::setFullScreen(false); + + return true; +} + +impHandler0(stopSit) +{ + if (localPlayer != nullptr) + { + localPlayer->stopAttack(); + // not consume if target attack key pressed + if (inputManager.isActionActive(InputAction::TARGET_ATTACK)) + return false; + if (localPlayer->getTarget() == nullptr) + { + doSit(); + return true; + } + return true; + } + return false; +} + +impHandler0(showKeyboard) +{ +#ifdef ANDROID +#ifdef USE_SDL2 + if (SDL_IsTextInputActive()) + SDL_StopTextInput(); + else + SDL_StartTextInput(); +#else // USE_SDL2 + + SDL_ANDROID_ToggleScreenKeyboardTextInput(nullptr); +#endif // USE_SDL2 + + return true; +#else // ANDROID + + return false; +#endif // ANDROID +} + +impHandler0(showWindows) +{ + if (popupMenu != nullptr) + { + popupMenu->showWindowsPopup(); + return true; + } + return false; +} + +impHandler0(openTrade) +{ + const Being *const being = localPlayer->getTarget(); + if ((being != nullptr) && being->getType() == ActorType::Player) + { + if (tradeHandler != nullptr) + tradeHandler->request(being); + tradePartnerName = being->getName(); + if (tradeWindow != nullptr) + tradeWindow->clear(); + return true; + } + return false; +} + +impHandler0(ipcToggle) +{ + if (ipc != nullptr) + { + IPC::stop(); + if (ipc == nullptr) + { + debugChatTab->chatLog("IPC service stopped.", + ChatMsgType::BY_SERVER); + } + else + { + debugChatTab->chatLog("Unable to stop IPC service.", + ChatMsgType::BY_SERVER); + } + } + else + { + IPC::start(); + if (ipc != nullptr) + { + debugChatTab->chatLog( + strprintf("IPC service available on port %d", ipc->getPort()), + ChatMsgType::BY_SERVER); + } + else + { + debugChatTab->chatLog("Unable to start IPC service", + ChatMsgType::BY_SERVER); + } + } + return true; +} + +impHandler(where) +{ + ChatTab *const tab = event.tab != nullptr ? event.tab : debugChatTab; + if (tab == nullptr) + return false; + std::ostringstream where; + where << Game::instance()->getCurrentMapName() << ", coordinates: " + << ((localPlayer->getPixelX() - mapTileSize / 2) / mapTileSize) + << ", " << ((localPlayer->getPixelY() - mapTileSize) / mapTileSize); + tab->chatLog(where.str(), ChatMsgType::BY_SERVER); + return true; +} + +impHandler0(who) +{ + if (chatHandler != nullptr) + chatHandler->who(); + return true; +} + +impHandler0(cleanGraphics) +{ + ResourceManager::clearCache(); + + if (debugChatTab != nullptr) + { + // TRANSLATORS: clear graphics command message + debugChatTab->chatLog(_("Cache cleaned"), + ChatMsgType::BY_SERVER); + } + return true; +} + +impHandler0(cleanFonts) +{ + if (gui != nullptr) + gui->clearFonts(); + if (debugChatTab != nullptr) + { + // TRANSLATORS: clear fonts cache message + debugChatTab->chatLog(_("Cache cleaned"), + ChatMsgType::BY_SERVER); + } + return true; +} + +impHandler(trade) +{ + if (actorManager == nullptr) + return false; + + const Being *being = actorManager->findBeingByName( + event.args, ActorType::Player); + if (being == nullptr) + being = localPlayer->getTarget(); + if (being != nullptr) + { + if (tradeHandler != nullptr) + tradeHandler->request(being); + tradePartnerName = being->getName(); + if (tradeWindow != nullptr) + tradeWindow->clear(); + } + return true; +} + +impHandler0(priceLoad) +{ + if (shopWindow != nullptr) + { + shopWindow->loadList(); + return true; + } + return false; +} + +impHandler0(priceSave) +{ + if (shopWindow != nullptr) + { + shopWindow->saveList(); + return true; + } + return false; +} + +impHandler0(cacheInfo) +{ + if ((chatWindow == nullptr) || (debugChatTab == nullptr)) + return false; + +/* + Font *const font = chatWindow->getFont(); + if (!font) + return; + + const TextChunkList *const cache = font->getCache(); + if (!cache) + return; + + unsigned int all = 0; + // TRANSLATORS: chat fonts message + debugChatTab->chatLog(_("font cache size"), ChatMsgType::BY_SERVER); + std::string str; + for (int f = 0; f < 256; f ++) + { + if (!cache[f].size) + { + const unsigned int sz = CAST_S32(cache[f].size); + all += sz; + str.append(strprintf("%d: %u, ", f, sz)); + } + } + debugChatTab->chatLog(str, ChatMsgType::BY_SERVER); + // TRANSLATORS: chat fonts message + debugChatTab->chatLog(strprintf("%s %d", _("Cache size:"), all), + ChatMsgType::BY_SERVER); +#ifdef DEBUG_FONT_COUNTERS + debugChatTab->chatLog("", ChatMsgType::BY_SERVER); + debugChatTab->chatLog(strprintf("%s %d", + // TRANSLATORS: chat fonts message + _("Created:"), font->getCreateCounter()), + ChatMsgType::BY_SERVER); + debugChatTab->chatLog(strprintf("%s %d", + // TRANSLATORS: chat fonts message + _("Deleted:"), font->getDeleteCounter()), + ChatMsgType::BY_SERVER); +#endif +*/ + return true; +} + +impHandler0(disconnect) +{ + if (gameHandler != nullptr) + gameHandler->disconnect2(); + return true; +} + +impHandler(undress) +{ + if ((actorManager == nullptr) || (localPlayer == nullptr)) + return false; + + const std::string args = event.args; + StringVect pars; + if (!splitParameters(pars, args, " ,", '\"')) + return false; + Being *target = nullptr; + const size_t sz = pars.size(); + if (sz == 0) + { + target = localPlayer->getTarget(); + } + else + { + if (pars[0][0] == ':') + { + target = actorManager->findBeing(fromInt(atoi( + pars[0].substr(1).c_str()), BeingId)); + if ((target != nullptr) && target->getType() == ActorType::Monster) + target = nullptr; + } + else + { + target = actorManager->findNearestByName(args); + } + } + + if (sz == 2) + { + const int itemId = atoi(pars[1].c_str()); + if (target != nullptr) + target->undressItemById(itemId); + } + else + { + if ((target != nullptr) && (beingHandler != nullptr)) + beingHandler->undress(target); + } + + return true; +} + +impHandler0(dirs) +{ + if (debugChatTab == nullptr) + return false; + + debugChatTab->chatLog("config directory: " + + settings.configDir, + ChatMsgType::BY_SERVER); + debugChatTab->chatLog("logs directory: " + + settings.localDataDir, + ChatMsgType::BY_SERVER); + debugChatTab->chatLog("screenshots directory: " + + settings.screenshotDir, + ChatMsgType::BY_SERVER); + debugChatTab->chatLog("temp directory: " + + settings.tempDir, + ChatMsgType::BY_SERVER); + return true; +} + +impHandler0(uptime) +{ + if (debugChatTab == nullptr) + return false; + + if (cur_time < start_time) + { + // TRANSLATORS: uptime command + debugChatTab->chatLog(strprintf(_("Client uptime: %s"), "unknown"), + ChatMsgType::BY_SERVER); + } + else + { + // TRANSLATORS: uptime command + debugChatTab->chatLog(strprintf(_("Client uptime: %s"), + timeDiffToString(CAST_S32(cur_time - start_time)).c_str()), + ChatMsgType::BY_SERVER); + } + return true; +} + +#ifdef DEBUG_DUMP_LEAKS1 +static void showRes(std::string str, ResourceManager::Resources *res) +{ + if (!res) + return; + + str.append(toString(res->size())); + if (debugChatTab) + debugChatTab->chatLog(str, ChatMsgType::BY_SERVER); + logger->log(str); + ResourceManager::ResourceIterator iter = res->begin(); + const ResourceManager::ResourceIterator iter_end = res->end(); + while (iter != iter_end) + { + if (iter->second && iter->second->mRefCount) + { + char type = ' '; + char isNew = 'N'; + if (iter->second->getDumped()) + isNew = 'O'; + else + iter->second->setDumped(true); + + SubImage *const subImage = dynamic_cast( + iter->second); + Image *const image = dynamic_cast(iter->second); + int id = 0; + if (subImage) + type = 'S'; + else if (image) + type = 'I'; + if (image) + id = image->getGLImage(); + logger->log("Resource %c%c: %s (%d) id=%d", type, + isNew, iter->second->getIdPath().c_str(), + iter->second->mRefCount, id); + } + ++ iter; + } +} + +impHandler(dump) +{ + if (!debugChatTab) + return false; + + if (!event.args.empty()) + { + ResourceManager::Resources *res = ResourceManager::getResources(); + // TRANSLATORS: dump command + showRes(_("Resource images:"), res); + res = ResourceManager::getOrphanedResources(); + // TRANSLATORS: dump command + showRes(_("Resource orphaned images:"), res); + } + else + { + ResourceManager::Resources *res = ResourceManager::getResources(); + // TRANSLATORS: dump command + debugChatTab->chatLog(_("Resource images:") + toString(res->size()), + ChatMsgType::BY_SERVER); + res = ResourceManager::getOrphanedResources(); + // TRANSLATORS: dump command + debugChatTab->chatLog(_("Resource orphaned images:") + + toString(res->size()), + ChatMsgType::BY_SERVER); + } + return true; +} + +#elif defined ENABLE_MEM_DEBUG +impHandler0(dump) +{ + nvwa::check_leaks(); + return true; +} +#else // DEBUG_DUMP_LEAKS1 + +impHandler0(dump) +{ + return true; +} +#endif // DEBUG_DUMP_LEAKS1 + +impHandler0(serverIgnoreAll) +{ + if (chatHandler != nullptr) + chatHandler->ignoreAll(); + return true; +} + +impHandler0(serverUnIgnoreAll) +{ + if (chatHandler != nullptr) + chatHandler->unIgnoreAll(); + return true; +} + +PRAGMA6(GCC diagnostic push) +PRAGMA6(GCC diagnostic ignored "-Wnull-dereference") +impHandler0(error) +{ + int *const ptr = nullptr; + *(ptr + 1) = 20; +// logger->log("test %d", *ptr); + exit(1); +} +PRAGMA6(GCC diagnostic pop) + +impHandler(dumpGraphics) +{ + std::string str = strprintf("%s,%s,%dX%dX%d,", PACKAGE_OS, SMALL_VERSION, + mainGraphics->getWidth(), mainGraphics->getHeight(), + mainGraphics->getBpp()); + + if (mainGraphics->getFullScreen()) + str.append("F"); + else + str.append("W"); + if (mainGraphics->getHWAccel()) + str.append("H"); + else + str.append("S"); + + if (mainGraphics->getDoubleBuffer()) + str.append("D"); + else + str.append("_"); + +#if defined USE_OPENGL + str.append(strprintf(",%d", mainGraphics->getOpenGL())); +#else // defined USE_OPENGL + + str.append(",0"); +#endif // defined USE_OPENGL + + str.append(strprintf(",%f,", static_cast(settings.guiAlpha))) + .append(config.getBoolValue("adjustPerfomance") ? "1" : "0") + .append(config.getBoolValue("alphaCache") ? "1" : "0") + .append(config.getBoolValue("enableMapReduce") ? "1" : "0") + .append(config.getBoolValue("beingopacity") ? "1" : "0") + .append(",") + .append(config.getBoolValue("enableAlphaFix") ? "1" : "0") + .append(config.getBoolValue("disableAdvBeingCaching") ? "1" : "0") + .append(config.getBoolValue("disableBeingCaching") ? "1" : "0") + .append(config.getBoolValue("particleeffects") ? "1" : "0") + .append(strprintf(",%d-%d", fps, config.getIntValue("fpslimit"))); + outStringNormal(event.tab, str, str); + return true; +} + +impHandler0(dumpEnvironment) +{ + logger->log1("Start environment variables"); + for (char **env = environ; *env != nullptr; ++ env) + logger->log1(*env); + logger->log1("End environment variables"); + if (debugChatTab != nullptr) + { + // TRANSLATORS: dump environment command + debugChatTab->chatLog(_("Environment variables dumped"), + ChatMsgType::BY_SERVER); + } + return true; +} + +impHandler(dumpTests) +{ + const std::string str = config.getStringValue("testInfo"); + outStringNormal(event.tab, str, str); + return true; +} + +impHandler0(dumpOGL) +{ +#if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__native_client__) + NormalOpenGLGraphics::dumpSettings(); +#endif // defined(USE_OPENGL) && !defined(ANDROID) && + // !defined(__native_client__) + + return true; +} + +#ifdef USE_OPENGL +impHandler(dumpGL) +{ + std::string str = graphicsManager.getGLVersion(); + outStringNormal(event.tab, str, str); + return true; +} +#else // USE_OPENGL + +impHandler0(dumpGL) +{ + return true; +} +#endif // USE_OPENGL + +impHandler(dumpMods) +{ + std::string str = "enabled mods: " + serverConfig.getValue("mods", ""); + outStringNormal(event.tab, str, str); + return true; +} + +#if defined USE_OPENGL && defined DEBUG_SDLFONT +impHandler0(testSdlFont) +{ + Font *font = new Font("fonts/dejavusans.ttf", 18); + timespec time1; + timespec time2; + NullOpenGLGraphics *nullGraphics = new NullOpenGLGraphics; + STD_VECTOR data; + volatile int width = 0; + + for (int f = 0; f < 300; f ++) + data.push_back("test " + toString(f) + "string"); + nullGraphics->beginDraw(); + + clock_gettime(CLOCK_MONOTONIC, &time1); + Color color(0, 0, 0, 255); + + for (int f = 0; f < 500; f ++) + { + FOR_EACH (STD_VECTOR::const_iterator, it, data) + { + width += font->getWidth(*it); + font->drawString(nullGraphics, color, color, *it, 10, 10); + } + FOR_EACH (STD_VECTOR::const_iterator, it, data) + font->drawString(nullGraphics, color, color, *it, 10, 10); + + font->doClean(); + } + + clock_gettime(CLOCK_MONOTONIC, &time2); + + delete nullGraphics; + delete font; + + int64_t diff = (static_cast( + time2.tv_sec) * 1000000000LL + static_cast( + time2.tv_nsec)) / 100000 - (static_cast( + time1.tv_sec) * 1000000000LL + static_cast( + time1.tv_nsec)) / 100000; + if (debugChatTab) + { + debugChatTab->chatLog("sdlfont time: " + toString(diff), + ChatMsgType::BY_SERVER); + } + return true; +} +#endif // defined USE_OPENGL && defined DEBUG_SDLFONT + +impHandler0(createItems) +{ + BuyDialog *const dialog = CREATEWIDGETR0(BuyDialog); + const ItemDB::ItemInfos &items = ItemDB::getItemInfos(); + FOR_EACH (ItemDB::ItemInfos::const_iterator, it, items) + { + const ItemInfo *const info = (*it).second; + if (info == nullptr) + continue; + const int id = info->getId(); + if (id <= 500) + continue; + + dialog->addItem(id, + ItemType::Unknown, + ItemColor_one, + 100, + 0); + } + dialog->sort(); + return true; +} + +impHandler(createItem) +{ + int id = 0; + int amount = 0; + + if (adminHandler == nullptr) + return false; + + if (parse2Int(event.args, id, amount)) + adminHandler->createItems(id, ItemColor_one, amount); + else + adminHandler->createItems(atoi(event.args.c_str()), ItemColor_one, 1); + return true; +} + +impHandler(uploadConfig) +{ + // TRANSLATORS: upload config chat message + uploadFile(_("Uploaded config into:"), + config.getFileName(), + "?xml", + event.tab); + return true; +} + +impHandler(uploadServerConfig) +{ + // TRANSLATORS: upload config chat message + uploadFile(_("Uploaded server config into:"), + serverConfig.getFileName(), + "?xml", + event.tab); + return true; +} + +impHandler(uploadLog) +{ + // TRANSLATORS: upload log chat message + uploadFile(_("Uploaded log into:"), + settings.logFileName, + "?txt", + event.tab); + return true; +} + +impHandler0(mercenaryFire) +{ + if (mercenaryHandler != nullptr) + mercenaryHandler->fire(); + return true; +} + +impHandler0(mercenaryToMaster) +{ + if (mercenaryHandler != nullptr) + mercenaryHandler->moveToMaster(); + return true; +} + +impHandler0(homunculusToMaster) +{ + if (homunculusHandler != nullptr) + homunculusHandler->moveToMaster(); + return true; +} + +impHandler0(homunculusFeed) +{ + if (homunculusHandler != nullptr) + homunculusHandler->feed(); + return true; +} + +impHandler(useItem) +{ + const int itemId = atoi(event.args.c_str()); + + if (itemId < SPELL_MIN_ID) + { + const Inventory *const inv = PlayerInfo::getInventory(); + if (inv != nullptr) + { + // +++ ignoring item color for now + const Item *const item = inv->findItem(itemId, + ItemColor_one); + PlayerInfo::useEquipItem(item, 0, Sfx_true); + } + } + else if (itemId < SKILL_MIN_ID && (spellManager != nullptr)) + { + spellManager->useItem(itemId); + } + else if (skillDialog != nullptr) + { + // +++ probably need get data parameter from args + skillDialog->useItem(itemId, + fromBool(config.getBoolValue("skillAutotarget"), AutoTarget), + 0, + std::string()); + } + return true; +} + +impHandler(useItemInv) +{ + int param1 = 0; + int param2 = 0; + const std::string args = event.args; + if (parse2Int(args, param1, param2)) + { + Item *const item = getItemByInvIndex(param1, + InventoryType::Inventory); + PlayerInfo::useEquipItem(item, CAST_S16(param2), Sfx_true); + } + else + { + Item *const item = getItemByInvIndex(atoi(event.args.c_str()), + InventoryType::Inventory); + PlayerInfo::useEquipItem(item, 0, Sfx_true); + } + return true; +} + +impHandler(invToStorage) +{ + Item *item = nullptr; + const int amount = getAmountFromEvent(event, item, + InventoryType::Inventory); + if (item == nullptr) + return true; + if (amount != 0) + { + if (inventoryHandler != nullptr) + { + inventoryHandler->moveItem2(InventoryType::Inventory, + item->getInvIndex(), + amount, + InventoryType::Storage); + } + } + else + { + ItemAmountWindow::showWindow(ItemAmountWindowUsage::StoreAdd, + inventoryWindow, item); + } + return true; +} + +impHandler(tradeAdd) +{ + Item *item = nullptr; + const int amount = getAmountFromEvent(event, item, + InventoryType::Inventory); + if ((item == nullptr) || PlayerInfo::isItemProtected(item->getId())) + return true; + + if (amount != 0) + { + if (tradeWindow != nullptr) + tradeWindow->tradeItem(item, amount, true); + } + else + { + ItemAmountWindow::showWindow(ItemAmountWindowUsage::TradeAdd, + tradeWindow, item); + } + return true; +} + +impHandler(storageToInv) +{ + Item *item = nullptr; + const int amount = getAmountFromEvent(event, item, InventoryType::Storage); + if (amount != 0) + { + if ((inventoryHandler != nullptr) && (item != nullptr)) + { + inventoryHandler->moveItem2(InventoryType::Storage, + item->getInvIndex(), + amount, + InventoryType::Inventory); + } + } + else + { + ItemAmountWindow::showWindow(ItemAmountWindowUsage::StoreRemove, + storageWindow, item); + } + return true; +} + +impHandler(protectItem) +{ + const int id = atoi(event.args.c_str()); + if (id > 0) + PlayerInfo::protectItem(id); + return true; +} + +impHandler(unprotectItem) +{ + const int id = atoi(event.args.c_str()); + if (id > 0) + PlayerInfo::unprotectItem(id); + return true; +} + +impHandler(kick) +{ + if ((localPlayer == nullptr) || (actorManager == nullptr)) + return false; + + Being *target = nullptr; + std::string args = event.args; + if (!args.empty()) + { + if (args[0] != ':') + { + target = actorManager->findNearestByName(args); + } + else + { + target = actorManager->findBeing(fromInt(atoi( + args.substr(1).c_str()), BeingId)); + } + } + if (target == nullptr) + target = localPlayer->getTarget(); + if ((target != nullptr) && (adminHandler != nullptr)) + adminHandler->kick(target->getId()); + return true; +} + +impHandler0(clearDrop) +{ + if (dropShortcut != nullptr) + dropShortcut->clear(); + return true; +} + +impHandler0(testInfo) +{ + if (actorManager != nullptr) + { + logger->log("actors count: %d", CAST_S32( + actorManager->size())); + return true; + } + return false; +} + +impHandler(craftKey) +{ + const int slot = (event.action - InputAction::CRAFT_1); + if (slot >= 0 && slot < 9) + { + if (inventoryWindow != nullptr) + inventoryWindow->moveItemToCraft(slot); + return true; + } + return false; +} + +impHandler0(resetGameModifiers) +{ + GameModifiers::resetModifiers(); + return true; +} + +impHandler(barToChat) +{ + if (chatWindow != nullptr) + { + chatWindow->addInputText(event.args); + return true; + } + return false; +} + +impHandler(seen) +{ + if (actorManager == nullptr) + return false; + + ChatTab *tab = event.tab; + if (tab == nullptr) + tab = localChatTab; + if (tab == nullptr) + return false; + + if (config.getBoolValue("enableIdCollecting") == false) + { + // TRANSLATORS: last seen disabled warning + tab->chatLog(_("Last seen disabled. " + "Enable in players / collect players id and seen log."), + ChatMsgType::BY_SERVER); + return true; + } + + const std::string name = event.args; + if (name.empty()) + return false; + + std::string dir = settings.usersDir; + dir.append(stringToHexPath(name)).append("/seen.txt"); + if (Files::existsLocal(dir)) + { + StringVect lines; + Files::loadTextFileLocal(dir, lines); + if (lines.size() < 3) + { + // TRANSLATORS: last seen error + tab->chatLog(_("You not saw this nick."), + ChatMsgType::BY_SERVER); + return true; + } + const std::string message = strprintf( + // TRANSLATORS: last seen message + _("Last seen for %s: %s"), + name.c_str(), + lines[2].c_str()); + tab->chatLog(message, ChatMsgType::BY_SERVER); + } + else + { + // TRANSLATORS: last seen error + tab->chatLog(_("You not saw this nick."), + ChatMsgType::BY_SERVER); + } + + return true; +} + +impHandler(dumpMemoryUsage) +{ + if (event.tab != nullptr) + memoryManager.printAllMemory(event.tab); + else + memoryManager.printAllMemory(localChatTab); + return true; +} + +impHandler(setEmoteType) +{ + const std::string &args = event.args; + if (args == "player" || args.empty()) + { + settings.emoteType = EmoteType::Player; + } + else if (args == "pet") + { + settings.emoteType = EmoteType::Pet; + } + else if (args == "homun" || args == "homunculus") + { + settings.emoteType = EmoteType::Homunculus; + } + else if (args == "merc" || args == "mercenary") + { + settings.emoteType = EmoteType::Mercenary; + } + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/chat.cpp b/src/progs/manaplus/actions/chat.cpp new file mode 100644 index 000000000..307e4556e --- /dev/null +++ b/src/progs/manaplus/actions/chat.cpp @@ -0,0 +1,808 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/chat.h" + +#include "configuration.h" + +#include "actions/actiondef.h" + +#include "const/gui/chat.h" + +#include "being/localplayer.h" + +#include "gui/sdlinput.h" + +#include "gui/windows/chatwindow.h" + +#include "listeners/inputactionreplaylistener.h" + +#include "net/charserverhandler.h" +#include "net/chathandler.h" +#include "net/guildhandler.h" +#include "net/net.h" +#include "net/partyhandler.h" + +#ifdef TMWA_SUPPORT +#include "net/tmwa/guildmanager.h" +#endif // TMWA_SUPPORT + +#include "resources/iteminfo.h" + +#include "resources/db/itemdb.h" + +#include "utils/booleanoptions.h" +#include "utils/chatutils.h" +#include "utils/parameters.h" + +#include "utils/translation/podict.h" + +#include "debug.h" + +const int DEFAULT_CHAT_WINDOW_SCROLL = 7; + +namespace Actions +{ + +static void outString(ChatTab *const tab, + const std::string &str, + const std::string &def) +{ + if (tab == nullptr) + { + if (chatHandler != nullptr) + chatHandler->talk(def, GENERAL_CHANNEL); + return; + } + + switch (tab->getType()) + { + case ChatTabType::PARTY: + { + if (partyHandler != nullptr) + partyHandler->chat(str); + break; + } + case ChatTabType::GUILD: + { + if ((guildHandler == nullptr) || (localPlayer == nullptr)) + return; + const Guild *const guild = localPlayer->getGuild(); + if (guild != nullptr) + { +#ifdef TMWA_SUPPORT + if (guild->getServerGuild()) + { + if (Net::getNetworkType() == ServerType::TMWATHENA) + return; + guildHandler->chat(str); + } + else if (guildManager != nullptr) + { + guildManager->chat(str); + } +#else // TMWA_SUPPORT + + if (guild->getServerGuild()) + guildHandler->chat(str); +#endif // TMWA_SUPPORT + } + break; + } + case ChatTabType::CHANNEL: + case ChatTabType::GM: + case ChatTabType::TRADE: + tab->chatInput(str); + break; + default: + case ChatTabType::UNKNOWN: + case ChatTabType::INPUT: + case ChatTabType::WHISPER: + case ChatTabType::DEBUG: + case ChatTabType::BATTLE: + case ChatTabType::LANG: + if (chatHandler != nullptr) + chatHandler->talk(str, GENERAL_CHANNEL); + break; + } +} + +impHandler0(toggleChat) +{ + return chatWindow != nullptr ? chatWindow->requestChatFocus() : false; +} + +impHandler0(prevChatTab) +{ + if (chatWindow != nullptr) + { + chatWindow->prevTab(); + return true; + } + return false; +} + +impHandler0(nextChatTab) +{ + if (chatWindow != nullptr) + { + chatWindow->nextTab(); + return true; + } + return false; +} + +impHandler0(closeChatTab) +{ + if (chatWindow != nullptr) + { + chatWindow->closeTab(); + return true; + } + return false; +} + +impHandler0(closeAllChatTabs) +{ + if (chatWindow != nullptr) + { + chatWindow->removeAllWhispers(); + chatWindow->saveState(); + return true; + } + return false; +} + +impHandler0(ignoreAllWhispers) +{ + if (chatWindow != nullptr) + { + chatWindow->ignoreAllWhispers(); + chatWindow->saveState(); + return true; + } + return false; +} + +impHandler0(scrollChatUp) +{ + if ((chatWindow != nullptr) && chatWindow->isWindowVisible()) + { + chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL); + return true; + } + return false; +} + +impHandler0(scrollChatDown) +{ + if ((chatWindow != nullptr) && chatWindow->isWindowVisible()) + { + chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL); + return true; + } + return false; +} + +static bool splitWhisper(const std::string &args, + std::string &recvnick, + std::string &message) +{ + if (args.substr(0, 1) == "\"") + { + const size_t pos = args.find('"', 1); + if (pos != std::string::npos) + { + recvnick = args.substr(1, pos - 1); + if (pos + 2 < args.length()) + message = args.substr(pos + 2, args.length()); + } + } + else + { + const size_t pos = args.find(' '); + if (pos != std::string::npos) + { + recvnick = args.substr(0, pos); + if (pos + 1 < args.length()) + message = args.substr(pos + 1, args.length()); + } + else + { + recvnick = std::string(args); + message.clear(); + } + } + + trim(message); + + if (message.length() > 0) + { + std::string playerName = localPlayer->getName(); + std::string tempNick = recvnick; + + toLower(playerName); + toLower(tempNick); + + if (tempNick == playerName || args.empty()) + return false; + + return true; + } + return false; +} + +impHandler(msg) +{ + std::string recvnick; + std::string message; + + if (splitWhisper(event.args, recvnick, message)) + { + if (chatWindow == nullptr) + return false; + ChatTab *const tab = chatWindow->addChatTab(recvnick, false, true); + if (tab != nullptr) + { + chatWindow->saveState(); + tab->chatInput(message); + } + } + else + { + if (event.tab != nullptr) + { + event.tab->chatLog( + // TRANSLATORS: whisper send + _("Cannot send empty whisper or channel message!"), + ChatMsgType::BY_SERVER); + } + } + return true; +} + +impHandler(msgText) +{ + if (chatWindow == nullptr) + return false; + + if (config.getBoolValue("whispertab")) + { + chatWindow->localChatInput("/q " + event.args); + } + else + { + chatWindow->addInputText(std::string("/w \"").append( + event.args).append("\" ")); + } + return true; +} + +impHandler(msg2) +{ + std::string recvnick; + std::string message; + + if (chatHandler != nullptr && + splitWhisper(event.args, recvnick, message)) + { + chatHandler->privateMessage(recvnick, message); + } + return true; +} + +impHandler(query) +{ + const std::string &args = event.args; + if (chatWindow != nullptr) + { + if (chatWindow->addChatTab(args, true, true) != nullptr) + { + chatWindow->saveState(); + return true; + } + } + + if (event.tab != nullptr) + { + // TRANSLATORS: new whisper or channel query + event.tab->chatLog(strprintf(_("Cannot create a whisper tab " + "\"%s\"! It probably already exists."), + args.c_str()), ChatMsgType::BY_SERVER); + } + return true; +} + +impHandler0(clearChatTab) +{ + if (chatWindow != nullptr) + { + chatWindow->clearTab(); + return true; + } + return false; +} + +impHandler(createParty) +{ + if (partyHandler == nullptr) + return false; + + if (event.args.empty()) + { + // TRANSLATORS: dialog header + inputActionReplayListener.openDialog(_("Create party"), + "", + InputAction::CREATE_PARTY); + } + else + { + partyHandler->create(event.args); + } + return true; +} + +impHandler(createGuild) +{ + if ((guildHandler == nullptr) || + Net::getNetworkType() == ServerType::TMWATHENA) + { + return false; + } + + if (event.args.empty()) + { + // TRANSLATORS: dialog header + inputActionReplayListener.openDialog(_("Create guild"), + "", + InputAction::CREATE_GUILD); + } + else + { + guildHandler->create(event.args); + } + return true; +} + +impHandler(party) +{ + if (!event.args.empty()) + { + if (partyHandler != nullptr) + partyHandler->invite(event.args); + } + else + { + if (event.tab != nullptr) + { + // TRANSLATORS: party invite message + event.tab->chatLog(_("Please specify a name."), + ChatMsgType::BY_SERVER); + } + } + return true; +} + +impHandler(guild) +{ + if ((guildHandler == nullptr) || (localPlayer == nullptr)) + return false; + + const std::string args = event.args; + if (!args.empty()) + { + const Guild *const guild = localPlayer->getGuild(); + if (guild != nullptr) + { +#ifdef TMWA_SUPPORT + if (guild->getServerGuild()) + guildHandler->invite(args); + else if (guildManager != nullptr) + GuildManager::invite(args); +#else // TMWA_SUPPORT + + guildHandler->invite(args); +#endif // TMWA_SUPPORT + } + } + else + { + if (event.tab != nullptr) + { + // TRANSLATORS: guild invite message + event.tab->chatLog(_("Please specify a name."), + ChatMsgType::BY_SERVER); + } + else if (localChatTab != nullptr) + { + // TRANSLATORS: guild invite message + localChatTab->chatLog(_("Please specify a name."), + ChatMsgType::BY_SERVER); + } + } + return true; +} + +impHandler(me) +{ + outString(event.tab, textToMe(event.args), event.args); + return true; +} + +impHandler(toggle) +{ + if (event.args.empty()) + { + if ((chatWindow != nullptr) && (event.tab != nullptr)) + { + event.tab->chatLog(chatWindow->getReturnTogglesChat() ? + // TRANSLATORS: message from toggle chat command + _("Return toggles chat.") : _("Message closes chat."), + ChatMsgType::BY_SERVER); + } + return true; + } + + switch (parseBoolean(event.args)) + { + case 1: + if (event.tab != nullptr) + { + // TRANSLATORS: message from toggle chat command + event.tab->chatLog(_("Return now toggles chat."), + ChatMsgType::BY_SERVER); + } + if (chatWindow != nullptr) + chatWindow->setReturnTogglesChat(true); + return true; + case 0: + if (event.tab != nullptr) + { + // TRANSLATORS: message from toggle chat command + event.tab->chatLog(_("Message now closes chat."), + ChatMsgType::BY_SERVER); + } + if (chatWindow != nullptr) + chatWindow->setReturnTogglesChat(false); + return true; + case -1: + if (event.tab != nullptr) + { + event.tab->chatLog(strprintf(BOOLEAN_OPTIONS, "toggle"), + ChatMsgType::BY_SERVER); + } + return true; + default: + return true; + } +} + +impHandler(kickParty) +{ + if (!event.args.empty()) + { + if (partyHandler != nullptr) + partyHandler->kick(event.args); + } + else + { + if (event.tab != nullptr) + { + // TRANSLATORS: party kick message + event.tab->chatLog(_("Please specify a name."), + ChatMsgType::BY_SERVER); + } + } + return true; +} + +impHandler(kickGuild) +{ + if (!event.args.empty()) + { + if (localPlayer != nullptr) + { + const Guild *const guild = localPlayer->getGuild(); + if (guild != nullptr) + { + if (guild->getServerGuild()) + { + if (guildHandler != nullptr) + guildHandler->kick(guild->getMember(event.args), ""); + } +#ifdef TMWA_SUPPORT + else if (guildManager != nullptr) + { + GuildManager::kick(event.args); + } +#endif // TMWA_SUPPORT + } + } + } + else + { + if (event.tab != nullptr) + { + // TRANSLATORS: party kick message + event.tab->chatLog(_("Please specify a name."), + ChatMsgType::BY_SERVER); + } + } + return true; +} + +impHandler(addText) +{ + if (chatWindow != nullptr) + chatWindow->addInputText(event.args); + return true; +} + +impHandler0(clearChat) +{ + if (chatWindow != nullptr) + chatWindow->clearTab(); + return true; +} + +impHandler0(chatGeneralTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::INPUT); + return true; +} + +impHandler0(chatDebugTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::DEBUG); + return true; +} + +impHandler0(chatBattleTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::BATTLE); + return true; +} + +impHandler0(chatTradeTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::TRADE); + return true; +} + +impHandler0(chatLangTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::LANG); + return true; +} + +impHandler0(chatGmTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::GM); + return true; +} + +impHandler0(chatPartyTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::PARTY); + return true; +} + +impHandler0(chatGuildTab) +{ + if (chatWindow != nullptr) + chatWindow->selectTabByType(ChatTabType::GUILD); + return true; +} + +impHandler(hat) +{ + if ((localPlayer == nullptr) || (charServerHandler == nullptr)) + return false; + + const int sprite = localPlayer->getSpriteID( + charServerHandler->hatSprite()); + std::string str; + if (sprite == 0) + { + // TRANSLATORS: equipped hat chat message + str = strprintf(_("no hat equipped.")); + } + else + { + const ItemInfo &info = ItemDB::get(sprite); + // TRANSLATORS: equipped hat chat message + str = strprintf(_("equipped hat %s."), + info.getName().c_str()); + } + outString(event.tab, str, str); + return true; +} + +impHandler(chatClipboard) +{ + int x = 0; + int y = 0; + + if ((chatWindow != nullptr) && parse2Int(event.args, x, y)) + { + chatWindow->copyToClipboard(x, y); + return true; + } + return false; +} + +impHandler(guildNotice) +{ + if (localPlayer == nullptr) + return false; + const std::string args = event.args; + if (args.empty()) + { + // TRANSLATORS: dialog header + inputActionReplayListener.openDialog(_("Guild notice"), + "", + InputAction::GUILD_NOTICE); + return true; + } + + std::string str2; + if (args.size() > 60) + str2 = args.substr(60); + const Guild *const guild = localPlayer->getGuild(); + if (guild != nullptr) + { + guildHandler->changeNotice(guild->getId(), + args.substr(0, 60), + str2); + } + return true; +} + +impHandler(translate) +{ + if (reverseDictionary == nullptr || + localPlayer == nullptr || + event.args.empty()) + { + return false; + } + + ChatTab *const tab = event.tab; + if (tab == nullptr) + return false; + + std::string srcStr = event.args; + std::string enStr; + toLower(srcStr); + if (localPlayer->getLanguageId() > 0) + { + if (reverseDictionary->haveStr(srcStr)) + enStr = reverseDictionary->getStr(srcStr); + else if (dictionary->haveStr(srcStr)) + enStr = srcStr; + } + else + { + if (dictionary->haveStr(srcStr)) + enStr = srcStr; + } + + if (enStr.empty()) + { + tab->chatLog( + // TRANSLATORS: translation error message + strprintf(_("No translation found for string: %s"), + srcStr.c_str()), + ChatMsgType::BY_SERVER); + return true; + } + + tab->chatInput(enStr); + return true; +} + +impHandler(sendGuiKey) +{ + if (guiInput == nullptr) + return false; + + const std::string args = event.args; + if (args.empty()) + return false; + StringVect pars; + if (!splitParameters(pars, args, " ,", '\"')) + return false; + const int sz = CAST_S32(pars.size()); + if (sz < 1) + return false; + + int keyValue = atoi(pars[0].c_str()); + if (keyValue == 0 && + pars[0].size() == 1) + { + keyValue = CAST_S32(pars[0][0]); + } + if (sz == 2) + { + const InputActionT actionId = inputManager.getActionByConfigField( + pars[1]); + guiInput->simulateKey(keyValue, actionId); + } + else + { + guiInput->simulateKey(keyValue, InputAction::NO_VALUE); + } + return true; +} + +impHandler(sendMouseKey) +{ + if (guiInput == nullptr) + return false; + const std::string args = event.args; + if (args.empty()) + return false; + StringVect pars; + if (!splitParameters(pars, args, " ,", '\"')) + return false; + const int sz = CAST_S32(pars.size()); + if (sz != 3) + return false; + + const int x = atoi(pars[0].c_str()); + const int y = atoi(pars[1].c_str()); + const int key1 = CAST_S32(MouseButton::LEFT); + const int key2 = CAST_S32(MouseButton::MIDDLE); + const int key = atoi(pars[2].c_str()); + if (key < key1 || key > key2) + return false; + guiInput->simulateMouseClick(x, + y, + static_cast(key)); + return true; +} + +impHandler(sendChars) +{ + if (guiInput == nullptr) + return false; + + const std::string args = event.args; + if (args.empty()) + return false; + + const size_t sz = args.size(); + for (size_t f = 0; f < sz; f ++) + { + guiInput->simulateKey(CAST_S32(args[f]), + InputAction::NO_VALUE); + } + + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/commands.cpp b/src/progs/manaplus/actions/commands.cpp new file mode 100644 index 000000000..f2d49b13b --- /dev/null +++ b/src/progs/manaplus/actions/commands.cpp @@ -0,0 +1,2156 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/commands.h" + +#include "actormanager.h" +#include "configuration.h" +#include "game.h" +#include "party.h" + +#include "actions/actiondef.h" + +#include "being/flooritem.h" +#include "being/localplayer.h" +#include "being/playerrelations.h" +#include "being/homunculusinfo.h" +#include "being/playerinfo.h" + +#include "const/resources/skill.h" + +#include "gui/viewport.h" + +#include "gui/popups/popupmenu.h" + +#include "gui/shortcut/emoteshortcut.h" +#include "gui/shortcut/itemshortcut.h" + +#include "gui/windows/mailwindow.h" + +#include "gui/windows/chatwindow.h" +#include "gui/windows/inventorywindow.h" +#include "gui/windows/npcdialog.h" +#include "gui/windows/outfitwindow.h" +#include "gui/windows/shortcutwindow.h" +#include "gui/windows/skilldialog.h" +#include "gui/windows/socialwindow.h" + +#include "gui/widgets/tabs/chat/whispertab.h" + +#include "input/inputactionoperators.h" + +#include "listeners/inputactionreplaylistener.h" + +#include "net/adminhandler.h" +#include "net/chathandler.h" +#include "net/guildhandler.h" +#include "net/familyhandler.h" +#include "net/homunculushandler.h" +#include "net/mail2handler.h" +#include "net/mailhandler.h" +#include "net/net.h" +#include "net/npchandler.h" +#include "net/partyhandler.h" +#include "net/serverfeatures.h" + +#include "resources/chatobject.h" + +#include "resources/db/itemdb.h" + +#include "resources/map/map.h" + +#include "resources/skill/skillinfo.h" + +#include "utils/booleanoptions.h" +#include "utils/chatutils.h" +#include "utils/copynpaste.h" +#include "utils/gmfunctions.h" +#include "utils/parameters.h" +#include "utils/process.h" + +#include "debug.h" + +namespace Actions +{ + +static std::string getNick(const InputEvent &event) +{ + std::string args = event.args; + if (args.empty()) + { + if (event.tab == nullptr || + event.tab->getType() != ChatTabType::WHISPER) + { + return std::string(); + } + + WhisperTab *const whisper = static_cast(event.tab); + if (whisper->getNick().empty()) + { + // TRANSLATORS: change relation + event.tab->chatLog(_("Please specify a name."), + ChatMsgType::BY_SERVER); + return std::string(); + } + args = whisper->getNick(); + } + return args; +} + +static void reportRelation(const InputEvent &event, + const RelationT &rel, + const std::string &str1, + const std::string &str2) +{ + if (event.tab != nullptr) + { + if (playerRelations.getRelation(event.args) == rel) + { + // TRANSLATORS: unignore command + event.tab->chatLog(str1, ChatMsgType::BY_SERVER); + } + else + { + // TRANSLATORS: unignore command + event.tab->chatLog(str2, ChatMsgType::BY_SERVER); + } + } +} + +static void changeRelation(const InputEvent &event, + const RelationT relation, + const std::string &relationText) +{ + std::string args = getNick(event); + if (args.empty()) + return; + + if (playerRelations.getRelation(args) == relation) + { + if (event.tab != nullptr) + { + // TRANSLATORS: change relation + event.tab->chatLog(strprintf(_("Player already %s!"), + relationText.c_str()), ChatMsgType::BY_SERVER); + return; + } + } + else + { + playerRelations.setRelation(args, relation); + } + + reportRelation(event, + relation, + // TRANSLATORS: change relation + strprintf(_("Player successfully %s!"), relationText.c_str()), + // TRANSLATORS: change relation + strprintf(_("Player could not be %s!"), relationText.c_str())); +} + +impHandler(chatAnnounce) +{ + if (adminHandler != nullptr) + { + adminHandler->announce(event.args); + return true; + } + return false; +} + +impHandler(chatIgnore) +{ + changeRelation(event, Relation::IGNORED, "ignored"); + return true; +} + +impHandler(chatUnignore) +{ + std::string args = getNick(event); + if (args.empty()) + return false; + + const RelationT rel = playerRelations.getRelation(args); + if (rel != Relation::NEUTRAL && rel != Relation::FRIEND) + { + playerRelations.setRelation(args, Relation::NEUTRAL); + } + else + { + if (event.tab != nullptr) + { + // TRANSLATORS: unignore command + event.tab->chatLog(_("Player wasn't ignored!"), + ChatMsgType::BY_SERVER); + } + return true; + } + + reportRelation(event, + Relation::NEUTRAL, + // TRANSLATORS: unignore command + _("Player no longer ignored!"), + // TRANSLATORS: unignore command + _("Player could not be unignored!")); + return true; +} + +impHandler(chatErase) +{ + std::string args = getNick(event); + if (args.empty()) + return false; + + if (playerRelations.getRelation(args) == Relation::ERASED) + { + if (event.tab != nullptr) + { + // TRANSLATORS: erase command + event.tab->chatLog(_("Player already erased!"), + ChatMsgType::BY_SERVER); + } + return true; + } + playerRelations.setRelation(args, Relation::ERASED); + + reportRelation(event, + Relation::ERASED, + // TRANSLATORS: erase command + _("Player no longer erased!"), + // TRANSLATORS: erase command + _("Player could not be erased!")); + return true; +} + +impHandler(chatFriend) +{ + // TRANSLATORS: adding friend command + changeRelation(event, Relation::FRIEND, _("friend")); + return true; +} + +impHandler(chatDisregard) +{ + // TRANSLATORS: disregard command + changeRelation(event, Relation::DISREGARDED, _("disregarded")); + return true; +} + +impHandler(chatNeutral) +{ + // TRANSLATORS: neutral command + changeRelation(event, Relation::NEUTRAL, _("neutral")); + return true; +} + +impHandler(chatBlackList) +{ + // TRANSLATORS: blacklist command + changeRelation(event, Relation::BLACKLISTED, _("blacklisted")); + return true; +} + +impHandler(chatEnemy) +{ + // TRANSLATORS: enemy command + changeRelation(event, Relation::ENEMY2, _("enemy")); + return true; +} + +impHandler(chatNuke) +{ + if (actorManager == nullptr) + return false; + + const std::string nick = getNick(event); + Being *const being = actorManager->findBeingByName( + nick, ActorType::Player); + if (being == nullptr) + return true; + + actorManager->addBlock(being->getId()); + actorManager->destroy(being); + return true; +} + +impHandler(chatAdd) +{ + if (chatWindow == nullptr) + return false; + + if (event.args.empty()) + return true; + + STD_VECTOR str; + splitToIntVector(str, event.args, ','); + if (str.empty()) + return true; + + int id = str[0]; + if (id == 0) + return true; + + if (ItemDB::exists(id)) + { + const std::string names = ItemDB::getNamesStr(str); + if (!names.empty()) + chatWindow->addItemText(names); + return true; + } + + const FloorItem *const floorItem = actorManager->findItem( + fromInt(id, BeingId)); + + if (floorItem != nullptr) + { + str[0] = floorItem->getItemId(); + const std::string names = ItemDB::getNamesStr(str); + chatWindow->addItemText(names); + } + return true; +} + +impHandler0(present) +{ + if (chatWindow != nullptr) + { + chatWindow->doPresent(); + return true; + } + return false; +} + +impHandler0(printAll) +{ + if (actorManager != nullptr) + { + actorManager->printAllToChat(); + return true; + } + return false; +} + +impHandler(move) +{ + int x = 0; + int y = 0; + + if ((localPlayer != nullptr) && parse2Int(event.args, x, y)) + { + localPlayer->setDestination(x, y); + return true; + } + return false; +} + +impHandler(setTarget) +{ + if ((actorManager == nullptr) || (localPlayer == nullptr)) + return false; + + Being *const target = actorManager->findNearestByName(event.args); + if (target != nullptr) + localPlayer->setTarget(target); + return true; +} + +impHandler(commandOutfit) +{ + if (outfitWindow != nullptr) + { + if (!event.args.empty()) + { + const std::string op = event.args.substr(0, 1); + if (op == "n") + { + outfitWindow->wearNextOutfit(true); + } + else if (op == "p") + { + outfitWindow->wearPreviousOutfit(true); + } + else + { + outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1, + false, true); + } + } + else + { + outfitWindow->wearOutfit(atoi(event.args.c_str()) - 1, + false, true); + } + return true; + } + return false; +} + +impHandler(commandEmote) +{ + LocalPlayer::emote(CAST_U8(atoi(event.args.c_str()))); + return true; +} + +impHandler(awayMessage) +{ + if (localPlayer != nullptr) + { + localPlayer->setAway(event.args); + return true; + } + return false; +} + +impHandler(pseudoAway) +{ + if (localPlayer != nullptr) + { + LocalPlayer::setPseudoAway(event.args); + localPlayer->updateStatus(); + return true; + } + return false; +} + +impHandler(follow) +{ + if (localPlayer == nullptr) + return false; + + if (!features.getBoolValue("allowFollow")) + return false; + + if (!event.args.empty()) + { + localPlayer->setFollow(event.args); + } + else if (event.tab != nullptr && + event.tab->getType() == ChatTabType::WHISPER) + { + localPlayer->setFollow(static_cast(event.tab)->getNick()); + } + else + { + const Being *const being = localPlayer->getTarget(); + if (being != nullptr) + localPlayer->setFollow(being->getName()); + } + return true; +} + +impHandler(navigate) +{ + if ((localPlayer == nullptr) || + !localPlayer->canMove()) + { + return false; + } + + int x = 0; + int y = 0; + + if (parse2Int(event.args, x, y)) + localPlayer->navigateTo(x, y); + else + localPlayer->navigateClean(); + return true; +} + +impHandler(navigateTo) +{ + if ((localPlayer == nullptr) || + !localPlayer->canMove()) + { + return false; + } + + const std::string args = event.args; + if (args.empty()) + return true; + + Being *const being = actorManager->findBeingByName(args); + if (being != nullptr) + { + localPlayer->navigateTo(being->getTileX(), being->getTileY()); + } + else if (localPlayer->isInParty()) + { + const Party *const party = localPlayer->getParty(); + if (party != nullptr) + { + const PartyMember *const m = party->getMember(args); + const PartyMember *const o = party->getMember( + localPlayer->getName()); + if (m != nullptr && + o != nullptr && + m->getMap() == o->getMap()) + { + localPlayer->navigateTo(m->getX(), m->getY()); + } + } + } + return true; +} + +impHandler(moveCamera) +{ + int x = 0; + int y = 0; + + if (viewport == nullptr) + return false; + + if (parse2Int(event.args, x, y)) + viewport->moveCameraToPosition(x * mapTileSize, y * mapTileSize); + return true; +} + +impHandler0(restoreCamera) +{ + if (viewport == nullptr) + return false; + + viewport->returnCamera(); + return true; +} + +impHandler(imitation) +{ + if (localPlayer == nullptr) + return false; + + if (!event.args.empty()) + { + localPlayer->setImitate(event.args); + } + else if (event.tab != nullptr && + event.tab->getType() == ChatTabType::WHISPER) + { + localPlayer->setImitate(static_cast( + event.tab)->getNick()); + } + else + { + localPlayer->setImitate(""); + } + return true; +} + +impHandler(sendMail) +{ +#ifdef TMWA_SUPPORT + const ServerTypeT type = Net::getNetworkType(); + if (type == ServerType::EATHENA || type == ServerType::EVOL2) +#endif // TMWA_SUPPORT + { + std::string name; + std::string text; + + if (parse2Str(event.args, name, text)) + { + if (settings.enableNewMailSystem) + { + mail2Handler->queueCheckName(MailQueueType::SendMail, + name, + // TRANSLATORS: quick mail message caption + _("Quick message"), + text, + 0); + } + else + { + // TRANSLATORS: quick mail message caption + mailHandler->send(name, _("Quick message"), text); + } + } + } +#ifdef TMWA_SUPPORT + else if (serverConfig.getBoolValue("enableManaMarketBot")) + { + chatHandler->privateMessage("ManaMarket", "!mail " + event.args); + return true; + } +#endif // TMWA_SUPPORT + + return false; +} + +impHandler(info) +{ + if (event.tab == nullptr || + localPlayer == nullptr || + Net::getNetworkType() == ServerType::TMWATHENA) + { + return false; + } + + if (guildHandler != nullptr && + event.tab->getType() == ChatTabType::GUILD) + { + const Guild *const guild = localPlayer->getGuild(); + if (guild != nullptr) + guildHandler->info(); + } + return true; +} + +impHandler(wait) +{ + if (localPlayer != nullptr) + { + localPlayer->waitFor(event.args); + return true; + } + return false; +} + +impHandler(addPriorityAttack) +{ + if ((actorManager == nullptr) || + actorManager->isInPriorityAttackList(event.args)) + { + return false; + } + + actorManager->removeAttackMob(event.args); + actorManager->addPriorityAttackMob(event.args); + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; +} + +impHandler(addAttack) +{ + if (actorManager == nullptr) + return false; + + actorManager->removeAttackMob(event.args); + actorManager->addAttackMob(event.args); + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; +} + +impHandler(removeAttack) +{ + if (actorManager == nullptr) + return false; + + if (event.args.empty()) + { + if (actorManager->isInAttackList(event.args)) + { + actorManager->removeAttackMob(event.args); + actorManager->addIgnoreAttackMob(event.args); + } + else + { + actorManager->removeAttackMob(event.args); + actorManager->addAttackMob(event.args); + } + } + else + { + actorManager->removeAttackMob(event.args); + } + + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; +} + +impHandler(addIgnoreAttack) +{ + if (actorManager == nullptr) + return false; + + actorManager->removeAttackMob(event.args); + actorManager->addIgnoreAttackMob(event.args); + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; +} + +impHandler(setDrop) +{ + GameModifiers::setQuickDropCounter(atoi(event.args.c_str())); + return true; +} + +impHandler(url) +{ + if (event.tab != nullptr) + { + std::string url1 = event.args; + if (!strStartWith(url1, "http") && !strStartWith(url1, "?")) + url1 = "http://" + url1; + std::string str(strprintf("[@@%s |%s@@]", + url1.c_str(), event.args.c_str())); + outStringNormal(event.tab, str, str); + return true; + } + return false; +} + +impHandler(openUrl) +{ + std::string url = event.args; + if (!strStartWith(url, "http")) + url = "http://" + url; + openBrowser(url); + return true; +} + +impHandler(execute) +{ + const size_t idx = event.args.find(' '); + std::string name; + std::string params; + if (idx == std::string::npos) + { + name = event.args; + } + else + { + name = event.args.substr(0, idx); + params = event.args.substr(idx + 1); + } + execFile(name, name, params, ""); + return true; +} + +impHandler(enableHighlight) +{ + if (event.tab != nullptr) + { + event.tab->setAllowHighlight(true); + if (chatWindow != nullptr) + { + chatWindow->saveState(); + return true; + } + } + return false; +} + +impHandler(disableHighlight) +{ + if (event.tab != nullptr) + { + event.tab->setAllowHighlight(false); + if (chatWindow != nullptr) + { + chatWindow->saveState(); + return true; + } + } + return false; +} + +impHandler(dontRemoveName) +{ + if (event.tab != nullptr) + { + event.tab->setRemoveNames(false); + if (chatWindow != nullptr) + { + chatWindow->saveState(); + return true; + } + } + return false; +} + +impHandler(removeName) +{ + if (event.tab != nullptr) + { + event.tab->setRemoveNames(true); + if (chatWindow != nullptr) + { + chatWindow->saveState(); + return true; + } + } + return false; +} + +impHandler(disableAway) +{ + if (event.tab != nullptr) + { + event.tab->setNoAway(true); + if (chatWindow != nullptr) + { + chatWindow->saveState(); + return true; + } + } + return false; +} + +impHandler(enableAway) +{ + if (event.tab != nullptr) + { + event.tab->setNoAway(false); + if (chatWindow != nullptr) + { + chatWindow->saveState(); + return true; + } + } + return false; +} + +impHandler(testParticle) +{ + if (localPlayer != nullptr) + { + localPlayer->setTestParticle(event.args); + return true; + } + return false; +} + +impHandler(talkRaw) +{ + if (chatHandler != nullptr) + { + chatHandler->talkRaw(event.args); + return true; + } + return false; +} + +impHandler(gm) +{ + if (chatHandler != nullptr) + { + Gm::runCommand("wgm", event.args); + return true; + } + return false; +} + +impHandler(hack) +{ + if (chatHandler != nullptr) + { + chatHandler->sendRaw(event.args); + return true; + } + return false; +} + +impHandler(debugSpawn) +{ + if (localPlayer == nullptr) + return false; + int cnt = atoi(event.args.c_str()); + if (cnt < 1) + cnt = 1; + const int half = cnt / 2; + const Map *const map = localPlayer->getMap(); + int x1 = -half; + if (x1 < 0) + x1 = 0; + int y1 = x1; + int x2 = cnt - half; + if (x2 > map->getWidth()) + x2 = map->getWidth(); + int y2 = x2; + + for (int x = x1; x < x2; x ++) + { + for (int y = y1; y < y2; y ++) + ActorManager::cloneBeing(localPlayer, x, y, cnt); + } + return true; +} + +impHandler(serverIgnoreWhisper) +{ + std::string args = getNick(event); + if (args.empty()) + return false; + + if (chatHandler != nullptr) + { + chatHandler->ignore(args); + return true; + } + return false; +} + +impHandler(serverUnIgnoreWhisper) +{ + std::string args = getNick(event); + if (args.empty()) + return false; + + if (chatHandler != nullptr) + { + chatHandler->unIgnore(args); + return true; + } + return false; +} + +impHandler(setHomunculusName) +{ + const std::string args = event.args; + if (args.empty()) + { + const HomunculusInfo *const info = PlayerInfo::getHomunculus(); + if (info != nullptr) + { + // TRANSLATORS: dialog header + inputActionReplayListener.openDialog(_("Rename your homun"), + info->name, + InputAction::HOMUNCULUS_SET_NAME); + } + return false; + } + + if (homunculusHandler != nullptr) + { + homunculusHandler->setName(args); + return true; + } + return false; +} + +impHandler0(fireHomunculus) +{ + if (homunculusHandler != nullptr) + { + homunculusHandler->fire(); + return true; + } + return false; +} + +impHandler0(leaveParty) +{ + if (partyHandler != nullptr) + { + partyHandler->leave(); + return true; + } + return false; +} + +impHandler0(leaveGuild) +{ + if ((guildHandler != nullptr) && (localPlayer != nullptr)) + { + const Guild *const guild = localPlayer->getGuild(); + if (guild != nullptr) + guildHandler->leave(guild->getId()); + return true; + } + return false; +} + +impHandler(warp) +{ + int x = 0; + int y = 0; + + if ((adminHandler != nullptr) && + (Game::instance() != nullptr) && + parse2Int(event.args, x, y)) + { + adminHandler->warp(Game::instance()->getCurrentMapName(), + x, y); + return true; + } + return false; +} + +impHandler(homunTalk) +{ + if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet()) + return false; + + std::string args = event.args; + if (findCutFirst(args, "/me ")) + args = textToMe(args); + if (homunculusHandler != nullptr) + { + homunculusHandler->talk(args); + return true; + } + return false; +} + +impHandler(homunEmote) +{ + if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet()) + return false; + + if ((homunculusHandler != nullptr) && + event.action >= InputAction::HOMUN_EMOTE_1 && + event.action <= InputAction::HOMUN_EMOTE_48) + { + const int emotion = event.action - InputAction::HOMUN_EMOTE_1; + if (emoteShortcut != nullptr) + homunculusHandler->emote(emoteShortcut->getEmote(emotion)); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + + return false; +} + +impHandler(commandHomunEmote) +{ + if ((serverFeatures == nullptr) || !serverFeatures->haveTalkPet()) + return false; + + if (homunculusHandler != nullptr) + { + homunculusHandler->emote(CAST_U8( + atoi(event.args.c_str()))); + return true; + } + return false; +} + +impHandler(createPublicChatRoom) +{ + if ((chatHandler == nullptr) || event.args.empty()) + return false; + chatHandler->createChatRoom(event.args, "", 100, true); + return true; +} + +impHandler(joinChatRoom) +{ + if (chatHandler == nullptr) + return false; + const std::string args = event.args; + if (args.empty()) + return false; + ChatObject *const chat = ChatObject::findByName(args); + if (chat == nullptr) + return false; + chatHandler->joinChat(chat, ""); + return true; +} + +impHandler0(leaveChatRoom) +{ + if (chatHandler != nullptr) + { + chatHandler->leaveChatRoom(); + return true; + } + return false; +} + +impHandler(confSet) +{ + std::string name; + std::string val; + + if (parse2Str(event.args, name, val)) + { + config.setValue(name, val); + return true; + } + return false; +} + +impHandler(serverConfSet) +{ + std::string name; + std::string val; + + if (parse2Str(event.args, name, val)) + { + serverConfig.setValue(name, val); + return true; + } + return false; +} + +impHandler(confGet) +{ + const std::string args = event.args; + if (args.empty()) + return false; + + // TRANSLATORS: result from command /confget + const std::string str = strprintf(_("Config value: %s"), + config.getStringValue(args).c_str()); + outStringNormal(event.tab, str, str); + return true; +} + +impHandler(serverConfGet) +{ + const std::string args = event.args; + if (args.empty()) + return false; + + // TRANSLATORS: result from command /serverconfget + const std::string str = strprintf(_("Server config value: %s"), + serverConfig.getStringValue(args).c_str()); + outStringNormal(event.tab, str, str); + return true; +} + +impHandler(slide) +{ + int x = 0; + int y = 0; + + if ((adminHandler != nullptr) && parse2Int(event.args, x, y)) + { + adminHandler->slide(x, y); + return true; + } + return false; +} + +impHandler(selectSkillLevel) +{ + int skill = 0; + int level = 0; + + if ((skillDialog != nullptr) && parse2Int(event.args, skill, level)) + { + skillDialog->selectSkillLevel(skill, level); + return true; + } + return false; +} + +impHandler(skill) +{ + StringVect vect; + splitToStringVector(vect, event.args, ' '); + const int sz = CAST_S32(vect.size()); + if (sz < 1) + return true; + const int skillId = atoi(vect[0].c_str()); + int level = 0; + std::string text; + if (sz > 1) + { + level = atoi(vect[1].c_str()); + if (sz > 2) + text = vect[2]; + } + // +++ add here also cast type and offsets + if (text.empty()) + { + SkillDialog::useSkill(skillId, + AutoTarget_true, + level, + false, + "", + CastType::Default, + 0, + 0); + } + else + { + SkillDialog::useSkill(skillId, + AutoTarget_true, + level, + true, + text, + CastType::Default, + 0, + 0); + } + return true; +} + +impHandler(craft) +{ + const std::string args = event.args; + if (args.empty() || (inventoryWindow == nullptr)) + return false; + + inventoryWindow->moveItemToCraft(atoi(args.c_str())); + return true; +} + +impHandler(npcClipboard) +{ + if (npcHandler != nullptr) + { + int x = 0; + int y = 0; + + NpcDialog *const dialog = npcHandler->getCurrentNpcDialog(); + + if ((dialog != nullptr) && parse2Int(event.args, x, y)) + { + dialog->copyToClipboard(x, y); + return true; + } + } + return false; +} + +impHandler(clipboardCopy) +{ + const std::string args = event.args; + if (args.empty()) + return false; + sendBuffer(args); + return true; +} + +impHandler(addPickup) +{ + if (actorManager != nullptr) + { + actorManager->removePickupItem(event.args); + actorManager->addPickupItem(event.args); + if (socialWindow != nullptr) + socialWindow->updatePickupFilter(); + return true; + } + return false; +} + +impHandler(removePickup) +{ + if (actorManager != nullptr) + { + if (event.args.empty()) + { // default pickup manipulation + if (actorManager->checkDefaultPickup()) + { + actorManager->removePickupItem(event.args); + actorManager->addIgnorePickupItem(event.args); + } + else + { + actorManager->removePickupItem(event.args); + actorManager->addPickupItem(event.args); + } + } + else + { // any other pickups + actorManager->removePickupItem(event.args); + } + if (socialWindow != nullptr) + socialWindow->updatePickupFilter(); + return true; + } + return false; +} + +impHandler(ignorePickup) +{ + if (actorManager != nullptr) + { + actorManager->removePickupItem(event.args); + actorManager->addIgnorePickupItem(event.args); + if (socialWindow != nullptr) + socialWindow->updatePickupFilter(); + return true; + } + return false; +} + +impHandler(monsterInfo) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->monsterInfo(args); + return true; +} + +impHandler(itemInfo) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->itemInfo(args); + return true; +} + +impHandler(whoDrops) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->whoDrops(args); + return true; +} + +impHandler(mobSearch) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->mobSearch(args); + return true; +} + +impHandler(mobSpawnSearch) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->mobSpawnSearch(args); + return true; +} + +impHandler(playerGmCommands) +{ + adminHandler->playerGmCommands(event.args); + return true; +} + +impHandler(playerCharGmCommands) +{ + adminHandler->playerCharGmCommands(event.args); + return true; +} + +impHandler(commandShowLevel) +{ + adminHandler->showLevel(event.args); + return true; +} + +impHandler(commandShowStats) +{ + adminHandler->showStats(event.args); + return true; +} + +impHandler(commandShowStorage) +{ + adminHandler->showStorageList(event.args); + return true; +} + +impHandler(commandShowCart) +{ + adminHandler->showCartList(event.args); + return true; +} + +impHandler(commandShowInventory) +{ + adminHandler->showInventoryList(event.args); + return true; +} + +impHandler(locatePlayer) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->locatePlayer(args); + return true; +} + +impHandler(commandShowAccountInfo) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->showAccountInfo(args); + return true; +} + +impHandler(commandSpawn) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->spawn(args); + return true; +} + +impHandler(commandSpawnSlave) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->spawnSlave(args); + return true; +} + +impHandler(commandSpawnClone) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->spawnClone(args); + return true; +} + +impHandler(commandSpawnSlaveClone) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->spawnSlaveClone(args); + return true; +} + +impHandler(commandSpawnEvilClone) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->spawnEvilClone(args); + return true; +} + +impHandler(commandSavePosition) +{ + adminHandler->savePosition(event.args); + return true; +} + +impHandler(commandLoadPosition) +{ + adminHandler->loadPosition(event.args); + return true; +} + +impHandler(commandRandomWarp) +{ + adminHandler->randomWarp(event.args); + return true; +} + +impHandler(commandGotoNpc) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->gotoNpc(args); + return true; +} + +impHandler(commandGotoPc) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->gotoName(args); + return true; +} + +impHandler(commandRecallPc) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->recallName(args); + return true; +} + +impHandler(commandIpCheck) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->ipcheckName(args); + return true; +} + +impHandler(commandKiller) +{ + adminHandler->killer(event.args); + return true; +} + +impHandler(commandKillable) +{ + adminHandler->killable(event.args); + return true; +} + +impHandler(commandHeal) +{ + adminHandler->heal(event.args); + return true; +} + +impHandler(commandAlive) +{ + adminHandler->alive(event.args); + return true; +} + +impHandler(commandDisguise) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->disguise(args); + return true; +} + +impHandler(commandImmortal) +{ + adminHandler->immortal(event.args); + return true; +} + +impHandler(commandHide) +{ + adminHandler->hide(event.args); + return true; +} + +impHandler(commandNuke) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->nuke(args); + return true; +} + +impHandler(commandKill) +{ + adminHandler->kill(event.args); + return true; +} + +impHandler(commandJail) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->jail(args); + return true; +} + +impHandler(commandUnjail) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->unjail(args); + return true; +} + +impHandler(commandNpcMove) +{ + const std::string args = event.args; + if (args.empty()) + return false; + StringVect pars; + if (!splitParameters(pars, args, " ,", '\"')) + return false; + + if (pars.size() != 3) + return false; + + adminHandler->npcMove(pars[0], + atoi(pars[1].c_str()), + atoi(pars[2].c_str())); + return true; +} + +impHandler(commandNpcHide) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->hideNpc(args); + return true; +} + +impHandler(commandNpcShow) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->showNpc(args); + return true; +} + +impHandler(commandChangePartyLeader) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->changePartyLeader(args); + return true; +} + +impHandler(commandPartyRecall) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->partyRecall(args); + return true; +} + +impHandler(commandBreakGuild) +{ + adminHandler->breakGuild(event.args); + return true; +} + +impHandler(commandGuildRecall) +{ + const std::string args = event.args; + if (args.empty()) + return false; + adminHandler->guildRecall(args); + return true; +} + +impHandler(mailTo) +{ + if (mailWindow == nullptr) + return false; + const std::string args = event.args; + if (settings.enableNewMailSystem) + { + mail2Handler->queueCheckName(MailQueueType::EditMail, + args, + std::string(), + std::string(), + 0); + } + else + { + mailWindow->createMail(args); + } + return true; +} + +impHandler(adoptChild) +{ + const std::string nick = getNick(event); + Being *const being = actorManager->findBeingByName( + nick, ActorType::Player); + if (being == nullptr) + return true; + familyHandler->askForChild(being); + return true; +} + +impHandler(showSkillLevels) +{ + const std::string args = event.args; + if (args.empty()) + return false; + const SkillInfo *restrict const skill = skillDialog->getSkill( + atoi(args.c_str())); + if (skill == nullptr) + return false; + popupMenu->showSkillLevelPopup(skill); + return true; +} + +impHandler(showSkillType) +{ + const std::string args = event.args; + if (args.empty()) + return false; + const SkillInfo *restrict const skill = skillDialog->getSkill( + atoi(args.c_str())); + if (skill == nullptr) + return false; + popupMenu->showSkillTypePopup(skill); + return true; +} + +impHandler(selectSkillType) +{ + int skill = 0; + int type = 0; + + if ((skillDialog != nullptr) && parse2Int(event.args, skill, type)) + { + skillDialog->selectSkillCastType(skill, + static_cast(type)); + return true; + } + return false; +} + +impHandler(showSkillOffsetX) +{ + const std::string args = event.args; + if (args.empty()) + return false; + const SkillInfo *restrict const skill = skillDialog->getSkill( + atoi(args.c_str())); + if (skill == nullptr) + return false; + popupMenu->showSkillOffsetPopup(skill, true); + return true; +} + +impHandler(showSkillOffsetY) +{ + const std::string args = event.args; + if (args.empty()) + return false; + const SkillInfo *restrict const skill = skillDialog->getSkill( + atoi(args.c_str())); + if (skill == nullptr) + return false; + popupMenu->showSkillOffsetPopup(skill, false); + return true; +} + +impHandler(setSkillOffsetX) +{ + int skill = 0; + int offset = 0; + + if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset)) + { + skillDialog->setSkillOffsetX(skill, offset); + return true; + } + return false; +} + +impHandler(setSkillOffsetY) +{ + int skill = 0; + int offset = 0; + + if ((skillDialog != nullptr) && parse2Int(event.args, skill, offset)) + { + skillDialog->setSkillOffsetY(skill, offset); + return true; + } + return false; +} + +impHandler(partyItemShare) +{ + if (localPlayer == nullptr) + return false; + + if (localPlayer->isInParty() == false) + return true; + + ChatTab *tab = event.tab; + if (tab == nullptr) + tab = localChatTab; + if (tab == nullptr) + return true; + + const std::string args = event.args; + if (args.empty()) + { + switch (partyHandler->getShareItems()) + { + case PartyShare::YES: + // TRANSLATORS: chat message + tab->chatLog(_("Item sharing enabled."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::NO: + // TRANSLATORS: chat message + tab->chatLog(_("Item sharing disabled."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::NOT_POSSIBLE: + // TRANSLATORS: chat message + tab->chatLog(_("Item sharing not possible."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::UNKNOWN: + // TRANSLATORS: chat message + tab->chatLog(_("Item sharing unknown."), + ChatMsgType::BY_SERVER); + return true; + default: + break; + } + } + + const signed char opt = parseBoolean(args); + + switch (opt) + { + case 1: + partyHandler->setShareItems( + PartyShare::YES); + break; + case 0: + partyHandler->setShareItems( + PartyShare::NO); + break; + case -1: + tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"), + ChatMsgType::BY_SERVER); + break; + default: + break; + } + return true; +} + +impHandler(partyExpShare) +{ + if (localPlayer == nullptr) + return false; + + if (localPlayer->isInParty() == false) + return true; + + ChatTab *tab = event.tab; + if (tab == nullptr) + tab = localChatTab; + if (tab == nullptr) + return true; + + const std::string args = event.args; + if (args.empty()) + { + switch (partyHandler->getShareExperience()) + { + case PartyShare::YES: + // TRANSLATORS: chat message + tab->chatLog(_("Experience sharing enabled."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::NO: + // TRANSLATORS: chat message + tab->chatLog(_("Experience sharing disabled."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::NOT_POSSIBLE: + // TRANSLATORS: chat message + tab->chatLog(_("Experience sharing not possible."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::UNKNOWN: + // TRANSLATORS: chat message + tab->chatLog(_("Experience sharing unknown."), + ChatMsgType::BY_SERVER); + return true; + default: + break; + } + } + + const signed char opt = parseBoolean(args); + + switch (opt) + { + case 1: + partyHandler->setShareExperience( + PartyShare::YES); + break; + case 0: + partyHandler->setShareExperience( + PartyShare::NO); + break; + case -1: + tab->chatLog(strprintf(BOOLEAN_OPTIONS, "exp"), + ChatMsgType::BY_SERVER); + break; + default: + break; + } + return true; +} + +impHandler(partyAutoItemShare) +{ + if (localPlayer == nullptr) + return false; + + if (localPlayer->isInParty() == false) + return true; + + ChatTab *tab = event.tab; + if (tab == nullptr) + tab = localChatTab; + if (tab == nullptr) + return true; + + const std::string args = event.args; + if (args.empty()) + { + switch (partyHandler->getShareAutoItems()) + { + case PartyShare::YES: + // TRANSLATORS: chat message + tab->chatLog(_("Auto item sharing enabled."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::NO: + // TRANSLATORS: chat message + tab->chatLog(_("Auto item sharing disabled."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::NOT_POSSIBLE: + // TRANSLATORS: chat message + tab->chatLog(_("Auto item sharing not possible."), + ChatMsgType::BY_SERVER); + return true; + case PartyShare::UNKNOWN: + // TRANSLATORS: chat message + tab->chatLog(_("Auto item sharing unknown."), + ChatMsgType::BY_SERVER); + return true; + default: + break; + } + } + + const signed char opt = parseBoolean(args); + + switch (opt) + { + case 1: + partyHandler->setShareAutoItems( + PartyShare::YES); + break; + case 0: + partyHandler->setShareAutoItems( + PartyShare::NO); + break; + case -1: + tab->chatLog(strprintf(BOOLEAN_OPTIONS, "item"), + ChatMsgType::BY_SERVER); + break; + default: + break; + } + return true; +} + +impHandler0(outfitToChat) +{ + if ((outfitWindow == nullptr) || (chatWindow == nullptr)) + return false; + + const std::string str = outfitWindow->getOutfitString(); + if (!str.empty()) + chatWindow->addInputText(str); + return true; +} + +impHandler0(outfitClear) +{ + if (outfitWindow == nullptr) + return false; + + outfitWindow->clearCurrentOutfit(); + return true; +} + +impHandler(moveAttackUp) +{ + if (actorManager == nullptr) + return false; + const std::string args = event.args; + const int idx = actorManager->getAttackMobIndex(args); + if (idx > 0) + { + std::list mobs + = actorManager->getAttackMobs(); + std::list::iterator it = mobs.begin(); + std::list::iterator it2 = it; + while (it != mobs.end()) + { + if (*it == args) + { + -- it2; + mobs.splice(it2, mobs, it); + actorManager->setAttackMobs(mobs); + actorManager->rebuildAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; + } + return false; +} + +impHandler(moveAttackDown) +{ + if (actorManager == nullptr) + return false; + const std::string args = event.args; + const int idx = actorManager->getAttackMobIndex(args); + const int size = actorManager->getAttackMobsSize(); + if (idx + 1 < size) + { + std::list mobs + = actorManager->getAttackMobs(); + std::list::iterator it = mobs.begin(); + std::list::iterator it2 = it; + while (it != mobs.end()) + { + if (*it == args) + { + ++ it2; + if (it2 == mobs.end()) + break; + + mobs.splice(it, mobs, it2); + actorManager->setAttackMobs(mobs); + actorManager->rebuildAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; + } + return false; +} + +impHandler(movePriorityAttackUp) +{ + if (actorManager == nullptr) + return false; + const std::string args = event.args; + const int idx = actorManager-> + getPriorityAttackMobIndex(args); + if (idx > 0) + { + std::list mobs + = actorManager->getPriorityAttackMobs(); + std::list::iterator it = mobs.begin(); + std::list::iterator it2 = it; + while (it != mobs.end()) + { + if (*it == args) + { + -- it2; + mobs.splice(it2, mobs, it); + actorManager->setPriorityAttackMobs(mobs); + actorManager->rebuildPriorityAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; + } + return false; +} + +impHandler(movePriorityAttackDown) +{ + if (actorManager == nullptr) + return false; + const std::string args = event.args; + const int idx = actorManager + ->getPriorityAttackMobIndex(args); + const int size = actorManager->getPriorityAttackMobsSize(); + if (idx + 1 < size) + { + std::list mobs + = actorManager->getPriorityAttackMobs(); + std::list::iterator it = mobs.begin(); + std::list::iterator it2 = it; + while (it != mobs.end()) + { + if (*it == args) + { + ++ it2; + if (it2 == mobs.end()) + break; + + mobs.splice(it, mobs, it2); + actorManager->setPriorityAttackMobs(mobs); + actorManager->rebuildPriorityAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow != nullptr) + socialWindow->updateAttackFilter(); + return true; + } + return false; +} + +impHandler(addSkillShortcut) +{ + const std::string args = event.args; + if (args.empty() || + itemShortcutWindow == nullptr) + { + return false; + } + const SkillInfo *restrict const skill = skillDialog->getSkill( + atoi(args.c_str())); + if (skill == nullptr) + return false; + + const int num = itemShortcutWindow->getTabIndex(); + if (num < 0 || + num >= CAST_S32(SHORTCUT_TABS) || + num == CAST_S32(SHORTCUT_AUTO_TAB)) + { + return false; + } + + ItemShortcut *const selShortcut = itemShortcut[num]; + const size_t index = selShortcut->getFreeIndex(); + if (index == SHORTCUT_ITEMS) + return true; + + selShortcut->setItem(index, + skill->id + SKILL_MIN_ID, + fromInt(skill->customSelectedLevel, ItemColor)); + selShortcut->setItemData(index, + skill->toDataStr()); + +// popupMenu->showSkillLevelPopup(skill); + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/move.cpp b/src/progs/manaplus/actions/move.cpp new file mode 100644 index 000000000..d2be4de7e --- /dev/null +++ b/src/progs/manaplus/actions/move.cpp @@ -0,0 +1,280 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/move.h" + +#include "game.h" + +#include "actions/actiondef.h" +#include "actions/pets.h" + +#include "being/crazymoves.h" +#include "being/localplayer.h" + +#include "enums/being/beingdirection.h" + +#include "gui/windows/socialwindow.h" +#include "gui/windows/npcdialog.h" +#include "gui/windows/outfitwindow.h" + +#include "gui/popups/popupmenu.h" + +#include "input/inputactionoperators.h" + +#include "net/playerhandler.h" + +#include "debug.h" + +namespace Actions +{ + +static bool closeMoveNpcDialog(bool focus) +{ + NpcDialog *const dialog = NpcDialog::getActive(); + if (dialog != nullptr) + { + if (dialog->isCloseState() != 0) + { + dialog->closeDialog(); + return true; + } + else if (focus) + { + dialog->refocus(); + } + } + return false; +} + +impHandler(moveUp) +{ + if (inputManager.isActionActive(InputAction::EMOTE)) + return directUp(event); + else if (inputManager.isActionActive(InputAction::PET_EMOTE)) + return petDirectUp(event); + else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) + return petMoveUp(event); + else if (!localPlayer->canMove()) + return directUp(event); + if (popupMenu->isPopupVisible()) + { + popupMenu->moveUp(); + return true; + } + return closeMoveNpcDialog(false); +} + +impHandler(moveDown) +{ + if (inputManager.isActionActive(InputAction::EMOTE)) + return directDown(event); + else if (inputManager.isActionActive(InputAction::PET_EMOTE)) + return petDirectDown(event); + else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) + return petMoveDown(event); + else if (!localPlayer->canMove()) + return directDown(event); + if (popupMenu->isPopupVisible()) + { + popupMenu->moveDown(); + return true; + } + return closeMoveNpcDialog(false); +} + +impHandler(moveLeft) +{ + if (outfitWindow != nullptr && + inputManager.isActionActive(InputAction::WEAR_OUTFIT)) + { + outfitWindow->wearPreviousOutfit(); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + if (inputManager.isActionActive(InputAction::EMOTE)) + return directLeft(event); + else if (inputManager.isActionActive(InputAction::PET_EMOTE)) + return petDirectLeft(event); + else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) + return petMoveLeft(event); + else if (!localPlayer->canMove()) + return directLeft(event); + return closeMoveNpcDialog(false); +} + +impHandler(moveRight) +{ + if (outfitWindow != nullptr && + inputManager.isActionActive(InputAction::WEAR_OUTFIT)) + { + outfitWindow->wearNextOutfit(); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + if (inputManager.isActionActive(InputAction::EMOTE)) + return directRight(event); + else if (inputManager.isActionActive(InputAction::PET_EMOTE)) + return petDirectRight(event); + else if (inputManager.isActionActive(InputAction::STOP_ATTACK)) + return petMoveRight(event); + else if (!localPlayer->canMove()) + return directRight(event); + return closeMoveNpcDialog(false); +} + +impHandler(moveForward) +{ + if (inputManager.isActionActive(InputAction::EMOTE)) + return directRight(event); + return closeMoveNpcDialog(false); +} + +impHandler(moveToPoint) +{ + const int num = event.action - InputAction::MOVE_TO_POINT_1; + if ((socialWindow != nullptr) && num >= 0) + { + socialWindow->selectPortal(num); + return true; + } + + return false; +} + +impHandler0(crazyMoves) +{ + if (localPlayer != nullptr) + { + ::crazyMoves->crazyMove(); + return true; + } + return false; +} + +impHandler0(moveToTarget) +{ + if (localPlayer != nullptr && + !inputManager.isActionActive(InputAction::TARGET_ATTACK) && + !inputManager.isActionActive(InputAction::ATTACK)) + { + localPlayer->moveToTarget(); + return true; + } + return false; +} + +impHandler0(moveToHome) +{ + if (localPlayer != nullptr && + !inputManager.isActionActive(InputAction::TARGET_ATTACK) && + !inputManager.isActionActive(InputAction::ATTACK)) + { + localPlayer->moveToHome(); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + return false; +} + +impHandler0(directUp) +{ + if (localPlayer != nullptr) + { + if (localPlayer->getDirection() != BeingDirection::UP) + { +// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) + { + localPlayer->setDirection(BeingDirection::UP); + if (playerHandler != nullptr) + playerHandler->setDirection(BeingDirection::UP); + } + } + return true; + } + return false; +} + +impHandler0(directDown) +{ + if (localPlayer != nullptr) + { + if (localPlayer->getDirection() != BeingDirection::DOWN) + { +// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) + { + localPlayer->setDirection(BeingDirection::DOWN); + if (playerHandler != nullptr) + { + playerHandler->setDirection( + BeingDirection::DOWN); + } + } + } + return true; + } + return false; +} + +impHandler0(directLeft) +{ + if (localPlayer != nullptr) + { + if (localPlayer->getDirection() != BeingDirection::LEFT) + { +// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) + { + localPlayer->setDirection(BeingDirection::LEFT); + if (playerHandler != nullptr) + { + playerHandler->setDirection( + BeingDirection::LEFT); + } + } + } + return true; + } + return false; +} + +impHandler0(directRight) +{ + if (localPlayer != nullptr) + { + if (localPlayer->getDirection() != BeingDirection::RIGHT) + { +// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) + { + localPlayer->setDirection(BeingDirection::RIGHT); + if (playerHandler != nullptr) + { + playerHandler->setDirection( + BeingDirection::RIGHT); + } + } + } + return true; + } + return false; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/pets.cpp b/src/progs/manaplus/actions/pets.cpp new file mode 100644 index 000000000..25c5f1411 --- /dev/null +++ b/src/progs/manaplus/actions/pets.cpp @@ -0,0 +1,248 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/pets.h" + +#include "actormanager.h" +#include "game.h" + +#include "actions/actiondef.h" + +#include "being/localplayer.h" +#include "being/playerinfo.h" + +#include "enums/being/beingdirection.h" + +#include "const/gui/chat.h" + +#include "input/inputactionoperators.h" + +#include "listeners/inputactionreplaylistener.h" + +#include "gui/shortcut/emoteshortcut.h" + +#include "net/chathandler.h" +#include "net/pethandler.h" +#include "net/serverfeatures.h" + +#include "utils/chatutils.h" +#include "utils/gettext.h" +#include "utils/stringutils.h" + +#include "debug.h" + +namespace Actions +{ + +static const Being *getPet() +{ + const BeingId id = PlayerInfo::getPetBeingId(); + if (id == BeingId_zero) + return nullptr; + return actorManager->findBeing(id); +} + +impHandler(commandEmotePet) +{ + petHandler->emote(CAST_U8(atoi(event.args.c_str()))); + return true; +} + +impHandler(talkPet) +{ + if (!serverFeatures->haveTalkPet()) + return false; + + std::string args = event.args; + if (findCutFirst(args, "/me ")) + args = textToMe(args); + chatHandler->talkPet(args, GENERAL_CHANNEL); + return true; +} + +impHandler(setPetName) +{ + const std::string args = event.args; + if (args.empty()) + { + const Being *const pet = getPet(); + if (pet == nullptr) + return false; + // TRANSLATORS: dialog header + inputActionReplayListener.openDialog(_("Rename your pet"), + pet->getName(), + InputAction::PET_SET_NAME); + return false; + } + + petHandler->setName(args); + return true; +} + +impHandler(petEmote) +{ + if (!serverFeatures->haveTalkPet()) + return false; + + if (event.action >= InputAction::PET_EMOTE_1 + && event.action <= InputAction::PET_EMOTE_48) + { + const int emotion = event.action - InputAction::PET_EMOTE_1; + if (emoteShortcut != nullptr) + petHandler->emote(emoteShortcut->getEmote(emotion)); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + + return false; +} + +impHandler(catchPet) +{ + if ((localPlayer == nullptr) || (actorManager == nullptr)) + return false; + + Being *target = nullptr; + const std::string args = event.args; + if (!args.empty()) + { + if (args[0] == ':') + { + target = actorManager->findBeing(fromInt(atoi( + args.substr(1).c_str()), BeingId)); + } + else + { + target = actorManager->findNearestByName(args); + } + } + + if (target == nullptr) + target = localPlayer->getTarget(); + else + localPlayer->setTarget(target); + if (target != nullptr) + petHandler->catchPet(target); + return true; +} + +impHandler0(petMoveUp) +{ + const Being *const pet = getPet(); + if (pet == nullptr) + return false; + petHandler->move(pet->getTileX(), pet->getTileY() - 1); + return true; +} + +impHandler0(petMoveDown) +{ + const Being *const pet = getPet(); + if (pet == nullptr) + return false; + petHandler->move(pet->getTileX(), pet->getTileY() + 1); + return true; +} + +impHandler0(petMoveLeft) +{ + const Being *const pet = getPet(); + if (pet == nullptr) + return false; + petHandler->move(pet->getTileX() - 1, pet->getTileY()); + return true; +} + +impHandler0(petMoveRight) +{ + const Being *const pet = getPet(); + if (pet == nullptr) + return false; + petHandler->move(pet->getTileX() + 1, pet->getTileY()); + return true; +} + +impHandler0(petDirectUp) +{ + petHandler->setDirection(BeingDirection::UP); + return true; +} + +impHandler0(petDirectDown) +{ + petHandler->setDirection(BeingDirection::DOWN); + return true; +} + +impHandler0(petDirectLeft) +{ + petHandler->setDirection(BeingDirection::LEFT); + return true; +} + +impHandler0(petDirectRight) +{ + petHandler->setDirection(BeingDirection::RIGHT); + return true; +} + +impHandler(petMove) +{ + int x = 0; + int y = 0; + + if (parse2Int(event.args, x, y)) + { + petHandler->move(x, y); + return true; + } + return false; +} + +impHandler0(petFeed) +{ + if (petHandler != nullptr) + petHandler->feed(); + return true; +} + +impHandler0(petDropLoot) +{ + if (petHandler != nullptr) + petHandler->dropLoot(); + return true; +} + +impHandler0(petReturnToEgg) +{ + if (petHandler != nullptr) + petHandler->returnToEgg(); + return true; +} + +impHandler0(petUnequip) +{ + if (petHandler != nullptr) + petHandler->unequip(); + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/statusbar.cpp b/src/progs/manaplus/actions/statusbar.cpp new file mode 100644 index 000000000..0d5ba68cd --- /dev/null +++ b/src/progs/manaplus/actions/statusbar.cpp @@ -0,0 +1,200 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/statusbar.h" + +#include "game.h" +#include "soundmanager.h" + +#include "actions/actiondef.h" + +#include "being/localplayer.h" +#include "being/playerrelation.h" +#include "being/playerrelations.h" + +#include "gui/viewport.h" + +#include "gui/widgets/tabs/chat/chattab.h" + +#include "listeners/updatestatuslistener.h" + +#include "resources/map/map.h" + +#include "utils/gettext.h" + +PRAGMA48(GCC diagnostic push) +PRAGMA48(GCC diagnostic ignored "-Wshadow") +#ifdef ANDROID +#ifndef USE_SDL2 +#include +#endif // USE_SDL2 +#endif // ANDROID +PRAGMA48(GCC diagnostic pop) + +#include "debug.h" + +namespace Actions +{ + +impHandler0(switchQuickDrop) +{ + callYellowBarCond(changeQuickDropCounter) +} + +impHandler0(changeCrazyMove) +{ + callYellowBar(changeCrazyMoveType); +} + +impHandler0(changePickupType) +{ + callYellowBar(changePickUpType); +} + +impHandler0(changeMoveType) +{ + callYellowBar(changeMoveType); +} + +impHandler0(changeAttackWeaponType) +{ + callYellowBar(changeAttackWeaponType); +} + +impHandler0(changeAttackType) +{ + callYellowBar(changeAttackType); +} + +impHandler0(changeTargetingType) +{ + callYellowBar(changeTargetingType); +} + +impHandler0(changeFollowMode) +{ + callYellowBar(changeFollowMode); +} + +impHandler0(changeImitationMode) +{ + callYellowBar(changeImitationMode); +} + +impHandler0(changeMagicAttackType) +{ + callYellowBar(changeMagicAttackType); +} + +impHandler0(changePvpMode) +{ + callYellowBar(changePvpAttackType); +} + +impHandler0(changeMoveToTarget) +{ + callYellowBar(changeMoveToTargetType); +} + +impHandler0(changeGameModifier) +{ + if (localPlayer != nullptr) + { + GameModifiers::changeGameModifiers(false); + return true; + } + return false; +} + +impHandler0(changeAudio) +{ + soundManager.changeAudio(); + if (localPlayer != nullptr) + localPlayer->updateMusic(); + return true; +} + +impHandler0(away) +{ + GameModifiers::changeAwayMode(true); + if (localPlayer != nullptr) + { + localPlayer->updateStatus(); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + return false; +} + +impHandler0(camera) +{ + if (viewport != nullptr) + { + viewport->toggleCameraMode(); + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + return true; + } + return false; +} + +impHandler0(changeMapMode) +{ + if (viewport != nullptr) + viewport->toggleMapDrawType(); + UpdateStatusListener::distributeEvent(); + if (Game::instance() != nullptr) + { + if (Map *const map = Game::instance()->getCurrentMap()) + map->redrawMap(); + } + return true; +} + +impHandler0(changeTrade) +{ + unsigned int deflt = playerRelations.getDefault(); + if ((deflt & PlayerRelation::TRADE) != 0u) + { + if (localChatTab != nullptr) + { + // TRANSLATORS: disable trades message + localChatTab->chatLog(_("Ignoring incoming trade requests"), + ChatMsgType::BY_SERVER); + } + deflt &= ~PlayerRelation::TRADE; + } + else + { + if (localChatTab != nullptr) + { + // TRANSLATORS: enable trades message + localChatTab->chatLog(_("Accepting incoming trade requests"), + ChatMsgType::BY_SERVER); + } + deflt |= PlayerRelation::TRADE; + } + + playerRelations.setDefault(deflt); + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/tabs.cpp b/src/progs/manaplus/actions/tabs.cpp new file mode 100644 index 000000000..99d964b40 --- /dev/null +++ b/src/progs/manaplus/actions/tabs.cpp @@ -0,0 +1,106 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/tabs.h" + +#include "actions/actiondef.h" + +#include "gui/windows/inventorywindow.h" +#include "gui/windows/socialwindow.h" +#include "gui/windows/shortcutwindow.h" + +#include "debug.h" + +namespace Actions +{ + +impHandler0(prevSocialTab) +{ + if (socialWindow != nullptr) + { + socialWindow->prevTab(); + return true; + } + return false; +} + +impHandler0(nextSocialTab) +{ + if (socialWindow != nullptr) + { + socialWindow->nextTab(); + return true; + } + return false; +} + +impHandler0(nextShortcutsTab) +{ + if (itemShortcutWindow != nullptr) + { + itemShortcutWindow->nextTab(); + return true; + } + return false; +} + +impHandler0(prevShortcutsTab) +{ + if (itemShortcutWindow != nullptr) + { + itemShortcutWindow->prevTab(); + return true; + } + return false; +} + +impHandler0(nextCommandsTab) +{ + if (spellShortcutWindow != nullptr) + { + spellShortcutWindow->nextTab(); + return true; + } + return false; +} + +impHandler0(prevCommandsTab) +{ + if (spellShortcutWindow != nullptr) + { + spellShortcutWindow->prevTab(); + return true; + } + return false; +} + +impHandler0(nextInvTab) +{ + InventoryWindow::nextTab(); + return true; +} + +impHandler0(prevInvTab) +{ + InventoryWindow::prevTab(); + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/target.cpp b/src/progs/manaplus/actions/target.cpp new file mode 100644 index 000000000..a72cbe502 --- /dev/null +++ b/src/progs/manaplus/actions/target.cpp @@ -0,0 +1,90 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/target.h" + +#include "actions/actiondef.h" + +#include "being/localplayer.h" + +#include "gui/popups/popupmenu.h" + +#include "debug.h" + +namespace Actions +{ + +static bool setTarget(const ActorTypeT type, const AllowSort allowSort) +{ + if (localPlayer != nullptr) + return localPlayer->setNewTarget(type, allowSort) != nullptr; + return false; +} + +impHandler0(targetPlayer) +{ + return setTarget(ActorType::Player, AllowSort_true); +} + +impHandler0(targetMonster) +{ + return setTarget(ActorType::Monster, AllowSort_true); +} + +impHandler0(targetClosestMonster) +{ + return setTarget(ActorType::Monster, AllowSort_false); +} + +impHandler0(targetNPC) +{ + return setTarget(ActorType::Npc, AllowSort_true); +} + +impHandler0(targetMercenary) +{ + return setTarget(ActorType::Mercenary, AllowSort_true); +} + +impHandler0(targetSkillUnit) +{ + return setTarget(ActorType::SkillUnit, AllowSort_true); +} + +impHandler0(targetPet) +{ + return setTarget(ActorType::Pet, AllowSort_true); +} + +impHandler0(contextMenu) +{ + if (localPlayer == nullptr) + return false; + const Being *const target = localPlayer->getTarget(); + if (target == nullptr) + return true; + + popupMenu->showPopup(target->getPixelX(), + target->getPixelY(), + target); + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/actions/windows.cpp b/src/progs/manaplus/actions/windows.cpp new file mode 100644 index 000000000..7c9b57d0a --- /dev/null +++ b/src/progs/manaplus/actions/windows.cpp @@ -0,0 +1,383 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-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 . + */ + +#include "actions/windows.h" + +#include "actormanager.h" +#include "client.h" + +#include "actions/actiondef.h" + +#include "being/localplayer.h" + +#include "gui/dialogsmanager.h" + +#include "gui/windows/bankwindow.h" +#include "gui/windows/skilldialog.h" +#include "gui/windows/socialwindow.h" +#include "gui/windows/statuswindow.h" +#include "gui/windows/questswindow.h" +#include "gui/windows/whoisonline.h" +#include "gui/windows/chatwindow.h" +#include "gui/windows/debugwindow.h" +#include "gui/windows/didyouknowwindow.h" +#include "gui/windows/equipmentwindow.h" +#include "gui/windows/helpwindow.h" +#include "gui/windows/inventorywindow.h" +#include "gui/windows/killstats.h" +#include "gui/windows/mailwindow.h" +#include "gui/windows/minimap.h" +#include "gui/windows/outfitwindow.h" +#include "gui/windows/setupwindow.h" +#include "gui/windows/serverinfowindow.h" +#include "gui/windows/shopwindow.h" +#include "gui/windows/shortcutwindow.h" +#include "gui/windows/updaterwindow.h" + +#include "gui/widgets/createwidget.h" + +#include "gui/widgets/tabs/chat/chattab.h" + +#include "utils/gettext.h" + +#include "net/net.h" + +#include "debug.h" + +namespace Actions +{ + +impHandler0(setupWindowShow) +{ + if (setupWindow != nullptr) + { + if (setupWindow->isWindowVisible()) + { + setupWindow->doCancel(); + } + else + { + setupWindow->setVisible(Visible_true); + setupWindow->requestMoveToTop(); + } + return true; + } + return false; +} + +impHandler0(hideWindows) +{ + if (setupWindow != nullptr) + setupWindow->hideWindows(); + return true; +} + +static bool showHelpPage(const std::string &page, const bool showHide) +{ + if (helpWindow != nullptr) + { + if (showHide && helpWindow->isWindowVisible()) + { + helpWindow->setVisible(Visible_false); + } + else + { + helpWindow->loadHelp(page); + helpWindow->requestMoveToTop(); + } + return true; + } + return false; +} + +impHandler(helpWindowShow) +{ + if ((chatWindow == nullptr) || !chatWindow->isInputFocused()) + return showHelpPage("index", true); + if (event.tab == nullptr) + return showHelpPage("chatcommands", true); + switch (event.tab->getType()) + { + case ChatTabType::PARTY: + return showHelpPage("chatparty", true); + case ChatTabType::GUILD: + return showHelpPage("chatguild", true); + case ChatTabType::WHISPER: + return showHelpPage("chatwhisper", true); + case ChatTabType::DEBUG: + return showHelpPage("chatdebug", true); + case ChatTabType::TRADE: + return showHelpPage("chattrade", true); + case ChatTabType::BATTLE: + return showHelpPage("chatbattle", true); + case ChatTabType::LANG: + return showHelpPage("chatlang", true); + case ChatTabType::GM: + return showHelpPage("chatgm", true); + case ChatTabType::CHANNEL: + return showHelpPage("chatchannel", true); + default: + case ChatTabType::UNKNOWN: + case ChatTabType::INPUT: + return showHelpPage("chatcommands", true); + } +} + +impHandler0(aboutWindowShow) +{ + return showHelpPage("about", false); +} + +static void showHideWindow(Window *const window) +{ + if (window != nullptr) + { + window->setVisible(fromBool( + !window->isWindowVisible(), Visible)); + if (window->isWindowVisible()) + window->requestMoveToTop(); + } +} + +impHandler0(statusWindowShow) +{ + showHideWindow(statusWindow); + return true; +} + +impHandler0(inventoryWindowShow) +{ + showHideWindow(inventoryWindow); + return true; +} + +impHandler0(equipmentWindowShow) +{ + showHideWindow(equipmentWindow); + return true; +} + +impHandler0(skillDialogShow) +{ + showHideWindow(skillDialog); + return true; +} + +impHandler0(minimapWindowShow) +{ + if (minimap != nullptr) + { + minimap->toggle(); + return true; + } + return false; +} + +impHandler0(chatWindowShow) +{ + showHideWindow(chatWindow); + return true; +} + +impHandler0(shortcutWindowShow) +{ + showHideWindow(itemShortcutWindow); + return true; +} + +impHandler0(debugWindowShow) +{ + showHideWindow(debugWindow); + return true; +} + +impHandler0(socialWindowShow) +{ + showHideWindow(socialWindow); + return true; +} + +impHandler0(emoteShortcutWindowShow) +{ + showHideWindow(emoteShortcutWindow); + return true; +} + +impHandler0(outfitWindowShow) +{ + showHideWindow(outfitWindow); + return true; +} + +impHandler0(shopWindowShow) +{ + showHideWindow(shopWindow); + return true; +} + +impHandler0(dropShortcutWindowShow) +{ + showHideWindow(dropShortcutWindow); + return true; +} + +impHandler0(killStatsWindowShow) +{ + showHideWindow(killStats); + return true; +} + +impHandler0(spellShortcutWindowShow) +{ + showHideWindow(spellShortcutWindow); + return true; +} + +impHandler0(whoIsOnlineWindowShow) +{ + showHideWindow(whoIsOnline); + return true; +} + +impHandler0(didYouKnowWindowShow) +{ + showHideWindow(didYouKnowWindow); + return true; +} + +impHandler0(questsWindowShow) +{ + showHideWindow(questsWindow); + return true; +} + +impHandler0(bankWindowShow) +{ +#ifdef TMWA_SUPPORT + if (Net::getNetworkType() == ServerType::TMWATHENA) + return false; +#endif // TMWA_SUPPORT + + showHideWindow(bankWindow); + return true; +} + +impHandler0(cartWindowShow) +{ + if (Net::getNetworkType() == ServerType::TMWATHENA || + (localPlayer == nullptr) || + !localPlayer->getHaveCart()) + { + return false; + } + + showHideWindow(cartWindow); + if (inventoryWindow != nullptr) + inventoryWindow->updateDropButton(); + return true; +} + +impHandler0(updaterWindowShow) +{ + if (updaterWindow != nullptr) + updaterWindow->deleteSelf(); + else + DialogsManager::createUpdaterWindow(); + return true; +} + +impHandler0(quickWindowShow) +{ + if (setupWindow != nullptr) + { + if (setupWindow->isWindowVisible()) + setupWindow->doCancel(); + setupWindow->setVisible(Visible_true); + // TRANSLATORS: settings tab name + setupWindow->activateTab(_("Quick")); + setupWindow->requestMoveToTop(); + return true; + } + return false; +} + +impHandler0(mailWindowShow) +{ + showHideWindow(mailWindow); + return true; +} + +impHandler0(serverInfoWindowShow) +{ + if (serverInfoWindow != nullptr && + serverInfoWindow->isWindowVisible()) + { + serverInfoWindow->close(); + serverInfoWindow = nullptr; + } + else + { + serverInfoWindow = CREATEWIDGETR(ServerInfoWindow, + client->getCurrentServer()); + serverInfoWindow->requestMoveToTop(); + } + return true; +} + +impHandler(showItems) +{ + const std::string args = event.args; + if (args.empty()) + return false; + + Being *being = nullptr; + if (args[0] == ':') + { + being = actorManager->findBeing(fromInt(atoi( + args.substr(1).c_str()), BeingId)); + if ((being != nullptr) && being->getType() == ActorType::Monster) + being = nullptr; + } + else + { + being = actorManager->findBeingByName(args, ActorType::Player); + } + if (being == nullptr) + return true; + if (being == localPlayer) + { + if (equipmentWindow != nullptr && + !equipmentWindow->isWindowVisible()) + { + equipmentWindow->setVisible(Visible_true); + } + } + else + { + if (beingEquipmentWindow != nullptr) + { + beingEquipmentWindow->setBeing(being); + beingEquipmentWindow->setVisible(Visible_true); + } + } + return true; +} + +} // namespace Actions diff --git a/src/progs/manaplus/client.cpp b/src/progs/manaplus/client.cpp new file mode 100644 index 000000000..6e245029d --- /dev/null +++ b/src/progs/manaplus/client.cpp @@ -0,0 +1,1981 @@ +/* + * 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 . + */ + +#include "progs/manaplus/client.h" + +#include "chatlogger.h" +#include "configmanager.h" +#include "dirs.h" +#include "eventsmanager.h" +#include "game.h" +#include "graphicsmanager.h" +#include "main.h" +#include "party.h" +#include "settings.h" +#include "soundmanager.h" +#include "spellmanager.h" + +#include "being/localplayer.h" +#include "being/playerinfo.h" +#include "being/playerrelations.h" + +#include "const/net/net.h" + +#include "enums/being/attributesstrings.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/shortcut/dropshortcut.h" +#include "gui/shortcut/emoteshortcut.h" +#include "gui/shortcut/itemshortcut.h" +#include "gui/shortcut/spellshortcut.h" + +#include "gui/windows/changeemaildialog.h" +#include "gui/windows/changepassworddialog.h" +#include "gui/windows/charselectdialog.h" +#include "gui/windows/connectiondialog.h" +#include "gui/windows/equipmentwindow.h" +#include "gui/windows/logindialog.h" +#include "gui/windows/npcdialog.h" +#include "gui/windows/okdialog.h" +#include "gui/windows/registerdialog.h" +#include "gui/windows/serverdialog.h" +#include "gui/windows/setupwindow.h" +#include "gui/windows/updaterwindow.h" +#include "gui/windows/quitdialog.h" +#include "gui/windows/worldselectdialog.h" + +#include "gui/widgets/button.h" +#include "gui/widgets/createwidget.h" +#include "gui/widgets/desktop.h" +#include "gui/widgets/windowcontainer.h" + +#include "input/inputmanager.h" +#include "input/joystick.h" +#include "input/keyboardconfig.h" + +#include "input/touch/touchmanager.h" + +#include "net/charserverhandler.h" +#include "net/chathandler.h" +#include "net/download.h" +#include "net/gamehandler.h" +#include "net/generalhandler.h" +#include "net/guildhandler.h" +#include "net/inventoryhandler.h" +#include "net/ipc.h" +#include "net/loginhandler.h" +#include "net/net.h" +#include "net/updatetypeoperators.h" +#include "net/packetlimiter.h" +#include "net/partyhandler.h" + +#ifdef TMWA_SUPPORT +#include "net/tmwa/guildmanager.h" +#endif // TMWA_SUPPORT + +#include "particle/particleengine.h" + +#include "resources/dbmanager.h" +#include "resources/imagehelper.h" + +#include "resources/dye/dyepalette.h" + +#include "resources/resourcemanager/resourcemanager.h" + +#include "resources/sprite/spritereference.h" + +#include "utils/checkutils.h" +#include "utils/cpu.h" +#include "utils/delete2.h" +#include "utils/dumplibs.h" +#include "utils/dumpsizes.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 "listeners/assertlistener.h" +#include "listeners/errorlistener.h" + +#ifdef USE_OPENGL +#include "test/testlauncher.h" +#include "test/testmain.h" +#else // USE_OPENGL +#include "configuration.h" +#endif // USE_OPENGL + +#ifdef WIN32 +PRAGMA48(GCC diagnostic push) +PRAGMA48(GCC diagnostic ignored "-Wshadow") +#include +PRAGMA48(GCC diagnostic pop) +#include "fs/specialfolder.h" +#undef ERROR +#endif // WIN32 + +#ifdef ANDROID +#ifndef USE_SDL2 +PRAGMA48(GCC diagnostic push) +PRAGMA48(GCC diagnostic ignored "-Wshadow") +#include +PRAGMA48(GCC diagnostic pop) +#include +#endif // USE_SDL2 +#endif // ANDROID + +#include + +#ifdef USE_MUMBLE +#include "mumblemanager.h" +#endif // USE_MUMBLE + +PRAGMA48(GCC diagnostic push) +PRAGMA48(GCC diagnostic ignored "-Wshadow") +#ifdef USE_SDL2 +#include +#else // USE_SDL2 +#include +#endif // USE_SDL2 +PRAGMA48(GCC diagnostic pop) + +#include "debug.h" + +std::string errorMessage; +LoginData loginData; + +Client *client = nullptr; + +extern FPSmanager fpsManager; +extern int evolPacketOffset; + +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; +volatile bool isTerminate = false; + +namespace +{ + class AccountListener final : public ActionListener + { + public: + AccountListener() + { } + + A_DELETE_COPY(AccountListener) + + void action(const ActionEvent &event A_UNUSED) override final + { + client->setState(State::CHAR_SELECT); + } + } accountListener; + + class LoginListener final : public ActionListener + { + public: + LoginListener() + { } + + A_DELETE_COPY(LoginListener) + + void action(const ActionEvent &event A_UNUSED) override final + { + client->setState(State::PRE_LOGIN); + } + } loginListener; +} // namespace + +Client::Client() : + ActionListener(), + mCurrentServer(), + mGame(nullptr), + mCurrentDialog(nullptr), + mQuitDialog(nullptr), + mSetupButton(nullptr), + mVideoButton(nullptr), + mHelpButton(nullptr), + mAboutButton(nullptr), + mThemesButton(nullptr), + mPerfomanceButton(nullptr), +#ifdef ANDROID + mCloseButton(nullptr), +#endif // ANDROID + mState(State::CHOOSE_SERVER), + mOldState(State::START), + mSkin(nullptr), + mButtonPadding(1), + mButtonSpacing(3), + mPing(0), + mConfigAutoSaved(false) +{ + WindowManager::init(); +} + +void Client::testsInit() +{ + if (!settings.options.test.empty() && + settings.options.test != "99") + { + gameInit(); + } + else + { + initRand(); + logger = new Logger; + Dirs::initLocalDataDir(); + Dirs::initTempDir(); + Dirs::initConfigDir(); + GettextHelper::initLang(); + } +} + +void Client::gameInit() +{ + logger = new Logger; + + initRand(); + + assertListener = new AssertListener; + // 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->log("Log file: " + settings.logFileName); + logger->setLogFile(settings.logFileName); + +#ifdef USE_FUZZER + Fuzzer::init(); +#endif // USE_FUZZER + + if (settings.options.ipc == true) + IPC::start(); + if (settings.options.test.empty()) + ConfigManager::backupConfig("config.xml"); + ConfigManager::initConfiguration(); + settings.init(); + Net::loadIgnorePackets(); + setPathsDefaults(paths); + initFeatures(); + 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(); + + updateEnv(); + dumpLibs(); + dumpSizes(); + + // 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); + + PacketLimiter::initPacketLimiter(); +#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__) && !defined(UNITTESTS) + if (!settings.options.safeMode && + settings.options.renderer < 0 && + settings.options.test.empty() && + !settings.options.validate && + !config.getBoolValue("videodetected")) + { + graphicsManager.detectVideoSettings(); + } +#endif // !defined(ANDROID) && !defined(__APPLE__) && + // !defined(__native_client__) && !defined(UNITTESTS) +#endif // defined(USE_OPENGL) + + initGraphics(); + + touchManager.init(); + +#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(); + ActorSprite::load(); + 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 + playerRelations.init(); + Joystick::init(); + WindowManager::createWindows(); + + keyboard.update(); + if (joystick != nullptr) + joystick->update(); + + // Initialize default server + mCurrentServer.hostname = settings.options.serverName; + mCurrentServer.port = settings.options.serverPort; + if (!settings.options.serverType.empty()) + { + mCurrentServer.type = ServerInfo::parseType( + settings.options.serverType); + } + + loginData.username = settings.options.username; + loginData.password = settings.options.password; + LoginDialog::savedPassword = settings.options.password; + loginData.remember = (serverConfig.getValue("remember", 1) != 0); + loginData.registerLogin = false; + + if (mCurrentServer.hostname.empty()) + { + mCurrentServer.hostname = branding.getValue("defaultServer", ""); + settings.options.serverName = mCurrentServer.hostname; + } + + if (mCurrentServer.port == 0) + { + mCurrentServer.port = CAST_U16(branding.getValue( + "defaultPort", CAST_S32(DEFAULT_PORT))); + mCurrentServer.type = ServerInfo::parseType( + branding.getValue("defaultServerType", "tmwathena")); + } + + chatLogger->setServerName(mCurrentServer.hostname); + + if (loginData.username.empty() && loginData.remember) + loginData.username = serverConfig.getValue("username", ""); + + 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); + initConfigListeners(); + + settings.guiAlpha = config.getFloatValue("guialpha"); + optionChanged("fpslimit"); + + start_time = time(nullptr); + + PlayerInfo::init(); + +#ifdef ANDROID +#ifndef USE_SDL2 + WindowManager::updateScreenKeyboard(SDL_GetScreenKeyboardHeight(nullptr)); +#endif // USE_SDL2 +#endif // ANDROID + +#ifdef USE_MUMBLE + if (!mumbleManager) + mumbleManager = new MumbleManager; +#endif // USE_MUMBLE + + mSkin = theme->load("windowmenu.xml", ""); + if (mSkin != nullptr) + { + mButtonPadding = mSkin->getPadding(); + mButtonSpacing = mSkin->getOption("spacing", 3); + } + if (settings.options.error) + inputManager.executeAction(InputAction::ERROR); + + if (settings.options.validate == true) + runValidate(); +} + +Client::~Client() +{ + if (!settings.options.testMode) + gameClear(); + else + testsClear(); + CHECKLISTENERS +} + +void Client::initConfigListeners() +{ + config.addListener("fpslimit", this); + config.addListener("guialpha", this); + config.addListener("gamma", this); + config.addListener("enableGamma", this); + config.addListener("particleEmitterSkip", this); + config.addListener("vsync", this); + config.addListener("repeateDelay", this); + config.addListener("repeateInterval", this); + config.addListener("logInput", this); +} + +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", + "keprohm.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::testsClear() +{ + if (!settings.options.test.empty()) + gameClear(); + else + BeingInfo::clear(); +} + +void Client::gameClear() +{ + if (logger != nullptr) + logger->log1("Quitting1"); + isTerminate = true; + config.removeListeners(this); + + delete2(assertListener); + + IPC::stop(); + eventsManager.shutdown(); + WindowManager::deleteWindows(); + if (windowContainer != nullptr) + windowContainer->slowLogic(); + + stopTimers(); + DbManager::unloadDb(); + + if (loginHandler != nullptr) + loginHandler->clearWorlds(); + + if (chatHandler != nullptr) + chatHandler->clear(); + + if (charServerHandler != nullptr) + charServerHandler->clear(); + + delete2(ipc); + +#ifdef USE_MUMBLE + delete2(mumbleManager); +#endif // USE_MUMBLE + + PlayerInfo::deinit(); + + // Before config.write() since it writes the shortcuts to the config + for (unsigned f = 0; f < SHORTCUT_TABS; f ++) + delete2(itemShortcut[f]) + delete2(emoteShortcut); + delete2(dropShortcut); + + playerRelations.store(); + + if (logger != nullptr) + logger->log1("Quitting2"); + + delete2(mCurrentDialog); + delete2(popupManager); + delete2(dialogsManager); + delete2(gui); + + if (inventoryHandler != nullptr) + inventoryHandler->clear(); + + if (logger != nullptr) + logger->log1("Quitting3"); + + touchManager.clear(); + + GraphicsManager::deleteRenderers(); + + if (logger != nullptr) + logger->log1("Quitting4"); + + XML::cleanupXML(); + + if (logger != nullptr) + logger->log1("Quitting5"); + + BeingInfo::clear(); + + // Shutdown sound + soundManager.close(); + + if (logger != nullptr) + logger->log1("Quitting6"); + + ActorSprite::unload(); + + 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(); +} + +int Client::testsExec() +{ +#ifdef USE_OPENGL + if (settings.options.test.empty()) + { + TestMain test; + return test.exec(); + } + else + { + TestLauncher launcher(settings.options.test); + return launcher.exec(); + } +#else // USE_OPENGL + + return 0; +#endif // USE_OPENGL +} + +#define ADDBUTTON(var, object) var = object; \ + x -= var->getWidth() + mButtonSpacing; \ + var->setPosition(x, mButtonPadding); \ + top->add(var); + +void Client::stateConnectGame1() +{ + if ((gameHandler != nullptr) && + (loginHandler != nullptr) && + gameHandler->isConnected()) + { + loginHandler->disconnect(); + } +} + +void Client::stateConnectServer1() +{ + if (mOldState == State::CHOOSE_SERVER) + { + settings.serverName = mCurrentServer.hostname; + ConfigManager::initServerConfig(mCurrentServer.hostname); + PacketLimiter::initPacketLimiter(); + initTradeFilter(); + Dirs::initUsersDir(); + playerRelations.init(); + + // Initialize the item and emote shortcuts. + for (unsigned f = 0; f < SHORTCUT_TABS; f ++) + { + delete itemShortcut[f]; + itemShortcut[f] = new ItemShortcut(f); + } + delete emoteShortcut; + emoteShortcut = new EmoteShortcut; + + // Initialize the drop shortcuts. + delete dropShortcut; + dropShortcut = new DropShortcut; + + initFeatures(); + PlayerInfo::loadData(); + loginData.registerUrl = mCurrentServer.registerUrl; + loginData.packetVersion = mCurrentServer.packetVersion; + if (!mCurrentServer.onlineListUrl.empty()) + settings.onlineListUrl = mCurrentServer.onlineListUrl; + else + settings.onlineListUrl = settings.serverName; + settings.persistentIp = mCurrentServer.persistentIp; + settings.supportUrl = mCurrentServer.supportUrl; + settings.updateMirrors = mCurrentServer.updateMirrors; + settings.enableRemoteCommands = (serverConfig.getValue( + "enableRemoteCommands", 1) != 0); + + if (settings.options.username.empty()) + { + if (loginData.remember) + loginData.username = serverConfig.getValue("username", ""); + else + loginData.username.clear(); + } + else + { + loginData.username = settings.options.username; + } + settings.login = loginData.username; + WindowManager::updateTitle(); + + loginData.remember = (serverConfig.getValue("remember", 1) != 0); + Net::connectToServer(mCurrentServer); + +#ifdef USE_MUMBLE + if (mumbleManager) + mumbleManager->setServer(mCurrentServer.hostname); +#endif // USE_MUMBLE + +#ifdef TMWA_SUPPORT + GuildManager::init(); +#endif // TMWA_SUPPORT + + if (!mConfigAutoSaved) + { + mConfigAutoSaved = true; + config.write(); + } + } + else if (mOldState != State::CHOOSE_SERVER && + (loginHandler != nullptr) && + loginHandler->isConnected()) + { + mState = State::PRE_LOGIN; + } +} + +void Client::stateWorldSelect1() +{ + if (mOldState == State::UPDATE && + (loginHandler != nullptr)) + { + if (loginHandler->getWorlds().size() < 2) + mState = State::PRE_LOGIN; + } +} + +void Client::stateGame1() +{ + if (gui == nullptr) + return; + + BasicContainer2 *const top = static_cast( + 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()); +} + +void Client::stateSwitchLogin1() +{ + if (mOldState == State::GAME && + (gameHandler != nullptr)) + { + gameHandler->disconnect(); + } +} + +int Client::gameExec() +{ + int lastTickTime = tick_time; + + while (mState != State::EXIT) + { + PROFILER_START(); + if (eventsManager.handleEvents()) + continue; + + BLOCK_START("Client::gameExec 3") + if (generalHandler != nullptr) + generalHandler->flushNetwork(); + BLOCK_END("Client::gameExec 3") + + 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 != nullptr) + mGame->logic(); + else if (gui != nullptr) + gui->handleInput(); + + ++lastTickTime; + k ++; + } + soundManager.logic(); + + logic_count += k; + if (gui != nullptr) + gui->slowLogic(); + if (mGame != nullptr) + 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(); + } + else if (mState == State::CONNECT_SERVER) + { + stateConnectServer1(); + } + else if (mState == State::WORLD_SELECT) + { + stateWorldSelect1(); + } + else if (mOldState == State::START || + (mOldState == State::GAME && mState != State::GAME)) + { + stateGame1(); + } + else if (mState == State::SWITCH_LOGIN) + { + stateSwitchLogin1(); + } + BLOCK_END("Client::gameExec 6") + + if (mState != mOldState) + { + BLOCK_START("Client::gameExec 7") + PlayerInfo::stateChange(mState); + + if (mOldState == State::GAME) + { + delete2(mGame); + assertListener = new AssertListener; + Game::clearInstance(); + ResourceManager::cleanOrphans(); + Party::clearParties(); + Guild::clearGuilds(); + NpcDialog::clearDialogs(); + if (guildHandler != nullptr) + guildHandler->clear(); + if (partyHandler != nullptr) + partyHandler->clear(); + if (chatLogger != nullptr) + chatLogger->clear(); + if (!settings.options.dataPath.empty()) + UpdaterWindow::unloadMods(settings.options.dataPath); + else + UpdaterWindow::unloadMods(settings.oldUpdates); + if (!settings.options.skipUpdate) + UpdaterWindow::unloadMods(settings.oldUpdates + "/fix/"); + } + else if (mOldState == State::CHAR_SELECT) + { + if (mState != State::CHANGEPASSWORD && + charServerHandler != nullptr) + { + charServerHandler->clear(); + } + } + + 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 != nullptr) + { + mQuitDialog->scheduleDelete(); + mQuitDialog = nullptr; + } + BLOCK_END("Client::gameExec 7") + + BLOCK_START("Client::gameExec 8") + switch (mState) + { + case State::CHOOSE_SERVER: + { + BLOCK_START("Client::gameExec STATE_CHOOSE_SERVER") + logger->log1("State: CHOOSE SERVER"); + unloadData(); + + // Allow changing this using a server choice dialog + // We show the dialog box only if the command-line + // options weren't set. + if (settings.options.serverName.empty() && + settings.options.serverPort == 0 && + !branding.getValue("onlineServerList", "a").empty()) + { + // Don't allow an alpha opacity + // lower than the default value + theme->setMinimumOpacity(0.8F); + + CREATEWIDGETV(mCurrentDialog, ServerDialog, + &mCurrentServer, + settings.configDir); + } + else + { + mState = State::CONNECT_SERVER; + + // Reset options so that cancelling or connect + // timeout will show the server dialog. + settings.options.serverName.clear(); + settings.options.serverPort = 0; + } + BLOCK_END("Client::gameExec STATE_CHOOSE_SERVER") + break; + } + + case State::CONNECT_SERVER: + BLOCK_START("Client::gameExec State::CONNECT_SERVER") + logger->log1("State: CONNECT SERVER"); + loginData.updateHosts.clear(); + CREATEWIDGETV(mCurrentDialog, ConnectionDialog, + // TRANSLATORS: connection dialog header + _("Connecting to server"), + State::SWITCH_SERVER); + TranslationManager::loadCurrentLang(); + TranslationManager::loadDictionaryLang(); + BLOCK_END("Client::gameExec State::CONNECT_SERVER") + break; + + case State::PRE_LOGIN: + logger->log1("State: PRE_LOGIN"); + break; + + case State::LOGIN: + BLOCK_START("Client::gameExec State::LOGIN") + logger->log1("State: LOGIN"); + // Don't allow an alpha opacity + // lower than the default value + theme->setMinimumOpacity(0.8F); + + if (packetVersion == 0) + { + packetVersion = loginData.packetVersion; + if (packetVersion != 0) + { + loginHandler->updatePacketVersion(); + logger->log("Preconfigured packet version: %d", + packetVersion); + } + } + + loginData.updateType = static_cast( + serverConfig.getValue("updateType", 0)); + + mSearchHash = Net::Download::adlerBuffer( + const_cast(mCurrentServer.hostname.c_str()), + CAST_S32(mCurrentServer.hostname.size())); + if (settings.options.username.empty() || + settings.options.password.empty()) + { + CREATEWIDGETV(mCurrentDialog, LoginDialog, + loginData, + &mCurrentServer, + &settings.options.updateHost); + } + else + { + mState = State::LOGIN_ATTEMPT; + // Clear the password so that when login fails, the + // dialog will show up next time. + settings.options.password.clear(); + } + BLOCK_END("Client::gameExec State::LOGIN") + break; + + case State::LOGIN_ATTEMPT: + BLOCK_START("Client::gameExec State::LOGIN_ATTEMPT") + logger->log1("State: LOGIN ATTEMPT"); + CREATEWIDGETV(mCurrentDialog, ConnectionDialog, + // TRANSLATORS: connection dialog header + _("Logging in"), + State::SWITCH_SERVER); + if (loginHandler != nullptr) + loginHandler->loginOrRegister(&loginData); + BLOCK_END("Client::gameExec State::LOGIN_ATTEMPT") + break; + + case State::WORLD_SELECT: + BLOCK_START("Client::gameExec State::WORLD_SELECT") + logger->log1("State: WORLD SELECT"); + { + TranslationManager::loadCurrentLang(); + TranslationManager::loadDictionaryLang(); + if (loginHandler == nullptr) + { + BLOCK_END("Client::gameExec State::WORLD_SELECT") + break; + } + Worlds worlds = loginHandler->getWorlds(); + + if (worlds.empty()) + { + // Trust that the netcode knows what it's doing + mState = State::UPDATE; + } + else if (worlds.size() == 1) + { + loginHandler->chooseServer( + 0, mCurrentServer.persistentIp); + mState = State::UPDATE; + } + else + { + CREATEWIDGETV(mCurrentDialog, WorldSelectDialog, + worlds); + if (settings.options.chooseDefault) + { + static_cast(mCurrentDialog) + ->action(ActionEvent(nullptr, "ok")); + } + } + } + BLOCK_END("Client::gameExec State::WORLD_SELECT") + break; + + case State::WORLD_SELECT_ATTEMPT: + BLOCK_START("Client::gameExec State::WORLD_SELECT_ATTEMPT") + logger->log1("State: WORLD SELECT ATTEMPT"); + CREATEWIDGETV(mCurrentDialog, ConnectionDialog, + // TRANSLATORS: connection dialog header + _("Entering game world"), + State::WORLD_SELECT); + BLOCK_END("Client::gameExec State::WORLD_SELECT_ATTEMPT") + break; + + case State::UPDATE: + BLOCK_START("Client::gameExec State::UPDATE") + logger->log1("State: UPDATE"); + + // Determine which source to use for the update host + if (!settings.options.updateHost.empty()) + settings.updateHost = settings.options.updateHost; + else + settings.updateHost = loginData.updateHost; + Dirs::initUpdatesDir(); + + if (!settings.oldUpdates.empty()) + UpdaterWindow::unloadUpdates(settings.oldUpdates); + + if (settings.options.skipUpdate) + { + mState = State::LOAD_DATA; + settings.oldUpdates.clear(); + UpdaterWindow::loadDirMods(settings.options.dataPath); + } + else if ((loginData.updateType & UpdateType::Skip) != 0) + { + settings.oldUpdates = pathJoin(settings.localDataDir, + settings.updatesDir); + UpdaterWindow::loadLocalUpdates(settings.oldUpdates); + mState = State::LOAD_DATA; + } + else + { + settings.oldUpdates = pathJoin(settings.localDataDir, + settings.updatesDir); + CREATEWIDGETV(mCurrentDialog, UpdaterWindow, + settings.updateHost, + settings.oldUpdates, + settings.options.dataPath.empty(), + loginData.updateType); + } + BLOCK_END("Client::gameExec State::UPDATE") + break; + + case State::LOAD_DATA: + { + BLOCK_START("Client::gameExec State::LOAD_DATA") + logger->log1("State: LOAD DATA"); + + loadData(); + + mState = State::GET_CHARACTERS; + BLOCK_END("Client::gameExec State::LOAD_DATA") + break; + } + case State::GET_CHARACTERS: + BLOCK_START("Client::gameExec State::GET_CHARACTERS") + logger->log1("State: GET CHARACTERS"); + CREATEWIDGETV(mCurrentDialog, ConnectionDialog, + // TRANSLATORS: connection dialog header + _("Requesting characters"), + State::SWITCH_SERVER); + if (charServerHandler != nullptr) + charServerHandler->requestCharacters(); + BLOCK_END("Client::gameExec State::GET_CHARACTERS") + break; + + case State::CHAR_SELECT: + BLOCK_START("Client::gameExec State::CHAR_SELECT") + logger->log1("State: CHAR SELECT"); + // Don't allow an alpha opacity + // lower than the default value + theme->setMinimumOpacity(0.8F); + + settings.login = loginData.username; + WindowManager::updateTitle(); + + CREATEWIDGETV(mCurrentDialog, CharSelectDialog, + loginData); + + if (!(static_cast(mCurrentDialog)) + ->selectByName(settings.options.character, + CharSelectDialog::Choose)) + { + (static_cast(mCurrentDialog)) + ->selectByName( + serverConfig.getValue("lastCharacter", ""), + settings.options.chooseDefault ? + CharSelectDialog::Choose : + CharSelectDialog::Focus); + } + + // Choosing character on the command line should work only + // once, clear it so that 'switch character' works. + settings.options.character.clear(); + BLOCK_END("Client::gameExec State::CHAR_SELECT") + break; + + case State::CONNECT_GAME: + BLOCK_START("Client::gameExec State::CONNECT_GAME") + logger->log1("State: CONNECT GAME"); + CREATEWIDGETV(mCurrentDialog, ConnectionDialog, + // TRANSLATORS: connection dialog header + _("Connecting to the game server"), + State::CHOOSE_SERVER); + if (gameHandler != nullptr) + gameHandler->connect(); + BLOCK_END("Client::gameExec State::CONNECT_GAME") + break; + + case State::CHANGE_MAP: + BLOCK_START("Client::gameExec State::CHANGE_MAP") + logger->log1("State: CHANGE_MAP"); + CREATEWIDGETV(mCurrentDialog, ConnectionDialog, + // TRANSLATORS: connection dialog header + _("Changing game servers"), + State::SWITCH_CHARACTER); + if (gameHandler != nullptr) + gameHandler->connect(); + BLOCK_END("Client::gameExec State::CHANGE_MAP") + break; + + case State::GAME: + BLOCK_START("Client::gameExec State::GAME") + if (localPlayer != nullptr) + { + logger->log("Memorizing selected character %s", + localPlayer->getName().c_str()); + serverConfig.setValue("lastCharacter", + localPlayer->getName()); +#ifdef USE_MUMBLE + if (mumbleManager) + mumbleManager->setPlayer(localPlayer->getName()); +#endif // USE_MUMBLE + } + + // Fade out logon-music here too to give the desired effect + // of "flowing" into the game. + soundManager.fadeOutMusic(1000); + + // Allow any alpha opacity + theme->setMinimumOpacity(-1.0F); + + if (chatLogger != nullptr) + chatLogger->setServerName(settings.serverName); + +#ifdef ANDROID + delete2(mCloseButton); +#endif // ANDROID + + delete2(mSetupButton); + delete2(mVideoButton); + delete2(mThemesButton); + delete2(mAboutButton); + delete2(mHelpButton); + delete2(mPerfomanceButton); + delete2(desktop); + + mCurrentDialog = nullptr; + + logger->log1("State: GAME"); + if (generalHandler != nullptr) + generalHandler->reloadPartially(); + mGame = new Game; + BLOCK_END("Client::gameExec State::GAME") + break; + + case State::LOGIN_ERROR: + BLOCK_START("Client::gameExec State::LOGIN_ERROR") + logger->log1("State: LOGIN ERROR"); + CREATEWIDGETV(mCurrentDialog, OkDialog, + // TRANSLATORS: error dialog header + _("Error"), + errorMessage, + // TRANSLATORS: ok dialog button + _("Close"), + DialogType::ERROR, + Modal_true, + ShowCenter_true, + nullptr, + 260); + mCurrentDialog->addActionListener(&loginListener); + mCurrentDialog = nullptr; // OkDialog deletes itself + BLOCK_END("Client::gameExec State::LOGIN_ERROR") + break; + + case State::ACCOUNTCHANGE_ERROR: + BLOCK_START("Client::gameExec State::ACCOUNTCHANGE_ERROR") + logger->log1("State: ACCOUNT CHANGE ERROR"); + CREATEWIDGETV(mCurrentDialog, OkDialog, + // TRANSLATORS: error dialog header + _("Error"), + errorMessage, + // TRANSLATORS: ok dialog button + _("Close"), + DialogType::ERROR, + Modal_true, + ShowCenter_true, + nullptr, + 260); + mCurrentDialog->addActionListener(&accountListener); + mCurrentDialog = nullptr; // OkDialog deletes itself + BLOCK_END("Client::gameExec State::ACCOUNTCHANGE_ERROR") + break; + + case State::REGISTER_PREP: + BLOCK_START("Client::gameExec State::REGISTER_PREP") + logger->log1("State: REGISTER_PREP"); + CREATEWIDGETV(mCurrentDialog, ConnectionDialog, + // TRANSLATORS: connection dialog header + _("Requesting registration details"), + State::LOGIN); + loginHandler->getRegistrationDetails(); + BLOCK_END("Client::gameExec State::REGISTER_PREP") + break; + + case State::REGISTER: + logger->log1("State: REGISTER"); + CREATEWIDGETV(mCurrentDialog, RegisterDialog, + loginData); + break; + + case State::REGISTER_ATTEMPT: + BLOCK_START("Client::gameExec State::REGISTER_ATTEMPT") + logger->log("Username is %s", loginData.username.c_str()); + if (loginHandler != nullptr) + loginHandler->registerAccount(&loginData); + BLOCK_END("Client::gameExec State::REGISTER_ATTEMPT") + break; + + case State::CHANGEPASSWORD: + BLOCK_START("Client::gameExec State::CHANGEPASSWORD") + logger->log1("State: CHANGE PASSWORD"); + CREATEWIDGETV(mCurrentDialog, ChangePasswordDialog, + loginData); + mCurrentDialog->setVisible(Visible_true); + BLOCK_END("Client::gameExec State::CHANGEPASSWORD") + break; + + case State::CHANGEPASSWORD_ATTEMPT: + BLOCK_START("Client::gameExec " + "State::CHANGEPASSWORD_ATTEMPT") + logger->log1("State: CHANGE PASSWORD ATTEMPT"); + if (loginHandler != nullptr) + { + loginHandler->changePassword(loginData.password, + loginData.newPassword); + } + BLOCK_END("Client::gameExec State::CHANGEPASSWORD_ATTEMPT") + break; + + case State::CHANGEPASSWORD_SUCCESS: + BLOCK_START("Client::gameExec " + "State::CHANGEPASSWORD_SUCCESS") + logger->log1("State: CHANGE PASSWORD SUCCESS"); + CREATEWIDGETV(mCurrentDialog, OkDialog, + // TRANSLATORS: password change message header + _("Password Change"), + // TRANSLATORS: password change message text + _("Password changed successfully!"), + // TRANSLATORS: ok dialog button + _("OK"), + DialogType::ERROR, + Modal_true, + ShowCenter_true, + nullptr, + 260); + mCurrentDialog->addActionListener(&accountListener); + mCurrentDialog = nullptr; // OkDialog deletes itself + loginData.password = loginData.newPassword; + loginData.newPassword.clear(); + BLOCK_END("Client::gameExec State::CHANGEPASSWORD_SUCCESS") + break; + + case State::CHANGEEMAIL: + logger->log1("State: CHANGE EMAIL"); + CREATEWIDGETV(mCurrentDialog, + ChangeEmailDialog, + loginData); + mCurrentDialog->setVisible(Visible_true); + break; + + case State::CHANGEEMAIL_ATTEMPT: + logger->log1("State: CHANGE EMAIL ATTEMPT"); + if (loginHandler != nullptr) + loginHandler->changeEmail(loginData.email); + break; + + case State::CHANGEEMAIL_SUCCESS: + logger->log1("State: CHANGE EMAIL SUCCESS"); + CREATEWIDGETV(mCurrentDialog, OkDialog, + // TRANSLATORS: email change message header + _("Email Change"), + // TRANSLATORS: email change message text + _("Email changed successfully!"), + // TRANSLATORS: ok dialog button + _("OK"), + DialogType::ERROR, + Modal_true, + ShowCenter_true, + nullptr, + 260); + mCurrentDialog->addActionListener(&accountListener); + mCurrentDialog = nullptr; // OkDialog deletes itself + break; + + case State::SWITCH_SERVER: + BLOCK_START("Client::gameExec State::SWITCH_SERVER") + logger->log1("State: SWITCH SERVER"); + + if (loginHandler != nullptr) + loginHandler->disconnect(); + if (gameHandler != nullptr) + { + gameHandler->disconnect(); + gameHandler->clear(); + } + settings.serverName.clear(); + settings.login.clear(); + WindowManager::updateTitle(); + serverConfig.write(); + serverConfig.unload(); + if (setupWindow != nullptr) + setupWindow->externalUnload(); + + mState = State::CHOOSE_SERVER; + BLOCK_END("Client::gameExec State::SWITCH_SERVER") + break; + + case State::SWITCH_LOGIN: + BLOCK_START("Client::gameExec State::SWITCH_LOGIN") + logger->log1("State: SWITCH LOGIN"); + + if (loginHandler != nullptr) + { + loginHandler->logout(); + loginHandler->disconnect(); + } + if (gameHandler != nullptr) + gameHandler->disconnect(); + if (loginHandler != nullptr) + loginHandler->connect(); + + settings.login.clear(); + WindowManager::updateTitle(); + mState = State::LOGIN; + BLOCK_END("Client::gameExec State::SWITCH_LOGIN") + break; + + case State::SWITCH_CHARACTER: + BLOCK_START("Client::gameExec State::SWITCH_CHARACTER") + logger->log1("State: SWITCH CHARACTER"); + + // Done with game + if (gameHandler != nullptr) + gameHandler->disconnect(); + + settings.login.clear(); + WindowManager::updateTitle(); + mState = State::GET_CHARACTERS; + BLOCK_END("Client::gameExec State::SWITCH_CHARACTER") + break; + + case State::LOGOUT_ATTEMPT: + logger->log1("State: LOGOUT ATTEMPT"); + break; + + case State::WAIT: + logger->log1("State: WAIT"); + break; + + case State::EXIT: + BLOCK_START("Client::gameExec State::EXIT") + logger->log1("State: EXIT"); + Net::unload(); + BLOCK_END("Client::gameExec State::EXIT") + break; + + case State::FORCE_QUIT: + BLOCK_START("Client::gameExec State::FORCE_QUIT") + logger->log1("State: FORCE QUIT"); + if (generalHandler != nullptr) + generalHandler->unload(); + mState = State::EXIT; + BLOCK_END("Client::gameExec State::FORCE_QUIT") + break; + + case State::ERROR: + BLOCK_START("Client::gameExec State::ERROR") + config.write(); + if (mOldState == State::GAME) + serverConfig.write(); + logger->log1("State: ERROR"); + logger->log("Error: %s\n", errorMessage.c_str()); + mCurrentDialog = DialogsManager::openErrorDialog( + // TRANSLATORS: error message header + _("Error"), + errorMessage, + Modal_true); + mCurrentDialog->addActionListener(&errorListener); + mCurrentDialog = nullptr; // OkDialog deletes itself + gameHandler->disconnect(); + BLOCK_END("Client::gameExec State::ERROR") + break; + + case State::AUTORECONNECT_SERVER: + // ++++++ + break; + + case State::START: + default: + mState = State::FORCE_QUIT; + break; + } + BLOCK_END("Client::gameExec 8") + } + PROFILER_END(); + } + + return 0; +} + +void Client::optionChanged(const std::string &name) +{ + if (name == "fpslimit") + { + const int fpsLimit = config.getIntValue("fpslimit"); + settings.limitFps = fpsLimit > 0; + WindowManager::setFramerate(fpsLimit); + } + else if (name == "guialpha" || + name == "enableGuiOpacity") + { + const float alpha = config.getFloatValue("guialpha"); + settings.guiAlpha = alpha; + ImageHelper::setEnableAlpha(alpha != 1.0F && + config.getBoolValue("enableGuiOpacity")); + } + else if (name == "gamma" || + name == "enableGamma") + { + WindowManager::applyGamma(); + } + else if (name == "particleEmitterSkip") + { + ParticleEngine::emitterSkip = + config.getIntValue("particleEmitterSkip") + 1; + } + else if (name == "vsync") + { + WindowManager::applyVSync(); + } + else if (name == "repeateInterval" || + name == "repeateDelay") + { + WindowManager::applyKeyRepeat(); + } +} + +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; + } + + if (setupWindow != nullptr) + { + setupWindow->setVisible(fromBool( + !setupWindow->isWindowVisible(), Visible)); + if (setupWindow->isWindowVisible()) + { + if (!tab.empty()) + setupWindow->activateTab(tab); + setupWindow->requestMoveToTop(); + } + } +} + +void Client::initFeatures() +{ + features.init(paths.getStringValue("featuresFile"), + UseVirtFs_true, + SkipError_true); + setFeaturesDefaults(features); + settings.fixDeadAnimation = features.getBoolValue("fixDeadAnimation"); +} + +void Client::initPaths() +{ + settings.gmCommandSymbol = paths.getStringValue("gmCommandSymbol"); + settings.gmCharCommandSymbol = paths.getStringValue("gmCharCommandSymbol"); + settings.linkCommandSymbol = paths.getStringValue("linkCommandSymbol"); + if (settings.linkCommandSymbol.empty()) + settings.linkCommandSymbol = "="; + settings.overweightPercent = paths.getIntValue("overweightPercent"); + settings.playerNameOffset = paths.getIntValue( + "playerNameOffset"); + settings.playerBadgeAtRightOffset = paths.getIntValue( + "playerBadgeAtRightOffset"); + settings.unknownSkillsAutoTab = paths.getBoolValue("unknownSkillsAutoTab"); + settings.enableNewMailSystem = paths.getBoolValue("enableNewMailSystem"); +} + +void Client::initTradeFilter() +{ + const std::string tradeListName = + settings.serverConfigDir + "/tradefilter.txt"; + + std::ofstream tradeFile; + struct stat statbuf; + + if ((stat(tradeListName.c_str(), &statbuf) != 0) || + !S_ISREG(statbuf.st_mode)) + { + tradeFile.open(tradeListName.c_str(), + std::ios::out); + if (tradeFile.is_open()) + { + tradeFile << ": sell" << std::endl; + tradeFile << ": buy" << std::endl; + tradeFile << ": trade" << std::endl; + tradeFile << "i sell" << std::endl; + tradeFile << "i buy" << std::endl; + tradeFile << "i trade" << std::endl; + tradeFile << "i trading" << std::endl; + tradeFile << "i am buy" << std::endl; + tradeFile << "i am sell" << std::endl; + tradeFile << "i am trade" << std::endl; + tradeFile << "i am trading" << std::endl; + tradeFile << "i'm buy" << std::endl; + tradeFile << "i'm sell" << std::endl; + tradeFile << "i'm trade" << std::endl; + tradeFile << "i'm trading" << std::endl; + } + else + { + reportAlways("Error opening file for writing: %s", + tradeListName.c_str()); + } + tradeFile.close(); + } +} + +bool Client::isTmw() +{ + const std::string &name = settings.serverName; + if (name == "server.themanaworld.org" || + name == "themanaworld.org" || + name == "167.114.129.72") + { + return true; + } + return false; +} + +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() +{ + if ((gameHandler == nullptr) || + !gameHandler->mustPing()) + { + return; + } + + if (get_elapsed_time1(mPing) > 1500) + { + mPing = tick_time; + if (mState == State::UPDATE || + mState == State::LOGIN || + mState == State::LOGIN_ATTEMPT || + mState == State::REGISTER || + mState == State::REGISTER_ATTEMPT) + { + if (loginHandler != nullptr) + loginHandler->ping(); + if (generalHandler != nullptr) + generalHandler->flushSend(); + } + else if (mState == State::CHAR_SELECT) + { + if (charServerHandler != nullptr) + charServerHandler->ping(); + if (generalHandler != nullptr) + generalHandler->flushSend(); + } + } +} + +void Client::loadData() +{ + // 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( + 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(); + if (SpriteReference::Empty == nullptr) + { + SpriteReference::Empty = new SpriteReference( + paths.getStringValue("spriteErrorFile"), + 0); + } + + if (BeingInfo::unknown == nullptr) + BeingInfo::unknown = new BeingInfo; + + initFeatures(); + TranslationManager::loadCurrentLang(); + TranslationManager::loadDictionaryLang(); + PlayerInfo::stateChange(mState); + + delete spellManager; + spellManager = new SpellManager; + delete spellShortcut; + spellShortcut = new SpellShortcut; + + AttributesEnum::init(); + DbManager::loadDb(); + EquipmentWindow::prepareSlotNames(); + + ActorSprite::load(); + + if (desktop != nullptr) + desktop->reloadWallpaper(); +} + +void Client::unloadData() +{ + DbManager::unloadDb(); + mCurrentServer.supportUrl.clear(); + settings.supportUrl.clear(); + if (settings.options.dataPath.empty()) + { + // Add customdata directory + VirtFs::searchAndRemoveArchives( + "customdata/", + "zip"); + } + + if (!settings.oldUpdates.empty()) + { + UpdaterWindow::unloadUpdates(settings.oldUpdates); + settings.oldUpdates.clear(); + } + + if (!settings.options.skipUpdate) + { + VirtFs::searchAndRemoveArchives( + pathJoin(settings.updatesDir, "local/"), + "zip"); + + VirtFs::unmountDirSilent(pathJoin( + settings.localDataDir, + settings.updatesDir, + "local/")); + } + + ResourceManager::clearCache(); + + loginData.clearUpdateHost(); + serverVersion = 0; + packetVersion = 0; + tmwServerVersion = 0; + evolPacketOffset = 0; +} + +void Client::runValidate() +{ + loadData(); + WindowManager::createValidateWindows(); + + WindowManager::deleteValidateWindows(); + unloadData(); + delete2(client); + VirtFs::deinit(); + exit(0); +} diff --git a/src/progs/manaplus/client.h b/src/progs/manaplus/client.h new file mode 100644 index 000000000..af537bb68 --- /dev/null +++ b/src/progs/manaplus/client.h @@ -0,0 +1,167 @@ +/* + * 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 . + */ + +#ifndef PROGS_MANAPLUS_CLIENT_H +#define PROGS_MANAPLUS_CLIENT_H + +#include "enums/state.h" + +#include "listeners/actionlistener.h" +#include "listeners/configlistener.h" + +#include "net/serverinfo.h" + +#include "localconsts.h" + +class Button; +class Game; +class LoginData; +class Skin; +class Window; +class QuitDialog; + +extern bool isSafeMode; +extern int serverVersion; +extern unsigned int tmwServerVersion; +extern time_t start_time; +extern int textures_count; + +extern std::string errorMessage; +extern LoginData loginData; + +/** + * The core part of the client. This class initializes all subsystems, runs + * the event loop, and shuts everything down again. + */ +class Client final : public ConfigListener, + public ActionListener +{ + public: + Client(); + + A_DELETE_COPY(Client) + + ~Client(); + + void gameInit(); + + void testsInit(); + + int gameExec(); + + static int testsExec(); + + void setState(const StateT state) + { mState = state; } + + StateT getState() const noexcept2 A_WARN_UNUSED + { return mState; } + + static bool isTmw() A_WARN_UNUSED; + + void optionChanged(const std::string &name) override final; + + void action(const ActionEvent &event) override final; + + static void initTradeFilter(); + + void moveButtons(const int width); + + void windowRemoved(const Window *const window); + + void slowLogic(); + + ServerInfo &getCurrentServer() + { return mCurrentServer; } + + private: + void initSoundManager(); + + void initConfigListeners(); + + static void initGraphics(); + + static void initFeatures(); + + static void initPaths(); + + void gameClear(); + + void testsClear(); + +#ifdef ANDROID + static void logVars(); +#else // ANDROID + + static void logVars() A_CONST; +#endif // ANDROID + + void stateConnectGame1(); + + void stateConnectServer1(); + + void stateWorldSelect1(); + + void stateGame1(); + + void stateSwitchLogin1(); + + void loadData(); + + void unloadData(); + + void runValidate() +#ifndef BAD_CILKPLUS + __attribute__ ((noreturn)) +#endif // BAD_CILKPLUS +; + + ServerInfo mCurrentServer; + + Game *mGame; + Window *mCurrentDialog; + QuitDialog *mQuitDialog; + Button *mSetupButton; + Button *mVideoButton; + Button *mHelpButton; + Button *mAboutButton; + Button *mThemesButton; + Button *mPerfomanceButton; +#ifdef ANDROID + Button *mCloseButton; +#endif // ANDROID + + StateT mState; + StateT mOldState; + + Skin *mSkin; + int mButtonPadding; + int mButtonSpacing; + int mPing; + bool mConfigAutoSaved; +}; + +extern Client *client; +extern unsigned int mLastHost; +extern unsigned long mSearchHash; + +#endif // PROGS_MANAPLUS_CLIENT_H diff --git a/src/progs/manaplus/gui/viewport.cpp b/src/progs/manaplus/gui/viewport.cpp new file mode 100644 index 000000000..de7571c7c --- /dev/null +++ b/src/progs/manaplus/gui/viewport.cpp @@ -0,0 +1,1148 @@ +/* + * 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 . + */ + +#include "progs/manaplus/gui/viewport.h" + +#include "actormanager.h" +#include "configuration.h" +#include "game.h" +#include "settings.h" +#include "sdlshared.h" +#include "textmanager.h" + +#include "being/flooritem.h" +#include "being/localplayer.h" +#include "being/playerinfo.h" + +#include "enums/resources/map/blockmask.h" +#include "enums/resources/map/mapitemtype.h" + +#include "gui/gui.h" +#include "gui/popupmanager.h" +#include "gui/userpalette.h" + +#include "gui/fonts/font.h" + +#include "gui/popups/beingpopup.h" +#include "gui/popups/popupmenu.h" +#include "gui/popups/textpopup.h" + +#include "gui/windows/ministatuswindow.h" + +#include "input/inputmanager.h" + +#include "utils/checkutils.h" +#include "utils/foreach.h" + +#include "resources/map/map.h" +#include "resources/map/mapitem.h" +#include "resources/map/speciallayer.h" + +#include "debug.h" + +Viewport *viewport = nullptr; + +extern volatile int tick_time; + +Viewport::Viewport() : + WindowContainer(nullptr), + MouseListener(), + ConfigListener(), + mMouseX(0), + mMouseY(0), + mMap(nullptr), + mHoverBeing(nullptr), + mHoverItem(nullptr), + mHoverSign(nullptr), + mScrollRadius(config.getIntValue("ScrollRadius")), + mScrollLaziness(config.getIntValue("ScrollLaziness")), + mScrollCenterOffsetX(config.getIntValue("ScrollCenterOffsetX")), + mScrollCenterOffsetY(config.getIntValue("ScrollCenterOffsetY")), + mMousePressX(0), + mMousePressY(0), + mPixelViewX(0), + mPixelViewY(0), + mMidTileX(0), + mMidTileY(0), + mViewXmax(0), + mViewYmax(0), + mLocalWalkTime(-1), + mCameraRelativeX(0), + mCameraRelativeY(0), + mShowBeingPopup(config.getBoolValue("showBeingPopup")), + mSelfMouseHeal(config.getBoolValue("selfMouseHeal")), + mEnableLazyScrolling(config.getBoolValue("enableLazyScrolling")), + mMouseDirectionMove(config.getBoolValue("mouseDirectionMove")), + mLongMouseClick(config.getBoolValue("longmouseclick")), + mAllowMoveByMouse(config.getBoolValue("allowMoveByMouse")), + mMouseClicked(false), + mPlayerFollowMouse(false) +{ + setOpaque(Opaque_false); + addMouseListener(this); + + config.addListener("ScrollLaziness", this); + config.addListener("ScrollRadius", this); + config.addListener("showBeingPopup", this); + config.addListener("selfMouseHeal", this); + config.addListener("enableLazyScrolling", this); + config.addListener("mouseDirectionMove", this); + config.addListener("longmouseclick", this); + config.addListener("allowMoveByMouse", this); + + setFocusable(true); + updateMidVars(); +} + +Viewport::~Viewport() +{ + config.removeListeners(this); + CHECKLISTENERS +} + +void Viewport::setMap(Map *const map) +{ + if ((mMap != nullptr) && (map != nullptr)) + map->setDrawLayersFlags(mMap->getDrawLayersFlags()); + mMap = map; + updateMaxVars(); +} + +void Viewport::draw(Graphics *const graphics) +{ + BLOCK_START("Viewport::draw 1") + static int lastTick = tick_time; + + if ((mMap == nullptr) || (localPlayer == nullptr)) + { + graphics->setColor(Color(64, 64, 64)); + graphics->fillRectangle( + Rect(0, 0, getWidth(), getHeight())); + BLOCK_END("Viewport::draw 1") + return; + } + + // Avoid freaking out when tick_time overflows + if (tick_time < lastTick) + lastTick = tick_time; + + // Calculate viewpoint + + const int player_x = localPlayer->mPixelX - mMidTileX; + const int player_y = localPlayer->mPixelY - mMidTileY; + + if (mScrollLaziness < 1) + mScrollLaziness = 1; // Avoids division by zero + + if (mEnableLazyScrolling) + { + int cnt = 0; + + // Apply lazy scrolling + while (lastTick < tick_time && cnt < mapTileSize) + { + if (player_x > mPixelViewX + mScrollRadius) + { + mPixelViewX += CAST_S32( + static_cast(player_x + - mPixelViewX - mScrollRadius) / + static_cast(mScrollLaziness)); + } + if (player_x < mPixelViewX - mScrollRadius) + { + mPixelViewX += CAST_S32( + static_cast(player_x + - mPixelViewX + mScrollRadius) / + static_cast(mScrollLaziness)); + } + if (player_y > mPixelViewY + mScrollRadius) + { + mPixelViewY += CAST_S32( + static_cast(player_y + - mPixelViewY - mScrollRadius) / + static_cast(mScrollLaziness)); + } + if (player_y < mPixelViewY - mScrollRadius) + { + mPixelViewY += CAST_S32( + static_cast(player_y + - mPixelViewY + mScrollRadius) / + static_cast(mScrollLaziness)); + } + lastTick ++; + cnt ++; + } + + // Auto center when player is off screen + if (cnt > 30 || player_x - mPixelViewX + > graphics->mWidth / 2 || mPixelViewX + - player_x > graphics->mWidth / 2 || mPixelViewY + - player_y > graphics->getHeight() / 2 || player_y + - mPixelViewY > graphics->getHeight() / 2) + { + if (player_x <= 0 || player_y <= 0) + { + logger->log("incorrect player position: %d, %d, %d, %d", + player_x, player_y, mPixelViewX, mPixelViewY); + logger->log("tile position: %d, %d", + localPlayer->getTileX(), localPlayer->getTileY()); + } + mPixelViewX = player_x; + mPixelViewY = player_y; + } + } + else + { + mPixelViewX = player_x; + mPixelViewY = player_y; + } + + if (mPixelViewX < 0) + mPixelViewX = 0; + if (mPixelViewY < 0) + mPixelViewY = 0; + if (mPixelViewX > mViewXmax) + mPixelViewX = mViewXmax; + if (mPixelViewY > mViewYmax) + mPixelViewY = mViewYmax; + + // Draw tiles and sprites + mMap->draw(graphics, mPixelViewX, mPixelViewY); + + const MapTypeT drawType = settings.mapDrawType; + if (drawType != MapType::NORMAL) + { + if (drawType != MapType::SPECIAL4) + { + mMap->drawCollision(graphics, mPixelViewX, + mPixelViewY, drawType); + } + if (drawType == MapType::DEBUGTYPE) + drawDebugPath(graphics); + } + + if (localPlayer->getCheckNameSetting()) + { + localPlayer->setCheckNameSetting(false); + localPlayer->setName(localPlayer->getName()); + } + + // Draw text + if (textManager != nullptr) + textManager->draw(graphics, mPixelViewX, mPixelViewY); + + // Draw player names, speech, and emotion sprite as needed + const ActorSprites &actors = actorManager->getAll(); + FOR_EACH (ActorSpritesIterator, it, actors) + { + if ((*it)->getType() == ActorType::FloorItem) + continue; + Being *const b = static_cast(*it); + b->drawEmotion(graphics, mPixelViewX, mPixelViewY); + b->drawSpeech(mPixelViewX, mPixelViewY); + } + + if (miniStatusWindow != nullptr) + miniStatusWindow->drawIcons(graphics); + + // Draw contained widgets + WindowContainer::draw(graphics); + BLOCK_END("Viewport::draw 1") +} + +void Viewport::safeDraw(Graphics *const graphics) +{ + Viewport::draw(graphics); +} + +void Viewport::logic() +{ + BLOCK_START("Viewport::logic") + // Make the player follow the mouse position + // if the mouse is dragged elsewhere than in a window. + Gui::getMouseState(mMouseX, mMouseY); + BLOCK_END("Viewport::logic") +} + +void Viewport::followMouse() +{ + if (gui == nullptr) + return; + const MouseStateType button = Gui::getMouseState(mMouseX, mMouseY); + // If the left button is dragged + if (mPlayerFollowMouse && ((button & SDL_BUTTON(1)) != 0)) + { + // We create a mouse event and send it to mouseDragged. + const MouseEvent event(nullptr, + MouseEventType::DRAGGED, + MouseButton::LEFT, + mMouseX, + mMouseY, + 0); + + walkByMouse(event); + } +} + +void Viewport::drawDebugPath(Graphics *const graphics) +{ + if (localPlayer == nullptr || + userPalette == nullptr || + actorManager == nullptr || + mMap == nullptr || + gui == nullptr) + { + return; + } + + Gui::getMouseState(mMouseX, mMouseY); + + static Path debugPath; + static Vector lastMouseDestination = Vector(0.0F, 0.0F); + const int mousePosX = mMouseX + mPixelViewX; + const int mousePosY = mMouseY + mPixelViewY; + Vector mouseDestination(mousePosX, mousePosY); + + if (mouseDestination.x != lastMouseDestination.x + || mouseDestination.y != lastMouseDestination.y) + { + debugPath = mMap->findPath( + CAST_S32(localPlayer->mPixelX - mapTileSize / 2) / mapTileSize, + CAST_S32(localPlayer->mPixelY - mapTileSize) / mapTileSize, + mousePosX / mapTileSize, + mousePosY / mapTileSize, + localPlayer->getBlockWalkMask(), + 500); + lastMouseDestination = mouseDestination; + } + drawPath(graphics, debugPath, userPalette->getColorWithAlpha( + UserColorId::ROAD_POINT)); + + const ActorSprites &actors = actorManager->getAll(); + FOR_EACH (ActorSpritesConstIterator, it, actors) + { + const Being *const being = dynamic_cast(*it); + if ((being != nullptr) && being != localPlayer) + { + const Path &beingPath = being->getPath(); + drawPath(graphics, beingPath, userPalette->getColorWithAlpha( + UserColorId::ROAD_POINT)); + } + } +} + +void Viewport::drawPath(Graphics *const graphics, + const Path &path, + const Color &color) const +{ + graphics->setColor(color); + Font *const font = getFont(); + + int cnt = 1; + FOR_EACH (Path::const_iterator, i, path) + { + const int squareX = i->x * mapTileSize - mPixelViewX + 12; + const int squareY = i->y * mapTileSize - mPixelViewY + 12; + + graphics->fillRectangle(Rect(squareX, squareY, 8, 8)); + if (mMap != nullptr) + { + const std::string str = toString(cnt); + font->drawString(graphics, + color, color, + str, + squareX + 4 - font->getWidth(str) / 2, + squareY + 12); + } + cnt ++; + } +} + +bool Viewport::openContextMenu(const MouseEvent &event) +{ + mPlayerFollowMouse = false; + const int eventX = event.getX(); + const int eventY = event.getY(); + if (popupMenu == nullptr) + return false; + if (mHoverBeing != nullptr) + { + validateSpeed(); + if (actorManager != nullptr) + { + STD_VECTOR beings; + const int x = mMouseX + mPixelViewX; + const int y = mMouseY + mPixelViewY; + actorManager->findBeingsByPixel(beings, x, y, AllPlayers_true); + if (beings.size() > 1) + popupMenu->showPopup(eventX, eventY, beings); + else + popupMenu->showPopup(eventX, eventY, mHoverBeing); + return true; + } + } + else if (mHoverItem != nullptr) + { + validateSpeed(); + popupMenu->showPopup(eventX, eventY, mHoverItem); + return true; + } + else if (mHoverSign != nullptr) + { + validateSpeed(); + popupMenu->showPopup(eventX, eventY, mHoverSign); + return true; + } + else if (settings.cameraMode != 0u) + { + if (mMap == nullptr) + return false; + popupMenu->showMapPopup(eventX, eventY, + (mMouseX + mPixelViewX) / mMap->getTileWidth(), + (mMouseY + mPixelViewY) / mMap->getTileHeight(), + false); + return true; + } + return false; +} + +bool Viewport::leftMouseAction() +{ + const bool stopAttack = inputManager.isActionActive( + InputAction::STOP_ATTACK); + // Interact with some being + if (mHoverBeing != nullptr) + { + if (!mHoverBeing->isAlive()) + return true; + + if (mHoverBeing->canTalk()) + { + validateSpeed(); + mHoverBeing->talkTo(); + return true; + } + + const ActorTypeT type = mHoverBeing->getType(); + switch (type) + { + case ActorType::Player: + validateSpeed(); + if (actorManager != nullptr) + { +#ifdef TMWA_SUPPORT + if (localPlayer != mHoverBeing || mSelfMouseHeal) + actorManager->heal(mHoverBeing); +#endif // TMWA_SUPPORT + + if (localPlayer == mHoverBeing && + mHoverItem != nullptr) + { + localPlayer->pickUp(mHoverItem); + } + return true; + } + break; + case ActorType::Monster: + case ActorType::Npc: + case ActorType::SkillUnit: + if (!stopAttack) + { + if (localPlayer->withinAttackRange(mHoverBeing) || + inputManager.isActionActive(InputAction::ATTACK)) + { + validateSpeed(); + if (!mStatsReUpdated && localPlayer != mHoverBeing) + { + localPlayer->attack(mHoverBeing, + !inputManager.isActionActive( + InputAction::STOP_ATTACK)); + return true; + } + } + else if (!inputManager.isActionActive( + InputAction::ATTACK)) + { + validateSpeed(); + if (!mStatsReUpdated && localPlayer != mHoverBeing) + { + localPlayer->setGotoTarget(mHoverBeing); + return true; + } + } + } + break; + case ActorType::FloorItem: + case ActorType::Portal: + case ActorType::Pet: + case ActorType::Mercenary: + case ActorType::Homunculus: + case ActorType::Elemental: + break; + case ActorType::Unknown: + case ActorType::Avatar: + default: + reportAlways("Left click on unknown actor type: %d", + CAST_S32(type)); + break; + } + } + // Picks up a item if we clicked on one + if (mHoverItem != nullptr) + { + validateSpeed(); + localPlayer->pickUp(mHoverItem); + } + else if (stopAttack) + { + if (mMap != nullptr) + { + const int mouseTileX = (mMouseX + mPixelViewX) + / mMap->getTileWidth(); + const int mouseTileY = (mMouseY + mPixelViewY) + / mMap->getTileHeight(); + inputManager.executeChatCommand(InputAction::PET_MOVE, + strprintf("%d %d", mouseTileX, mouseTileY), + nullptr); + } + return true; + } + // Just walk around + else if (!inputManager.isActionActive(InputAction::ATTACK) && + localPlayer->canMove()) + { + validateSpeed(); + localPlayer->stopAttack(); + localPlayer->cancelFollow(); + mPlayerFollowMouse = mAllowMoveByMouse; + if (mPlayerFollowMouse) + { + // Make the player go to the mouse position + followMouse(); + } + } + return false; +} + +void Viewport::mousePressed(MouseEvent &event) +{ + if (event.getSource() != this || event.isConsumed()) + return; + + // Check if we are alive and kickin' + if ((mMap == nullptr) || (localPlayer == nullptr)) + return; + + // Check if we are busy + // if commented, allow context menu if npc dialog open + if (PlayerInfo::isTalking()) + { + mMouseClicked = false; + return; + } + + mMouseClicked = true; + + mMousePressX = event.getX(); + mMousePressY = event.getY(); + const MouseButtonT eventButton = event.getButton(); + const int pixelX = mMousePressX + mPixelViewX; + const int pixelY = mMousePressY + mPixelViewY; + + // Right click might open a popup + if (eventButton == MouseButton::RIGHT) + { + if (openContextMenu(event)) + return; + } + + // If a popup is active, just remove it + if (PopupManager::isPopupMenuVisible()) + { + mPlayerFollowMouse = false; + PopupManager::hidePopupMenu(); + return; + } + + // Left click can cause different actions + if (!mLongMouseClick && eventButton == MouseButton::LEFT) + { + if (leftMouseAction()) + { + mPlayerFollowMouse = false; + return; + } + } + else if (eventButton == MouseButton::MIDDLE) + { + mPlayerFollowMouse = false; + validateSpeed(); + // Find the being nearest to the clicked position + if (actorManager != nullptr) + { + Being *const target = actorManager->findNearestLivingBeing( + pixelX, pixelY, 20, ActorType::Monster, nullptr); + + if (target != nullptr) + localPlayer->setTarget(target); + } + } +} + +void Viewport::getMouseTile(int &destX, int &destY) const +{ + getMouseTile(mMouseX, mMouseY, destX, destY); +} + +void Viewport::getMouseTile(const int x, const int y, + int &destX, int &destY) const +{ + if (mMap == nullptr) + return; + const int tw = mMap->getTileWidth(); + const int th = mMap->getTileHeight(); + destX = CAST_S32(x + mPixelViewX) + / static_cast(tw); + + if (mMap->isHeightsPresent()) + { + const int th2 = th / 2; + const int clickY = y + mPixelViewY - th2; + destY = y + mPixelViewY; + int newDiffY = 1000000; + const int heightTiles = mainGraphics->mHeight / th; + const int tileViewY = mPixelViewY / th; + for (int f = tileViewY; f < tileViewY + heightTiles; f ++) + { + if (!mMap->getWalk(destX, + f, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + continue; + } + + const int offset = mMap->getHeightOffset( + destX, f) * th2; + const int pixelF = f * th; + const int diff = abs(clickY + offset - pixelF); + if (diff < newDiffY) + { + destY = pixelF; + newDiffY = diff; + } + } + destY /= 32; + } + else + { + destY = CAST_S32((y + mPixelViewY) / static_cast(th)); + } +} + +void Viewport::walkByMouse(const MouseEvent &event) +{ + if ((mMap == nullptr) || (localPlayer == nullptr)) + return; + if (mPlayerFollowMouse + && !inputManager.isActionActive(InputAction::STOP_ATTACK) + && !inputManager.isActionActive(InputAction::UNTARGET)) + { + if (!mMouseDirectionMove) + mPlayerFollowMouse = false; + if (mLocalWalkTime != localPlayer->getActionTime()) + { + mLocalWalkTime = cur_time; + localPlayer->unSetPickUpTarget(); + int playerX = localPlayer->getTileX(); + int playerY = localPlayer->getTileY(); + if (mMouseDirectionMove) + { + const int width = mainGraphics->mWidth / 2; + const int height = mainGraphics->mHeight / 2; + const float wh = static_cast(width) + / static_cast(height); + int x = event.getX() - width; + int y = event.getY() - height; + if ((x == 0) && (y == 0)) + return; + const int x2 = abs(x); + const int y2 = abs(y); + const float diff = 2; + int dx = 0; + int dy = 0; + if (x2 > y2) + { + if (y2 != 0 && + static_cast(x2) / static_cast(y2) / + wh > diff) + { + y = 0; + } + } + else + { + if ((x2 != 0) && y2 * wh / x2 > diff) + x = 0; + } + if (x > 0) + dx = 1; + else if (x < 0) + dx = -1; + if (y > 0) + dy = 1; + else if (y < 0) + dy = -1; + + if (mMap->getWalk(playerX + dx, + playerY + dy, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + localPlayer->navigateTo(playerX + dx, playerY + dy); + } + else + { + if ((dx != 0) && (dy != 0)) + { + // try avoid diagonal collision + if (x2 > y2) + { + if (mMap->getWalk(playerX + dx, + playerY, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + dy = 0; + } + else + { + dx = 0; + } + } + else + { + if (mMap->getWalk(playerX, + playerY + dy, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + dx = 0; + } + else + { + dy = 0; + } + } + } + else + { + // try avoid vertical or horisontal collision + if (dx == 0) + { + if (mMap->getWalk(playerX + 1, + playerY + dy, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + dx = 1; + } + if (mMap->getWalk(playerX - 1, + playerY + dy, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + dx = -1; + } + } + if (dy == 0) + { + if (mMap->getWalk(playerX + dx, + playerY + 1, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + dy = 1; + } + if (mMap->getWalk(playerX + dx, + playerY - 1, + BlockMask::WALL | + BlockMask::AIR | + BlockMask::WATER | + BlockMask::PLAYERWALL)) + { + dy = -1; + } + } + } + localPlayer->navigateTo(playerX + dx, playerY + dy); + } + } + else + { + int destX; + int destY; + getMouseTile(event.getX(), event.getY(), + destX, destY); + if (playerX != destX || playerY != destY) + { + if (!localPlayer->navigateTo(destX, destY)) + { + if (playerX > destX) + playerX --; + else if (playerX < destX) + playerX ++; + if (playerY > destY) + playerY --; + else if (playerY < destY) + playerY ++; + if (mMap->getWalk(playerX, playerY, 0)) + localPlayer->navigateTo(playerX, playerY); + } + } + } + } + } +} + +void Viewport::mouseDragged(MouseEvent &event) +{ + if (event.getSource() != this || event.isConsumed()) + { + mPlayerFollowMouse = false; + return; + } + if (mAllowMoveByMouse && + mMouseClicked && + (localPlayer != nullptr) && + localPlayer->canMove()) + { + if (abs(event.getX() - mMousePressX) > 32 + || abs(event.getY() - mMousePressY) > 32) + { + mPlayerFollowMouse = true; + } + + walkByMouse(event); + } +} + +void Viewport::mouseReleased(MouseEvent &event) +{ + mPlayerFollowMouse = false; + mLocalWalkTime = -1; + if (mLongMouseClick && mMouseClicked) + { + mMouseClicked = false; + if (event.getSource() != this || event.isConsumed()) + return; + const MouseButtonT eventButton = event.getButton(); + if (eventButton == MouseButton::LEFT) + { + // long button press + if ((gui != nullptr) && gui->isLongPress()) + { + if (openContextMenu(event)) + { + gui->resetClickCount(); + return; + } + } + else + { + if (leftMouseAction()) + return; + } + walkByMouse(event); + } + } +} + +void Viewport::optionChanged(const std::string &name) +{ + if (name == "ScrollLaziness") + mScrollLaziness = config.getIntValue("ScrollLaziness"); + else if (name == "ScrollRadius") + mScrollRadius = config.getIntValue("ScrollRadius"); + else if (name == "showBeingPopup") + mShowBeingPopup = config.getBoolValue("showBeingPopup"); + else if (name == "selfMouseHeal") + mSelfMouseHeal = config.getBoolValue("selfMouseHeal"); + else if (name == "enableLazyScrolling") + mEnableLazyScrolling = config.getBoolValue("enableLazyScrolling"); + else if (name == "mouseDirectionMove") + mMouseDirectionMove = config.getBoolValue("mouseDirectionMove"); + else if (name == "longmouseclick") + mLongMouseClick = config.getBoolValue("longmouseclick"); + else if (name == "allowMoveByMouse") + mAllowMoveByMouse = config.getBoolValue("allowMoveByMouse"); +} + +void Viewport::mouseMoved(MouseEvent &event) +{ + // Check if we are on the map + if (mMap == nullptr || + localPlayer == nullptr || + actorManager == nullptr) + { + return; + } + + if (mMouseDirectionMove) + mPlayerFollowMouse = false; + + const int x = mMouseX + mPixelViewX; + const int y = mMouseY + mPixelViewY; + + ActorTypeT type = ActorType::Unknown; + mHoverBeing = actorManager->findBeingByPixel(x, y, AllPlayers_true); + if (mHoverBeing != nullptr) + type = mHoverBeing->getType(); + if ((mHoverBeing != nullptr) + && (type == ActorType::Player + || type == ActorType::Npc + || type == ActorType::Homunculus + || type == ActorType::Mercenary + || type == ActorType::Pet)) + { + PopupManager::hideTextPopup(); + if (mShowBeingPopup && (beingPopup != nullptr)) + beingPopup->show(mMouseX, mMouseY, mHoverBeing); + } + else + { + PopupManager::hideBeingPopup(); + } + + mHoverItem = actorManager->findItem(x / mMap->getTileWidth(), + y / mMap->getTileHeight()); + + if ((mHoverBeing == nullptr) && (mHoverItem == nullptr)) + { + const SpecialLayer *const specialLayer = mMap->getSpecialLayer(); + if (specialLayer != nullptr) + { + const int mouseTileX = (mMouseX + mPixelViewX) + / mMap->getTileWidth(); + const int mouseTileY = (mMouseY + mPixelViewY) + / mMap->getTileHeight(); + + mHoverSign = specialLayer->getTile(mouseTileX, mouseTileY); + if (mHoverSign != nullptr && + mHoverSign->getType() != MapItemType::EMPTY) + { + if (!mHoverSign->getComment().empty()) + { + PopupManager::hideBeingPopup(); + if (textPopup != nullptr) + { + textPopup->show(mMouseX, mMouseY, + mHoverSign->getComment()); + } + } + else + { + if (PopupManager::isTextPopupVisible()) + PopupManager::hideTextPopup(); + } + gui->setCursorType(Cursor::CURSOR_UP); + return; + } + } + } + if (!event.isConsumed() && + PopupManager::isTextPopupVisible()) + { + PopupManager::hideTextPopup(); + } + + if (mHoverBeing != nullptr) + { + switch (type) + { + case ActorType::Npc: + case ActorType::Monster: + case ActorType::Portal: + case ActorType::Pet: + case ActorType::Mercenary: + case ActorType::Homunculus: + case ActorType::SkillUnit: + case ActorType::Elemental: + gui->setCursorType(mHoverBeing->getHoverCursor()); + break; + + case ActorType::Avatar: + case ActorType::FloorItem: + case ActorType::Unknown: + case ActorType::Player: + default: + gui->setCursorType(Cursor::CURSOR_POINTER); + break; + } + } + // Item mouseover + else if (mHoverItem != nullptr) + { + gui->setCursorType(mHoverItem->getHoverCursor()); + } + else + { + gui->setCursorType(Cursor::CURSOR_POINTER); + } +} + +void Viewport::toggleMapDrawType() +{ + settings.mapDrawType = static_cast( + CAST_S32(settings.mapDrawType) + 1); + if (settings.mapDrawType > MapType::BLACKWHITE) + settings.mapDrawType = MapType::NORMAL; + if (mMap != nullptr) + mMap->setDrawLayersFlags(settings.mapDrawType); +} + +void Viewport::toggleCameraMode() +{ + settings.cameraMode ++; + if (settings.cameraMode > 1) + settings.cameraMode = 0; + if (settings.cameraMode == 0u) + { + mCameraRelativeX = 0; + mCameraRelativeY = 0; + updateMidVars(); + } + UpdateStatusListener::distributeEvent(); +} + +void Viewport::clearHover(const ActorSprite *const actor) +{ + if (mHoverBeing == actor) + mHoverBeing = nullptr; + + if (mHoverItem == actor) + mHoverItem = nullptr; +} + +void Viewport::cleanHoverItems() +{ + mHoverBeing = nullptr; + mHoverItem = nullptr; + mHoverSign = nullptr; +} + +void Viewport::moveCamera(const int dx, const int dy) +{ + mCameraRelativeX += dx; + mCameraRelativeY += dy; + updateMidVars(); +} + +void Viewport::moveCameraToActor(const BeingId actorId, + const int x, const int y) +{ + if ((localPlayer == nullptr) || (actorManager == nullptr)) + return; + + const Actor *const actor = actorManager->findBeing(actorId); + if (actor == nullptr) + return; + settings.cameraMode = 1; + mCameraRelativeX = actor->mPixelX - localPlayer->mPixelX + x; + mCameraRelativeY = actor->mPixelY - localPlayer->mPixelY + y; + updateMidVars(); +} + +void Viewport::moveCameraToPosition(const int x, const int y) +{ + if (localPlayer == nullptr) + return; + + settings.cameraMode = 1; + mCameraRelativeX = x - localPlayer->mPixelX; + mCameraRelativeY = y - localPlayer->mPixelY; + updateMidVars(); +} + +void Viewport::moveCameraRelative(const int x, const int y) +{ + settings.cameraMode = 1; + mCameraRelativeX += x; + mCameraRelativeY += y; + updateMidVars(); +} + +void Viewport::returnCamera() +{ + settings.cameraMode = 0; + mCameraRelativeX = 0; + mCameraRelativeY = 0; + updateMidVars(); +} + +void Viewport::validateSpeed() +{ + if (!inputManager.isActionActive(InputAction::TARGET_ATTACK) && + !inputManager.isActionActive(InputAction::ATTACK)) + { + if (Game::instance() != nullptr) + Game::instance()->setValidSpeed(); + } +} + +void Viewport::updateMidVars() +{ + mMidTileX = (mainGraphics->mWidth + mScrollCenterOffsetX) / 2 + - mCameraRelativeX; + mMidTileY = (mainGraphics->mHeight + mScrollCenterOffsetY) / 2 + - mCameraRelativeY; +} + +void Viewport::updateMaxVars() +{ + if (mMap == nullptr) + return; + mViewXmax = mMap->getWidth() * mMap->getTileWidth() + - mainGraphics->mWidth; + mViewYmax = mMap->getHeight() * mMap->getTileHeight() + - mainGraphics->mHeight; +} + +void Viewport::videoResized() +{ + updateMidVars(); + updateMaxVars(); +} diff --git a/src/progs/manaplus/gui/viewport.h b/src/progs/manaplus/gui/viewport.h new file mode 100644 index 000000000..62982fc89 --- /dev/null +++ b/src/progs/manaplus/gui/viewport.h @@ -0,0 +1,249 @@ +/* + * 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 . + */ + +#ifndef PROGS_MANAPLUS_GUI_VIEWPORT_H +#define PROGS_MANAPLUS_GUI_VIEWPORT_H + +#include "position.h" + +#include "enums/simpletypes/beingid.h" + +#include "gui/widgets/windowcontainer.h" + +#include "listeners/mouselistener.h" + +class ActorSprite; +class Being; +class FloorItem; +class Graphics; +class Map; +class MapItem; + +/** + * The viewport on the map. Displays the current map and handles mouse input + * and the popup menu. + */ +class Viewport final : public WindowContainer, + public MouseListener, + public ConfigListener +{ + public: + /** + * Constructor. + */ + Viewport(); + + A_DELETE_COPY(Viewport) + + /** + * Destructor. + */ + ~Viewport(); + + /** + * Sets the map displayed by the viewport. + */ + void setMap(Map *const map); + + /** + * Draws the viewport. + */ + void draw(Graphics *const graphics) override final A_NONNULL(2); + + void safeDraw(Graphics *const graphics) override final A_NONNULL(2); + + /** + * Implements player to keep following mouse. + */ + void logic() override final; + + /** + * Toggles whether the path debug graphics are shown. normal, + * debug with all images and grid, debug with out big images + * and with out grid. + */ + void toggleMapDrawType(); + + void toggleCameraMode(); + + /** + * Handles mouse press on map. + */ + void mousePressed(MouseEvent &event) override final; + + /** + * Handles mouse move on map + */ + void mouseDragged(MouseEvent &event) override final; + + /** + * Handles mouse button release on map. + */ + void mouseReleased(MouseEvent &event) override final; + + /** + * Handles mouse move on map. + */ + void mouseMoved(MouseEvent &event) override final; + + /** + * A relevant config option changed. + */ + void optionChanged(const std::string &name) override final; + + /** + * Returns camera x offset in pixels. + */ + int getCameraX() const noexcept2 A_WARN_UNUSED + { return mPixelViewX; } + + /** + * Returns camera y offset in pixels. + */ + int getCameraY() const noexcept2 A_WARN_UNUSED + { return mPixelViewY; } + + /** + * Changes viewpoint by relative pixel coordinates. + */ + void scrollBy(const int x, const int y) + { mPixelViewX += x; mPixelViewY += y; } + + /** + * Clear all hover item, being etc + */ + void cleanHoverItems(); + + Map *getMap() const noexcept2 A_WARN_UNUSED + { return mMap; } + + void moveCamera(const int dx, const int dy); + + int getCameraRelativeX() const noexcept2 A_WARN_UNUSED + { return mCameraRelativeX; } + + int getCameraRelativeY() const noexcept2 A_WARN_UNUSED + { return mCameraRelativeY; } + + void setCameraRelativeX(const int n) + { mCameraRelativeX = n; updateMidVars(); } + + void setCameraRelativeY(const int n) + { mCameraRelativeY = n; updateMidVars(); } + + void moveCameraToActor(const BeingId actorId, + const int x = 0, + const int y = 0); + + void moveCameraToPosition(const int x, const int y); + + void moveCameraRelative(const int x, const int y); + + void returnCamera(); + + void getMouseTile(int &destX, int &destY) const; + + void videoResized(); + + int mMouseX; /**< Current mouse position in pixels. */ + int mMouseY; /**< Current mouse position in pixels. */ + + protected: + friend class ActorManager; + + /// Clears any matching hovers + void clearHover(const ActorSprite *const actor); + + void updateMidVars(); + + void updateMaxVars(); + + static void validateSpeed(); + + private: + /** + * Finds a path from the player to the mouse, and draws it. This is for + * debug purposes. + */ + void drawDebugPath(Graphics *const graphics) A_NONNULL(2); + + /** + * Draws the given path. + */ + void drawPath(Graphics *const graphics, + const Path &path, + const Color &color = Color(255, 0, 0)) + const A_NONNULL(2); + + bool leftMouseAction(); + + bool openContextMenu(const MouseEvent &event); + + void walkByMouse(const MouseEvent &event); + + void getMouseTile(const int x, + const int y, + int &destX, + int &destY) const; + + /** + * Make the player go to the mouse position. + */ + void followMouse(); + + Map *mMap; /**< The current map. */ + + Being *mHoverBeing; /**< Being mouse is currently over. */ + FloorItem *mHoverItem; /**< FloorItem mouse is currently over. */ + MapItem *mHoverSign; /**< Map sign mouse is currently over. */ + + int mScrollRadius; + int mScrollLaziness; + int mScrollCenterOffsetX; + int mScrollCenterOffsetY; + int mMousePressX; + int mMousePressY; + int mPixelViewX; /**< Current viewpoint in pixels. */ + int mPixelViewY; /**< Current viewpoint in pixels. */ + int mMidTileX; + int mMidTileY; + int mViewXmax; + int mViewYmax; + + time_t mLocalWalkTime; + + int mCameraRelativeX; + int mCameraRelativeY; + + bool mShowBeingPopup; + bool mSelfMouseHeal; + bool mEnableLazyScrolling; + bool mMouseDirectionMove; + bool mLongMouseClick; + bool mAllowMoveByMouse; + bool mMouseClicked; + bool mPlayerFollowMouse; +}; + +extern Viewport *viewport; /**< The viewport. */ + +#endif // PROGS_MANAPLUS_GUI_VIEWPORT_H -- cgit v1.2.3-60-g2f50