diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-08-30 15:11:45 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-08-30 15:11:45 +0300 |
commit | 7c8e0e0454f2e9acfde62faf669a1628e3935a58 (patch) | |
tree | 5beb7c7506fcea774c2102a16a1886e923ad0891 /src | |
parent | a0157bd0f1909af5758adc32370125bdb76ccc5a (diff) | |
download | mv-7c8e0e0454f2e9acfde62faf669a1628e3935a58.tar.gz mv-7c8e0e0454f2e9acfde62faf669a1628e3935a58.tar.bz2 mv-7c8e0e0454f2e9acfde62faf669a1628e3935a58.tar.xz mv-7c8e0e0454f2e9acfde62faf669a1628e3935a58.zip |
Move receive code from playerhandler into separate file.
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/net/ea/playerhandler.cpp | 176 | ||||
-rw-r--r-- | src/net/ea/playerhandler.h | 19 | ||||
-rw-r--r-- | src/net/ea/playerrecv.cpp | 229 | ||||
-rw-r--r-- | src/net/ea/playerrecv.h | 51 | ||||
-rw-r--r-- | src/net/eathena/playerhandler.cpp | 442 | ||||
-rw-r--r-- | src/net/eathena/playerhandler.h | 41 | ||||
-rw-r--r-- | src/net/eathena/playerrecv.cpp | 436 | ||||
-rw-r--r-- | src/net/eathena/playerrecv.h | 57 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.cpp | 150 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.h | 5 | ||||
-rw-r--r-- | src/net/tmwa/playerrecv.cpp | 166 | ||||
-rw-r--r-- | src/net/tmwa/playerrecv.h | 39 |
14 files changed, 1035 insertions, 788 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a6f85bda..4b2990385 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1393,6 +1393,8 @@ SET(SRCS_EVOL net/ea/partyrecv.h net/ea/playerhandler.cpp net/ea/playerhandler.h + net/ea/playerrecv.cpp + net/ea/playerrecv.h net/ea/skillhandler.cpp net/ea/skillhandler.h net/ea/token.h @@ -1468,6 +1470,8 @@ SET(SRCS_TMWA net/tmwa/pethandler.h net/tmwa/playerhandler.cpp net/tmwa/playerhandler.h + net/tmwa/playerrecv.cpp + net/tmwa/playerrecv.h net/tmwa/protocol.h net/tmwa/questhandler.cpp net/tmwa/questhandler.h @@ -1683,6 +1687,8 @@ SET(SRCS_EATHENA net/eathena/petrecv.h net/eathena/playerhandler.cpp net/eathena/playerhandler.h + net/eathena/playerrecv.cpp + net/eathena/playerrecv.h net/eathena/protocol.h net/eathena/questhandler.cpp net/eathena/questhandler.h diff --git a/src/Makefile.am b/src/Makefile.am index 350087d44..80a877368 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1235,6 +1235,8 @@ manaplus_SOURCES += main.cpp \ net/ea/partyrecv.h \ net/ea/playerhandler.cpp \ net/ea/playerhandler.h \ + net/ea/playerrecv.cpp \ + net/ea/playerrecv.h \ net/ea/skillhandler.cpp \ net/ea/skillhandler.h \ net/ea/token.h \ @@ -1311,6 +1313,8 @@ manaplus_SOURCES += \ net/tmwa/pethandler.h \ net/tmwa/playerhandler.cpp \ net/tmwa/playerhandler.h \ + net/tmwa/playerrecv.cpp \ + net/tmwa/playerrecv.h \ net/tmwa/protocol.h \ net/tmwa/questhandler.cpp \ net/tmwa/questhandler.h \ @@ -1529,6 +1533,8 @@ manaplus_SOURCES += gui/windows/bankwindow.cpp \ net/eathena/petrecv.h \ net/eathena/playerhandler.cpp \ net/eathena/playerhandler.h \ + net/eathena/playerrecv.cpp \ + net/eathena/playerrecv.h \ net/eathena/protocol.h \ net/eathena/questhandler.cpp \ net/eathena/questhandler.h \ diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp index ead22a984..70d162cbc 100644 --- a/src/net/ea/playerhandler.cpp +++ b/src/net/ea/playerhandler.cpp @@ -41,6 +41,7 @@ #include "resources/map/map.h" #include "net/ea/eaprotocol.h" +#include "net/ea/playerrecv.h" #include "debug.h" @@ -80,170 +81,6 @@ Vector PlayerHandler::getDefaultWalkSpeed() const return Vector(150, 150, 0); } -void PlayerHandler::processPlayerWarp(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerWarp") - std::string mapPath = msg.readString(16, "map name"); - int x = msg.readInt16("x"); - int y = msg.readInt16("y"); - - logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y); - - if (!localPlayer) - logger->log1("SMSG_PLAYER_WARP localPlayer null"); - - /* - * We must clear the local player's target *before* the call - * to changeMap, as it deletes all beings. - */ - if (localPlayer) - localPlayer->stopAttack(); - - Game *const game = Game::instance(); - if (!game) - { - BLOCK_END("PlayerHandler::processPlayerWarp") - return; - } - - const std::string ¤tMapName = game->getCurrentMapName(); - const bool sameMap = (currentMapName == mapPath); - - // Switch the actual map, deleting the previous one if necessary - mapPath = mapPath.substr(0, mapPath.rfind(".")); - game->changeMap(mapPath); - - int scrollOffsetX = 0; - int scrollOffsetY = 0; - - if (localPlayer) - { - const Map *const map = game->getCurrentMap(); - if (map) - { - if (x >= map->getWidth()) - x = map->getWidth() - 1; - if (y >= map->getHeight()) - y = map->getHeight() - 1; - if (x < 0) - x = 0; - if (y < 0) - y = 0; - /* Scroll if neccessary */ - if (!sameMap - || (abs(x - localPlayer->getTileX()) - > MAP_TELEPORT_SCROLL_DISTANCE) - || (abs(y - localPlayer->getTileY()) - > MAP_TELEPORT_SCROLL_DISTANCE)) - { - scrollOffsetX = (x - localPlayer->getTileX()) - * map->getTileWidth(); - scrollOffsetY = (y - localPlayer->getTileY()) - * map->getTileHeight(); - } - } - - localPlayer->setAction(BeingAction::STAND, 0); - localPlayer->setTileCoords(x, y); - localPlayer->updatePets(); - localPlayer->navigateClean(); - } - - logger->log("Adjust scrolling by %d:%d", scrollOffsetX, scrollOffsetY); - - if (viewport) - { - viewport->returnCamera(); - viewport->scrollBy(scrollOffsetX, scrollOffsetY); - } - BLOCK_END("PlayerHandler::processPlayerWarp") -} - -void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerStatUpdate1") - const int type = msg.readInt16("type"); - const int value = msg.readInt32("value"); - if (!localPlayer) - { - BLOCK_END("PlayerHandler::processPlayerStatUpdate1") - return; - } - - playerHandler->setStat(msg, type, value, NoStat, Notify_true); - BLOCK_END("PlayerHandler::processPlayerStatUpdate1") -} - -void PlayerHandler::processPlayerStatUpdate2(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerStatUpdate2") - const int type = msg.readInt16("type"); - const int value = msg.readInt32("value"); - playerHandler->setStat(msg, type, value, NoStat, Notify_true); - BLOCK_END("PlayerHandler::processPlayerStatUpdate2") -} - -void PlayerHandler::processPlayerStatUpdate3(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerStatUpdate3") - const int type = msg.readInt32("type"); - const int base = msg.readInt32("base"); - const int bonus = msg.readInt32("bonus"); - - playerHandler->setStat(msg, type, base, bonus, Notify_false); - BLOCK_END("PlayerHandler::processPlayerStatUpdate3") -} - -void PlayerHandler::processPlayerStatUpdate4(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerStatUpdate4") - const uint16_t type = msg.readInt16("type"); - const uint8_t ok = msg.readUInt8("flag"); - const int value = msg.readUInt8("value"); - - if (ok != 1) - { - const int oldValue = PlayerInfo::getStatBase( - static_cast<AttributesT>(type)); - const int points = PlayerInfo::getAttribute(Attributes::CHAR_POINTS) - + oldValue - value; - PlayerInfo::setAttribute(Attributes::CHAR_POINTS, points); - NotifyManager::notify(NotifyTypes::SKILL_RAISE_ERROR); - } - - playerHandler->setStat(msg, type, value, NoStat, Notify_true); - BLOCK_END("PlayerHandler::processPlayerStatUpdate4") -} - -void PlayerHandler::processPlayerStatUpdate6(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerStatUpdate6") - const int type = msg.readInt16("type"); - const int value = msg.readUInt8("value"); - if (statusWindow) - playerHandler->setStat(msg, type, value, NoStat, Notify_true); - BLOCK_END("PlayerHandler::processPlayerStatUpdate6") -} - -void PlayerHandler::processPlayerArrowMessage(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerArrowMessage") - const int type = msg.readInt16("type"); - switch (type) - { - case 0: - NotifyManager::notify(NotifyTypes::ARROWS_EQUIP_NEEDED); - break; - case 3: - // arrows equiped - break; - default: - UNIMPLIMENTEDPACKET; - break; - } - BLOCK_END("PlayerHandler::processPlayerArrowMessage") -} - bool PlayerHandler::canUseMagic() const { return PlayerInfo::getStatEffective(Attributes::MATK) > 0; @@ -454,15 +291,4 @@ void PlayerHandler::setStat(Net::MessageIn &msg, } } -void PlayerHandler::processMapMusic(Net::MessageIn &msg) -{ - const int size = msg.readInt16("len") - 5; - const std::string music = msg.readString(size, "name"); - soundManager.playMusic(music); - - Map *const map = viewport->getMap(); - if (map) - map->setMusicFile(music); -} - } // namespace Ea diff --git a/src/net/ea/playerhandler.h b/src/net/ea/playerhandler.h index 33465eb80..c2d41a372 100644 --- a/src/net/ea/playerhandler.h +++ b/src/net/ea/playerhandler.h @@ -60,25 +60,6 @@ class PlayerHandler notfinal : public Net::PlayerHandler const int base, const int mod, const Notify notify) const override; - - static const int NoStat = INT_MAX; - - protected: - static void processPlayerWarp(Net::MessageIn &msg); - - static void processPlayerStatUpdate1(Net::MessageIn &msg); - - static void processPlayerStatUpdate2(Net::MessageIn &msg); - - static void processPlayerStatUpdate3(Net::MessageIn &msg); - - static void processPlayerStatUpdate4(Net::MessageIn &msg); - - static void processPlayerStatUpdate6(Net::MessageIn &msg); - - static void processPlayerArrowMessage(Net::MessageIn &msg); - - static void processMapMusic(Net::MessageIn &msg); }; } // namespace Ea diff --git a/src/net/ea/playerrecv.cpp b/src/net/ea/playerrecv.cpp new file mode 100644 index 000000000..cd24559dd --- /dev/null +++ b/src/net/ea/playerrecv.cpp @@ -0,0 +1,229 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2015 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "net/ea/playerrecv.h" + +#include "game.h" +#include "party.h" +#include "notifymanager.h" +#include "soundmanager.h" +#include "units.h" + +#include "being/localplayer.h" +#include "being/playerinfo.h" + +#include "enums/resources/notifytypes.h" + +#include "gui/viewport.h" + +#include "gui/windows/skilldialog.h" +#include "gui/windows/statuswindow.h" + +#include "resources/map/map.h" + +#include "net/ea/eaprotocol.h" + +#include "debug.h" + +// Max. distance we are willing to scroll after a teleport; +// everything beyond will reset the port hard. +static const int MAP_TELEPORT_SCROLL_DISTANCE = 8; + +namespace Ea +{ + +void PlayerRecv::processPlayerWarp(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerWarp") + std::string mapPath = msg.readString(16, "map name"); + int x = msg.readInt16("x"); + int y = msg.readInt16("y"); + + logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y); + + if (!localPlayer) + logger->log1("SMSG_PLAYER_WARP localPlayer null"); + + /* + * We must clear the local player's target *before* the call + * to changeMap, as it deletes all beings. + */ + if (localPlayer) + localPlayer->stopAttack(); + + Game *const game = Game::instance(); + if (!game) + { + BLOCK_END("PlayerRecv::processPlayerWarp") + return; + } + + const std::string ¤tMapName = game->getCurrentMapName(); + const bool sameMap = (currentMapName == mapPath); + + // Switch the actual map, deleting the previous one if necessary + mapPath = mapPath.substr(0, mapPath.rfind(".")); + game->changeMap(mapPath); + + int scrollOffsetX = 0; + int scrollOffsetY = 0; + + if (localPlayer) + { + const Map *const map = game->getCurrentMap(); + if (map) + { + if (x >= map->getWidth()) + x = map->getWidth() - 1; + if (y >= map->getHeight()) + y = map->getHeight() - 1; + if (x < 0) + x = 0; + if (y < 0) + y = 0; + /* Scroll if neccessary */ + if (!sameMap + || (abs(x - localPlayer->getTileX()) + > MAP_TELEPORT_SCROLL_DISTANCE) + || (abs(y - localPlayer->getTileY()) + > MAP_TELEPORT_SCROLL_DISTANCE)) + { + scrollOffsetX = (x - localPlayer->getTileX()) + * map->getTileWidth(); + scrollOffsetY = (y - localPlayer->getTileY()) + * map->getTileHeight(); + } + } + + localPlayer->setAction(BeingAction::STAND, 0); + localPlayer->setTileCoords(x, y); + localPlayer->updatePets(); + localPlayer->navigateClean(); + } + + logger->log("Adjust scrolling by %d:%d", scrollOffsetX, scrollOffsetY); + + if (viewport) + { + viewport->returnCamera(); + viewport->scrollBy(scrollOffsetX, scrollOffsetY); + } + BLOCK_END("PlayerRecv::processPlayerWarp") +} + +void PlayerRecv::processPlayerStatUpdate1(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerStatUpdate1") + const int type = msg.readInt16("type"); + const int value = msg.readInt32("value"); + if (!localPlayer) + { + BLOCK_END("PlayerRecv::processPlayerStatUpdate1") + return; + } + + playerHandler->setStat(msg, type, value, NoStat, Notify_true); + BLOCK_END("PlayerRecv::processPlayerStatUpdate1") +} + +void PlayerRecv::processPlayerStatUpdate2(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerStatUpdate2") + const int type = msg.readInt16("type"); + const int value = msg.readInt32("value"); + playerHandler->setStat(msg, type, value, NoStat, Notify_true); + BLOCK_END("PlayerRecv::processPlayerStatUpdate2") +} + +void PlayerRecv::processPlayerStatUpdate3(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerStatUpdate3") + const int type = msg.readInt32("type"); + const int base = msg.readInt32("base"); + const int bonus = msg.readInt32("bonus"); + + playerHandler->setStat(msg, type, base, bonus, Notify_false); + BLOCK_END("PlayerRecv::processPlayerStatUpdate3") +} + +void PlayerRecv::processPlayerStatUpdate4(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerStatUpdate4") + const uint16_t type = msg.readInt16("type"); + const uint8_t ok = msg.readUInt8("flag"); + const int value = msg.readUInt8("value"); + + if (ok != 1) + { + const int oldValue = PlayerInfo::getStatBase( + static_cast<AttributesT>(type)); + const int points = PlayerInfo::getAttribute(Attributes::CHAR_POINTS) + + oldValue - value; + PlayerInfo::setAttribute(Attributes::CHAR_POINTS, points); + NotifyManager::notify(NotifyTypes::SKILL_RAISE_ERROR); + } + + playerHandler->setStat(msg, type, value, NoStat, Notify_true); + BLOCK_END("PlayerRecv::processPlayerStatUpdate4") +} + +void PlayerRecv::processPlayerStatUpdate6(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerStatUpdate6") + const int type = msg.readInt16("type"); + const int value = msg.readUInt8("value"); + if (statusWindow) + playerHandler->setStat(msg, type, value, NoStat, Notify_true); + BLOCK_END("PlayerRecv::processPlayerStatUpdate6") +} + +void PlayerRecv::processPlayerArrowMessage(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerArrowMessage") + const int type = msg.readInt16("type"); + switch (type) + { + case 0: + NotifyManager::notify(NotifyTypes::ARROWS_EQUIP_NEEDED); + break; + case 3: + // arrows equiped + break; + default: + UNIMPLIMENTEDPACKET; + break; + } + BLOCK_END("PlayerRecv::processPlayerArrowMessage") +} + +void PlayerRecv::processMapMusic(Net::MessageIn &msg) +{ + const int size = msg.readInt16("len") - 5; + const std::string music = msg.readString(size, "name"); + soundManager.playMusic(music); + + Map *const map = viewport->getMap(); + if (map) + map->setMusicFile(music); +} + +} // namespace Ea diff --git a/src/net/ea/playerrecv.h b/src/net/ea/playerrecv.h new file mode 100644 index 000000000..ec1d20685 --- /dev/null +++ b/src/net/ea/playerrecv.h @@ -0,0 +1,51 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2015 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NET_EA_PLAYERRECV_H +#define NET_EA_PLAYERRECV_H + +#include "net/playerhandler.h" + +#include <climits> + +namespace Net +{ + class MessageIn; +} + +namespace Ea +{ + namespace PlayerRecv + { + void processPlayerWarp(Net::MessageIn &msg); + void processPlayerStatUpdate1(Net::MessageIn &msg); + void processPlayerStatUpdate2(Net::MessageIn &msg); + void processPlayerStatUpdate3(Net::MessageIn &msg); + void processPlayerStatUpdate4(Net::MessageIn &msg); + void processPlayerStatUpdate6(Net::MessageIn &msg); + void processPlayerArrowMessage(Net::MessageIn &msg); + void processMapMusic(Net::MessageIn &msg); + } // namespace PlayerRecv + static const int NoStat = INT_MAX; +} // namespace Ea + +#endif // NET_EA_PLAYERRECV_H diff --git a/src/net/eathena/playerhandler.cpp b/src/net/eathena/playerhandler.cpp index 2988bf21b..4779cee4b 100644 --- a/src/net/eathena/playerhandler.cpp +++ b/src/net/eathena/playerhandler.cpp @@ -39,7 +39,10 @@ #include "input/inputmanager.h" +#include "net/ea/playerrecv.h" + #include "net/eathena/messageout.h" +#include "net/eathena/playerrecv.h" #include "net/eathena/protocol.h" #include "net/eathena/inventoryhandler.h" @@ -97,116 +100,116 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) switch (msg.getId()) { case SMSG_WALK_RESPONSE: - processWalkResponse(msg); + PlayerRecv::processWalkResponse(msg); break; case SMSG_PLAYER_WARP: - processPlayerWarp(msg); + Ea::PlayerRecv::processPlayerWarp(msg); break; case SMSG_PLAYER_STAT_UPDATE_1: - processPlayerStatUpdate1(msg); + Ea::PlayerRecv::processPlayerStatUpdate1(msg); break; case SMSG_PLAYER_STAT_UPDATE_2: - processPlayerStatUpdate2(msg); + Ea::PlayerRecv::processPlayerStatUpdate2(msg); break; case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute - processPlayerStatUpdate3(msg); + Ea::PlayerRecv::processPlayerStatUpdate3(msg); break; case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack - processPlayerStatUpdate4(msg); + Ea::PlayerRecv::processPlayerStatUpdate4(msg); break; // Updates stats and status points case SMSG_PLAYER_STAT_UPDATE_5: - processPlayerStatUpdate5(msg); + PlayerRecv::processPlayerStatUpdate5(msg); break; case SMSG_PLAYER_STAT_UPDATE_6: - processPlayerStatUpdate6(msg); + Ea::PlayerRecv::processPlayerStatUpdate6(msg); break; case SMSG_PLAYER_ARROW_MESSAGE: - processPlayerArrowMessage(msg); + Ea::PlayerRecv::processPlayerArrowMessage(msg); break; case SMSG_PLAYER_SHORTCUTS: - processPlayerShortcuts(msg); + PlayerRecv::processPlayerShortcuts(msg); break; case SMSG_PLAYER_SHOW_EQUIP: - processPlayerShowEquip(msg); + PlayerRecv::processPlayerShowEquip(msg); break; case SMSG_PLAYER_GET_EXP: - processPlayerGetExp(msg); + PlayerRecv::processPlayerGetExp(msg); break; case SMSG_PVP_INFO: - processPvpInfo(msg); + PlayerRecv::processPvpInfo(msg); break; case SMSG_PLAYER_HEAL: - processPlayerHeal(msg); + PlayerRecv::processPlayerHeal(msg); break; case SMSG_PLAYER_SKILL_MESSAGE: - processPlayerSkillMessage(msg); + PlayerRecv::processPlayerSkillMessage(msg); break; case SMSG_MAP_MASK: - processMapMask(msg); + PlayerRecv::processMapMask(msg); break; case SMSG_MAP_MUSIC: - processMapMusic(msg); + Ea::PlayerRecv::processMapMusic(msg); break; case SMSG_ONLINE_LIST: - processOnlineList(msg); + PlayerRecv::processOnlineList(msg); break; case SMSG_PLAYER_NOTIFY_MAPINFO: - processNotifyMapInfo(msg); + PlayerRecv::processNotifyMapInfo(msg); break; case SMSG_PLAYER_FAME_BLACKSMITH: - processPlayerFameBlacksmith(msg); + PlayerRecv::processPlayerFameBlacksmith(msg); break; case SMSG_PLAYER_FAME_ALCHEMIST: - processPlayerFameAlchemist(msg); + PlayerRecv::processPlayerFameAlchemist(msg); break; case SMSG_PLAYER_UPGRADE_MESSAGE: - processPlayerUpgradeMessage(msg); + PlayerRecv::processPlayerUpgradeMessage(msg); break; case SMSG_PLAYER_FAME_TAEKWON: - processPlayerFameTaekwon(msg); + PlayerRecv::processPlayerFameTaekwon(msg); break; case SMSG_PLAYER_READ_BOOK: - processPlayerReadBook(msg); + PlayerRecv::processPlayerReadBook(msg); break; case SMSG_PLAYER_EQUIP_TICK_ACK: - processPlayerEquipTickAck(msg); + PlayerRecv::processPlayerEquipTickAck(msg); break; case SMSG_AUTOSHADOW_SPELL_LIST: - processPlayerAutoShadowSpellList(msg); + PlayerRecv::processPlayerAutoShadowSpellList(msg); break; case SMSG_PLAYER_RANK_POINTS: - processPlayerRankPoints(msg); + PlayerRecv::processPlayerRankPoints(msg); break; case SMSG_PLAYER_CLIENT_COMMAND: - processPlayerClientCommand(msg); + PlayerRecv::processPlayerClientCommand(msg); break; default: @@ -358,175 +361,6 @@ void PlayerHandler::setMemo() const createOutPacket(CMSG_PLAYER_SET_MEMO); } -void PlayerHandler::processPlayerShortcuts(Net::MessageIn &msg) -{ - // +++ player shortcuts ignored. It also disabled on server side. - // may be in future better use it? - msg.readUInt8("unused?"); - for (int f = 0; f < 27; f ++) - { - msg.readUInt8("type 0: item, 1: skill"); - msg.readInt32("item or skill id"); - msg.readInt16("skill level"); - } - msg.skip(77, "unused"); -} - -void PlayerHandler::processPlayerShowEquip(Net::MessageIn &msg) -{ - // +++ for now server allow only switch this option but not using it. - msg.readUInt8("show equip"); // 1 mean need open "equipment" window -} - -void PlayerHandler::processPlayerStatUpdate5(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerStatUpdate5") - PlayerInfo::setAttribute(Attributes::CHAR_POINTS, - msg.readInt16("char points")); - - unsigned int val = msg.readUInt8("str"); - PlayerInfo::setStatBase(Attributes::STR, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::STR, - msg.readUInt8("str cost")); - } - else - { - msg.readUInt8("str need"); - } - - val = msg.readUInt8("agi"); - PlayerInfo::setStatBase(Attributes::AGI, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::AGI, - msg.readUInt8("agi cost")); - } - else - { - msg.readUInt8("agi cost"); - } - - val = msg.readUInt8("vit"); - PlayerInfo::setStatBase(Attributes::VIT, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::VIT, - msg.readUInt8("vit cost")); - } - else - { - msg.readUInt8("vit cost"); - } - - val = msg.readUInt8("int"); - PlayerInfo::setStatBase(Attributes::INT, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::INT, - msg.readUInt8("int cost")); - } - else - { - msg.readUInt8("int cost"); - } - - val = msg.readUInt8("dex"); - PlayerInfo::setStatBase(Attributes::DEX, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::DEX, - msg.readUInt8("dex cost")); - } - else - { - msg.readUInt8("dex cost"); - } - - val = msg.readUInt8("luk"); - PlayerInfo::setStatBase(Attributes::LUK, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::LUK, - msg.readUInt8("luk cost")); - } - else - { - msg.readUInt8("luk cost"); - } - - PlayerInfo::setStatBase(Attributes::ATK, - msg.readInt16("left atk"), Notify_false); - PlayerInfo::setStatMod(Attributes::ATK, msg.readInt16("right atk")); - PlayerInfo::updateAttrs(); - - val = msg.readInt16("right matk"); - PlayerInfo::setStatBase(Attributes::MATK, val, Notify_false); - - val = msg.readInt16("left matk"); - PlayerInfo::setStatMod(Attributes::MATK, val); - - PlayerInfo::setStatBase(Attributes::DEF, - msg.readInt16("left def"), Notify_false); - PlayerInfo::setStatMod(Attributes::DEF, msg.readInt16("right def")); - - PlayerInfo::setStatBase(Attributes::MDEF, - msg.readInt16("left mdef"), Notify_false); - PlayerInfo::setStatMod(Attributes::MDEF, msg.readInt16("right mdef")); - - PlayerInfo::setStatBase(Attributes::HIT, msg.readInt16("hit")); - - PlayerInfo::setStatBase(Attributes::FLEE, - msg.readInt16("flee"), Notify_false); - PlayerInfo::setStatMod(Attributes::FLEE, msg.readInt16("flee2/10")); - - PlayerInfo::setStatBase(Attributes::CRIT, msg.readInt16("crit/10")); - - PlayerInfo::setAttribute(Attributes::ATTACK_DELAY, - msg.readInt16("attack speed")); - msg.readInt16("plus speed = 0"); - - BLOCK_END("PlayerHandler::processPlayerStatUpdate5") -} - -void PlayerHandler::processPlayerGetExp(Net::MessageIn &msg) -{ - if (!localPlayer) - return; - const BeingId id = msg.readBeingId("player id"); - const int exp = msg.readInt32("exp amount"); - const int stat = msg.readInt16("exp type"); - const bool fromQuest = msg.readInt16("is from quest"); - if (!fromQuest && id == localPlayer->getId()) - { - if (stat == 1) - localPlayer->addXpMessage(exp); - else if (stat == 2) - localPlayer->addJobMessage(exp); - else - UNIMPLIMENTEDPACKET; - } - // need show particle depend on isQuest flag, for now ignored -} - -void PlayerHandler::processWalkResponse(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processWalkResponse") - /* - * This client assumes that all walk messages succeed, - * and that the server will send a correction notice - * otherwise. - */ - uint16_t srcX, srcY, dstX, dstY; - msg.readInt32("tick"); - msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path"); - msg.readUInt8("(sx<<4) | (sy&0x0f)"); - if (localPlayer) - localPlayer->setRealPos(dstX, dstY); - BLOCK_END("PlayerHandler::processWalkResponse") -} - void PlayerHandler::doriDori() const { createOutPacket(CMSG_DORI_DORI); @@ -544,16 +378,6 @@ void PlayerHandler::requestPvpInfo() const outMsg.writeInt32(0, "account id"); } -void PlayerHandler::processPvpInfo(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt32("char id"); - msg.readBeingId("account id"); - msg.readInt32("pvp won"); - msg.readInt32("pvp lost"); - msg.readInt32("pvp point"); -} - void PlayerHandler::revive() const { createOutPacket(CMSG_PLAYER_AUTO_REVIVE); @@ -566,63 +390,6 @@ void PlayerHandler::setViewEquipment(const bool allow) const outMsg.writeInt32(allow ? 1 : 0, "allow"); } -void PlayerHandler::processPlayerHeal(Net::MessageIn &msg) -{ - if (!localPlayer) - return; - - const int type = msg.readInt16("var id"); - const int amount = msg.readInt16("value"); - if (type == 5) - localPlayer->addHpMessage(amount); - else if (type == 7) - localPlayer->addSpMessage(amount); -} - -void PlayerHandler::processPlayerSkillMessage(Net::MessageIn &msg) -{ - const int message = msg.readInt32("type"); - switch (message) - { - case 0x15: - NotifyManager::notify(NotifyTypes::SKILL_END_ALL_NEGATIVE_STATUS); - break; - case 0x16: - NotifyManager::notify(NotifyTypes::SKILL_IMMUNITY_TO_ALL_STATUSES); - break; - case 0x17: - NotifyManager::notify(NotifyTypes::SKILL_MAX_HP); - break; - case 0x18: - NotifyManager::notify(NotifyTypes::SKILL_MAX_SP); - break; - case 0x19: - NotifyManager::notify(NotifyTypes::SKILL_ALL_STATUS_PLUS_20); - break; - case 0x1c: - NotifyManager::notify(NotifyTypes::SKILL_ENCHANT_WEAPON_HOLY); - break; - case 0x1d: - NotifyManager::notify(NotifyTypes::SKILL_ENCHANT_ARMOR_HOLY); - break; - case 0x1e: - NotifyManager::notify(NotifyTypes::SKILL_DEF_PLUS_25); - break; - case 0x1f: - NotifyManager::notify(NotifyTypes::SKILL_ATTACK_PLUS_100); - break; - case 0x20: - NotifyManager::notify(NotifyTypes::SKILL_FLEE_PLUS_50); - break; - case 0x28: - NotifyManager::notify(NotifyTypes::SKILL_FULL_STRIP_FAILED); - break; - default: - NotifyManager::notify(NotifyTypes::SKILL_MESSAGE_UNKNOWN); - break; - } -} - void PlayerHandler::setStat(Net::MessageIn &msg, const int type, const int base, @@ -632,151 +399,4 @@ void PlayerHandler::setStat(Net::MessageIn &msg, Ea::PlayerHandler::setStat(msg, type, base, mod, notify); } -void PlayerHandler::processNotifyMapInfo(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt16("type"); -} - -void PlayerHandler::processPlayerFameBlacksmith(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt32("points"); - msg.readInt32("total points"); -} - -void PlayerHandler::processPlayerFameAlchemist(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt32("points"); - msg.readInt32("total points"); -} - -void PlayerHandler::processPlayerUpgradeMessage(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt32("result"); - msg.readInt16("item id"); -} - -void PlayerHandler::processPlayerFameTaekwon(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt32("points"); - msg.readInt32("total points"); -} - -void PlayerHandler::processPlayerReadBook(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt32("book id"); - msg.readInt32("page"); -} - -void PlayerHandler::processPlayerEquipTickAck(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt32("unused"); - msg.readInt32("flag"); -} - -void PlayerHandler::processPlayerAutoShadowSpellList(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - const int count = (msg.readInt16("len") - 8) / 2; - for (int f = 0; f < count; f ++) - msg.readInt16("skill id"); -} - -void PlayerHandler::processPlayerRankPoints(Net::MessageIn &msg) -{ - UNIMPLIMENTEDPACKET; - msg.readInt16("type"); - msg.readInt32("points"); - msg.readInt32("fame"); -} - -void PlayerHandler::processPlayerClientCommand(Net::MessageIn &msg) -{ - const int sz = msg.readInt16("len") - 4; - std::string command = msg.readString(sz, "command"); - std::string cmd; - std::string args; - - if (!parse2Str(command, cmd, args)) - { - cmd = command; - args.clear(); - } - inputManager.executeChatCommand(cmd, args, nullptr); -} - -void PlayerHandler::processOnlineList(Net::MessageIn &msg) -{ - if (!whoIsOnline) - return; - - BLOCK_START("PlayerHandler::processOnlineList") - const int size = msg.readInt16("len") - 4; - std::vector<OnlinePlayer*> arr; - - if (!size) - { - if (whoIsOnline) - whoIsOnline->loadList(arr); - BLOCK_END("PlayerHandler::processOnlineList") - return; - } - - char *const start = reinterpret_cast<char*>(msg.readBytes(size, "nicks")); - if (!start) - { - BLOCK_END("PlayerHandler::processOnlineList") - return; - } - - const char *buf = start; - - int addVal = 3; - - while (buf - start + 1 < size - && *(buf + static_cast<size_t>(addVal))) - { - unsigned char status = *buf; - buf ++; - unsigned char level = *buf; - buf ++; - unsigned char ver = *buf; - buf ++; - - GenderT gender = Gender::UNSPECIFIED; - if (config.getBoolValue("showgender")) - { - if (status & BeingFlag::GENDER_MALE) - gender = Gender::MALE; - else if (status & BeingFlag::GENDER_OTHER) - gender = Gender::OTHER; - else - gender = Gender::FEMALE; - } - arr.push_back(new OnlinePlayer(static_cast<const char*>(buf), - status, level, gender, ver)); - buf += strlen(buf) + 1; - } - - if (whoIsOnline) - whoIsOnline->loadList(arr); - delete [] start; - BLOCK_END("PlayerHandler::processOnlineList") -} - -void PlayerHandler::processMapMask(Net::MessageIn &msg) -{ - const int mask = msg.readInt32("mask"); - msg.readInt32("unused"); - Map *const map = Game::instance()->getCurrentMap(); - if (map) - map->setMask(mask); -} - } // namespace EAthena diff --git a/src/net/eathena/playerhandler.h b/src/net/eathena/playerhandler.h index d32d06ab9..82a060d04 100644 --- a/src/net/eathena/playerhandler.h +++ b/src/net/eathena/playerhandler.h @@ -70,52 +70,11 @@ class PlayerHandler final : public MessageHandler, public Ea::PlayerHandler void revive() const override final; void setViewEquipment(const bool allow) const override final; - protected: void setStat(Net::MessageIn &msg, const int type, const int base, const int mod, const Notify notify) const override final; - - static void processPlayerShortcuts(Net::MessageIn &msg); - - static void processPlayerShowEquip(Net::MessageIn &msg); - - static void processPlayerStatUpdate5(Net::MessageIn &msg); - - static void processPlayerGetExp(Net::MessageIn &msg); - - static void processPvpInfo(Net::MessageIn &msg); - - static void processPlayerHeal(Net::MessageIn &msg); - - static void processPlayerSkillMessage(Net::MessageIn &msg); - - static void processWalkResponse(Net::MessageIn &msg); - - static void processNotifyMapInfo(Net::MessageIn &msg); - - static void processPlayerFameBlacksmith(Net::MessageIn &msg); - - static void processPlayerFameAlchemist(Net::MessageIn &msg); - - static void processPlayerUpgradeMessage(Net::MessageIn &msg); - - static void processPlayerFameTaekwon(Net::MessageIn &msg); - - static void processPlayerReadBook(Net::MessageIn &msg); - - static void processPlayerEquipTickAck(Net::MessageIn &msg); - - static void processPlayerAutoShadowSpellList(Net::MessageIn &msg); - - static void processPlayerRankPoints(Net::MessageIn &msg); - - static void processPlayerClientCommand(Net::MessageIn &msg); - - static void processOnlineList(Net::MessageIn &msg); - - static void processMapMask(Net::MessageIn &msg); }; } // namespace EAthena diff --git a/src/net/eathena/playerrecv.cpp b/src/net/eathena/playerrecv.cpp new file mode 100644 index 000000000..778cb7579 --- /dev/null +++ b/src/net/eathena/playerrecv.cpp @@ -0,0 +1,436 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2015 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "net/eathena/playerrecv.h" + +#include "configuration.h" +#include "game.h" +#include "notifymanager.h" + +#include "being/beingflag.h" +#include "being/localplayer.h" +#include "being/playerinfo.h" + +#include "enums/resources/notifytypes.h" + +#include "gui/onlineplayer.h" + +#include "gui/windows/statuswindow.h" +#include "gui/windows/whoisonline.h" + +#include "input/inputmanager.h" + +#include "net/eathena/messageout.h" +#include "net/eathena/protocol.h" +#include "net/eathena/inventoryhandler.h" + +#include "resources/map/map.h" + +#include "debug.h" + +namespace EAthena +{ + +void PlayerRecv::processPlayerShortcuts(Net::MessageIn &msg) +{ + // +++ player shortcuts ignored. It also disabled on server side. + // may be in future better use it? + msg.readUInt8("unused?"); + for (int f = 0; f < 27; f ++) + { + msg.readUInt8("type 0: item, 1: skill"); + msg.readInt32("item or skill id"); + msg.readInt16("skill level"); + } + msg.skip(77, "unused"); +} + +void PlayerRecv::processPlayerShowEquip(Net::MessageIn &msg) +{ + // +++ for now server allow only switch this option but not using it. + msg.readUInt8("show equip"); // 1 mean need open "equipment" window +} + +void PlayerRecv::processPlayerStatUpdate5(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerStatUpdate5") + PlayerInfo::setAttribute(Attributes::CHAR_POINTS, + msg.readInt16("char points")); + + unsigned int val = msg.readUInt8("str"); + PlayerInfo::setStatBase(Attributes::STR, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::STR, + msg.readUInt8("str cost")); + } + else + { + msg.readUInt8("str need"); + } + + val = msg.readUInt8("agi"); + PlayerInfo::setStatBase(Attributes::AGI, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::AGI, + msg.readUInt8("agi cost")); + } + else + { + msg.readUInt8("agi cost"); + } + + val = msg.readUInt8("vit"); + PlayerInfo::setStatBase(Attributes::VIT, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::VIT, + msg.readUInt8("vit cost")); + } + else + { + msg.readUInt8("vit cost"); + } + + val = msg.readUInt8("int"); + PlayerInfo::setStatBase(Attributes::INT, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::INT, + msg.readUInt8("int cost")); + } + else + { + msg.readUInt8("int cost"); + } + + val = msg.readUInt8("dex"); + PlayerInfo::setStatBase(Attributes::DEX, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::DEX, + msg.readUInt8("dex cost")); + } + else + { + msg.readUInt8("dex cost"); + } + + val = msg.readUInt8("luk"); + PlayerInfo::setStatBase(Attributes::LUK, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::LUK, + msg.readUInt8("luk cost")); + } + else + { + msg.readUInt8("luk cost"); + } + + PlayerInfo::setStatBase(Attributes::ATK, + msg.readInt16("left atk"), Notify_false); + PlayerInfo::setStatMod(Attributes::ATK, msg.readInt16("right atk")); + PlayerInfo::updateAttrs(); + + val = msg.readInt16("right matk"); + PlayerInfo::setStatBase(Attributes::MATK, val, Notify_false); + + val = msg.readInt16("left matk"); + PlayerInfo::setStatMod(Attributes::MATK, val); + + PlayerInfo::setStatBase(Attributes::DEF, + msg.readInt16("left def"), Notify_false); + PlayerInfo::setStatMod(Attributes::DEF, msg.readInt16("right def")); + + PlayerInfo::setStatBase(Attributes::MDEF, + msg.readInt16("left mdef"), Notify_false); + PlayerInfo::setStatMod(Attributes::MDEF, msg.readInt16("right mdef")); + + PlayerInfo::setStatBase(Attributes::HIT, msg.readInt16("hit")); + + PlayerInfo::setStatBase(Attributes::FLEE, + msg.readInt16("flee"), Notify_false); + PlayerInfo::setStatMod(Attributes::FLEE, msg.readInt16("flee2/10")); + + PlayerInfo::setStatBase(Attributes::CRIT, msg.readInt16("crit/10")); + + PlayerInfo::setAttribute(Attributes::ATTACK_DELAY, + msg.readInt16("attack speed")); + msg.readInt16("plus speed = 0"); + + BLOCK_END("PlayerRecv::processPlayerStatUpdate5") +} + +void PlayerRecv::processPlayerGetExp(Net::MessageIn &msg) +{ + if (!localPlayer) + return; + const BeingId id = msg.readBeingId("player id"); + const int exp = msg.readInt32("exp amount"); + const int stat = msg.readInt16("exp type"); + const bool fromQuest = msg.readInt16("is from quest"); + if (!fromQuest && id == localPlayer->getId()) + { + if (stat == 1) + localPlayer->addXpMessage(exp); + else if (stat == 2) + localPlayer->addJobMessage(exp); + else + UNIMPLIMENTEDPACKET; + } + // need show particle depend on isQuest flag, for now ignored +} + +void PlayerRecv::processWalkResponse(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processWalkResponse") + /* + * This client assumes that all walk messages succeed, + * and that the server will send a correction notice + * otherwise. + */ + uint16_t srcX, srcY, dstX, dstY; + msg.readInt32("tick"); + msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path"); + msg.readUInt8("(sx<<4) | (sy&0x0f)"); + if (localPlayer) + localPlayer->setRealPos(dstX, dstY); + BLOCK_END("PlayerRecv::processWalkResponse") +} + +void PlayerRecv::processPvpInfo(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt32("char id"); + msg.readBeingId("account id"); + msg.readInt32("pvp won"); + msg.readInt32("pvp lost"); + msg.readInt32("pvp point"); +} + +void PlayerRecv::processPlayerHeal(Net::MessageIn &msg) +{ + if (!localPlayer) + return; + + const int type = msg.readInt16("var id"); + const int amount = msg.readInt16("value"); + if (type == 5) + localPlayer->addHpMessage(amount); + else if (type == 7) + localPlayer->addSpMessage(amount); +} + +void PlayerRecv::processPlayerSkillMessage(Net::MessageIn &msg) +{ + const int message = msg.readInt32("type"); + switch (message) + { + case 0x15: + NotifyManager::notify(NotifyTypes::SKILL_END_ALL_NEGATIVE_STATUS); + break; + case 0x16: + NotifyManager::notify(NotifyTypes::SKILL_IMMUNITY_TO_ALL_STATUSES); + break; + case 0x17: + NotifyManager::notify(NotifyTypes::SKILL_MAX_HP); + break; + case 0x18: + NotifyManager::notify(NotifyTypes::SKILL_MAX_SP); + break; + case 0x19: + NotifyManager::notify(NotifyTypes::SKILL_ALL_STATUS_PLUS_20); + break; + case 0x1c: + NotifyManager::notify(NotifyTypes::SKILL_ENCHANT_WEAPON_HOLY); + break; + case 0x1d: + NotifyManager::notify(NotifyTypes::SKILL_ENCHANT_ARMOR_HOLY); + break; + case 0x1e: + NotifyManager::notify(NotifyTypes::SKILL_DEF_PLUS_25); + break; + case 0x1f: + NotifyManager::notify(NotifyTypes::SKILL_ATTACK_PLUS_100); + break; + case 0x20: + NotifyManager::notify(NotifyTypes::SKILL_FLEE_PLUS_50); + break; + case 0x28: + NotifyManager::notify(NotifyTypes::SKILL_FULL_STRIP_FAILED); + break; + default: + NotifyManager::notify(NotifyTypes::SKILL_MESSAGE_UNKNOWN); + break; + } +} + +void PlayerRecv::processNotifyMapInfo(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt16("type"); +} + +void PlayerRecv::processPlayerFameBlacksmith(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt32("points"); + msg.readInt32("total points"); +} + +void PlayerRecv::processPlayerFameAlchemist(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt32("points"); + msg.readInt32("total points"); +} + +void PlayerRecv::processPlayerUpgradeMessage(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt32("result"); + msg.readInt16("item id"); +} + +void PlayerRecv::processPlayerFameTaekwon(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt32("points"); + msg.readInt32("total points"); +} + +void PlayerRecv::processPlayerReadBook(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt32("book id"); + msg.readInt32("page"); +} + +void PlayerRecv::processPlayerEquipTickAck(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt32("unused"); + msg.readInt32("flag"); +} + +void PlayerRecv::processPlayerAutoShadowSpellList(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + const int count = (msg.readInt16("len") - 8) / 2; + for (int f = 0; f < count; f ++) + msg.readInt16("skill id"); +} + +void PlayerRecv::processPlayerRankPoints(Net::MessageIn &msg) +{ + UNIMPLIMENTEDPACKET; + msg.readInt16("type"); + msg.readInt32("points"); + msg.readInt32("fame"); +} + +void PlayerRecv::processPlayerClientCommand(Net::MessageIn &msg) +{ + const int sz = msg.readInt16("len") - 4; + std::string command = msg.readString(sz, "command"); + std::string cmd; + std::string args; + + if (!parse2Str(command, cmd, args)) + { + cmd = command; + args.clear(); + } + inputManager.executeChatCommand(cmd, args, nullptr); +} + +void PlayerRecv::processOnlineList(Net::MessageIn &msg) +{ + if (!whoIsOnline) + return; + + BLOCK_START("PlayerRecv::processOnlineList") + const int size = msg.readInt16("len") - 4; + std::vector<OnlinePlayer*> arr; + + if (!size) + { + if (whoIsOnline) + whoIsOnline->loadList(arr); + BLOCK_END("PlayerRecv::processOnlineList") + return; + } + + char *const start = reinterpret_cast<char*>(msg.readBytes(size, "nicks")); + if (!start) + { + BLOCK_END("PlayerRecv::processOnlineList") + return; + } + + const char *buf = start; + + int addVal = 3; + + while (buf - start + 1 < size + && *(buf + static_cast<size_t>(addVal))) + { + unsigned char status = *buf; + buf ++; + unsigned char level = *buf; + buf ++; + unsigned char ver = *buf; + buf ++; + + GenderT gender = Gender::UNSPECIFIED; + if (config.getBoolValue("showgender")) + { + if (status & BeingFlag::GENDER_MALE) + gender = Gender::MALE; + else if (status & BeingFlag::GENDER_OTHER) + gender = Gender::OTHER; + else + gender = Gender::FEMALE; + } + arr.push_back(new OnlinePlayer(static_cast<const char*>(buf), + status, level, gender, ver)); + buf += strlen(buf) + 1; + } + + if (whoIsOnline) + whoIsOnline->loadList(arr); + delete [] start; + BLOCK_END("PlayerRecv::processOnlineList") +} + +void PlayerRecv::processMapMask(Net::MessageIn &msg) +{ + const int mask = msg.readInt32("mask"); + msg.readInt32("unused"); + Map *const map = Game::instance()->getCurrentMap(); + if (map) + map->setMask(mask); +} + +} // namespace EAthena diff --git a/src/net/eathena/playerrecv.h b/src/net/eathena/playerrecv.h new file mode 100644 index 000000000..78ada4d92 --- /dev/null +++ b/src/net/eathena/playerrecv.h @@ -0,0 +1,57 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2015 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NET_EATHENA_PLAYERRECV_H +#define NET_EATHENA_PLAYERRECV_H + +#include "net/ea/playerhandler.h" + +#include "net/eathena/messagehandler.h" + +namespace EAthena +{ + namespace PlayerRecv + { + void processPlayerShortcuts(Net::MessageIn &msg); + void processPlayerShowEquip(Net::MessageIn &msg); + void processPlayerStatUpdate5(Net::MessageIn &msg); + void processPlayerGetExp(Net::MessageIn &msg); + void processPvpInfo(Net::MessageIn &msg); + void processPlayerHeal(Net::MessageIn &msg); + void processPlayerSkillMessage(Net::MessageIn &msg); + void processWalkResponse(Net::MessageIn &msg); + void processNotifyMapInfo(Net::MessageIn &msg); + void processPlayerFameBlacksmith(Net::MessageIn &msg); + void processPlayerFameAlchemist(Net::MessageIn &msg); + void processPlayerUpgradeMessage(Net::MessageIn &msg); + void processPlayerFameTaekwon(Net::MessageIn &msg); + void processPlayerReadBook(Net::MessageIn &msg); + void processPlayerEquipTickAck(Net::MessageIn &msg); + void processPlayerAutoShadowSpellList(Net::MessageIn &msg); + void processPlayerRankPoints(Net::MessageIn &msg); + void processPlayerClientCommand(Net::MessageIn &msg); + void processOnlineList(Net::MessageIn &msg); + void processMapMask(Net::MessageIn &msg); + } // namespace PlayerRecv +} // namespace EAthena + +#endif // NET_EATHENA_PLAYERRECV_H diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index f0d9d5b08..312a95644 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -27,8 +27,11 @@ #include "gui/windows/statuswindow.h" +#include "net/ea/playerrecv.h" + #include "net/tmwa/inventoryhandler.h" #include "net/tmwa/messageout.h" +#include "net/tmwa/playerrecv.h" #include "net/tmwa/protocol.h" #include "debug.h" @@ -67,44 +70,44 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) switch (msg.getId()) { case SMSG_WALK_RESPONSE: - processWalkResponse(msg); + PlayerRecv::processWalkResponse(msg); break; case SMSG_PLAYER_WARP: - processPlayerWarp(msg); + Ea::PlayerRecv::processPlayerWarp(msg); break; case SMSG_PLAYER_STAT_UPDATE_1: - processPlayerStatUpdate1(msg); + Ea::PlayerRecv::processPlayerStatUpdate1(msg); break; case SMSG_PLAYER_STAT_UPDATE_2: - processPlayerStatUpdate2(msg); + Ea::PlayerRecv::processPlayerStatUpdate2(msg); break; case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute - processPlayerStatUpdate3(msg); + Ea::PlayerRecv::processPlayerStatUpdate3(msg); break; case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack - processPlayerStatUpdate4(msg); + Ea::PlayerRecv::processPlayerStatUpdate4(msg); break; // Updates stats and status points case SMSG_PLAYER_STAT_UPDATE_5: - processPlayerStatUpdate5(msg); + PlayerRecv::processPlayerStatUpdate5(msg); break; case SMSG_PLAYER_STAT_UPDATE_6: - processPlayerStatUpdate6(msg); + Ea::PlayerRecv::processPlayerStatUpdate6(msg); break; case SMSG_PLAYER_ARROW_MESSAGE: - processPlayerArrowMessage(msg); + Ea::PlayerRecv::processPlayerArrowMessage(msg); break; case SMSG_MAP_MUSIC: - processMapMusic(msg); + Ea::PlayerRecv::processMapMusic(msg); break; default: @@ -235,133 +238,6 @@ void PlayerHandler::updateStatus(const uint8_t status A_UNUSED) const { } -void PlayerHandler::processPlayerStatUpdate5(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processPlayerStatUpdate5") - PlayerInfo::setAttribute(Attributes::CHAR_POINTS, - msg.readInt16("char points")); - - unsigned int val = msg.readUInt8("str"); - PlayerInfo::setStatBase(Attributes::STR, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::STR, - msg.readUInt8("str cost")); - } - else - { - msg.readUInt8("str cost"); - } - - val = msg.readUInt8("agi"); - PlayerInfo::setStatBase(Attributes::AGI, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::AGI, - msg.readUInt8("agi cost")); - } - else - { - msg.readUInt8("agi cost"); - } - - val = msg.readUInt8("vit"); - PlayerInfo::setStatBase(Attributes::VIT, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::VIT, - msg.readUInt8("vit cost")); - } - else - { - msg.readUInt8("vit cost"); - } - - val = msg.readUInt8("int"); - PlayerInfo::setStatBase(Attributes::INT, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::INT, - msg.readUInt8("int cost")); - } - else - { - msg.readUInt8("int cost"); - } - - val = msg.readUInt8("dex"); - PlayerInfo::setStatBase(Attributes::DEX, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::DEX, - msg.readUInt8("dex cost")); - } - else - { - msg.readUInt8("dex cost"); - } - - val = msg.readUInt8("luk"); - PlayerInfo::setStatBase(Attributes::LUK, val); - if (statusWindow) - { - statusWindow->setPointsNeeded(Attributes::LUK, - msg.readUInt8("luk cost")); - } - else - { - msg.readUInt8("luk cost"); - } - - PlayerInfo::setStatBase(Attributes::ATK, - msg.readInt16("atk"), Notify_false); - PlayerInfo::setStatMod(Attributes::ATK, msg.readInt16("atk+")); - PlayerInfo::updateAttrs(); - - val = msg.readInt16("matk"); - PlayerInfo::setStatBase(Attributes::MATK, val, Notify_false); - - val = msg.readInt16("matk+"); - PlayerInfo::setStatMod(Attributes::MATK, val); - - PlayerInfo::setStatBase(Attributes::DEF, - msg.readInt16("def"), Notify_false); - PlayerInfo::setStatMod(Attributes::DEF, msg.readInt16("def+")); - - PlayerInfo::setStatBase(Attributes::MDEF, - msg.readInt16("mdef"), Notify_false); - PlayerInfo::setStatMod(Attributes::MDEF, msg.readInt16("mdef+")); - - PlayerInfo::setStatBase(Attributes::HIT, msg.readInt16("hit")); - - PlayerInfo::setStatBase(Attributes::FLEE, - msg.readInt16("flee"), Notify_false); - PlayerInfo::setStatMod(Attributes::FLEE, msg.readInt16("flee+")); - - PlayerInfo::setStatBase(Attributes::CRIT, msg.readInt16("crit")); - - PlayerInfo::setStatBase(Attributes::MANNER, msg.readInt16("manner")); - msg.readInt16("unused?"); - BLOCK_END("PlayerHandler::processPlayerStatUpdate5") -} - -void PlayerHandler::processWalkResponse(Net::MessageIn &msg) -{ - BLOCK_START("PlayerHandler::processWalkResponse") - /* - * This client assumes that all walk messages succeed, - * and that the server will send a correction notice - * otherwise. - */ - uint16_t srcX, srcY, dstX, dstY; - msg.readInt32("tick"); - msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path"); - msg.readUInt8("unused"); - if (localPlayer) - localPlayer->setRealPos(dstX, dstY); - BLOCK_END("PlayerHandler::processWalkResponse") -} - void PlayerHandler::setShortcut(const int idx A_UNUSED, const uint8_t type A_UNUSED, const int id A_UNUSED, diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index f4e9e1e44..5af3e9676 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -79,16 +79,11 @@ class PlayerHandler final : public MessageHandler, public Ea::PlayerHandler void setViewEquipment(const bool allow) const override final; - protected: void setStat(Net::MessageIn &msg, const int type, const int base, const int mod, const Notify notify) const override final; - - static void processPlayerStatUpdate5(Net::MessageIn &msg); - - static void processWalkResponse(Net::MessageIn &msg); }; } // namespace TmwAthena diff --git a/src/net/tmwa/playerrecv.cpp b/src/net/tmwa/playerrecv.cpp new file mode 100644 index 000000000..88d2062bb --- /dev/null +++ b/src/net/tmwa/playerrecv.cpp @@ -0,0 +1,166 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2015 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "net/tmwa/playerrecv.h" + +#include "being/localplayer.h" +#include "being/playerinfo.h" + +#include "gui/windows/statuswindow.h" + +#include "net/tmwa/inventoryhandler.h" +#include "net/tmwa/messageout.h" +#include "net/tmwa/protocol.h" + +#include "debug.h" + +namespace TmwAthena +{ + +void PlayerRecv::processPlayerStatUpdate5(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processPlayerStatUpdate5") + PlayerInfo::setAttribute(Attributes::CHAR_POINTS, + msg.readInt16("char points")); + + unsigned int val = msg.readUInt8("str"); + PlayerInfo::setStatBase(Attributes::STR, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::STR, + msg.readUInt8("str cost")); + } + else + { + msg.readUInt8("str cost"); + } + + val = msg.readUInt8("agi"); + PlayerInfo::setStatBase(Attributes::AGI, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::AGI, + msg.readUInt8("agi cost")); + } + else + { + msg.readUInt8("agi cost"); + } + + val = msg.readUInt8("vit"); + PlayerInfo::setStatBase(Attributes::VIT, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::VIT, + msg.readUInt8("vit cost")); + } + else + { + msg.readUInt8("vit cost"); + } + + val = msg.readUInt8("int"); + PlayerInfo::setStatBase(Attributes::INT, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::INT, + msg.readUInt8("int cost")); + } + else + { + msg.readUInt8("int cost"); + } + + val = msg.readUInt8("dex"); + PlayerInfo::setStatBase(Attributes::DEX, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::DEX, + msg.readUInt8("dex cost")); + } + else + { + msg.readUInt8("dex cost"); + } + + val = msg.readUInt8("luk"); + PlayerInfo::setStatBase(Attributes::LUK, val); + if (statusWindow) + { + statusWindow->setPointsNeeded(Attributes::LUK, + msg.readUInt8("luk cost")); + } + else + { + msg.readUInt8("luk cost"); + } + + PlayerInfo::setStatBase(Attributes::ATK, + msg.readInt16("atk"), Notify_false); + PlayerInfo::setStatMod(Attributes::ATK, msg.readInt16("atk+")); + PlayerInfo::updateAttrs(); + + val = msg.readInt16("matk"); + PlayerInfo::setStatBase(Attributes::MATK, val, Notify_false); + + val = msg.readInt16("matk+"); + PlayerInfo::setStatMod(Attributes::MATK, val); + + PlayerInfo::setStatBase(Attributes::DEF, + msg.readInt16("def"), Notify_false); + PlayerInfo::setStatMod(Attributes::DEF, msg.readInt16("def+")); + + PlayerInfo::setStatBase(Attributes::MDEF, + msg.readInt16("mdef"), Notify_false); + PlayerInfo::setStatMod(Attributes::MDEF, msg.readInt16("mdef+")); + + PlayerInfo::setStatBase(Attributes::HIT, msg.readInt16("hit")); + + PlayerInfo::setStatBase(Attributes::FLEE, + msg.readInt16("flee"), Notify_false); + PlayerInfo::setStatMod(Attributes::FLEE, msg.readInt16("flee+")); + + PlayerInfo::setStatBase(Attributes::CRIT, msg.readInt16("crit")); + + PlayerInfo::setStatBase(Attributes::MANNER, msg.readInt16("manner")); + msg.readInt16("unused?"); + BLOCK_END("PlayerRecv::processPlayerStatUpdate5") +} + +void PlayerRecv::processWalkResponse(Net::MessageIn &msg) +{ + BLOCK_START("PlayerRecv::processWalkResponse") + /* + * This client assumes that all walk messages succeed, + * and that the server will send a correction notice + * otherwise. + */ + uint16_t srcX, srcY, dstX, dstY; + msg.readInt32("tick"); + msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path"); + msg.readUInt8("unused"); + if (localPlayer) + localPlayer->setRealPos(dstX, dstY); + BLOCK_END("PlayerRecv::processWalkResponse") +} + +} // namespace TmwAthena diff --git a/src/net/tmwa/playerrecv.h b/src/net/tmwa/playerrecv.h new file mode 100644 index 000000000..0fcadb104 --- /dev/null +++ b/src/net/tmwa/playerrecv.h @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2015 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NET_TMWA_PLAYERRECV_H +#define NET_TMWA_PLAYERRECV_H + +#include "net/ea/playerhandler.h" + +#include "net/tmwa/messagehandler.h" + +namespace TmwAthena +{ + namespace PlayerRecv + { + void processPlayerStatUpdate5(Net::MessageIn &msg); + void processWalkResponse(Net::MessageIn &msg); + } // namespace PlayerRecv +} // namespace TmwAthena + +#endif // NET_TMWA_PLAYERRECV_H |