Advertisement
Guest User

protocol

a guest
Feb 20th, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 79.98 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. ////////////////////////////////////////////////////////////////////////
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16. ////////////////////////////////////////////////////////////////////////
  17. #include "otpch.h"
  18. #include <boost/function.hpp>
  19. #include <iostream>
  20. #include <iomanip>
  21.  
  22. #include "protocolgame.h"
  23. #include "textlogger.h"
  24.  
  25. #include "waitlist.h"
  26. #include "player.h"
  27.  
  28. #include "connection.h"
  29. #include "networkmessage.h"
  30. #include "outputmessage.h"
  31.  
  32. #include "iologindata.h"
  33. #include "ioban.h"
  34.  
  35. #include "items.h"
  36. #include "tile.h"
  37. #include "house.h"
  38.  
  39. #include "actions.h"
  40. #include "creatureevent.h"
  41. #include "quests.h"
  42.  
  43. #include "chat.h"
  44. #include "configmanager.h"
  45. #include "game.h"
  46.  
  47. #include "resources.h"
  48.  
  49. #if defined(WINDOWS) && !defined(_CONSOLE)
  50. #include "gui.h"
  51. #endif
  52.  
  53. extern Game g_game;
  54. extern ConfigManager g_config;
  55. extern Actions actions;
  56. extern CreatureEvents* g_creatureEvents;
  57. extern Chat g_chat;
  58.  
  59. template<class FunctionType>
  60. void ProtocolGame::addGameTaskInternal(uint32_t delay, const FunctionType& func)
  61. {
  62.     if(delay > 0)
  63.         Dispatcher::getInstance().addTask(createTask(delay, func));
  64.     else
  65.         Dispatcher::getInstance().addTask(createTask(func));
  66. }
  67.  
  68. #ifdef __ENABLE_SERVER_DIAGNOSTIC__
  69. uint32_t ProtocolGame::protocolGameCount = 0;
  70.  
  71. #endif
  72. void ProtocolGame::setPlayer(Player* p)
  73. {
  74.     player = p;
  75. }
  76.  
  77. void ProtocolGame::releaseProtocol()
  78. {
  79.     if(player && player->client == this)
  80.         player->client = NULL;
  81.  
  82.     Protocol::releaseProtocol();
  83. }
  84.  
  85. void ProtocolGame::deleteProtocolTask()
  86. {
  87.     if(player)
  88.     {
  89.         g_game.freeThing(player);
  90.         player = NULL;
  91.     }
  92.  
  93.     Protocol::deleteProtocolTask();
  94. }
  95.  
  96. bool ProtocolGame::login(const std::string& name, uint32_t id, const std::string&,
  97.     OperatingSystem_t operatingSystem, uint16_t version, bool gamemaster)
  98. {
  99.     //dispatcher thread
  100.     PlayerVector players = g_game.getPlayersByName(name);
  101.     Player* _player = NULL;
  102.     if(!players.empty())
  103.         _player = players[random_range(0, (players.size() - 1))];
  104.  
  105.     bool accountManager = g_config.getBool(ConfigManager::ACCOUNT_MANAGER);
  106.     if(!_player || g_config.getNumber(ConfigManager::ALLOW_CLONES) ||
  107.         (accountManager && name == "Account Manager"))
  108.     {
  109.         player = new Player(name, this);
  110.         player->addRef();
  111.  
  112.         player->setID();
  113.         if(!IOLoginData::getInstance()->loadPlayer(player, name, true))
  114.         {
  115.             disconnectClient(0x14, "Your character could not be loaded.");
  116.             return false;
  117.         }
  118.  
  119.         Ban ban;
  120.         ban.value = player->getGUID();
  121.         ban.param = PLAYERBAN_BANISHMENT;
  122.  
  123.         ban.type = BAN_PLAYER;
  124.         if(IOBan::getInstance()->getData(ban) && !player->hasFlag(PlayerFlag_CannotBeBanned))
  125.         {
  126.             bool deletion = ban.expires < 0;
  127.             std::string name_ = "Automatic ";
  128.             if(!ban.adminId)
  129.                 name_ += (deletion ? "deletion" : "banishment");
  130.             else
  131.                 IOLoginData::getInstance()->getNameByGuid(ban.adminId, name_, true);
  132.  
  133.             std::stringstream stream;
  134.             stream << "Your account has been " << (deletion ? "deleted" : "banished") << " at:\n" << formatDateEx(ban.added, "%d %b %Y").c_str() << " by: " << name_.c_str()
  135.                 << "\nReason:\n" << getReason(ban.reason).c_str() << ".\nComment:\n" << ban.comment.c_str() << ".\nYour " << (deletion ? "account won't be undeleted" : "banishment will be lifted at:\n")
  136.                 << (deletion ? "" : formatDateEx(ban.expires).c_str());
  137.             disconnectClient(0x14, stream.str().c_str());
  138.             return false;
  139.         }
  140.  
  141.         if(IOBan::getInstance()->isPlayerBanished(player->getGUID(), PLAYERBAN_LOCK) && id != 1)
  142.         {
  143.             if(g_config.getBool(ConfigManager::NAMELOCK_MANAGER))
  144.             {
  145.                 player->name = "Account Manager";
  146.                 player->accountManager = MANAGER_NAMELOCK;
  147.  
  148.                 player->managerNumber = id;
  149.                 player->managerString2 = name;
  150.             }
  151.             else
  152.             {
  153.                 disconnectClient(0x14, "Your character has been namelocked.");
  154.                 return false;
  155.             }
  156.         }
  157.         else if(player->getName() == "Account Manager")
  158.         {
  159.             if(!g_config.getBool(ConfigManager::ACCOUNT_MANAGER))
  160.             {
  161.                 disconnectClient(0x14, "Account Manager is disabled.");
  162.                 return false;
  163.             }
  164.  
  165.             if(id != 1)
  166.             {
  167.                 player->accountManager = MANAGER_ACCOUNT;
  168.                 player->managerNumber = id;
  169.             }
  170.             else
  171.                 player->accountManager = MANAGER_NEW;
  172.         }
  173.  
  174.         if(gamemaster && !player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges))
  175.         {
  176.             disconnectClient(0x14, "You are not a gamemaster! Turn off the gamemaster mode in your IP changer.");
  177.             return false;
  178.         }
  179.  
  180.         if(!player->hasFlag(PlayerFlag_CanAlwaysLogin))
  181.         {
  182.             if(g_game.getGameState() == GAMESTATE_CLOSING)
  183.             {
  184.                 disconnectClient(0x14, "Gameworld is just going down, please come back later.");
  185.                 return false;
  186.             }
  187.  
  188.             if(g_game.getGameState() == GAMESTATE_CLOSED)
  189.             {
  190.                 disconnectClient(0x14, "Gameworld is currently closed, please come back later.");
  191.                 return false;
  192.             }
  193.         }
  194.  
  195.         if(g_config.getBool(ConfigManager::ONE_PLAYER_ON_ACCOUNT) && !player->isAccountManager() &&
  196.             !IOLoginData::getInstance()->hasCustomFlag(id, PlayerCustomFlag_CanLoginMultipleCharacters))
  197.         {
  198.             bool found = false;
  199.             PlayerVector tmp = g_game.getPlayersByAccount(id);
  200.             for(PlayerVector::iterator it = tmp.begin(); it != tmp.end(); ++it)
  201.             {
  202.                 if((*it)->getName() != name)
  203.                     continue;
  204.  
  205.                 found = true;
  206.                 break;
  207.             }
  208.  
  209.             if(tmp.size() > 0 && !found)
  210.             {
  211.                 disconnectClient(0x14, "You may only login with one character\nof your account at the same time.");
  212.                 return false;
  213.             }
  214.         }
  215.  
  216.         if(!WaitingList::getInstance()->login(player))
  217.         {
  218.             if(OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false))
  219.             {
  220.                 TRACK_MESSAGE(output);
  221.                 std::stringstream ss;
  222.                 ss << "Too many players online.\n" << "You are ";
  223.  
  224.                 int32_t slot = WaitingList::getInstance()->getSlot(player);
  225.                 if(slot)
  226.                 {
  227.                     ss << "at ";
  228.                     if(slot > 0)
  229.                         ss << slot;
  230.                     else
  231.                         ss << "unknown";
  232.  
  233.                     ss << " place on the waiting list.";
  234.                 }
  235.                 else
  236.                     ss << "awaiting connection...";
  237.  
  238.                 output->put<char>(0x16);
  239.                 output->putString(ss.str());
  240.                 output->put<char>(WaitingList::getTime(slot));
  241.                 OutputMessagePool::getInstance()->send(output);
  242.             }
  243.  
  244.             disconnect();
  245.             return false;
  246.         }
  247.  
  248.         if(!IOLoginData::getInstance()->loadPlayer(player, name))
  249.         {
  250.             disconnectClient(0x14, "Your character could not be loaded.");
  251.             return false;
  252.         }
  253.  
  254.         player->setClientVersion(version);
  255.         player->setOperatingSystem(operatingSystem);
  256.  
  257.         if(player->isUsingOtclient())
  258.         {
  259.             player->registerCreatureEvent("ExtendedOpcode");
  260.         }
  261.  
  262.         player->lastIP = player->getIP();
  263.         player->lastLoad = OTSYS_TIME();
  264.         player->lastLogin = std::max(time(NULL), player->lastLogin + 1);
  265.  
  266.         if(!g_game.placeCreature(player, player->getLoginPosition()) && !g_game.placeCreature(player, player->getMasterPosition(), false, true))
  267.         {
  268.             disconnectClient(0x14, "Temple position is wrong. Contact with the administration.");
  269.             return false;
  270.         }
  271.  
  272.         m_acceptPackets = true;
  273.         return true;
  274.     }
  275.  
  276.     if(gamemaster && !_player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges))
  277.     {
  278.         disconnectClient(0x14, "You are not a gamemaster! Turn off the gamemaster mode in your IP changer.");
  279.         return false;
  280.     }
  281.  
  282.     if(_player->hasClient())
  283.     {
  284.         if(m_eventConnect || !g_config.getBool(ConfigManager::REPLACE_KICK_ON_LOGIN))
  285.         {
  286.             // task has already been scheduled just bail out (should not be overriden)
  287.             disconnectClient(0x14, "You are already logged in.");
  288.             return false;
  289.         }
  290.  
  291.         _player->client->disconnect();
  292.         _player->isConnecting = true;
  293.         _player->setClientVersion(version);
  294.  
  295.         addRef();
  296.         m_eventConnect = Scheduler::getInstance().addEvent(createSchedulerTask(
  297.             1000, boost::bind(&ProtocolGame::connect, this, _player->getID(), operatingSystem, version)));
  298.         return true;
  299.     }
  300.  
  301.     addRef();
  302.     return connect(_player->getID(), operatingSystem, version);
  303. }
  304.  
  305. bool ProtocolGame::logout(bool displayEffect, bool forceLogout)
  306. {
  307.     //dispatcher thread
  308.     if(!player)
  309.         return false;
  310.  
  311.     if(player->hasCondition(CONDITION_EXHAUST, 1))
  312.     {
  313.         player->sendTextMessage(MSG_STATUS_SMALL, "You have to wait a while.");
  314.         return false;
  315.     }
  316.  
  317.     if(!player->isRemoved())
  318.     {
  319.         if(!forceLogout)
  320.         {
  321.             if(!IOLoginData::getInstance()->hasCustomFlag(player->getAccount(), PlayerCustomFlag_CanLogoutAnytime))
  322.             {
  323.                 if(player->getTile()->hasFlag(TILESTATE_NOLOGOUT))
  324.                 {
  325.                     if(Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST, 500, 0, false, 1))
  326.                         player->addCondition(condition);
  327.  
  328.                     player->sendCancelMessage(RET_YOUCANNOTLOGOUTHERE);
  329.                     return false;
  330.                 }
  331.  
  332.                 if(player->getZone() != ZONE_PROTECTION && player->hasCondition(CONDITION_INFIGHT))
  333.                 {
  334.                     if(Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST, 500, 0, false, 1))
  335.                         player->addCondition(condition);
  336.  
  337.                     player->sendCancelMessage(RET_YOUMAYNOTLOGOUTDURINGAFIGHT);
  338.                     return false;
  339.                 }
  340.  
  341.                 if(!g_creatureEvents->playerLogout(player, false)) //let the script handle the error message
  342.                     return false;
  343.             }
  344.             else
  345.                 g_creatureEvents->playerLogout(player, true);
  346.         }
  347.         else if(!g_creatureEvents->playerLogout(player, true))
  348.             return false;
  349.  
  350.         if(displayEffect && !player->isGhost())
  351.             g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  352.     }
  353.  
  354.     disconnect();
  355.     if(player->isRemoved())
  356.         return true;
  357.  
  358.     return g_game.removeCreature(player);
  359. }
  360.  
  361. bool ProtocolGame::connect(uint32_t playerId, OperatingSystem_t operatingSystem, uint16_t version)
  362. {
  363.     unRef();
  364.     m_eventConnect = 0;
  365.  
  366.     Player* _player = g_game.getPlayerByID(playerId);
  367.     if(!_player || _player->isRemoved() || _player->hasClient())
  368.     {
  369.         disconnectClient(0x14, "You are already logged in.");
  370.         return false;
  371.     }
  372.  
  373.     player = _player;
  374.     player->addRef();
  375.     player->client = this;
  376.     player->isConnecting = false;
  377.  
  378.     player->sendCreatureAppear(player);
  379.     player->setOperatingSystem(operatingSystem);
  380.     player->setClientVersion(version);
  381.  
  382.     player->lastIP = player->getIP();
  383.     player->lastLoad = OTSYS_TIME();
  384.  
  385.     g_chat.reOpenChannels(player);
  386.     m_acceptPackets = true;
  387.     return true;
  388. }
  389.  
  390. void ProtocolGame::disconnect()
  391. {
  392.     if(Connection_ptr connection = getConnection())
  393.         connection->close();
  394. }
  395.  
  396. void ProtocolGame::disconnectClient(uint8_t error, const char* message)
  397. {
  398.     OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
  399.     if(!output)
  400.         return;
  401.  
  402.     TRACK_MESSAGE(output);
  403.     output->put<char>(error);
  404.     output->putString(message);
  405.  
  406.     OutputMessagePool::getInstance()->send(output);
  407.     disconnect();
  408. }
  409.  
  410. void ProtocolGame::onConnect()
  411. {
  412.     OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
  413.     if(!output)
  414.         return;
  415.  
  416.     TRACK_MESSAGE(output);
  417.     enableChecksum();
  418.  
  419.     output->put<char>(0x1F);
  420.     output->put<uint16_t>(random_range(0, 0xFFFF));
  421.     output->put<uint16_t>(0x00);
  422.     output->put<char>(random_range(0, 0xFF));
  423.  
  424.     OutputMessagePool::getInstance()->send(output);
  425. }
  426.  
  427. void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
  428. {
  429.     if(
  430. #if defined(WINDOWS) && !defined(_CONSOLE)
  431.         !GUI::getInstance()->m_connections ||
  432. #endif
  433.         g_game.getGameState() == GAMESTATE_SHUTDOWN)
  434.     {
  435.         disconnect();
  436.         return;
  437.     }
  438.  
  439.     OperatingSystem_t operatingSystem = (OperatingSystem_t)msg.get<uint16_t>();
  440.     uint16_t version = msg.get<uint16_t>();
  441.  
  442.     if(!RSA_decrypt(msg))
  443.     {
  444.         disconnect();
  445.         return;
  446.     }
  447.  
  448.     uint32_t key[4] = {msg.get<uint32_t>(), msg.get<uint32_t>(), msg.get<uint32_t>(), msg.get<uint32_t>()};
  449.     enableXTEAEncryption();
  450.  
  451.     setXTEAKey(key);
  452.     if(operatingSystem >= CLIENTOS_OTCLIENT_LINUX)
  453.         sendExtendedOpcode(0x00, std::string());
  454.  
  455.     bool gamemaster = (msg.get<char>() != (char)0);
  456.     std::string name = msg.getString(), character = msg.getString(), password = msg.getString();
  457.  
  458.     msg.skip(6);
  459.     if(!g_config.getBool(ConfigManager::MANUAL_ADVANCED_CONFIG))
  460.     {
  461.         if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX)
  462.         {
  463.             disconnectClient(0x14, CLIENT_VERSION_STRING);
  464.             return;
  465.         }
  466.     else
  467.         if(version < g_config.getNumber(ConfigManager::VERSION_MIN) || version > g_config.getNumber(ConfigManager::VERSION_MAX))
  468.         {
  469.             disconnectClient(0x14, g_config.getString(ConfigManager::VERSION_MSG).c_str());
  470.             return;
  471.         }
  472.     }
  473.  
  474.     if(name.empty())
  475.     {
  476.         if(!g_config.getBool(ConfigManager::ACCOUNT_MANAGER))
  477.         {
  478.             disconnectClient(0x14, "Invalid account name.");
  479.             return;
  480.         }
  481.  
  482.         name = "1";
  483.         password = "1";
  484.     }
  485.  
  486.     if(g_game.getGameState() < GAMESTATE_NORMAL)
  487.     {
  488.         disconnectClient(0x14, "Gameworld is just starting up, please wait.");
  489.         return;
  490.     }
  491.  
  492.     if(g_game.getGameState() == GAMESTATE_MAINTAIN)
  493.     {
  494.         disconnectClient(0x14, "Gameworld is under maintenance, please re-connect in a while.");
  495.         return;
  496.     }
  497.  
  498.     if(ConnectionManager::getInstance()->isDisabled(getIP(), protocolId))
  499.     {
  500.         disconnectClient(0x14, "Too many connections attempts from your IP address, please try again later.");
  501.         return;
  502.     }
  503.  
  504.     if(IOBan::getInstance()->isIpBanished(getIP()))
  505.     {
  506.         disconnectClient(0x14, "Your IP is banished!");
  507.         return;
  508.     }
  509.  
  510.     uint32_t id = 1;
  511.     if(!IOLoginData::getInstance()->getAccountId(name, id))
  512.     {
  513.         ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, false);
  514.         disconnectClient(0x14, "Invalid account name.");
  515.         return;
  516.     }
  517.  
  518.     std::string hash, salt;
  519.     if(!IOLoginData::getInstance()->getPassword(id, hash, salt, character) || !encryptTest(salt + password, hash))
  520.     {
  521.         ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, false);
  522.         disconnectClient(0x14, "Invalid password.");
  523.         return;
  524.     }
  525.  
  526.     Ban ban;
  527.     ban.value = id;
  528.  
  529.     ban.type = BAN_ACCOUNT;
  530.     if(IOBan::getInstance()->getData(ban) && !IOLoginData::getInstance()->hasFlag(id, PlayerFlag_CannotBeBanned))
  531.     {
  532.         bool deletion = ban.expires < 0;
  533.         std::string name_ = "Automatic ";
  534.         if(!ban.adminId)
  535.             name_ += (deletion ? "deletion" : "banishment");
  536.         else
  537.             IOLoginData::getInstance()->getNameByGuid(ban.adminId, name_, true);
  538.  
  539.         std::stringstream stream;
  540.         stream << "Your account has been " << (deletion ? "deleted" : "banished") << " at:\n" << formatDateEx(ban.added, "%d %b %Y").c_str() << " by: " << name_.c_str()
  541.                << ".\nThe comment given was:\n" << ban.comment.c_str() << ".\nYour " << (deletion ? "account won't be undeleted" : "banishment will be lifted at:\n")
  542.                << (deletion ? "" : formatDateEx(ban.expires).c_str()) << ".";
  543.  
  544.         disconnectClient(0x14, stream.str().c_str());
  545.         return;
  546.     }
  547.  
  548.     ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, true);
  549.     Dispatcher::getInstance().addTask(createTask(boost::bind(
  550.         &ProtocolGame::login, this, character, id, password, operatingSystem, version, gamemaster)));
  551. }
  552.  
  553. void ProtocolGame::parsePacket(NetworkMessage &msg)
  554. {
  555.     if(!player || !m_acceptPackets || g_game.getGameState() == GAMESTATE_SHUTDOWN || !msg.size())
  556.         return;
  557.  
  558.     uint32_t now = time(NULL);
  559.     if(m_packetTime != now)
  560.     {
  561.         m_packetTime = now;
  562.         m_packetCount = 0;
  563.     }
  564.  
  565.     ++m_packetCount;
  566.     if(m_packetCount > (uint32_t)g_config.getNumber(ConfigManager::PACKETS_PER_SECOND))
  567.         return;
  568.  
  569.     uint8_t recvbyte = msg.get<char>();
  570.     if(player->isRemoved() && recvbyte != 0x14) //a dead player cannot performs actions
  571.         return;
  572.  
  573.     if(player->isAccountManager())
  574.     {
  575.         switch(recvbyte)
  576.         {
  577.             case 0x14: parseLogout(msg); break;
  578.             case 0x96: parseSay(msg); break;
  579.             case 0x1E: parseReceivePing(msg); break;
  580.             case 0xC9: parseUpdateTile(msg); break;
  581.             case 0xE8: parseDebugAssert(msg); break;
  582.             case 0xA1: parseCancelTarget(msg); break;
  583.  
  584.             default:
  585.                 parseCancelWalk(msg);
  586.             break;
  587.         }
  588.     }
  589.     else
  590.     {
  591.         switch(recvbyte)
  592.         {
  593.             case 0x14: parseLogout(msg); break;
  594.             case 0x1E: parseReceivePing(msg); break;
  595.             case 0x32: parseExtendedOpcode(msg); break;
  596.             case 0x64: parseAutoWalk(msg); break;
  597.             case 0x65:
  598.             case 0x66:
  599.             case 0x67:
  600.             case 0x68: parseMove(msg, (Direction)(recvbyte - 0x65)); break;
  601.             case 0x69: addGameTask(&Game::playerStopAutoWalk, player->getID()); break;
  602.             case 0x6A: parseMove(msg, NORTHEAST); break;
  603.             case 0x6B: parseMove(msg, SOUTHEAST); break;
  604.             case 0x6C: parseMove(msg, SOUTHWEST); break;
  605.             case 0x6D: parseMove(msg, NORTHWEST); break;
  606.             case 0x6F:
  607.             case 0x70:
  608.             case 0x71:
  609.             case 0x72: parseTurn(msg, (Direction)(recvbyte - 0x6F)); break;
  610.             case 0x78: parseThrow(msg); break;
  611.             case 0x79: parseLookInShop(msg); break;
  612.             case 0x7A: parsePlayerPurchase(msg); break;
  613.             case 0x7B: parsePlayerSale(msg); break;
  614.             case 0x7C: parseCloseShop(msg); break;
  615.             case 0x7D: parseRequestTrade(msg); break;
  616.             case 0x7E: parseLookInTrade(msg); break;
  617.             case 0x7F: parseAcceptTrade(msg); break;
  618.             case 0x80: parseCloseTrade(); break;
  619.             case 0x82: parseUseItem(msg); break;
  620.             case 0x83: parseUseItemEx(msg); break;
  621.             case 0x84: parseBattleWindow(msg); break;
  622.             case 0x85: parseRotateItem(msg); break;
  623.             case 0x87: parseCloseContainer(msg); break;
  624.             case 0x88: parseUpArrowContainer(msg); break;
  625.             case 0x89: parseTextWindow(msg); break;
  626.             case 0x8A: parseHouseWindow(msg); break;
  627.             case 0x8C: parseLookAt(msg); break;
  628.             case 0x8D: parseLookInBattleList(msg); break;
  629.             case 0x96: parseSay(msg); break;
  630.             case 0x97: parseGetChannels(msg); break;
  631.             case 0x98: parseOpenChannel(msg); break;
  632.             case 0x99: parseCloseChannel(msg); break;
  633.             case 0x9A: parseOpenPrivate(msg); break;
  634.             case 0x9E: parseCloseNpc(msg); break;
  635.             case 0x9B: parseProcessRuleViolation(msg); break;
  636.             case 0x9C: parseCloseRuleViolation(msg); break;
  637.             case 0x9D: parseCancelRuleViolation(msg); break;
  638.             case 0xA0: parseFightModes(msg); break;
  639.             case 0xA1: parseAttack(msg); break;
  640.             case 0xA2: parseFollow(msg); break;
  641.             case 0xA3: parseInviteToParty(msg); break;
  642.             case 0xA4: parseJoinParty(msg); break;
  643.             case 0xA5: parseRevokePartyInvite(msg); break;
  644.             case 0xA6: parsePassPartyLeadership(msg); break;
  645.             case 0xA7: parseLeaveParty(msg); break;
  646.             case 0xA8: parseSharePartyExperience(msg); break;
  647.             case 0xAA: parseCreatePrivateChannel(msg); break;
  648.             case 0xAB: parseChannelInvite(msg); break;
  649.             case 0xAC: parseChannelExclude(msg); break;
  650.             case 0xBE: parseCancelMove(msg); break;
  651.             case 0xC9: parseUpdateTile(msg); break;
  652.             case 0xCA: parseUpdateContainer(msg); break;
  653.             case 0xD2:
  654.                 if((!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || !g_config.getBool(
  655.                     ConfigManager::DISABLE_OUTFITS_PRIVILEGED)) && (g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT)
  656.                     || g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS) || g_config.getBool(ConfigManager::ALLOW_CHANGEADDONS)))
  657.                     parseRequestOutfit(msg);
  658.                 break;
  659.             case 0xD3:
  660.                 if((!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || !g_config.getBool(ConfigManager::DISABLE_OUTFITS_PRIVILEGED))
  661.                     && (g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS) || g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT)))
  662.                     parseSetOutfit(msg);
  663.                 break;
  664.             case 0xDC: parseAddVip(msg); break;
  665.             case 0xDD: parseRemoveVip(msg); break;
  666.             case 0xE6: parseBugReport(msg); break;
  667.             case 0xE7: parseViolationWindow(msg); break;
  668.             case 0xE8: parseDebugAssert(msg); break;
  669.             case 0xF0: parseQuests(msg); break;
  670.             case 0xF1: parseQuestInfo(msg); break;
  671.             case 0xF2: parseViolationReport(msg); break;
  672.  
  673.             default:
  674.             {
  675.                 std::stringstream s;
  676.                 s << "Sent unknown byte: 0x" << std::hex << (int16_t)recvbyte << std::dec;
  677.                 Logger::getInstance()->eFile("bots/" + player->getName() + ".log", s.str(), true);
  678.                 break;
  679.             }
  680.         }
  681.     }
  682. }
  683.  
  684. void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage_ptr msg)
  685. {
  686.     int32_t count = 0;
  687.     if(tile->ground)
  688.     {
  689.         msg->putItem(tile->ground);
  690.         ++count;
  691.     }
  692.  
  693.     const TileItemVector* items = tile->getItemList();
  694.     const CreatureVector* creatures = tile->getCreatures();
  695.  
  696.     ItemVector::const_iterator it;
  697.     if(items)
  698.     {
  699.         for(it = items->getBeginTopItem(); (it != items->getEndTopItem() && count < 10); ++it, ++count)
  700.             msg->putItem(*it);
  701.     }
  702.  
  703.     if(creatures)
  704.     {
  705.         for(CreatureVector::const_reverse_iterator cit = creatures->rbegin(); (cit != creatures->rend() && count < 10); ++cit)
  706.         {
  707.             if(!player->canSeeCreature(*cit))
  708.                 continue;
  709.  
  710.             bool known;
  711.             uint32_t removedKnown;
  712.             checkCreatureAsKnown((*cit)->getID(), known, removedKnown);
  713.  
  714.             AddCreature(msg, (*cit), known, removedKnown);
  715.             ++count;
  716.         }
  717.     }
  718.  
  719.     if(items)
  720.     {
  721.         for(it = items->getBeginDownItem(); (it != items->getEndDownItem() && count < 10); ++it, ++count)
  722.             msg->putItem(*it);
  723.     }
  724. }
  725.  
  726. void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z,
  727.     int32_t width, int32_t height, NetworkMessage_ptr msg)
  728. {
  729.     int32_t skip = -1, startz, endz, zstep = 0;
  730.     if(z > 7)
  731.     {
  732.         startz = z - 2;
  733.         endz = std::min((int32_t)MAP_MAX_LAYERS - 1, z + 2);
  734.         zstep = 1;
  735.     }
  736.     else
  737.     {
  738.         startz = 7;
  739.         endz = 0;
  740.         zstep = -1;
  741.     }
  742.  
  743.     for(int32_t nz = startz; nz != endz + zstep; nz += zstep)
  744.         GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip);
  745.  
  746.     if(skip >= 0)
  747.     {
  748.         msg->put<char>(skip);
  749.         msg->put<char>(0xFF);
  750.         //cc += skip;
  751.     }
  752. }
  753.  
  754. void ProtocolGame::GetFloorDescription(NetworkMessage_ptr msg, int32_t x, int32_t y, int32_t z,
  755.         int32_t width, int32_t height, int32_t offset, int32_t& skip)
  756. {
  757.     Tile* tile = NULL;
  758.     for(int32_t nx = 0; nx < width; ++nx)
  759.     {
  760.         for(int32_t ny = 0; ny < height; ++ny)
  761.         {
  762.             if((tile = g_game.getTile(Position(x + nx + offset, y + ny + offset, z))))
  763.             {
  764.                 if(skip >= 0)
  765.                 {
  766.                     msg->put<char>(skip);
  767.                     msg->put<char>(0xFF);
  768.                 }
  769.  
  770.                 skip = 0;
  771.                 GetTileDescription(tile, msg);
  772.             }
  773.             else if(++skip == 0xFF)
  774.             {
  775.                 msg->put<char>(0xFF);
  776.                 msg->put<char>(0xFF);
  777.                 skip = -1;
  778.             }
  779.         }
  780.     }
  781. }
  782.  
  783. void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool& known, uint32_t& removedKnown)
  784. {
  785.     // loop through the known creature list and check if the given creature is in
  786.     for(std::list<uint32_t>::iterator it = knownCreatureList.begin(); it != knownCreatureList.end(); ++it)
  787.     {
  788.         if((*it) != id)
  789.             continue;
  790.  
  791.         // know... make the creature even more known...
  792.         knownCreatureList.erase(it);
  793.         knownCreatureList.push_back(id);
  794.  
  795.         known = true;
  796.         return;
  797.     }
  798.  
  799.     // ok, he is unknown...
  800.     known = false;
  801.     // ... but not in future
  802.     knownCreatureList.push_back(id);
  803.     // too many known creatures?
  804.     if(knownCreatureList.size() > 250)
  805.     {
  806.         // lets try to remove one from the end of the list
  807.         Creature* c = NULL;
  808.         for(int32_t n = 0; n < 250; ++n)
  809.         {
  810.             removedKnown = knownCreatureList.front();
  811.             if(!(c = g_game.getCreatureByID(removedKnown)) || !canSee(c))
  812.                 break;
  813.  
  814.             // this creature we can't remove, still in sight, so back to the end
  815.             knownCreatureList.pop_front();
  816.             knownCreatureList.push_back(removedKnown);
  817.         }
  818.  
  819.         // hopefully we found someone to remove :S, we got only 250 tries
  820.         // if not... lets kick some players with debug errors :)
  821.         knownCreatureList.pop_front();
  822.     }
  823.     else // we can cache without problems :)
  824.         removedKnown = 0;
  825. }
  826.  
  827. bool ProtocolGame::canSee(const Creature* c) const
  828. {
  829.     return !c->isRemoved() && player->canSeeCreature(c) && canSee(c->getPosition());
  830. }
  831.  
  832. bool ProtocolGame::canSee(const Position& pos) const
  833. {
  834.     return canSee(pos.x, pos.y, pos.z);
  835. }
  836.  
  837. bool ProtocolGame::canSee(uint16_t x, uint16_t y, uint16_t z) const
  838. {
  839.     const Position& myPos = player->getPosition();
  840.     if(myPos.z <= 7)
  841.     {
  842.         //we are on ground level or above (7 -> 0), view is from 7 -> 0
  843.         if(z > 7)
  844.             return false;
  845.     }
  846.     else if(myPos.z >= 8 && std::abs(myPos.z - z) > 2) //we are underground (8 -> 15), view is +/- 2 from the floor we stand on
  847.         return false;
  848.  
  849.     //negative offset means that the action taken place is on a lower floor than ourself
  850.     int32_t offsetz = myPos.z - z;
  851.     return ((x >= myPos.x - 8 + offsetz) && (x <= myPos.x + 9 + offsetz) &&
  852.         (y >= myPos.y - 6 + offsetz) && (y <= myPos.y + 7 + offsetz));
  853. }
  854.  
  855. //********************** Parse methods *******************************//
  856. void ProtocolGame::parseLogout(NetworkMessage&)
  857. {
  858.     Dispatcher::getInstance().addTask(createTask(boost::bind(&ProtocolGame::logout, this, true, false)));
  859. }
  860.  
  861. void ProtocolGame::parseCancelWalk(NetworkMessage&)
  862. {
  863.     Dispatcher::getInstance().addTask(createTask(boost::bind(&ProtocolGame::sendCancelWalk, this)));
  864. }
  865.  
  866. void ProtocolGame::parseCancelTarget(NetworkMessage&)
  867. {
  868.     Dispatcher::getInstance().addTask(createTask(boost::bind(&ProtocolGame::sendCancelTarget, this)));
  869. }
  870.  
  871. void ProtocolGame::parseCreatePrivateChannel(NetworkMessage&)
  872. {
  873.     addGameTask(&Game::playerCreatePrivateChannel, player->getID());
  874. }
  875.  
  876. void ProtocolGame::parseChannelInvite(NetworkMessage& msg)
  877. {
  878.     const std::string name = msg.getString();
  879.     addGameTask(&Game::playerChannelInvite, player->getID(), name);
  880. }
  881.  
  882. void ProtocolGame::parseChannelExclude(NetworkMessage& msg)
  883. {
  884.     const std::string name = msg.getString();
  885.     addGameTask(&Game::playerChannelExclude, player->getID(), name);
  886. }
  887.  
  888. void ProtocolGame::parseGetChannels(NetworkMessage&)
  889. {
  890.     addGameTask(&Game::playerRequestChannels, player->getID());
  891. }
  892.  
  893. void ProtocolGame::parseOpenChannel(NetworkMessage& msg)
  894. {
  895.     uint16_t channelId = msg.get<uint16_t>();
  896.     addGameTask(&Game::playerOpenChannel, player->getID(), channelId);
  897. }
  898.  
  899. void ProtocolGame::parseCloseChannel(NetworkMessage& msg)
  900. {
  901.     uint16_t channelId = msg.get<uint16_t>();
  902.     addGameTask(&Game::playerCloseChannel, player->getID(), channelId);
  903. }
  904.  
  905. void ProtocolGame::parseOpenPrivate(NetworkMessage& msg)
  906. {
  907.     const std::string receiver = msg.getString();
  908.     addGameTask(&Game::playerOpenPrivateChannel, player->getID(), receiver);
  909. }
  910.  
  911. void ProtocolGame::parseCloseNpc(NetworkMessage&)
  912. {
  913.     addGameTask(&Game::playerCloseNpcChannel, player->getID());
  914. }
  915.  
  916. void ProtocolGame::parseProcessRuleViolation(NetworkMessage& msg)
  917. {
  918.     const std::string reporter = msg.getString();
  919.     addGameTask(&Game::playerProcessRuleViolation, player->getID(), reporter);
  920. }
  921.  
  922. void ProtocolGame::parseCloseRuleViolation(NetworkMessage& msg)
  923. {
  924.     const std::string reporter = msg.getString();
  925.     addGameTask(&Game::playerCloseRuleViolation, player->getID(), reporter);
  926. }
  927.  
  928. void ProtocolGame::parseCancelRuleViolation(NetworkMessage&)
  929. {
  930.     addGameTask(&Game::playerCancelRuleViolation, player->getID());
  931. }
  932.  
  933. void ProtocolGame::parseViolationWindow(NetworkMessage& msg)
  934. {
  935.     std::string target = msg.getString();
  936.     uint8_t reason = msg.get<char>();
  937.     ViolationAction_t action = (ViolationAction_t)msg.get<char>();
  938.     std::string comment = msg.getString();
  939.     std::string statement = msg.getString();
  940.     uint32_t statementId = (uint32_t)msg.get<uint16_t>();
  941.     bool ipBanishment = (msg.get<char>() == 0x01);
  942.     addGameTask(&Game::playerViolationWindow, player->getID(), target,
  943.         reason, action, comment, statement, statementId, ipBanishment);
  944. }
  945.  
  946. void ProtocolGame::parseCancelMove(NetworkMessage&)
  947. {
  948.     addGameTask(&Game::playerCancelAttackAndFollow, player->getID());
  949. }
  950.  
  951. void ProtocolGame::parseReceivePing(NetworkMessage&)
  952. {
  953.     addGameTask(&Game::playerReceivePing, player->getID());
  954. }
  955.  
  956. void ProtocolGame::parseAutoWalk(NetworkMessage& msg)
  957. {
  958.     uint8_t dirCount = msg.get<char>();
  959.     if(dirCount > 128) //client limit
  960.     {
  961.         for(uint8_t i = 0; i < dirCount; ++i)
  962.             msg.get<char>();
  963.  
  964.         std::stringstream s;
  965.         s << "Attempt to auto walk for " << (uint16_t)dirCount << " steps - client is limited to 128 steps.";
  966.         Logger::getInstance()->eFile("bots/" + player->getName() + ".log", s.str(), true);
  967.         return;
  968.     }
  969.  
  970.     std::list<Direction> path;
  971.     for(uint8_t i = 0; i < dirCount; ++i)
  972.     {
  973.         Direction dir = SOUTH;
  974.         switch(msg.get<char>())
  975.         {
  976.             case 1:
  977.                 dir = EAST;
  978.                 break;
  979.             case 2:
  980.                 dir = NORTHEAST;
  981.                 break;
  982.             case 3:
  983.                 dir = NORTH;
  984.                 break;
  985.             case 4:
  986.                 dir = NORTHWEST;
  987.                 break;
  988.             case 5:
  989.                 dir = WEST;
  990.                 break;
  991.             case 6:
  992.                 dir = SOUTHWEST;
  993.                 break;
  994.             case 7:
  995.                 dir = SOUTH;
  996.                 break;
  997.             case 8:
  998.                 dir = SOUTHEAST;
  999.                 break;
  1000.             default:
  1001.                 continue;
  1002.         }
  1003.  
  1004.         path.push_back(dir);
  1005.     }
  1006.  
  1007.     addGameTask(&Game::playerAutoWalk, player->getID(), path);
  1008. }
  1009.  
  1010. void ProtocolGame::parseMove(NetworkMessage&, Direction dir)
  1011. {
  1012.     addGameTask(&Game::playerMove, player->getID(), dir);
  1013. }
  1014.  
  1015. void ProtocolGame::parseTurn(NetworkMessage&, Direction dir)
  1016. {
  1017.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), dir);
  1018. }
  1019.  
  1020. void ProtocolGame::parseRequestOutfit(NetworkMessage&)
  1021. {
  1022.     addGameTask(&Game::playerRequestOutfit, player->getID());
  1023. }
  1024.  
  1025. void ProtocolGame::parseSetOutfit(NetworkMessage& msg)
  1026. {
  1027.     Outfit_t newOutfit = player->defaultOutfit;
  1028.     if(g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT))
  1029.         newOutfit.lookType = msg.get<uint16_t>();
  1030.     else
  1031.         msg.skip(2);
  1032.  
  1033.     if(g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS))
  1034.     {
  1035.         newOutfit.lookHead = msg.get<char>();
  1036.         newOutfit.lookBody = msg.get<char>();
  1037.         newOutfit.lookLegs = msg.get<char>();
  1038.         newOutfit.lookFeet = msg.get<char>();
  1039.     }
  1040.     else
  1041.         msg.skip(4);
  1042.  
  1043.     if(g_config.getBool(ConfigManager::ALLOW_CHANGEADDONS))
  1044.         newOutfit.lookAddons = msg.get<char>();
  1045.     else
  1046.         msg.skip(1);
  1047.  
  1048.     addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit);
  1049. }
  1050.  
  1051. void ProtocolGame::parseUseItem(NetworkMessage& msg)
  1052. {
  1053.     Position pos = msg.getPosition();
  1054.     uint16_t spriteId = msg.get<uint16_t>();
  1055.     int16_t stackpos = msg.get<char>();
  1056.     uint8_t index = msg.get<char>();
  1057.     bool isHotkey = (pos.x == 0xFFFF && !pos.y && !pos.z);
  1058.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItem, player->getID(), pos, stackpos, index, spriteId, isHotkey);
  1059. }
  1060.  
  1061. void ProtocolGame::parseUseItemEx(NetworkMessage& msg)
  1062. {
  1063.     Position fromPos = msg.getPosition();
  1064.     uint16_t fromSpriteId = msg.get<uint16_t>();
  1065.     int16_t fromStackpos = msg.get<char>();
  1066.     Position toPos = msg.getPosition();
  1067.     uint16_t toSpriteId = msg.get<uint16_t>();
  1068.     int16_t toStackpos = msg.get<char>();
  1069.     bool isHotkey = (fromPos.x == 0xFFFF && !fromPos.y && !fromPos.z);
  1070.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItemEx, player->getID(),
  1071.         fromPos, fromStackpos, fromSpriteId, toPos, toStackpos, toSpriteId, isHotkey);
  1072. }
  1073.  
  1074. void ProtocolGame::parseBattleWindow(NetworkMessage& msg)
  1075. {
  1076.     Position fromPos = msg.getPosition();
  1077.     uint16_t spriteId = msg.get<uint16_t>();
  1078.     int16_t fromStackpos = msg.get<char>();
  1079.     uint32_t creatureId = msg.get<uint32_t>();
  1080.     bool isHotkey = (fromPos.x == 0xFFFF && !fromPos.y && !fromPos.z);
  1081.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseBattleWindow, player->getID(), fromPos, fromStackpos, creatureId, spriteId, isHotkey);
  1082. }
  1083.  
  1084. void ProtocolGame::parseCloseContainer(NetworkMessage& msg)
  1085. {
  1086.     uint8_t cid = msg.get<char>();
  1087.     addGameTask(&Game::playerCloseContainer, player->getID(), cid);
  1088. }
  1089.  
  1090. void ProtocolGame::parseUpArrowContainer(NetworkMessage& msg)
  1091. {
  1092.     uint8_t cid = msg.get<char>();
  1093.     addGameTask(&Game::playerMoveUpContainer, player->getID(), cid);
  1094. }
  1095.  
  1096. void ProtocolGame::parseUpdateTile(NetworkMessage& msg)
  1097. {
  1098.     Position pos = msg.getPosition();
  1099.     addGameTask(&Game::playerUpdateTile, player->getID(), pos);
  1100. }
  1101.  
  1102. void ProtocolGame::parseUpdateContainer(NetworkMessage& msg)
  1103. {
  1104.     uint8_t cid = msg.get<char>();
  1105.     addGameTask(&Game::playerUpdateContainer, player->getID(), cid);
  1106. }
  1107.  
  1108. void ProtocolGame::parseThrow(NetworkMessage& msg)
  1109. {
  1110.     Position fromPos = msg.getPosition();
  1111.     uint16_t spriteId = msg.get<uint16_t>();
  1112.     int16_t fromStackpos = msg.get<char>();
  1113.     Position toPos = msg.getPosition();
  1114.     uint8_t count = msg.get<char>();
  1115.     if(toPos != fromPos)
  1116.         addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerMoveThing,
  1117.             player->getID(), fromPos, spriteId, fromStackpos, toPos, count);
  1118. }
  1119.  
  1120. void ProtocolGame::parseLookAt(NetworkMessage& msg)
  1121. {
  1122.     Position pos = msg.getPosition();
  1123.     uint16_t spriteId = msg.get<uint16_t>();
  1124.     int16_t stackpos = msg.get<char>();
  1125.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookAt, player->getID(), pos, spriteId, stackpos);
  1126. }
  1127.  
  1128. void ProtocolGame::parseLookInBattleList(NetworkMessage& msg)
  1129. {
  1130.     uint32_t creatureId = msg.get<uint32_t>();
  1131.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInBattleList, player->getID(), creatureId);
  1132. }
  1133.  
  1134. void ProtocolGame::parseSay(NetworkMessage& msg)
  1135. {
  1136.     std::string receiver;
  1137.     uint16_t channelId = 0;
  1138.  
  1139.     MessageClasses type = (MessageClasses)msg.get<char>();
  1140.     switch(type)
  1141.     {
  1142.         case MSG_PRIVATE:
  1143.         case MSG_GAMEMASTER_PRIVATE:
  1144.         case MSG_RVR_ANSWER:
  1145.             receiver = msg.getString();
  1146.             break;
  1147.  
  1148.         case MSG_CHANNEL:
  1149.         case MSG_CHANNEL_HIGHLIGHT:
  1150.         case MSG_GAMEMASTER_CHANNEL:
  1151.         case MSG_GAMEMASTER_ANONYMOUS:
  1152.             channelId = msg.get<uint16_t>();
  1153.             break;
  1154.  
  1155.         default:
  1156.             break;
  1157.     }
  1158.  
  1159.     const std::string text = msg.getString();
  1160.     if(text.length() > 255) //client limit
  1161.     {
  1162.         std::stringstream s;
  1163.         s << "Attempt to send message with size " << text.length() << " - client is limited to 255 characters.";
  1164.         Logger::getInstance()->eFile("bots/" + player->getName() + ".log", s.str(), true);
  1165.         return;
  1166.     }
  1167.  
  1168.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSay, player->getID(), channelId, type, receiver, text);
  1169. }
  1170.  
  1171. void ProtocolGame::parseFightModes(NetworkMessage& msg)
  1172. {
  1173.     uint8_t rawFightMode = msg.get<char>(); //1 - offensive, 2 - balanced, 3 - defensive
  1174.     uint8_t rawChaseMode = msg.get<char>(); //0 - stand while fightning, 1 - chase opponent
  1175.     uint8_t rawSecureMode = msg.get<char>(); //0 - can't attack unmarked, 1 - can attack unmarked
  1176.  
  1177.     chaseMode_t chaseMode = CHASEMODE_STANDSTILL;
  1178.     if(rawChaseMode == 1)
  1179.         chaseMode = CHASEMODE_FOLLOW;
  1180.  
  1181.     fightMode_t fightMode = FIGHTMODE_ATTACK;
  1182.     if(rawFightMode == 2)
  1183.         fightMode = FIGHTMODE_BALANCED;
  1184.     else if(rawFightMode == 3)
  1185.         fightMode = FIGHTMODE_DEFENSE;
  1186.  
  1187.     secureMode_t secureMode = SECUREMODE_OFF;
  1188.     if(rawSecureMode == 1)
  1189.         secureMode = SECUREMODE_ON;
  1190.  
  1191.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSetFightModes, player->getID(), fightMode, chaseMode, secureMode);
  1192. }
  1193.  
  1194. void ProtocolGame::parseAttack(NetworkMessage& msg)
  1195. {
  1196.     uint32_t creatureId = msg.get<uint32_t>();
  1197.     // msg.get<uint32_t>(); creatureId (same as above)
  1198.     addGameTask(&Game::playerSetAttackedCreature, player->getID(), creatureId);
  1199. }
  1200.  
  1201. void ProtocolGame::parseFollow(NetworkMessage& msg)
  1202. {
  1203.     uint32_t creatureId = msg.get<uint32_t>();
  1204.     // msg.get<uint32_t>(); creatureId (same as above)
  1205.     addGameTask(&Game::playerFollowCreature, player->getID(), creatureId);
  1206. }
  1207.  
  1208. void ProtocolGame::parseTextWindow(NetworkMessage& msg)
  1209. {
  1210.     uint32_t windowTextId = msg.get<uint32_t>();
  1211.     const std::string newText = msg.getString();
  1212.     addGameTask(&Game::playerWriteItem, player->getID(), windowTextId, newText);
  1213. }
  1214.  
  1215. void ProtocolGame::parseHouseWindow(NetworkMessage &msg)
  1216. {
  1217.     uint8_t doorId = msg.get<char>();
  1218.     uint32_t id = msg.get<uint32_t>();
  1219.     const std::string text = msg.getString();
  1220.     addGameTask(&Game::playerUpdateHouseWindow, player->getID(), doorId, id, text);
  1221. }
  1222.  
  1223. void ProtocolGame::parseLookInShop(NetworkMessage &msg)
  1224. {
  1225.     uint16_t id = msg.get<uint16_t>();
  1226.     uint8_t count = msg.get<char>();
  1227.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInShop, player->getID(), id, count);
  1228. }
  1229.  
  1230. void ProtocolGame::parsePlayerPurchase(NetworkMessage &msg)
  1231. {
  1232.     uint16_t id = msg.get<uint16_t>();
  1233.     uint16_t count = msg.get<char>();
  1234.     uint16_t amount = msg.get<char>();
  1235.     bool ignoreCap = (msg.get<char>() != (char)0);
  1236.     bool inBackpacks = (msg.get<char>() != (char)0);
  1237.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerPurchaseItem, player->getID(), id, count, amount, ignoreCap, inBackpacks);
  1238. }
  1239.  
  1240. void ProtocolGame::parsePlayerSale(NetworkMessage &msg)
  1241. {
  1242.     uint16_t id = msg.get<uint16_t>();
  1243.     uint16_t count = msg.get<char>();
  1244.     uint16_t amount = msg.get<char>();
  1245.     bool ignoreEquipped = (msg.get<char>() != (char)0);
  1246.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSellItem, player->getID(), id, count, amount, ignoreEquipped);
  1247. }
  1248.  
  1249. void ProtocolGame::parseCloseShop(NetworkMessage&)
  1250. {
  1251.     addGameTask(&Game::playerCloseShop, player->getID());
  1252. }
  1253.  
  1254. void ProtocolGame::parseRequestTrade(NetworkMessage& msg)
  1255. {
  1256.     Position pos = msg.getPosition();
  1257.     uint16_t spriteId = msg.get<uint16_t>();
  1258.     int16_t stackpos = msg.get<char>();
  1259.     uint32_t playerId = msg.get<uint32_t>();
  1260.     addGameTask(&Game::playerRequestTrade, player->getID(), pos, stackpos, playerId, spriteId);
  1261. }
  1262.  
  1263. void ProtocolGame::parseAcceptTrade(NetworkMessage&)
  1264. {
  1265.     addGameTask(&Game::playerAcceptTrade, player->getID());
  1266. }
  1267.  
  1268. void ProtocolGame::parseLookInTrade(NetworkMessage& msg)
  1269. {
  1270.     bool counter = (msg.get<char>() != (char)0);
  1271.     int32_t index = msg.get<char>();
  1272.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInTrade, player->getID(), counter, index);
  1273. }
  1274.  
  1275. void ProtocolGame::parseCloseTrade()
  1276. {
  1277.     addGameTask(&Game::playerCloseTrade, player->getID());
  1278. }
  1279.  
  1280. void ProtocolGame::parseAddVip(NetworkMessage& msg)
  1281. {
  1282.     const std::string name = msg.getString();
  1283.     if(name.size() > 30)
  1284.         return;
  1285.  
  1286.     addGameTask(&Game::playerRequestAddVip, player->getID(), name);
  1287. }
  1288.  
  1289. void ProtocolGame::parseRemoveVip(NetworkMessage& msg)
  1290. {
  1291.     uint32_t guid = msg.get<uint32_t>();
  1292.     addGameTask(&Game::playerRequestRemoveVip, player->getID(), guid);
  1293. }
  1294.  
  1295. void ProtocolGame::parseRotateItem(NetworkMessage& msg)
  1296. {
  1297.     Position pos = msg.getPosition();
  1298.     uint16_t spriteId = msg.get<uint16_t>();
  1299.     int16_t stackpos = msg.get<char>();
  1300.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerRotateItem, player->getID(), pos, stackpos, spriteId);
  1301. }
  1302.  
  1303. void ProtocolGame::parseDebugAssert(NetworkMessage& msg)
  1304. {
  1305.     if(m_debugAssertSent)
  1306.         return;
  1307.  
  1308.     std::stringstream s;
  1309.     s << "----- " << formatDate() << " - " << player->getName() << " (" << convertIPAddress(getIP())
  1310.         << ") -----" << std::endl
  1311.         << msg.getString() << std::endl
  1312.         << msg.getString() << std::endl
  1313.         << msg.getString() << std::endl
  1314.         << msg.getString() << std::endl
  1315.         << std::endl;
  1316.  
  1317.     m_debugAssertSent = true;
  1318.     Logger::getInstance()->iFile(LOGFILE_ASSERTIONS, s.str(), false);
  1319. }
  1320.  
  1321. void ProtocolGame::parseBugReport(NetworkMessage& msg)
  1322. {
  1323.     std::string comment = msg.getString();
  1324.     addGameTask(&Game::playerReportBug, player->getID(), comment);
  1325. }
  1326.  
  1327. void ProtocolGame::parseInviteToParty(NetworkMessage& msg)
  1328. {
  1329.     uint32_t targetId = msg.get<uint32_t>();
  1330.     addGameTask(&Game::playerInviteToParty, player->getID(), targetId);
  1331. }
  1332.  
  1333. void ProtocolGame::parseJoinParty(NetworkMessage& msg)
  1334. {
  1335.     uint32_t targetId = msg.get<uint32_t>();
  1336.     addGameTask(&Game::playerJoinParty, player->getID(), targetId);
  1337. }
  1338.  
  1339. void ProtocolGame::parseRevokePartyInvite(NetworkMessage& msg)
  1340. {
  1341.     uint32_t targetId = msg.get<uint32_t>();
  1342.     addGameTask(&Game::playerRevokePartyInvitation, player->getID(), targetId);
  1343. }
  1344.  
  1345. void ProtocolGame::parsePassPartyLeadership(NetworkMessage& msg)
  1346. {
  1347.     uint32_t targetId = msg.get<uint32_t>();
  1348.     addGameTask(&Game::playerPassPartyLeadership, player->getID(), targetId);
  1349. }
  1350.  
  1351. void ProtocolGame::parseLeaveParty(NetworkMessage&)
  1352. {
  1353.     addGameTask(&Game::playerLeaveParty, player->getID(), false);
  1354. }
  1355.  
  1356. void ProtocolGame::parseSharePartyExperience(NetworkMessage& msg)
  1357. {
  1358.     bool activate = (msg.get<char>() != (char)0);
  1359.     addGameTask(&Game::playerSharePartyExperience, player->getID(), activate);
  1360. }
  1361.  
  1362. void ProtocolGame::parseQuests(NetworkMessage&)
  1363. {
  1364.     addGameTask(&Game::playerQuests, player->getID());
  1365. }
  1366.  
  1367. void ProtocolGame::parseQuestInfo(NetworkMessage& msg)
  1368. {
  1369.     uint16_t questId = msg.get<uint16_t>();
  1370.     addGameTask(&Game::playerQuestInfo, player->getID(), questId);
  1371. }
  1372.  
  1373. void ProtocolGame::parseViolationReport(NetworkMessage& msg)
  1374. {
  1375.     ReportType_t type = (ReportType_t)msg.get<char>();
  1376.     uint8_t reason = msg.get<char>();
  1377.  
  1378.     std::string name = msg.getString(), comment = msg.getString(), translation = "";
  1379.     if(type != REPORT_BOT)
  1380.         translation = msg.getString();
  1381.  
  1382.     uint32_t statementId = 0;
  1383.     if(type == REPORT_STATEMENT)
  1384.         statementId = msg.get<uint32_t>();
  1385.  
  1386.     addGameTask(&Game::playerReportViolation, player->getID(), type, reason, name, comment, translation, statementId);
  1387. }
  1388.  
  1389. //********************** Send methods *******************************//
  1390. void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver)
  1391. {
  1392.     NetworkMessage_ptr msg = getOutputBuffer();
  1393.     if(!msg)
  1394.         return;
  1395.  
  1396.     TRACK_MESSAGE(msg);
  1397.     msg->put<char>(0xAD);
  1398.     msg->putString(receiver);
  1399. }
  1400.  
  1401. void ProtocolGame::sendCreatureOutfit(const Creature* creature, const Outfit_t& outfit)
  1402. {
  1403.     if(!canSee(creature))
  1404.         return;
  1405.  
  1406.     NetworkMessage_ptr msg = getOutputBuffer();
  1407.     if(!msg)
  1408.         return;
  1409.  
  1410.     TRACK_MESSAGE(msg);
  1411.     msg->put<char>(0x8E);
  1412.     msg->put<uint32_t>(creature->getID());
  1413.     AddCreatureOutfit(msg, creature, outfit);
  1414. }
  1415.  
  1416. void ProtocolGame::sendCreatureLight(const Creature* creature)
  1417. {
  1418.     if(!canSee(creature))
  1419.         return;
  1420.  
  1421.     NetworkMessage_ptr msg = getOutputBuffer();
  1422.     if(!msg)
  1423.         return;
  1424.  
  1425.     TRACK_MESSAGE(msg);
  1426.     AddCreatureLight(msg, creature);
  1427. }
  1428.  
  1429. void ProtocolGame::sendWorldLight(const LightInfo& lightInfo)
  1430. {
  1431.     NetworkMessage_ptr msg = getOutputBuffer();
  1432.     if(!msg)
  1433.         return;
  1434.  
  1435.     TRACK_MESSAGE(msg);
  1436.     AddWorldLight(msg, lightInfo);
  1437. }
  1438.  
  1439. void ProtocolGame::sendCreatureWalkthrough(const Creature* creature, bool walkthrough)
  1440. {
  1441.     if(!canSee(creature))
  1442.         return;
  1443.  
  1444.     NetworkMessage_ptr msg = getOutputBuffer();
  1445.     if(!msg)
  1446.         return;
  1447.  
  1448.     TRACK_MESSAGE(msg);
  1449.     msg->put<char>(0x92);
  1450.     msg->put<uint32_t>(creature->getID());
  1451.     msg->put<char>(!walkthrough);
  1452. }
  1453.  
  1454. void ProtocolGame::sendCreatureShield(const Creature* creature)
  1455. {
  1456.     if(!canSee(creature))
  1457.         return;
  1458.  
  1459.     NetworkMessage_ptr msg = getOutputBuffer();
  1460.     if(!msg)
  1461.         return;
  1462.  
  1463.     TRACK_MESSAGE(msg);
  1464.     msg->put<char>(0x91);
  1465.     msg->put<uint32_t>(creature->getID());
  1466.     msg->put<char>(player->getPartyShield(creature));
  1467. }
  1468.  
  1469. void ProtocolGame::sendCreatureSkull(const Creature* creature)
  1470. {
  1471.     if(!canSee(creature))
  1472.         return;
  1473.  
  1474.     NetworkMessage_ptr msg = getOutputBuffer();
  1475.     if(!msg)
  1476.         return;
  1477.  
  1478.     TRACK_MESSAGE(msg);
  1479.     msg->put<char>(0x90);
  1480.     msg->put<uint32_t>(creature->getID());
  1481.     msg->put<char>(player->getSkullType(creature));
  1482. }
  1483.  
  1484. void ProtocolGame::sendCreatureSquare(const Creature* creature, uint8_t color)
  1485. {
  1486.     if(!canSee(creature))
  1487.         return;
  1488.  
  1489.     NetworkMessage_ptr msg = getOutputBuffer();
  1490.     if(!msg)
  1491.         return;
  1492.  
  1493.     TRACK_MESSAGE(msg);
  1494.     msg->put<char>(0x86);
  1495.     msg->put<uint32_t>(creature->getID());
  1496.     msg->put<char>(color);
  1497. }
  1498.  
  1499. void ProtocolGame::sendTutorial(uint8_t tutorialId)
  1500. {
  1501.     NetworkMessage_ptr msg = getOutputBuffer();
  1502.     if(!msg)
  1503.         return;
  1504.  
  1505.     TRACK_MESSAGE(msg);
  1506.     msg->put<char>(0xDC);
  1507.     msg->put<char>(tutorialId);
  1508. }
  1509.  
  1510. void ProtocolGame::sendAddMarker(const Position& pos, MapMarks_t markType, const std::string& desc)
  1511. {
  1512.     NetworkMessage_ptr msg = getOutputBuffer();
  1513.     if(!msg)
  1514.         return;
  1515.  
  1516.     TRACK_MESSAGE(msg);
  1517.     msg->put<char>(0xDD);
  1518.     msg->putPosition(pos);
  1519.     msg->put<char>(markType);
  1520.     msg->putString(desc);
  1521. }
  1522.  
  1523. void ProtocolGame::sendReLoginWindow()
  1524. {
  1525.     NetworkMessage_ptr msg = getOutputBuffer();
  1526.     if(!msg)
  1527.         return;
  1528.  
  1529.     TRACK_MESSAGE(msg);
  1530.     msg->put<char>(0x28);
  1531. }
  1532.  
  1533. void ProtocolGame::sendStats()
  1534. {
  1535.     NetworkMessage_ptr msg = getOutputBuffer();
  1536.     if(!msg)
  1537.         return;
  1538.  
  1539.     TRACK_MESSAGE(msg);
  1540.     AddPlayerStats(msg);
  1541. }
  1542.  
  1543. void ProtocolGame::sendTextMessage(MessageClasses mClass, const std::string& message)
  1544. {
  1545.     NetworkMessage_ptr msg = getOutputBuffer();
  1546.     if(!msg)
  1547.         return;
  1548.  
  1549.     TRACK_MESSAGE(msg);
  1550.     AddTextMessage(msg, mClass, message);
  1551. }
  1552.  
  1553. void ProtocolGame::sendClosePrivate(uint16_t channelId)
  1554. {
  1555.     NetworkMessage_ptr msg = getOutputBuffer();
  1556.     if(!msg)
  1557.         return;
  1558.  
  1559.     TRACK_MESSAGE(msg);
  1560.     if(channelId == CHANNEL_GUILD || channelId == CHANNEL_PARTY)
  1561.         g_chat.removeUserFromChannel(player, channelId);
  1562.  
  1563.     msg->put<char>(0xB3);
  1564.     msg->put<uint16_t>(channelId);
  1565. }
  1566.  
  1567. void ProtocolGame::sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName)
  1568. {
  1569.     NetworkMessage_ptr msg = getOutputBuffer();
  1570.     if(!msg)
  1571.         return;
  1572.  
  1573.     TRACK_MESSAGE(msg);
  1574.     msg->put<char>(0xB2);
  1575.     msg->put<uint16_t>(channelId);
  1576.     msg->putString(channelName);
  1577. }
  1578.  
  1579. void ProtocolGame::sendChannelsDialog(const ChannelsList& channels)
  1580. {
  1581.     NetworkMessage_ptr msg = getOutputBuffer();
  1582.     if(!msg)
  1583.         return;
  1584.  
  1585.     TRACK_MESSAGE(msg);
  1586.     msg->put<char>(0xAB);
  1587.  
  1588.     msg->put<char>(channels.size());
  1589.     for(ChannelsList::const_iterator it = channels.begin(); it != channels.end(); ++it)
  1590.     {
  1591.         msg->put<uint16_t>(it->first);
  1592.         msg->putString(it->second);
  1593.     }
  1594. }
  1595.  
  1596. void ProtocolGame::sendChannel(uint16_t channelId, const std::string& channelName)
  1597. {
  1598.     NetworkMessage_ptr msg = getOutputBuffer();
  1599.     if(!msg)
  1600.         return;
  1601.  
  1602.     TRACK_MESSAGE(msg);
  1603.     msg->put<char>(0xAC);
  1604.  
  1605.     msg->put<uint16_t>(channelId);
  1606.     msg->putString(channelName);
  1607. }
  1608.  
  1609. void ProtocolGame::sendIcons(int32_t icons)
  1610. {
  1611.     NetworkMessage_ptr msg = getOutputBuffer();
  1612.     if(!msg)
  1613.         return;
  1614.  
  1615.     TRACK_MESSAGE(msg);
  1616.     msg->put<char>(0xA2);
  1617.     msg->put<uint16_t>(icons);
  1618. }
  1619.  
  1620. void ProtocolGame::sendContainer(uint32_t cid, const Container* container, bool hasParent)
  1621. {
  1622.     NetworkMessage_ptr msg = getOutputBuffer();
  1623.     if(!msg)
  1624.         return;
  1625.  
  1626.     TRACK_MESSAGE(msg);
  1627.     msg->put<char>(0x6E);
  1628.     msg->put<char>(cid);
  1629.  
  1630.     msg->putItem(container);
  1631.     msg->putString(container->getName());
  1632.     msg->put<char>(container->capacity());
  1633.  
  1634.     msg->put<char>(hasParent ? 0x01 : 0x00);
  1635.     msg->put<char>(std::min(container->size(), 255U));
  1636.  
  1637.     ItemList::const_iterator cit = container->getItems();
  1638.     for(uint32_t i = 0; cit != container->getEnd() && i < 255; ++cit, ++i)
  1639.         msg->putItem(*cit);
  1640. }
  1641.  
  1642. void ProtocolGame::sendShop(Npc*, const ShopInfoList& shop)
  1643. {
  1644.     NetworkMessage_ptr msg = getOutputBuffer();
  1645.     if(!msg)
  1646.         return;
  1647.  
  1648.     TRACK_MESSAGE(msg);
  1649.     msg->put<char>(0x7A);
  1650.     msg->put<char>(std::min(shop.size(), (size_t)255));
  1651.  
  1652.     ShopInfoList::const_iterator it = shop.begin();
  1653.     for(uint16_t i = 0; it != shop.end() && i < 255; ++it, ++i)
  1654.         AddShopItem(msg, (*it));
  1655. }
  1656.  
  1657. void ProtocolGame::sendCloseShop()
  1658. {
  1659.     NetworkMessage_ptr msg = getOutputBuffer();
  1660.     if(!msg)
  1661.         return;
  1662.  
  1663.     TRACK_MESSAGE(msg);
  1664.     msg->put<char>(0x7C);
  1665. }
  1666.  
  1667. void ProtocolGame::sendGoods(const ShopInfoList& shop)
  1668. {
  1669.     NetworkMessage_ptr msg = getOutputBuffer();
  1670.     if(!msg)
  1671.         return;
  1672.  
  1673.     TRACK_MESSAGE(msg);
  1674.     msg->put<char>(0x7B);
  1675.     msg->put<uint32_t>((uint32_t)g_game.getMoney(player));
  1676.  
  1677.     std::map<uint32_t, uint32_t> goodsMap;
  1678.     if(shop.size() >= 5)
  1679.     {
  1680.         for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit)
  1681.         {
  1682.             if(sit->sellPrice < 0)
  1683.                 continue;
  1684.  
  1685.             int8_t subType = -1;
  1686.             if(sit->subType)
  1687.             {
  1688.                 const ItemType& it = Item::items[sit->itemId];
  1689.                 if(it.hasSubType() && !it.stackable)
  1690.                     subType = sit->subType;
  1691.             }
  1692.  
  1693.             uint32_t count = player->__getItemTypeCount(sit->itemId, subType);
  1694.             if(count > 0)
  1695.                 goodsMap[sit->itemId] = count;
  1696.         }
  1697.     }
  1698.     else
  1699.     {
  1700.         std::map<uint32_t, uint32_t> tmpMap;
  1701.         player->__getAllItemTypeCount(tmpMap);
  1702.         for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit)
  1703.         {
  1704.             if(sit->sellPrice < 0)
  1705.                 continue;
  1706.  
  1707.             int8_t subType = -1;
  1708.             const ItemType& it = Item::items[sit->itemId];
  1709.             if(sit->subType && it.hasSubType() && !it.stackable)
  1710.                 subType = sit->subType;
  1711.  
  1712.             if(subType != -1)
  1713.             {
  1714.                 uint32_t count = subType;
  1715.                 if(!it.isFluidContainer() && !it.isSplash())
  1716.                     count = player->__getItemTypeCount(sit->itemId, subType);
  1717.  
  1718.                 if(count > 0)
  1719.                     goodsMap[sit->itemId] = count;
  1720.                 else
  1721.                     goodsMap[sit->itemId] = 0;
  1722.             }
  1723.             else
  1724.                 goodsMap[sit->itemId] = tmpMap[sit->itemId];
  1725.         }
  1726.     }
  1727.  
  1728.     msg->put<char>(std::min(goodsMap.size(), (size_t)255));
  1729.     std::map<uint32_t, uint32_t>::const_iterator it = goodsMap.begin();
  1730.     for(uint32_t i = 0; it != goodsMap.end() && i < 255; ++it, ++i)
  1731.     {
  1732.         msg->putItemId(it->first);
  1733.         msg->put<char>(std::min(it->second, (uint32_t)255));
  1734.     }
  1735. }
  1736.  
  1737. void ProtocolGame::sendRuleViolationsChannel(uint16_t channelId)
  1738. {
  1739.     NetworkMessage_ptr msg = getOutputBuffer();
  1740.     if(msg)
  1741.     {
  1742.         TRACK_MESSAGE(msg);
  1743.         msg->put<char>(0xAE);
  1744.         msg->put<uint16_t>(channelId);
  1745.         for(RuleViolationsMap::const_iterator it = g_game.getRuleViolations().begin(); it != g_game.getRuleViolations().end(); ++it)
  1746.         {
  1747.             RuleViolation& rvr = *it->second;
  1748.             if(rvr.isOpen && rvr.reporter)
  1749.                 AddCreatureSpeak(msg, rvr.reporter, MSG_RVR_CHANNEL, rvr.text, channelId, NULL, rvr.time);
  1750.         }
  1751.     }
  1752. }
  1753.  
  1754. void ProtocolGame::sendRemoveReport(const std::string& name)
  1755. {
  1756.     NetworkMessage_ptr msg = getOutputBuffer();
  1757.     if(msg)
  1758.     {
  1759.         TRACK_MESSAGE(msg);
  1760.         msg->put<char>(0xAF);
  1761.         msg->putString(name);
  1762.     }
  1763. }
  1764.  
  1765. void ProtocolGame::sendRuleViolationCancel(const std::string& name)
  1766. {
  1767.     NetworkMessage_ptr msg = getOutputBuffer();
  1768.     if(msg)
  1769.     {
  1770.         TRACK_MESSAGE(msg);
  1771.         msg->put<char>(0xB0);
  1772.         msg->putString(name);
  1773.     }
  1774. }
  1775.  
  1776. void ProtocolGame::sendLockRuleViolation()
  1777. {
  1778.     NetworkMessage_ptr msg = getOutputBuffer();
  1779.     if(msg)
  1780.     {
  1781.         TRACK_MESSAGE(msg);
  1782.         msg->put<char>(0xB1);
  1783.     }
  1784. }
  1785.  
  1786. void ProtocolGame::sendTradeItemRequest(const Player* _player, const Item* item, bool ack)
  1787. {
  1788.     NetworkMessage_ptr msg = getOutputBuffer();
  1789.     if(!msg)
  1790.         return;
  1791.  
  1792.     TRACK_MESSAGE(msg);
  1793.     if(ack)
  1794.         msg->put<char>(0x7D);
  1795.     else
  1796.         msg->put<char>(0x7E);
  1797.  
  1798.     msg->putString(_player->getName());
  1799.     if(const Container* container = item->getContainer())
  1800.     {
  1801.         msg->put<char>(container->getItemHoldingCount() + 1);
  1802.         msg->putItem(item);
  1803.         for(ContainerIterator it = container->begin(); it != container->end(); ++it)
  1804.             msg->putItem(*it);
  1805.     }
  1806.     else
  1807.     {
  1808.         msg->put<char>(1);
  1809.         msg->putItem(item);
  1810.     }
  1811. }
  1812.  
  1813. void ProtocolGame::sendCloseTrade()
  1814. {
  1815.     NetworkMessage_ptr msg = getOutputBuffer();
  1816.     if(!msg)
  1817.         return;
  1818.  
  1819.     TRACK_MESSAGE(msg);
  1820.     msg->put<char>(0x7F);
  1821. }
  1822.  
  1823. void ProtocolGame::sendCloseContainer(uint32_t cid)
  1824. {
  1825.     NetworkMessage_ptr msg = getOutputBuffer();
  1826.     if(!msg)
  1827.         return;
  1828.  
  1829.     TRACK_MESSAGE(msg);
  1830.     msg->put<char>(0x6F);
  1831.     msg->put<char>(cid);
  1832. }
  1833.  
  1834. void ProtocolGame::sendCreatureTurn(const Creature* creature, int16_t stackpos)
  1835. {
  1836.     if(stackpos >= 10 || !canSee(creature))
  1837.         return;
  1838.  
  1839.     NetworkMessage_ptr msg = getOutputBuffer();
  1840.     if(!msg)
  1841.         return;
  1842.  
  1843.     TRACK_MESSAGE(msg);
  1844.     msg->put<char>(0x6B);
  1845.     msg->putPosition(creature->getPosition());
  1846.     msg->put<char>(stackpos);
  1847.     msg->put<uint16_t>(0x63);
  1848.     msg->put<uint32_t>(creature->getID());
  1849.     msg->put<char>(creature->getDirection());
  1850. }
  1851.  
  1852. void ProtocolGame::sendCreatureSay(const Creature* creature, MessageClasses type, const std::string& text, Position* pos, uint32_t statementId)
  1853. {
  1854.     NetworkMessage_ptr msg = getOutputBuffer();
  1855.     if(!msg)
  1856.         return;
  1857.  
  1858.     TRACK_MESSAGE(msg);
  1859.     AddCreatureSpeak(msg, creature, type, text, 0, pos, statementId);
  1860. }
  1861.  
  1862. void ProtocolGame::sendCreatureChannelSay(const Creature* creature, MessageClasses type, const std::string& text, uint16_t channelId, uint32_t statementId)
  1863. {
  1864.     NetworkMessage_ptr msg = getOutputBuffer();
  1865.     if(!msg)
  1866.         return;
  1867.  
  1868.     TRACK_MESSAGE(msg);
  1869.     AddCreatureSpeak(msg, creature, type, text, channelId, NULL, statementId);
  1870. }
  1871.  
  1872. void ProtocolGame::sendStatsMessage(MessageClasses type, const std::string& message,
  1873.     Position pos, MessageDetails* details/* = NULL*/)
  1874. {
  1875.     NetworkMessage_ptr msg = getOutputBuffer();
  1876.     if(!msg)
  1877.         return;
  1878.  
  1879.     TRACK_MESSAGE(msg);
  1880.     AddTextMessage(msg, type, message, &pos, details);
  1881. }
  1882.  
  1883. void ProtocolGame::sendCancel(const std::string& message)
  1884. {
  1885.     NetworkMessage_ptr msg = getOutputBuffer();
  1886.     if(!msg)
  1887.         return;
  1888.  
  1889.     TRACK_MESSAGE(msg);
  1890.     AddTextMessage(msg, MSG_STATUS_SMALL, message);
  1891. }
  1892.  
  1893. void ProtocolGame::sendCancelTarget()
  1894. {
  1895.     NetworkMessage_ptr msg = getOutputBuffer();
  1896.     if(!msg)
  1897.         return;
  1898.  
  1899.     TRACK_MESSAGE(msg);
  1900.     msg->put<char>(0xA3);
  1901.     msg->put<uint32_t>(0);
  1902. }
  1903.  
  1904. void ProtocolGame::sendChangeSpeed(const Creature* creature, uint32_t speed)
  1905. {
  1906.     if(!canSee(creature))
  1907.         return;
  1908.  
  1909.     NetworkMessage_ptr msg = getOutputBuffer();
  1910.     if(!msg)
  1911.         return;
  1912.  
  1913.     TRACK_MESSAGE(msg);
  1914.     msg->put<char>(0x8F);
  1915.     msg->put<uint32_t>(creature->getID());
  1916.     msg->put<uint16_t>(speed);
  1917. }
  1918.  
  1919. void ProtocolGame::sendCancelWalk()
  1920. {
  1921.     NetworkMessage_ptr msg = getOutputBuffer();
  1922.     if(!msg)
  1923.         return;
  1924.  
  1925.     TRACK_MESSAGE(msg);
  1926.     msg->put<char>(0xB5);
  1927.     msg->put<char>(player->getDirection());
  1928. }
  1929.  
  1930. void ProtocolGame::sendSkills()
  1931. {
  1932.     NetworkMessage_ptr msg = getOutputBuffer();
  1933.     if(!msg)
  1934.         return;
  1935.  
  1936.     TRACK_MESSAGE(msg);
  1937.     AddPlayerSkills(msg);
  1938. }
  1939.  
  1940. void ProtocolGame::sendPing()
  1941. {
  1942.     NetworkMessage_ptr msg = getOutputBuffer();
  1943.     if(!msg)
  1944.         return;
  1945.  
  1946.     TRACK_MESSAGE(msg);
  1947.     msg->put<char>(0x1E);
  1948. }
  1949.  
  1950. void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint16_t type)
  1951. {
  1952.     if(!canSee(from) && !canSee(to))
  1953.         return;
  1954.  
  1955.     NetworkMessage_ptr msg = getOutputBuffer();
  1956.     if(!msg)
  1957.         return;
  1958.  
  1959.     TRACK_MESSAGE(msg);
  1960.     AddDistanceShoot(msg, from, to, type);
  1961. }
  1962.  
  1963. void ProtocolGame::sendMagicEffect(const Position& pos, uint16_t type)
  1964. {
  1965.     if(!canSee(pos))
  1966.         return;
  1967.  
  1968.     NetworkMessage_ptr msg = getOutputBuffer();
  1969.     if(!msg)
  1970.         return;
  1971.  
  1972.     TRACK_MESSAGE(msg);
  1973.     AddMagicEffect(msg, pos, type);
  1974. }
  1975.  
  1976. void ProtocolGame::sendAnimatedText(const Position& pos, uint8_t color, std::string text)
  1977. {
  1978.     if(!canSee(pos))
  1979.         return;
  1980.  
  1981.     NetworkMessage_ptr msg = getOutputBuffer();
  1982.     if(!msg)
  1983.         return;
  1984.  
  1985.     TRACK_MESSAGE(msg);
  1986.     AddAnimatedText(msg, pos, color, text);
  1987. }
  1988.  
  1989. void ProtocolGame::sendCreatureHealth(const Creature* creature)
  1990. {
  1991.     if(!canSee(creature))
  1992.         return;
  1993.  
  1994.     NetworkMessage_ptr msg = getOutputBuffer();
  1995.     if(!msg)
  1996.         return;
  1997.  
  1998.     TRACK_MESSAGE(msg);
  1999.     AddCreatureHealth(msg, creature);
  2000. }
  2001.  
  2002. void ProtocolGame::sendFYIBox(const std::string& message)
  2003. {
  2004.     if(message.empty() || message.length() > 1018) //Prevent client debug when message is empty or length is > 1018 (not confirmed)
  2005.     {
  2006.         std::clog << "[Warning - ProtocolGame::sendFYIBox] Trying to send an empty or too huge message." << std::endl;
  2007.         return;
  2008.     }
  2009.  
  2010.     NetworkMessage_ptr msg = getOutputBuffer();
  2011.     if(!msg)
  2012.         return;
  2013.  
  2014.     TRACK_MESSAGE(msg);
  2015.     msg->put<char>(0x15);
  2016.     msg->putString(message);
  2017. }
  2018.  
  2019. //tile
  2020. void ProtocolGame::sendAddTileItem(const Tile*, const Position& pos, uint32_t stackpos, const Item* item)
  2021. {
  2022.     if(!canSee(pos))
  2023.         return;
  2024.  
  2025.     NetworkMessage_ptr msg = getOutputBuffer();
  2026.     if(!msg)
  2027.         return;
  2028.  
  2029.     TRACK_MESSAGE(msg);
  2030.     AddTileItem(msg, pos, stackpos, item);
  2031. }
  2032.  
  2033. void ProtocolGame::sendUpdateTileItem(const Tile*, const Position& pos, uint32_t stackpos, const Item* item)
  2034. {
  2035.     if(!canSee(pos))
  2036.         return;
  2037.  
  2038.     NetworkMessage_ptr msg = getOutputBuffer();
  2039.     if(!msg)
  2040.         return;
  2041.  
  2042.     TRACK_MESSAGE(msg);
  2043.     UpdateTileItem(msg, pos, stackpos, item);
  2044. }
  2045.  
  2046. void ProtocolGame::sendRemoveTileItem(const Tile*, const Position& pos, uint32_t stackpos)
  2047. {
  2048.     if(!canSee(pos))
  2049.         return;
  2050.  
  2051.     NetworkMessage_ptr msg = getOutputBuffer();
  2052.     if(!msg)
  2053.         return;
  2054.  
  2055.     TRACK_MESSAGE(msg);
  2056.     RemoveTileItem(msg, pos, stackpos);
  2057. }
  2058.  
  2059. void ProtocolGame::sendUpdateTile(const Tile* tile, const Position& pos)
  2060. {
  2061.     if(!canSee(pos))
  2062.         return;
  2063.  
  2064.     NetworkMessage_ptr msg = getOutputBuffer();
  2065.     if(!msg)
  2066.         return;
  2067.  
  2068.     TRACK_MESSAGE(msg);
  2069.     msg->put<char>(0x69);
  2070.     msg->putPosition(pos);
  2071.     if(tile)
  2072.     {
  2073.         GetTileDescription(tile, msg);
  2074.         msg->put<char>(0x00);
  2075.         msg->put<char>(0xFF);
  2076.     }
  2077.     else
  2078.     {
  2079.         msg->put<char>(0x01);
  2080.         msg->put<char>(0xFF);
  2081.     }
  2082. }
  2083.  
  2084. void ProtocolGame::sendAddCreature(const Creature* creature, const Position& pos, uint32_t stackpos)
  2085. {
  2086.     if(!canSee(creature))
  2087.         return;
  2088.  
  2089.     NetworkMessage_ptr msg = getOutputBuffer();
  2090.     if(!msg)
  2091.         return;
  2092.  
  2093.     TRACK_MESSAGE(msg);
  2094.     if(creature != player)
  2095.     {
  2096.         AddTileCreature(msg, pos, stackpos, creature);
  2097.         return;
  2098.     }
  2099.  
  2100.     msg->put<char>(0x0A);
  2101.     msg->put<uint32_t>(player->getID());
  2102.     msg->put<uint16_t>(0x32);
  2103.  
  2104.     msg->put<char>(player->hasFlag(PlayerFlag_CanReportBugs));
  2105.     if(Group* group = player->getGroup())
  2106.     {
  2107.         int32_t reasons = group->getViolationReasons();
  2108.         if(reasons > 1)
  2109.         {
  2110.             msg->put<char>(0x0B);
  2111.             for(int32_t i = 0; i < 20; ++i)
  2112.             {
  2113.                 if(i < 4)
  2114.                     msg->put<char>(group->getNameViolationFlags());
  2115.                 else if(i < reasons)
  2116.                     msg->put<char>(group->getStatementViolationFlags());
  2117.                 else
  2118.                     msg->put<char>(0);
  2119.             }
  2120.         }
  2121.     }
  2122.  
  2123.     AddMapDescription(msg, pos);
  2124.     for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
  2125.         AddInventoryItem(msg, (slots_t)i, player->getInventoryItem((slots_t)i));
  2126.  
  2127.     AddPlayerStats(msg);
  2128.     AddPlayerSkills(msg);
  2129.  
  2130.     LightInfo lightInfo;
  2131.     g_game.getWorldLightInfo(lightInfo);
  2132.  
  2133.     AddWorldLight(msg, lightInfo);
  2134.     AddCreatureLight(msg, creature);
  2135.  
  2136.     player->sendIcons();
  2137.     for(VIPSet::iterator it = player->VIPList.begin(); it != player->VIPList.end(); ++it)
  2138.     {
  2139.         std::string vipName;
  2140.         if(IOLoginData::getInstance()->getNameByGuid((*it), vipName))
  2141.         {
  2142.             Player* tmpPlayer = g_game.getPlayerByName(vipName);
  2143.             sendVIP((*it), vipName, (tmpPlayer && player->canSeeCreature(tmpPlayer)));
  2144.         }
  2145.     }
  2146. }
  2147.  
  2148. void ProtocolGame::sendRemoveCreature(const Creature*, const Position& pos, uint32_t stackpos)
  2149. {
  2150.     if(!canSee(pos))
  2151.         return;
  2152.  
  2153.     NetworkMessage_ptr msg = getOutputBuffer();
  2154.     if(!msg)
  2155.         return;
  2156.  
  2157.     TRACK_MESSAGE(msg);
  2158.     RemoveTileItem(msg, pos, stackpos);
  2159. }
  2160.  
  2161. void ProtocolGame::sendMoveCreature(const Creature* creature, const Tile*, const Position& newPos,
  2162.     uint32_t newStackpos, const Tile*, const Position& oldPos, uint32_t oldStackpos, bool teleport)
  2163. {
  2164.     if(creature == player)
  2165.     {
  2166.         NetworkMessage_ptr msg = getOutputBuffer();
  2167.         if(!msg)
  2168.             return;
  2169.  
  2170.         TRACK_MESSAGE(msg);
  2171.         if(teleport || oldStackpos >= 10)
  2172.         {
  2173.             RemoveTileItem(msg, oldPos, oldStackpos);
  2174.             AddMapDescription(msg, newPos);
  2175.         }
  2176.         else
  2177.         {
  2178.             if(oldPos.z != 7 || newPos.z < 8)
  2179.             {
  2180.                 msg->put<char>(0x6D);
  2181.                 msg->putPosition(oldPos);
  2182.                 msg->put<char>(oldStackpos);
  2183.                 msg->putPosition(newPos);
  2184.             }
  2185.             else
  2186.                 RemoveTileItem(msg, oldPos, oldStackpos);
  2187.  
  2188.             if(newPos.z > oldPos.z)
  2189.                 MoveDownCreature(msg, creature, newPos, oldPos, oldStackpos);
  2190.             else if(newPos.z < oldPos.z)
  2191.                 MoveUpCreature(msg, creature, newPos, oldPos, oldStackpos);
  2192.  
  2193.             if(oldPos.y > newPos.y) // north, for old x
  2194.             {
  2195.                 msg->put<char>(0x65);
  2196.                 GetMapDescription(oldPos.x - 8, newPos.y - 6, newPos.z, 18, 1, msg);
  2197.             }
  2198.             else if(oldPos.y < newPos.y) // south, for old x
  2199.             {
  2200.                 msg->put<char>(0x67);
  2201.                 GetMapDescription(oldPos.x - 8, newPos.y + 7, newPos.z, 18, 1, msg);
  2202.             }
  2203.  
  2204.             if(oldPos.x < newPos.x) // east, [with new y]
  2205.             {
  2206.                 msg->put<char>(0x66);
  2207.                 GetMapDescription(newPos.x + 9, newPos.y - 6, newPos.z, 1, 14, msg);
  2208.             }
  2209.             else if(oldPos.x > newPos.x) // west, [with new y]
  2210.             {
  2211.                 msg->put<char>(0x68);
  2212.                 GetMapDescription(newPos.x - 8, newPos.y - 6, newPos.z, 1, 14, msg);
  2213.             }
  2214.         }
  2215.     }
  2216.     else if(canSee(oldPos) && canSee(newPos))
  2217.     {
  2218.         if(!player->canSeeCreature(creature))
  2219.             return;
  2220.  
  2221.         NetworkMessage_ptr msg = getOutputBuffer();
  2222.         if(!msg)
  2223.             return;
  2224.  
  2225.         TRACK_MESSAGE(msg);
  2226.         if(!teleport && (oldPos.z != 7 || newPos.z < 8) && oldStackpos < 10)
  2227.         {
  2228.             msg->put<char>(0x6D);
  2229.             msg->putPosition(oldPos);
  2230.             msg->put<char>(oldStackpos);
  2231.             msg->putPosition(newPos);
  2232.         }
  2233.         else
  2234.         {
  2235.             RemoveTileItem(msg, oldPos, oldStackpos);
  2236.             AddTileCreature(msg, newPos, newStackpos, creature);
  2237.         }
  2238.     }
  2239.     else if(canSee(oldPos))
  2240.     {
  2241.         if(!player->canSeeCreature(creature))
  2242.             return;
  2243.  
  2244.         NetworkMessage_ptr msg = getOutputBuffer();
  2245.         if(!msg)
  2246.             return;
  2247.  
  2248.             TRACK_MESSAGE(msg);
  2249.             RemoveTileItem(msg, oldPos, oldStackpos);
  2250.     }
  2251.     else if(canSee(newPos) && player->canSeeCreature(creature))
  2252.     {
  2253.         NetworkMessage_ptr msg = getOutputBuffer();
  2254.         if(!msg)
  2255.             return;
  2256.  
  2257.             TRACK_MESSAGE(msg);
  2258.             AddTileCreature(msg, newPos, newStackpos, creature);
  2259.     }
  2260. }
  2261.  
  2262. //inventory
  2263. void ProtocolGame::sendAddInventoryItem(slots_t slot, const Item* item)
  2264. {
  2265.     NetworkMessage_ptr msg = getOutputBuffer();
  2266.     if(!msg)
  2267.         return;
  2268.  
  2269.     TRACK_MESSAGE(msg);
  2270.     AddInventoryItem(msg, slot, item);
  2271. }
  2272.  
  2273. void ProtocolGame::sendUpdateInventoryItem(slots_t slot, const Item* item)
  2274. {
  2275.     NetworkMessage_ptr msg = getOutputBuffer();
  2276.     if(!msg)
  2277.         return;
  2278.  
  2279.     TRACK_MESSAGE(msg);
  2280.     UpdateInventoryItem(msg, slot, item);
  2281. }
  2282.  
  2283. void ProtocolGame::sendRemoveInventoryItem(slots_t slot)
  2284. {
  2285.     NetworkMessage_ptr msg = getOutputBuffer();
  2286.     if(!msg)
  2287.         return;
  2288.  
  2289.     TRACK_MESSAGE(msg);
  2290.     RemoveInventoryItem(msg, slot);
  2291. }
  2292.  
  2293. //containers
  2294. void ProtocolGame::sendAddContainerItem(uint8_t cid, const Item* item)
  2295. {
  2296.     NetworkMessage_ptr msg = getOutputBuffer();
  2297.     if(!msg)
  2298.         return;
  2299.  
  2300.     TRACK_MESSAGE(msg);
  2301.     AddContainerItem(msg, cid, item);
  2302. }
  2303.  
  2304. void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint8_t slot, const Item* item)
  2305. {
  2306.     NetworkMessage_ptr msg = getOutputBuffer();
  2307.     if(!msg)
  2308.         return;
  2309.  
  2310.     TRACK_MESSAGE(msg);
  2311.     UpdateContainerItem(msg, cid, slot, item);
  2312. }
  2313.  
  2314. void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint8_t slot)
  2315. {
  2316.     NetworkMessage_ptr msg = getOutputBuffer();
  2317.     if(!msg)
  2318.         return;
  2319.  
  2320.     TRACK_MESSAGE(msg);
  2321.     RemoveContainerItem(msg, cid, slot);
  2322. }
  2323.  
  2324. void ProtocolGame::sendTextWindow(uint32_t windowTextId, Item* item, uint16_t maxLen, bool canWrite)
  2325. {
  2326.     NetworkMessage_ptr msg = getOutputBuffer();
  2327.     if(!msg)
  2328.         return;
  2329.  
  2330.     TRACK_MESSAGE(msg);
  2331.     msg->put<char>(0x96);
  2332.     msg->put<uint32_t>(windowTextId);
  2333.     msg->putItem(item);
  2334.     if(canWrite)
  2335.     {
  2336.         msg->put<uint16_t>(maxLen);
  2337.         msg->putString(item->getText());
  2338.     }
  2339.     else
  2340.     {
  2341.         msg->put<uint16_t>(item->getText().size());
  2342.         msg->putString(item->getText());
  2343.     }
  2344.  
  2345.     const std::string& writer = item->getWriter();
  2346.     if(writer.size())
  2347.         msg->putString(writer);
  2348.     else
  2349.         msg->putString("");
  2350.  
  2351.     time_t writtenDate = item->getDate();
  2352.     if(writtenDate > 0)
  2353.         msg->putString(formatDate(writtenDate));
  2354.     else
  2355.         msg->putString("");
  2356. }
  2357.  
  2358. void ProtocolGame::sendHouseWindow(uint32_t windowTextId, House*,
  2359.     uint32_t, const std::string& text)
  2360. {
  2361.     NetworkMessage_ptr msg = getOutputBuffer();
  2362.     if(!msg)
  2363.         return;
  2364.  
  2365.     TRACK_MESSAGE(msg);
  2366.     msg->put<char>(0x97);
  2367.     msg->put<char>(0x00);
  2368.     msg->put<uint32_t>(windowTextId);
  2369.     msg->putString(text);
  2370. }
  2371.  
  2372. void ProtocolGame::sendOutfitWindow()
  2373. {
  2374.     NetworkMessage_ptr msg = getOutputBuffer();
  2375.     if(!msg)
  2376.         return;
  2377.  
  2378.     TRACK_MESSAGE(msg);
  2379.     msg->put<char>(0xC8);
  2380.     AddCreatureOutfit(msg, player, player->getDefaultOutfit(), true);
  2381.  
  2382.     std::list<Outfit> outfitList;
  2383.     for(OutfitMap::iterator it = player->outfits.begin(); it != player->outfits.end(); ++it)
  2384.     {
  2385.         if(player->canWearOutfit(it->first, it->second.addons))
  2386.             outfitList.push_back(it->second);
  2387.     }
  2388.  
  2389.     if(outfitList.size())
  2390.     {
  2391.         msg->put<char>((size_t)std::min((size_t)OUTFITS_MAX_NUMBER, outfitList.size()));
  2392.         std::list<Outfit>::iterator it = outfitList.begin();
  2393.         for(int32_t i = 0; it != outfitList.end() && i < OUTFITS_MAX_NUMBER; ++it, ++i)
  2394.         {
  2395.             msg->put<uint16_t>(it->lookType);
  2396.             msg->putString(it->name);
  2397.             if(player->hasCustomFlag(PlayerCustomFlag_CanWearAllAddons))
  2398.                 msg->put<char>(0x03);
  2399.             else if(!g_config.getBool(ConfigManager::ADDONS_PREMIUM) || player->isPremium())
  2400.                 msg->put<char>(it->addons);
  2401.             else
  2402.                 msg->put<char>(0x00);
  2403.         }
  2404.     }
  2405.     else
  2406.     {
  2407.         msg->put<char>(1);
  2408.         msg->put<uint16_t>(player->getDefaultOutfit().lookType);
  2409.         msg->putString("Your outfit");
  2410.         msg->put<char>(player->getDefaultOutfit().lookAddons);
  2411.     }
  2412.  
  2413.     player->hasRequestedOutfit(true);
  2414. }
  2415.  
  2416. void ProtocolGame::sendQuests()
  2417. {
  2418.     NetworkMessage_ptr msg = getOutputBuffer();
  2419.     if(!msg)
  2420.         return;
  2421.  
  2422.     TRACK_MESSAGE(msg);
  2423.     msg->put<char>(0xF0);
  2424.  
  2425.     msg->put<uint16_t>(Quests::getInstance()->getQuestCount(player));
  2426.     for(QuestList::const_iterator it = Quests::getInstance()->getFirstQuest(); it != Quests::getInstance()->getLastQuest(); ++it)
  2427.     {
  2428.         if(!(*it)->isStarted(player))
  2429.             continue;
  2430.  
  2431.         msg->put<uint16_t>((*it)->getId());
  2432.         msg->putString((*it)->getName());
  2433.         msg->put<char>((*it)->isCompleted(player));
  2434.     }
  2435. }
  2436.  
  2437. void ProtocolGame::sendQuestInfo(Quest* quest)
  2438. {
  2439.     NetworkMessage_ptr msg = getOutputBuffer();
  2440.     if(!msg)
  2441.         return;
  2442.  
  2443.     TRACK_MESSAGE(msg);
  2444.     msg->put<char>(0xF1);
  2445.     msg->put<uint16_t>(quest->getId());
  2446.  
  2447.     msg->put<char>(quest->getMissionCount(player));
  2448.     for(MissionList::const_iterator it = quest->getFirstMission(); it != quest->getLastMission(); ++it)
  2449.     {
  2450.         if(!(*it)->isStarted(player))
  2451.             continue;
  2452.  
  2453.         msg->putString((*it)->getName(player));
  2454.         msg->putString((*it)->getDescription(player));
  2455.     }
  2456. }
  2457.  
  2458. void ProtocolGame::sendVIPLogIn(uint32_t guid)
  2459. {
  2460.     NetworkMessage_ptr msg = getOutputBuffer();
  2461.     if(!msg)
  2462.         return;
  2463.  
  2464.     TRACK_MESSAGE(msg);
  2465.     msg->put<char>(0xD3);
  2466.     msg->put<uint32_t>(guid);
  2467. }
  2468.  
  2469. void ProtocolGame::sendVIPLogOut(uint32_t guid)
  2470. {
  2471.     NetworkMessage_ptr msg = getOutputBuffer();
  2472.     if(!msg)
  2473.         return;
  2474.  
  2475.     TRACK_MESSAGE(msg);
  2476.     msg->put<char>(0xD4);
  2477.     msg->put<uint32_t>(guid);
  2478. }
  2479.  
  2480. void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, bool online)
  2481. {
  2482.     NetworkMessage_ptr msg = getOutputBuffer();
  2483.     if(!msg)
  2484.         return;
  2485.  
  2486.     TRACK_MESSAGE(msg);
  2487.     msg->put<char>(0xD2);
  2488.     msg->put<uint32_t>(guid);
  2489.     msg->putString(name);
  2490.     msg->put<char>(online ? 1 : 0);
  2491. }
  2492.  
  2493. void ProtocolGame::reloadCreature(const Creature* creature)
  2494. {
  2495.     if(!canSee(creature))
  2496.         return;
  2497.  
  2498.     // we are cheating the client in here!
  2499.     uint32_t stackpos = creature->getTile()->getClientIndexOfThing(player, creature);
  2500.     if(stackpos >= 10)
  2501.         return;
  2502.  
  2503.     NetworkMessage_ptr msg = getOutputBuffer();
  2504.     if(!msg)
  2505.         return;
  2506.  
  2507.     TRACK_MESSAGE(msg);
  2508.     if(std::find(knownCreatureList.begin(), knownCreatureList.end(),
  2509.         creature->getID()) != knownCreatureList.end())
  2510.     {
  2511.         RemoveTileItem(msg, creature->getPosition(), stackpos);
  2512.         msg->put<char>(0x6A);
  2513.  
  2514.         msg->putPosition(creature->getPosition());
  2515.         msg->put<char>(stackpos);
  2516.         AddCreature(msg, creature, false, creature->getID());
  2517.     }
  2518.     else
  2519.         AddTileCreature(msg, creature->getPosition(), stackpos, creature);
  2520. }
  2521.  
  2522. void ProtocolGame::AddMapDescription(NetworkMessage_ptr msg, const Position& pos)
  2523. {
  2524.     msg->put<char>(0x64);
  2525.     msg->putPosition(player->getPosition());
  2526.     GetMapDescription(pos.x - 8, pos.y - 6, pos.z, 18, 14, msg);
  2527. }
  2528.  
  2529. void ProtocolGame::AddTextMessage(NetworkMessage_ptr msg, MessageClasses mClass, const std::string& message,
  2530.     Position* pos/* = NULL*/, MessageDetails* details/* = NULL*/)
  2531. {
  2532.     if(mClass >= MSG_STATUS_CONSOLE_RED)
  2533.     {
  2534.         if(mClass <= MSG_STATUS_CONSOLE_BLUE)
  2535.         {
  2536.             msg->put<char>(0xB4);
  2537.             msg->put<char>(mClass);
  2538.             msg->putString(message);
  2539.         }
  2540.  
  2541.         if(details)
  2542.         {
  2543.             AddAnimatedText(msg, *pos, details->color, asString(details->value));
  2544.             if(details->sub)
  2545.                 AddAnimatedText(msg, *pos, details->sub->color, asString(details->sub->value));
  2546.         }
  2547.     }
  2548. }
  2549.  
  2550. void ProtocolGame::AddAnimatedText(NetworkMessage_ptr msg, const Position& pos,
  2551.     uint8_t color, const std::string& text)
  2552. {
  2553.     msg->put<char>(0x84);
  2554.     msg->putPosition(pos);
  2555.     msg->put<char>(color);
  2556.     msg->putString(text);
  2557. }
  2558.  
  2559. void ProtocolGame::AddMagicEffect(NetworkMessage_ptr msg, const Position& pos, uint16_t type)
  2560. {
  2561.     msg->put<char>(0x83);
  2562.     msg->putPosition(pos);
  2563.     msg->put<char>(type + 1); //msg->put<uint16_t>(type + 1); isso estava na outra src
  2564. }
  2565.  
  2566. void ProtocolGame::AddDistanceShoot(NetworkMessage_ptr msg, const Position& from, const Position& to,
  2567.     uint16_t type)
  2568. {
  2569.     msg->put<char>(0x85);
  2570.     msg->putPosition(from);
  2571.     msg->putPosition(to);
  2572.     msg->put<char>(type + 1); //msg->put<uint16_t>(type + 1);
  2573. }
  2574.  
  2575. void ProtocolGame::AddCreature(NetworkMessage_ptr msg, const Creature* creature, bool known, uint32_t remove)
  2576. {
  2577.     if(!known)
  2578.     {
  2579.         msg->put<uint16_t>(0x61);
  2580.         msg->put<uint32_t>(remove);
  2581.         msg->put<uint32_t>(creature->getID());
  2582.         msg->putString(creature->getHideName() ? "" : creature->getName());
  2583.     }
  2584.     else
  2585.     {
  2586.         msg->put<uint16_t>(0x62);
  2587.         msg->put<uint32_t>(creature->getID());
  2588.     }
  2589.  
  2590.     if(!creature->getHideHealth()) //lks mechido
  2591.         msg->put<char>((uint32_t)std::ceil(creature->getHealth() * 100. / std::max(creature->getMaxHealth(), (int32_t)1))); //foi add antes do 1 (int32_t)
  2592.     else
  2593.         msg->put<char>(0x00);
  2594.  
  2595.     msg->put<char>((uint8_t)creature->getDirection());
  2596.     AddCreatureOutfit(msg, creature, creature->getCurrentOutfit());
  2597.  
  2598.     LightInfo lightInfo;
  2599.     creature->getCreatureLight(lightInfo);
  2600.  
  2601.     msg->put<char>(lightInfo.level);
  2602.     msg->put<char>(lightInfo.color);
  2603.  
  2604.     msg->put<uint16_t>(creature->getStepSpeed());
  2605.     msg->put<char>(player->getSkullType(creature));
  2606.     msg->put<char>(player->getPartyShield(creature));
  2607.     if(!known)
  2608.         msg->put<char>(player->getGuildEmblem(creature));
  2609.  
  2610.     msg->put<char>(!player->canWalkthrough(creature));
  2611. }
  2612.  
  2613. void ProtocolGame::AddPlayerStats(NetworkMessage_ptr msg)
  2614. {
  2615.     msg->put<char>(0xA0);
  2616.     msg->put<uint32_t>(std::ceil((float)player->getHealth() * 100 / std::max(player->getMaxHealth(), 1)));
  2617.     msg->put<uint32_t>(100);
  2618.     //msg->put<uint16_t>(player->getHealth());
  2619.     //msg->put<uint16_t>(player->getPlayerInfo(PLAYERINFO_MAXHEALTH));
  2620.     msg->put<uint32_t>(uint32_t(player->getFreeCapacity() * 100));
  2621.     uint64_t experience = player->getExperience();
  2622.     if(experience > 0x7FFFFFFF)
  2623.         msg->put<uint32_t>(0x7FFFFFFF);
  2624.     else
  2625.         msg->put<uint32_t>(experience);
  2626.  
  2627.     msg->put<uint16_t>(player->getPlayerInfo(PLAYERINFO_LEVEL));
  2628.     msg->put<char>(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT));
  2629.     msg->put<uint32_t>(std::ceil((float)player->getMana() * 100 / std::max(player->getMaxMana(), 1)));
  2630.     msg->put<uint32_t>(100);
  2631.     //msg->put<uint16_t>(player->getPlayerInfo(PLAYERINFO_MANA));
  2632.     //msg->put<uint16_t>(player->getPlayerInfo(PLAYERINFO_MAXMANA));
  2633.     //msg->put<char>(player->getPlayerInfo(PLAYERINFO_MAGICLEVEL)); //mudado
  2634.     msg->put<uint16_t>(player->getPlayerInfo(PLAYERINFO_MAGICLEVEL));
  2635.     msg->put<char>(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT));
  2636.     //msg->put<char>(player->getPlayerInfo(PLAYERINFO_SOUL)); //mudado
  2637.     msg->put<uint16_t>(player->getPlayerInfo(PLAYERINFO_SOUL));
  2638.     msg->put<uint16_t>(player->getStaminaMinutes());
  2639. }
  2640.  
  2641. void ProtocolGame::AddPlayerSkills(NetworkMessage_ptr msg)
  2642. {
  2643.     msg->put<char>(0xA1);
  2644.     /*for(uint8_t i = 0; i <= SKILL_LAST; ++i)
  2645.     {
  2646.         msg->put<char>(player->getSkill((skills_t)i, SKILL_LEVEL));
  2647.         msg->put<char>(player->getSkill((skills_t)i, SKILL_PERCENT));
  2648.     }*/
  2649.     msg->put<uint16_t>(player->getSkill(SKILL_FIST, SKILL_LEVEL));
  2650.     msg->put<char>(player->getSkill(SKILL_FIST, SKILL_PERCENT));
  2651.     msg->put<uint16_t>(player->getSkill(SKILL_CLUB, SKILL_LEVEL));
  2652.     msg->put<char>(player->getSkill(SKILL_CLUB, SKILL_PERCENT));
  2653.     msg->put<uint16_t>(player->getSkill(SKILL_SWORD, SKILL_LEVEL));
  2654.     msg->put<char>(player->getSkill(SKILL_SWORD, SKILL_PERCENT));
  2655.     msg->put<uint16_t>(player->getSkill(SKILL_AXE, SKILL_LEVEL));
  2656.     msg->put<char>(player->getSkill(SKILL_AXE, SKILL_PERCENT));
  2657.     msg->put<uint16_t>(player->getSkill(SKILL_DIST, SKILL_LEVEL));
  2658.     msg->put<char>(player->getSkill(SKILL_DIST, SKILL_PERCENT));
  2659.     msg->put<uint16_t>(player->getSkill(SKILL_SHIELD, SKILL_LEVEL));
  2660.     msg->put<char>(player->getSkill(SKILL_SHIELD, SKILL_PERCENT));
  2661.     msg->put<uint16_t>(player->getSkill(SKILL_FISH, SKILL_LEVEL));
  2662.     msg->put<char>(player->getSkill(SKILL_FISH, SKILL_PERCENT));
  2663. }
  2664.  
  2665. void ProtocolGame::AddCreatureSpeak(NetworkMessage_ptr msg, const Creature* creature, MessageClasses type,
  2666.     std::string text, uint16_t channelId, Position* pos, uint32_t statementId)
  2667. {
  2668.     if(type > MSG_SPEAK_MONSTER_LAST)
  2669.         return;
  2670.  
  2671.     msg->put<char>(0xAA);
  2672.     if(creature)
  2673.     {
  2674.         msg->put<uint32_t>(statementId);
  2675.         if(creature->getSpeakType() != MSG_NONE)
  2676.             type = creature->getSpeakType();
  2677.  
  2678.         switch(type)
  2679.         {
  2680.             case MSG_GAMEMASTER_ANONYMOUS:
  2681.                 msg->putString("");
  2682.                 break;
  2683.             case MSG_RVR_ANSWER:
  2684.                 msg->putString("Gamemaster");
  2685.                 break;
  2686.             default:
  2687.                 msg->putString(!creature->getHideName() ? creature->getName() : "");
  2688.                 break;
  2689.         }
  2690.  
  2691.         const Player* speaker = creature->getPlayer();
  2692.         if(speaker && !speaker->isAccountManager() && !speaker->hasCustomFlag(PlayerCustomFlag_HideLevel))
  2693.             msg->put<uint16_t>(speaker->getPlayerInfo(PLAYERINFO_LEVEL));
  2694.         else
  2695.             msg->put<uint16_t>(0x00);
  2696.     }
  2697.     else
  2698.     {
  2699.         msg->put<uint32_t>(0x00);
  2700.         msg->putString("");
  2701.         msg->put<uint16_t>(0x00);
  2702.     }
  2703.  
  2704.     msg->put<char>(type);
  2705.     switch(type)
  2706.     {
  2707.         case MSG_SPEAK_SAY:
  2708.         case MSG_SPEAK_WHISPER:
  2709.         case MSG_SPEAK_YELL:
  2710.         case MSG_SPEAK_MONSTER_SAY:
  2711.         case MSG_SPEAK_MONSTER_YELL:
  2712.         case MSG_NPC_FROM:
  2713.         {
  2714.             if(pos)
  2715.                 msg->putPosition(*pos);
  2716.             else if(creature)
  2717.                 msg->putPosition(creature->getPosition());
  2718.             else
  2719.                 msg->putPosition(Position(0,0,7));
  2720.  
  2721.             break;
  2722.         }
  2723.  
  2724.         case MSG_CHANNEL:
  2725.         case MSG_CHANNEL_HIGHLIGHT:
  2726.         case MSG_GAMEMASTER_CHANNEL:
  2727.         case MSG_GAMEMASTER_ANONYMOUS:
  2728.             msg->put<uint16_t>(channelId);
  2729.             break;
  2730.  
  2731.         case MSG_RVR_CHANNEL:
  2732.         {
  2733.             msg->put<uint32_t>(uint32_t(OTSYS_TIME() / 1000 & 0xFFFFFFFF) - statementId/*use it as time:)*/);
  2734.             break;
  2735.         }
  2736.  
  2737.         default:
  2738.             break;
  2739.     }
  2740.  
  2741.     msg->putString(text);
  2742. }
  2743.  
  2744. void ProtocolGame::AddCreatureHealth(NetworkMessage_ptr msg,const Creature* creature)
  2745. {
  2746.     msg->put<char>(0x8C);
  2747.     msg->put<uint32_t>(creature->getID());
  2748.     if(!creature->getHideHealth()) //modificado lks
  2749.         msg->put<char>((uint32_t)std::ceil(creature->getHealth() * 100. / std::max(creature->getMaxHealth(), (int32_t)1)));
  2750.     else
  2751.         msg->put<char>(0x00);
  2752. }
  2753.  
  2754. void ProtocolGame::AddCreatureOutfit(NetworkMessage_ptr msg, const Creature* creature, const Outfit_t& outfit, bool outfitWindow/* = false*/)
  2755. {
  2756.     if(outfitWindow || (!creature->isInvisible() && (!creature->isGhost()
  2757.         || !g_config.getBool(ConfigManager::GHOST_INVISIBLE_EFFECT))))
  2758.     {
  2759.         msg->put<uint16_t>(outfit.lookType);
  2760.         if(outfit.lookType)
  2761.         {
  2762.             msg->put<char>(outfit.lookHead);
  2763.             msg->put<char>(outfit.lookBody);
  2764.             msg->put<char>(outfit.lookLegs);
  2765.             msg->put<char>(outfit.lookFeet);
  2766.             msg->put<char>(outfit.lookAddons);
  2767.         }
  2768.         else if(outfit.lookTypeEx)
  2769.             msg->putItemId(outfit.lookTypeEx);
  2770.         else
  2771.             msg->put<uint16_t>(outfit.lookTypeEx);
  2772.     }
  2773.     else
  2774.         msg->put<uint32_t>(0x00);
  2775. }
  2776.  
  2777. void ProtocolGame::AddWorldLight(NetworkMessage_ptr msg, const LightInfo& lightInfo)
  2778. {
  2779.     msg->put<char>(0x82);
  2780.     msg->put<char>(lightInfo.level);
  2781.     msg->put<char>(lightInfo.color);
  2782. }
  2783.  
  2784. void ProtocolGame::AddCreatureLight(NetworkMessage_ptr msg, const Creature* creature)
  2785. {
  2786.     msg->put<char>(0x8D);
  2787.     msg->put<uint32_t>(creature->getID());
  2788.  
  2789.     LightInfo lightInfo;
  2790.     creature->getCreatureLight(lightInfo);
  2791.  
  2792.     msg->put<char>(lightInfo.level);
  2793.     msg->put<char>(lightInfo.color);
  2794. }
  2795.  
  2796. //tile
  2797. void ProtocolGame::AddTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Item* item)
  2798. {
  2799.     if(stackpos >= 10)
  2800.         return;
  2801.  
  2802.     msg->put<char>(0x6A);
  2803.     msg->putPosition(pos);
  2804.     msg->put<char>(stackpos);
  2805.     msg->putItem(item);
  2806. }
  2807.  
  2808. void ProtocolGame::AddTileCreature(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Creature* creature)
  2809. {
  2810.     if(stackpos >= 10)
  2811.         return;
  2812.  
  2813.     msg->put<char>(0x6A);
  2814.     msg->putPosition(pos);
  2815.     msg->put<char>(stackpos);
  2816.  
  2817.     bool known;
  2818.     uint32_t removedKnown;
  2819.     checkCreatureAsKnown(creature->getID(), known, removedKnown);
  2820.     AddCreature(msg, creature, known, removedKnown);
  2821. }
  2822.  
  2823. void ProtocolGame::UpdateTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Item* item)
  2824. {
  2825.     if(stackpos >= 10)
  2826.         return;
  2827.  
  2828.     msg->put<char>(0x6B);
  2829.     msg->putPosition(pos);
  2830.     msg->put<char>(stackpos);
  2831.     msg->putItem(item);
  2832. }
  2833.  
  2834. void ProtocolGame::RemoveTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos)
  2835. {
  2836.     if(stackpos >= 10)
  2837.         return;
  2838.  
  2839.     msg->put<char>(0x6C);
  2840.     msg->putPosition(pos);
  2841.     msg->put<char>(stackpos);
  2842. }
  2843.  
  2844. void ProtocolGame::MoveUpCreature(NetworkMessage_ptr msg, const Creature* creature,
  2845.     const Position& newPos, const Position& oldPos, uint32_t)
  2846. {
  2847.     if(creature != player)
  2848.         return;
  2849.  
  2850.     msg->put<char>(0xBE); //floor change up
  2851.     if(newPos.z == 7) //going to surface
  2852.     {
  2853.         int32_t skip = -1;
  2854.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 5, 18, 14, 3, skip); //(floor 7 and 6 already set)
  2855.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 4, 18, 14, 4, skip);
  2856.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 3, 18, 14, 5, skip);
  2857.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 2, 18, 14, 6, skip);
  2858.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 1, 18, 14, 7, skip);
  2859.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 0, 18, 14, 8, skip);
  2860.         if(skip >= 0)
  2861.         {
  2862.             msg->put<char>(skip);
  2863.             msg->put<char>(0xFF);
  2864.         }
  2865.     }
  2866.     else if(newPos.z > 7) //underground, going one floor up (still underground)
  2867.     {
  2868.         int32_t skip = -1;
  2869.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, oldPos.z - 3, 18, 14, 3, skip);
  2870.         if(skip >= 0)
  2871.         {
  2872.             msg->put<char>(skip);
  2873.             msg->put<char>(0xFF);
  2874.         }
  2875.     }
  2876.  
  2877.     //moving up a floor up makes us out of sync
  2878.     //west
  2879.     msg->put<char>(0x68);
  2880.     GetMapDescription(oldPos.x - 8, oldPos.y + 1 - 6, newPos.z, 1, 14, msg);
  2881.  
  2882.     //north
  2883.     msg->put<char>(0x65);
  2884.     GetMapDescription(oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 1, msg);
  2885. }
  2886.  
  2887. void ProtocolGame::MoveDownCreature(NetworkMessage_ptr msg, const Creature* creature,
  2888.     const Position& newPos, const Position& oldPos, uint32_t)
  2889. {
  2890.     if(creature != player)
  2891.         return;
  2892.  
  2893.     msg->put<char>(0xBF); //floor change down
  2894.     if(newPos.z == 8) //going from surface to underground
  2895.     {
  2896.         int32_t skip = -1;
  2897.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 14, -1, skip);
  2898.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 1, 18, 14, -2, skip);
  2899.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);
  2900.         if(skip >= 0)
  2901.         {
  2902.             msg->put<char>(skip);
  2903.             msg->put<char>(0xFF);
  2904.         }
  2905.     }
  2906.     else if(newPos.z > oldPos.z && newPos.z > 8 && newPos.z < 14) //going further down
  2907.     {
  2908.         int32_t skip = -1;
  2909.         GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);
  2910.         if(skip >= 0)
  2911.         {
  2912.             msg->put<char>(skip);
  2913.             msg->put<char>(0xFF);
  2914.         }
  2915.     }
  2916.  
  2917.     //moving down a floor makes us out of sync
  2918.     //east
  2919.     msg->put<char>(0x66);
  2920.     GetMapDescription(oldPos.x + 9, oldPos.y - 1 - 6, newPos.z, 1, 14, msg);
  2921.  
  2922.     //south
  2923.     msg->put<char>(0x67);
  2924.     GetMapDescription(oldPos.x - 8, oldPos.y + 7, newPos.z, 18, 1, msg);
  2925. }
  2926.  
  2927. //inventory
  2928. void ProtocolGame::AddInventoryItem(NetworkMessage_ptr msg, slots_t slot, const Item* item)
  2929. {
  2930.     if(item)
  2931.     {
  2932.         msg->put<char>(0x78);
  2933.         msg->put<char>(slot);
  2934.         msg->putItem(item);
  2935.     }
  2936.     else
  2937.         RemoveInventoryItem(msg, slot);
  2938. }
  2939.  
  2940. void ProtocolGame::RemoveInventoryItem(NetworkMessage_ptr msg, slots_t slot)
  2941. {
  2942.     msg->put<char>(0x79);
  2943.     msg->put<char>(slot);
  2944. }
  2945.  
  2946. void ProtocolGame::UpdateInventoryItem(NetworkMessage_ptr msg, slots_t slot, const Item* item)
  2947. {
  2948.     AddInventoryItem(msg, slot, item);
  2949. }
  2950.  
  2951. //containers
  2952. void ProtocolGame::AddContainerItem(NetworkMessage_ptr msg, uint8_t cid, const Item* item)
  2953. {
  2954.     msg->put<char>(0x70);
  2955.     msg->put<char>(cid);
  2956.     msg->putItem(item);
  2957. }
  2958.  
  2959. void ProtocolGame::UpdateContainerItem(NetworkMessage_ptr msg, uint8_t cid, uint8_t slot, const Item* item)
  2960. {
  2961.     msg->put<char>(0x71);
  2962.     msg->put<char>(cid);
  2963.     msg->put<char>(slot);
  2964.     msg->putItem(item);
  2965. }
  2966.  
  2967. void ProtocolGame::RemoveContainerItem(NetworkMessage_ptr msg, uint8_t cid, uint8_t slot)
  2968. {
  2969.     msg->put<char>(0x72);
  2970.     msg->put<char>(cid);
  2971.     msg->put<char>(slot);
  2972. }
  2973.  
  2974. void ProtocolGame::sendChannelMessage(std::string author, std::string text, MessageClasses type, uint16_t channel)
  2975. {
  2976.     NetworkMessage_ptr msg = getOutputBuffer();
  2977.     if(!msg)
  2978.         return;
  2979.  
  2980.     TRACK_MESSAGE(msg);
  2981.     msg->put<char>(0xAA);
  2982.     msg->put<uint32_t>(0x00);
  2983.     msg->putString(author);
  2984.     msg->put<uint16_t>(0x00);
  2985.     msg->put<char>(type);
  2986.     msg->put<uint16_t>(channel);
  2987.     msg->putString(text);
  2988. }
  2989.  
  2990. void ProtocolGame::AddShopItem(NetworkMessage_ptr msg, const ShopInfo& item)
  2991. {
  2992.     const ItemType& it = Item::items[item.itemId];
  2993.     msg->put<uint16_t>(it.clientId);
  2994.     if(it.isSplash() || it.isFluidContainer())
  2995.         msg->put<char>(serverFluidToClient(item.subType));
  2996.     else if(it.stackable || it.charges)
  2997.         msg->put<char>(item.subType);
  2998.     else
  2999.         msg->put<char>(0x00);
  3000.  
  3001.     msg->putString(item.itemName);
  3002.     msg->put<uint32_t>(uint32_t(it.weight * 100));
  3003.     msg->put<uint32_t>(item.buyPrice);
  3004.     msg->put<uint32_t>(item.sellPrice);
  3005. }
  3006.  
  3007. void ProtocolGame::parseExtendedOpcode(NetworkMessage& msg)
  3008. {
  3009.     uint8_t opcode = msg.get<char>();
  3010.     std::string buffer = msg.getString();
  3011.  
  3012.     // process additional opcodes via lua script event
  3013.     addGameTask(&Game::parsePlayerExtendedOpcode, player->getID(), opcode, buffer);
  3014. }
  3015.  
  3016. void ProtocolGame::sendExtendedOpcode(uint8_t opcode, const std::string& buffer)
  3017. {
  3018.     // extended opcodes can only be send to players using otclient, cipsoft's tibia can't understand them
  3019.     if(player && !player->isUsingOtclient())
  3020.         return;
  3021.  
  3022.     NetworkMessage_ptr msg = getOutputBuffer();
  3023.     if(!msg)
  3024.         return;
  3025.  
  3026.     TRACK_MESSAGE(msg);
  3027.     msg->put<char>(0x32);
  3028.     msg->put<char>(opcode);
  3029.     msg->putString(buffer);
  3030. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement