joadson

New Protocolgame.cpp

Jan 14th, 2021
1,525
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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 "resources.h"
  19.  
  20. #include <boost/function.hpp>
  21. #include <iostream>
  22. #include "iomarket.h"
  23. #include "protocolgame.h"
  24. #include "textlogger.h"
  25.  
  26. #include "waitlist.h"
  27. #include "player.h"
  28.  
  29. #include "connection.h"
  30. #include "networkmessage.h"
  31. #include "outputmessage.h"
  32.  
  33. #include "iologindata.h"
  34. #include "ioban.h"
  35.  
  36. #include "items.h"
  37. #include "tile.h"
  38. #include "house.h"
  39.  
  40. #include "actions.h"
  41. #include "creatureevent.h"
  42. #include "quests.h"
  43.  
  44. #include "chat.h"
  45. #include "configmanager.h"
  46. #include "game.h"
  47.  
  48. #if defined(WINDOWS) && !defined(__CONSOLE__)
  49. #include "gui.h"
  50. #endif
  51.  
  52. extern Game g_game;
  53. extern ConfigManager g_config;
  54. extern Actions actions;
  55. extern CreatureEvents* g_creatureEvents;
  56. extern Chat g_chat;
  57.  
  58. template<class FunctionType>
  59. void ProtocolGame::addGameTaskInternal(uint32_t delay, const FunctionType& func)
  60. {
  61.     if(delay > 0)
  62.         Dispatcher::getInstance().addTask(createTask(delay, func));
  63.     else
  64.         Dispatcher::getInstance().addTask(createTask(func));
  65. }
  66.  
  67. #ifdef __ENABLE_SERVER_DIAGNOSTIC__
  68. uint32_t ProtocolGame::protocolGameCount = 0;
  69. #endif
  70.  
  71. void ProtocolGame::setPlayer(Player* p)
  72. {
  73.     player = p;
  74. }
  75.  
  76. void ProtocolGame::releaseProtocol()
  77. {
  78.     if(player && player->client == this)
  79.         player->client = NULL;
  80.  
  81.     Protocol::releaseProtocol();
  82. }
  83.  
  84. void ProtocolGame::deleteProtocolTask()
  85. {
  86.     if(player)
  87.     {
  88.         g_game.freeThing(player);
  89.         player = NULL;
  90.     }
  91.  
  92.     Protocol::deleteProtocolTask();
  93. }
  94.  
  95. bool ProtocolGame::login(const std::string& name, uint32_t id, const std::string& password,
  96.     OperatingSystem_t operatingSystem, uint16_t version, bool gamemaster)
  97. {
  98.     //dispatcher thread
  99.     PlayerVector players = g_game.getPlayersByName(name);
  100.     Player* _player = NULL;
  101.     if(!players.empty())
  102.         _player = players[random_range(0, (players.size() - 1))];
  103.  
  104.     if(!_player || name == "Account Manager" || g_config.getNumber(ConfigManager::ALLOW_CLONES) > (int32_t)players.size())
  105.     {
  106.         player = new Player(name, this);
  107.         player->addRef();
  108.  
  109.         player->setID();
  110.         if(!IOLoginData::getInstance()->loadPlayer(player, name, true))
  111.         {
  112.             disconnectClient(0x14, "Your character could not be loaded.");
  113.             return false;
  114.         }
  115.  
  116.         Ban ban;
  117.         ban.value = player->getID();
  118.         ban.param = PLAYERBAN_BANISHMENT;
  119.  
  120.         ban.type = BAN_PLAYER;
  121.         if(IOBan::getInstance()->getData(ban) && !player->hasFlag(PlayerFlag_CannotBeBanned))
  122.         {
  123.             bool deletion = ban.expires < 0;
  124.             std::string name_ = "Automatic ";
  125.             if(!ban.adminId)
  126.                 name_ += (deletion ? "deletion" : "banishment");
  127.             else
  128.                 IOLoginData::getInstance()->getNameByGuid(ban.adminId, name_, true);
  129.  
  130.             char buffer[500 + ban.comment.length()];
  131.             sprintf(buffer, "Your character has been %s at:\n%s by: %s,\nfor the following reason:\n%s.\nThe action taken was:\n%s.\nThe comment given was:\n%s.\nYour %s%s.",
  132.                 (deletion ? "deleted" : "banished"), formatDateShort(ban.added).c_str(), name_.c_str(),
  133.                 getReason(ban.reason).c_str(), getAction(ban.action, false).c_str(), ban.comment.c_str(),
  134.                 (deletion ? "character won't be undeleted" : "banishment will be lifted at:\n"),
  135.                 (deletion ? "." : formatDateShort(ban.expires, true).c_str()));
  136.  
  137.             disconnectClient(0x14, buffer);
  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" && g_config.getBool(ConfigManager::ACCOUNT_MANAGER))
  158.         {
  159.             if(id != 1)
  160.             {
  161.                 player->accountManager = MANAGER_ACCOUNT;
  162.                 player->managerNumber = id;
  163.             }
  164.             else
  165.                 player->accountManager = MANAGER_NEW;
  166.         }
  167.  
  168.         if(gamemaster && !player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges))
  169.         {
  170.             disconnectClient(0x14, "You are not a gamemaster! Turn off the gamemaster mode in your IP changer.");
  171.             return false;
  172.         }
  173.  
  174.         if(!player->hasFlag(PlayerFlag_CanAlwaysLogin))
  175.         {
  176.             if(g_game.getGameState() == GAME_STATE_CLOSING)
  177.             {
  178.                 disconnectClient(0x14, "Gameworld is just going down, please come back later.");
  179.                 return false;
  180.             }
  181.  
  182.             if(g_game.getGameState() == GAME_STATE_CLOSED)
  183.             {
  184.                 disconnectClient(0x14, "Gameworld is currently closed, please come back later.");
  185.                 return false;
  186.             }
  187.         }
  188.  
  189.         if(g_config.getBool(ConfigManager::ONE_PLAYER_ON_ACCOUNT) && !player->isAccountManager() &&
  190.             !IOLoginData::getInstance()->hasCustomFlag(id, PlayerCustomFlag_CanLoginMultipleCharacters))
  191.         {
  192.             bool found = false;
  193.             PlayerVector tmp = g_game.getPlayersByAccount(id);
  194.             for(PlayerVector::iterator it = tmp.begin(); it != tmp.end(); ++it)
  195.             {
  196.                 if((*it)->getName() != name)
  197.                     continue;
  198.  
  199.                 found = true;
  200.                 break;
  201.             }
  202.  
  203.             if(tmp.size() > 0 && !found)
  204.             {
  205.                 disconnectClient(0x14, "You may only login with one character\nof your account at the same time.");
  206.                 return false;
  207.             }
  208.         }
  209.  
  210.         if(!WaitingList::getInstance()->login(player))
  211.         {
  212.             if(OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false))
  213.             {
  214.                 TRACK_MESSAGE(output);
  215.                 std::stringstream ss;
  216.                 ss << "Too many players online.\n" << "You are ";
  217.  
  218.                 int32_t slot = WaitingList::getInstance()->getSlot(player);
  219.                 if(slot)
  220.                 {
  221.                     ss << "at ";
  222.                     if(slot > 0)
  223.                         ss << slot;
  224.                     else
  225.                         ss << "unknown";
  226.  
  227.                     ss << " place on the waiting list.";
  228.                 }
  229.                 else
  230.                     ss << "awaiting connection...";
  231.  
  232.                 output->AddByte(0x16);
  233.                 output->AddString(ss.str());
  234.                 output->AddByte(WaitingList::getTime(slot));
  235.                 OutputMessagePool::getInstance()->send(output);
  236.             }
  237.  
  238.             getConnection()->close();
  239.             return false;
  240.         }
  241.  
  242.         if(!IOLoginData::getInstance()->loadPlayer(player, name))
  243.         {
  244.             disconnectClient(0x14, "Your character could not be loaded.");
  245.             return false;
  246.         }
  247.  
  248.         player->setOperatingSystem(operatingSystem);
  249.         player->setClientVersion(version);
  250.         if(!g_game.placeCreature(player, player->getLoginPosition()) && !g_game.placeCreature(player, player->getMasterPosition(), false, true))
  251.         {
  252.             disconnectClient(0x14, "Temple position is wrong. Contact with the administration.");
  253.             return false;
  254.  
  255.         }
  256.  
  257.         player->lastIP = player->getIP();
  258.         player->lastLoad = OTSYS_TIME();
  259.         player->lastLogin = std::max(time(NULL), player->lastLogin + 1);
  260.  
  261.         m_acceptPackets = true;
  262.         return true;
  263.     }
  264.     else if(_player->client)
  265.     {
  266.         if(m_eventConnect || !g_config.getBool(ConfigManager::REPLACE_KICK_ON_LOGIN))
  267.         {
  268.             //A task has already been scheduled just bail out (should not be overriden)
  269.             disconnectClient(0x14, "You are already logged in.");
  270.             return false;
  271.         }
  272.  
  273.         g_chat.removeUserFromAllChannels(_player);
  274.         _player->disconnect();
  275.         _player->isConnecting = true;
  276.  
  277.         addRef();
  278.         m_eventConnect = Scheduler::getInstance().addEvent(createSchedulerTask(
  279.             1000, boost::bind(&ProtocolGame::connect, this, _player->getID(), operatingSystem, version)));
  280.         return true;
  281.     }
  282.  
  283.     addRef();
  284.     return connect(_player->getID(), operatingSystem, version);
  285. }
  286.  
  287. bool ProtocolGame::logout(bool displayEffect, bool forceLogout)
  288. {
  289.     //dispatcher thread
  290.     if(!player)
  291.         return false;
  292.  
  293.     if(!player->isRemoved())
  294.     {
  295.         if(!forceLogout)
  296.         {
  297.             if(!IOLoginData::getInstance()->hasCustomFlag(player->getAccount(), PlayerCustomFlag_CanLogoutAnytime))
  298.             {
  299.                 if(player->getTile()->hasFlag(TILESTATE_NOLOGOUT))
  300.                 {
  301.                     player->sendCancelMessage(RET_YOUCANNOTLOGOUTHERE);
  302.                     return false;
  303.                 }
  304.  
  305.                 if(player->hasCondition(CONDITION_INFIGHT))
  306.                 {
  307.                     player->sendCancelMessage(RET_YOUMAYNOTLOGOUTDURINGAFIGHT);
  308.                     return false;
  309.                 }
  310.  
  311.                 if(!g_creatureEvents->playerLogout(player, false)) //let the script handle the error message
  312.                     return false;
  313.             }
  314.             else
  315.                 g_creatureEvents->playerLogout(player, false);
  316.         }
  317.         else if(!g_creatureEvents->playerLogout(player, true))
  318.             return false;
  319.     }
  320.     else
  321.         displayEffect = false;
  322.  
  323.     if(displayEffect && !player->isGhost())
  324.         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
  325.  
  326.     if(Connection_ptr connection = getConnection())
  327.         connection->close();
  328.  
  329.     return g_game.removeCreature(player);
  330. }
  331.  
  332. bool ProtocolGame::connect(uint32_t playerId, OperatingSystem_t operatingSystem, uint16_t version)
  333. {
  334.     unRef();
  335.     m_eventConnect = 0;
  336.  
  337.     Player* _player = g_game.getPlayerByID(playerId);
  338.     if(!_player || _player->isRemoved() || _player->client)
  339.     {
  340.         disconnectClient(0x14, "You are already logged in.");
  341.         return false;
  342.     }
  343.  
  344.     player = _player;
  345.     player->addRef();
  346.     player->isConnecting = false;
  347.  
  348.     player->client = this;
  349.     player->sendCreatureAppear(player);
  350.  
  351.     player->setOperatingSystem(operatingSystem);
  352.     player->setClientVersion(version);
  353.  
  354.     player->lastIP = player->getIP();
  355.     player->lastLoad = OTSYS_TIME();
  356.     player->lastLogin = std::max(time(NULL), player->lastLogin + 1);
  357.  
  358.     m_acceptPackets = true;
  359.     return true;
  360. }
  361.  
  362. void ProtocolGame::disconnect()
  363. {
  364.     if(getConnection())
  365.         getConnection()->close();
  366. }
  367.  
  368. void ProtocolGame::disconnectClient(uint8_t error, const char* message)
  369. {
  370.     if(OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false))
  371.     {
  372.         TRACK_MESSAGE(output);
  373.         output->AddByte(error);
  374.         output->AddString(message);
  375.         OutputMessagePool::getInstance()->send(output);
  376.     }
  377.  
  378.     disconnect();
  379. }
  380.  
  381. void ProtocolGame::onConnect()
  382. {
  383.     if(OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false))
  384.     {
  385.         TRACK_MESSAGE(output);
  386.         enableChecksum();
  387.  
  388.         output->AddByte(0x1F);
  389.         output->AddU16(random_range(0, 0xFFFF));
  390.         output->AddU16(0x00);
  391.         output->AddByte(random_range(0, 0xFF));
  392.  
  393.         OutputMessagePool::getInstance()->send(output);
  394.     }
  395. }
  396.  
  397. void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
  398. {
  399.     parseFirstPacket(msg);
  400. }
  401.  
  402. bool ProtocolGame::parseFirstPacket(NetworkMessage& msg)
  403. {
  404.     if(
  405. #if defined(WINDOWS) && !defined(__CONSOLE__)
  406.         !GUI::getInstance()->m_connections ||
  407. #endif
  408.         g_game.getGameState() == GAME_STATE_SHUTDOWN)
  409.     {
  410.         getConnection()->close();
  411.         return false;
  412.     }
  413.  
  414.     OperatingSystem_t operatingSystem = (OperatingSystem_t)msg.GetU16();
  415.     uint16_t version = msg.GetU16();
  416.     if(!RSA_decrypt(msg))
  417.     {
  418.         getConnection()->close();
  419.         return false;
  420.     }
  421.  
  422.     uint32_t key[4] = {msg.GetU32(), msg.GetU32(), msg.GetU32(), msg.GetU32()};
  423.     enableXTEAEncryption();
  424.     setXTEAKey(key);
  425.  
  426.    
  427.         // notifies to otclient that this server can receive extended game protocol opcodes
  428.        if(operatingSystem >= CLIENTOS_OTCLIENT_LINUX)
  429.           sendExtendedOpcode(0x00, std::string());
  430.      
  431.  
  432.     bool gamemaster = msg.GetByte();
  433.     std::string name = msg.GetString(), character = msg.GetString(), password = msg.GetString();
  434.  
  435.     msg.SkipBytes(6); //841- wtf?
  436.     if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX)
  437.     {
  438.         disconnectClient(0x14, CLIENT_VERSION_STRING);
  439.         return false;
  440.     }
  441.    
  442.     if(!IOLoginData::getInstance()->accountNameExists(name))
  443.     {
  444.         disconnectClient(0x0A, "Account name existing.");
  445.         return false;
  446.     }
  447.    
  448.     if(character.empty() || !IOLoginData::getInstance()->playerExists(character))
  449.     {
  450.         disconnectClient(0x0A, "Character name existing.");
  451.         return false;
  452.     }  
  453.  
  454.     if(name.empty())
  455.     {
  456.         if(!g_config.getBool(ConfigManager::ACCOUNT_MANAGER))
  457.         {
  458.             disconnectClient(0x14, "Invalid account name.");
  459.             return false;
  460.         }
  461.  
  462.         name = "1";
  463.         password = "1";
  464.     }
  465.  
  466.     if(g_game.getGameState() < GAME_STATE_NORMAL)
  467.     {
  468.         disconnectClient(0x14, "Gameworld is just starting up, please wait.");
  469.         return false;
  470.     }
  471.  
  472.     if(g_game.getGameState() == GAME_STATE_MAINTAIN)
  473.     {
  474.         disconnectClient(0x14, "Gameworld is under maintenance, please re-connect in a while.");
  475.         return false;
  476.     }
  477.  
  478.     if(ConnectionManager::getInstance()->isDisabled(getIP(), protocolId))
  479.     {
  480.         disconnectClient(0x14, "Too many connections attempts from your IP address, please try again later.");
  481.         return false;
  482.     }
  483.  
  484.     if(IOBan::getInstance()->isIpBanished(getIP()))
  485.     {
  486.         disconnectClient(0x14, "Your IP is banished!");
  487.         return false;
  488.     }
  489.  
  490.     uint32_t id = 1;
  491.     if(!IOLoginData::getInstance()->getAccountId(name, id))
  492.     {
  493.         ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, false);
  494.         disconnectClient(0x14, "Invalid account name.");
  495.         return false;
  496.     }
  497.  
  498.     std::string hash;
  499.     if(!IOLoginData::getInstance()->getPassword(id, hash, character) || !encryptTest(password, hash))
  500.     {
  501.         ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, false);
  502.         disconnectClient(0x14, "Invalid password.");
  503.         return false;
  504.     }
  505.  
  506.     Ban ban;
  507.     ban.value = id;
  508.  
  509.     ban.type = BAN_ACCOUNT;
  510.     if(IOBan::getInstance()->getData(ban) && !IOLoginData::getInstance()->hasFlag(id, PlayerFlag_CannotBeBanned))
  511.     {
  512.         bool deletion = ban.expires < 0;
  513.         std::string name_ = "Automatic ";
  514.         if(!ban.adminId)
  515.             name_ += (deletion ? "deletion" : "banishment");
  516.         else
  517.             IOLoginData::getInstance()->getNameByGuid(ban.adminId, name_, true);
  518.  
  519.         char buffer[500 + ban.comment.length()];
  520.         sprintf(buffer, "Your account has been %s at:\n%s by: %s,\nfor the following reason:\n%s.\nThe action taken was:\n%s.\nThe comment given was:\n%s.\nYour %s%s.",
  521.             (deletion ? "deleted" : "banished"), formatDateShort(ban.added).c_str(), name_.c_str(),
  522.             getReason(ban.reason).c_str(), getAction(ban.action, false).c_str(), ban.comment.c_str(),
  523.             (deletion ? "account won't be undeleted" : "banishment will be lifted at:\n"),
  524.             (deletion ? "." : formatDateShort(ban.expires, true).c_str()));
  525.  
  526.         disconnectClient(0x14, buffer);
  527.         return false;
  528.     }
  529.  
  530.     ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, true);
  531.     Dispatcher::getInstance().addTask(createTask(boost::bind(
  532.         &ProtocolGame::login, this, character, id, password, operatingSystem, version, gamemaster)));
  533.     return true;
  534. }
  535.  
  536. void ProtocolGame::parsePacket(NetworkMessage &msg)
  537. {
  538.     if(!player || !m_acceptPackets || g_game.getGameState() == GAME_STATE_SHUTDOWN
  539.         || msg.getMessageLength() <= 0)
  540.         return;
  541.  
  542.     uint8_t recvbyte = msg.GetByte();
  543.     //a dead player cannot performs actions
  544.     if(player->isRemoved() && recvbyte != 0x14)
  545.         return;
  546.  
  547.     if(player->isTvWatching()){
  548.      if(recvbyte == 0x82 || recvbyte == 0x64 || recvbyte == 0x65 || recvbyte == 0x66 || recvbyte == 0x67 || recvbyte == 0x68 || recvbyte == 0x69 || recvbyte == 0x6A ||
  549.         recvbyte == 0x6B || recvbyte == 0x6C || recvbyte == 0x6D) // p´layer nao usar item em tv cam
  550.       return;
  551.     }
  552.  
  553.     if(player->isAccountManager())
  554.     {
  555.         switch(recvbyte)
  556.         {
  557.             case 0x14:
  558.                 parseLogout(msg);
  559.                 break;
  560.  
  561.             case 0x96:
  562.                 parseSay(msg);
  563.                 break;
  564.  
  565.             default:
  566.                 sendCancelWalk();
  567.                 break;
  568.         }
  569.     }
  570.     else
  571.     {
  572.         switch(recvbyte)
  573.         {
  574.             case 0x14: // logout
  575.                 parseLogout(msg);
  576.                 break;
  577.  
  578.             case 0x1E: // keep alive / ping response
  579.                 parseReceivePing(msg);
  580.                 break;
  581.  
  582.             case 0x32: // otclient extended opcode
  583.                 parseExtendedOpcode(msg);
  584.                 break;
  585.                
  586.             case 0x64: // move with steps
  587.                 parseAutoWalk(msg);
  588.                 break;
  589.  
  590.             case 0x65: // move north
  591.             case 0x66: // move east
  592.             case 0x67: // move south
  593.             case 0x68: // move west
  594.                 parseMove(msg, (Direction)(recvbyte - 0x65));
  595.                 break;
  596.  
  597.             case 0x69: // stop-autowalk
  598.                 addGameTask(&Game::playerStopAutoWalk, player->getID());
  599.                 break;
  600.  
  601.             case 0x6A:
  602.                 parseMove(msg, NORTHEAST);
  603.                 break;
  604.  
  605.             case 0x6B:
  606.                 parseMove(msg, SOUTHEAST);
  607.                 break;
  608.  
  609.             case 0x6C:
  610.                 parseMove(msg, SOUTHWEST);
  611.                 break;
  612.  
  613.             case 0x6D:
  614.                 parseMove(msg, NORTHWEST);
  615.                 break;
  616.  
  617.             case 0x6F: // turn north
  618.             case 0x70: // turn east
  619.             case 0x71: // turn south
  620.             case 0x72: // turn west
  621.                 parseTurn(msg, (Direction)(recvbyte - 0x6F));
  622.                 break;
  623.  
  624.             case 0x78: // throw item
  625.                 parseThrow(msg);
  626.                 break;
  627.  
  628.             case 0x79: // description in shop window
  629.                 parseLookInShop(msg);
  630.                 break;
  631.  
  632.             case 0x7A: // player bought from shop
  633.                 parsePlayerPurchase(msg);
  634.                 break;
  635.  
  636.             case 0x7B: // player sold to shop
  637.                 parsePlayerSale(msg);
  638.                 break;
  639.  
  640.             case 0x7C: // player closed shop window
  641.                 parseCloseShop(msg);
  642.                 break;
  643.  
  644.             case 0x7D: // Request trade
  645.                 parseRequestTrade(msg);
  646.                 break;
  647.  
  648.             case 0x7E: // Look at an item in trade
  649.                 parseLookInTrade(msg);
  650.                 break;
  651.  
  652.             case 0x7F: // Accept trade
  653.                 parseAcceptTrade(msg);
  654.                 break;
  655.  
  656.             case 0x80: // close/cancel trade
  657.                 parseCloseTrade();
  658.                 break;
  659.  
  660.             case 0x82: // use item
  661.                 parseUseItem(msg);
  662.                 break;
  663.  
  664.             case 0x83: // use item
  665.                 parseUseItemEx(msg);
  666.                 break;
  667.  
  668.             case 0x84: // battle window
  669.                 parseBattleWindow(msg);
  670.                 break;
  671.  
  672.             case 0x85: //rotate item
  673.                 parseRotateItem(msg);
  674.                 break;
  675.  
  676.             case 0x87: // close container
  677.                 parseCloseContainer(msg);
  678.                 break;
  679.  
  680.             case 0x88: //"up-arrow" - container
  681.                 parseUpArrowContainer(msg);
  682.                 break;
  683.  
  684.             case 0x89:
  685.                 parseTextWindow(msg);
  686.                 break;
  687.  
  688.             case 0x8A:
  689.                 parseHouseWindow(msg);
  690.                 break;
  691.  
  692.             case 0x8C: // throw item
  693.                 parseLookAt(msg);
  694.                 break;
  695.  
  696.             case 0x96: // say something
  697.                 parseSay(msg);
  698.                 break;
  699.  
  700.             case 0x97: // request channels
  701.                 parseGetChannels(msg);
  702.                 break;
  703.  
  704.             case 0x98: // open channel
  705.                 parseOpenChannel(msg);
  706.                 break;
  707.  
  708.             case 0x99: // close channel
  709.                 parseCloseChannel(msg);
  710.                 break;
  711.  
  712.             case 0x9A: // open priv
  713.                 parseOpenPriv(msg);
  714.                 break;
  715.  
  716.             case 0x9B: //process report
  717.                 parseProcessRuleViolation(msg);
  718.                 break;
  719.  
  720.             case 0x9C: //gm closes report
  721.                 parseCloseRuleViolation(msg);
  722.                 break;
  723.  
  724.             case 0x9D: //player cancels report
  725.                 parseCancelRuleViolation(msg);
  726.                 break;
  727.  
  728.             case 0x9E: // close NPC
  729.                 parseCloseNpc(msg);
  730.                 break;
  731.  
  732.             case 0xA0: // set attack and follow mode
  733.                 parseFightModes(msg);
  734.                 break;
  735.  
  736.             case 0xA1: // attack
  737.                 parseAttack(msg);
  738.                 break;
  739.  
  740.             case 0xA2: //follow
  741.                 parseFollow(msg);
  742.                 break;
  743.  
  744.             case 0xA3: // invite party
  745.                 parseInviteToParty(msg);
  746.                 break;
  747.  
  748.             case 0xA4: // join party
  749.                 parseJoinParty(msg);
  750.                 break;
  751.  
  752.             case 0xA5: // revoke party
  753.                 parseRevokePartyInvite(msg);
  754.                 break;
  755.  
  756.             case 0xA6: // pass leadership
  757.                 parsePassPartyLeadership(msg);
  758.                 break;
  759.  
  760.             case 0xA7: // leave party
  761.                 parseLeaveParty(msg);
  762.                 break;
  763.  
  764.             case 0xA8: // share exp
  765.                 parseSharePartyExperience(msg);
  766.                 break;
  767.  
  768.             case 0xAA:
  769.                 parseCreatePrivateChannel(msg);
  770.                 break;
  771.  
  772.             case 0xAB:
  773.                 parseChannelInvite(msg);
  774.                 break;
  775.  
  776.             case 0xAC:
  777.                 parseChannelExclude(msg);
  778.                 break;
  779.  
  780.             case 0xBE: // cancel move
  781.                 parseCancelMove(msg);
  782.                 break;
  783.  
  784.             case 0xC9: //client request to resend the tile
  785.                 parseUpdateTile(msg);
  786.                 break;
  787.  
  788.             case 0xCA: //client request to resend the container (happens when you store more than container maxsize)
  789.                 parseUpdateContainer(msg);
  790.                 break;
  791.  
  792.             case 0xD2: // request outfit
  793.                 if((!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || !g_config.getBool(
  794.                     ConfigManager::DISABLE_OUTFITS_PRIVILEGED)) && (g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT)
  795.                     || g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS) || g_config.getBool(ConfigManager::ALLOW_CHANGEADDONS)))
  796.                     parseRequestOutfit(msg);
  797.                 break;
  798.  
  799.             case 0xD3: // set outfit
  800.                 if((!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || !g_config.getBool(ConfigManager::DISABLE_OUTFITS_PRIVILEGED))
  801.                     && (g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS) || g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT)))
  802.                 parseSetOutfit(msg);
  803.                 break;
  804.  
  805.             case 0xDC:
  806.                 parseAddVip(msg);
  807.                 break;
  808.  
  809.             case 0xDD:
  810.                 parseRemoveVip(msg);
  811.                 break;
  812.  
  813.             case 0xE6:
  814.                 parseBugReport(msg);
  815.                 break;
  816.  
  817.             case 0xE7:
  818.                 parseViolationWindow(msg);
  819.                 break;
  820.  
  821.             case 0xE8:
  822.                 parseDebugAssert(msg);
  823.                 break;
  824.  
  825.             case 0xF0:
  826.                 parseQuests(msg);
  827.                 break;
  828.  
  829.             case 0xF1:
  830.                 parseQuestInfo(msg);
  831.                 break;
  832.                
  833.             case 0xF4:
  834.                 parseMarketLeave();
  835.                 break;
  836.  
  837.             case 0xF5:
  838.                 parseMarketBrowse(msg);
  839.                 break;
  840.  
  841.             case 0xF6:
  842.                 parseMarketCreateOffer(msg);
  843.                 break;
  844.  
  845.             case 0xF7:
  846.                 parseMarketCancelOffer(msg);
  847.                 break;
  848.  
  849.             case 0xF8:
  850.                 parseMarketAcceptOffer(msg);
  851.                 break;
  852.                
  853.             case 0xFF:
  854.                 parseMarketItemDesc(msg);
  855.                 break;
  856.  
  857.             default:
  858.             {
  859.                 if(g_config.getBool(ConfigManager::BAN_UNKNOWN_BYTES))
  860.                 {
  861.                     int64_t banTime = -1;
  862.                     ViolationAction_t action = ACTION_BANISHMENT;
  863.                     Account tmp = IOLoginData::getInstance()->loadAccount(player->getAccount(), true);
  864.  
  865.                     tmp.warnings++;
  866.                     if(tmp.warnings >= g_config.getNumber(ConfigManager::WARNINGS_TO_DELETION))
  867.                         action = ACTION_DELETION;
  868.                     else if(tmp.warnings >= g_config.getNumber(ConfigManager::WARNINGS_TO_FINALBAN))
  869.                     {
  870.                         banTime = time(NULL) + g_config.getNumber(ConfigManager::FINALBAN_LENGTH);
  871.                         action = ACTION_BANFINAL;
  872.                     }
  873.                     else
  874.                         banTime = time(NULL) + g_config.getNumber(ConfigManager::BAN_LENGTH);
  875.  
  876.                     if(IOBan::getInstance()->addAccountBanishment(tmp.number, banTime, 13, action,
  877.                         "Sending unknown packets to the server.", 0, player->getGUID()))
  878.                     {
  879.                         IOLoginData::getInstance()->saveAccount(tmp);
  880.                         player->sendTextMessage(MSG_INFO_DESCR, "You have been banished.");
  881.  
  882.                         g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_GREEN);
  883.                         Scheduler::getInstance().addEvent(createSchedulerTask(1000, boost::bind(
  884.                             &Game::kickPlayer, &g_game, player->getID(), false)));
  885.                     }
  886.                 }
  887.  
  888.                 std::stringstream hex, s;
  889.                 hex << "0x" << std::hex << (int16_t)recvbyte << std::dec;
  890.                 s << player->getName() << " sent unknown byte: " << hex << std::endl;
  891.  
  892.                 LOG_MESSAGE(LOGTYPE_NOTICE, s.str(), "PLAYER")
  893.                 Logger::getInstance()->eFile(getFilePath(FILE_TYPE_LOG, "bots/" + player->getName() + ".log").c_str(),
  894.                     "[" + formatDate() + "] Received byte " + hex.str(), false);
  895.                 break;
  896.             }
  897.         }
  898.     }
  899. }
  900.  
  901. void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage_ptr msg)
  902. {
  903.     if(!tile)
  904.         return;
  905.  
  906.     int32_t count = 0;
  907.     if(tile->ground)
  908.     {
  909.         msg->AddItem(tile->ground);
  910.         count++;
  911.     }
  912.  
  913.     const TileItemVector* items = tile->getItemList();
  914.     const CreatureVector* creatures = tile->getCreatures();
  915.  
  916.     ItemVector::const_iterator it;
  917.     if(items)
  918.     {
  919.         for(it = items->getBeginTopItem(); (it != items->getEndTopItem() && count < 10); ++it, ++count)
  920.             msg->AddItem(*it);
  921.     }
  922.  
  923.     if(creatures)
  924.     {
  925.         for(CreatureVector::const_reverse_iterator cit = creatures->rbegin(); (cit != creatures->rend() && count < 10); ++cit)
  926.         {
  927.             if(!player->canSeeCreature(*cit))
  928.                 continue;
  929.  
  930.             bool known;
  931.             uint32_t removedKnown;
  932.             checkCreatureAsKnown((*cit)->getID(), known, removedKnown);
  933.  
  934.             AddCreature(msg, (*cit), known, removedKnown);
  935.             count++;
  936.         }
  937.     }
  938.  
  939.     if(items)
  940.     {
  941.         for(it = items->getBeginDownItem(); (it != items->getEndDownItem() && count < 10); ++it, ++count)
  942.             msg->AddItem(*it);
  943.     }
  944. }
  945.  
  946. void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z,
  947.     int32_t width, int32_t height, NetworkMessage_ptr msg)
  948. {
  949.     int32_t skip = -1, startz, endz, zstep = 0;
  950.     if(z > 7)
  951.     {
  952.         startz = z - 2;
  953.         endz = std::min((int32_t)MAP_MAX_LAYERS - 1, z + 2);
  954.         zstep = 1;
  955.     }
  956.     else
  957.     {
  958.         startz = 7;
  959.         endz = 0;
  960.         zstep = -1;
  961.     }
  962.  
  963.     for(int32_t nz = startz; nz != endz + zstep; nz += zstep)
  964.         GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip);
  965.  
  966.     if(skip >= 0)
  967.     {
  968.         msg->AddByte(skip);
  969.         msg->AddByte(0xFF);
  970.         //cc += skip;
  971.     }
  972. }
  973.  
  974. void ProtocolGame::GetFloorDescription(NetworkMessage_ptr msg, int32_t x, int32_t y, int32_t z,
  975.         int32_t width, int32_t height, int32_t offset, int32_t& skip)
  976. {
  977.     Tile* tile = NULL;
  978.     for(int32_t nx = 0; nx < width; nx++)
  979.     {
  980.         for(int32_t ny = 0; ny < height; ny++)
  981.         {
  982.             if((tile = g_game.getTile(Position(x + nx + offset, y + ny + offset, z))))
  983.             {
  984.                 if(skip >= 0)
  985.                 {
  986.                     msg->AddByte(skip);
  987.                     msg->AddByte(0xFF);
  988.                 }
  989.  
  990.                 skip = 0;
  991.                 GetTileDescription(tile, msg);
  992.             }
  993.             else
  994.             {
  995.                 ++skip;
  996.                 if(skip == 0xFF)
  997.                 {
  998.                     msg->AddByte(0xFF);
  999.                     msg->AddByte(0xFF);
  1000.                     skip = -1;
  1001.                 }
  1002.             }
  1003.         }
  1004.     }
  1005. }
  1006.  
  1007. void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool& known, uint32_t& removedKnown)
  1008. {
  1009.     // loop through the known creature list and check if the given creature is in
  1010.     for(std::list<uint32_t>::iterator it = knownCreatureList.begin(); it != knownCreatureList.end(); ++it)
  1011.     {
  1012.         if((*it) != id)
  1013.             continue;
  1014.  
  1015.         // know... make the creature even more known...
  1016.         knownCreatureList.erase(it);
  1017.         knownCreatureList.push_back(id);
  1018.  
  1019.         known = true;
  1020.         return;
  1021.     }
  1022.  
  1023.     // ok, he is unknown...
  1024.     known = false;
  1025.     // ... but not in future
  1026.     knownCreatureList.push_back(id);
  1027.     // too many known creatures?
  1028.     if(knownCreatureList.size() > 250)
  1029.     {
  1030.         // lets try to remove one from the end of the list
  1031.         Creature* c = NULL;
  1032.         for(int32_t n = 0; n < 250; n++)
  1033.         {
  1034.             removedKnown = knownCreatureList.front();
  1035.             if(!(c = g_game.getCreatureByID(removedKnown)) || !canSee(c))
  1036.                 break;
  1037.  
  1038.             // this creature we can't remove, still in sight, so back to the end
  1039.             knownCreatureList.pop_front();
  1040.             knownCreatureList.push_back(removedKnown);
  1041.         }
  1042.  
  1043.         // hopefully we found someone to remove :S, we got only 250 tries
  1044.         // if not... lets kick some players with debug errors :)
  1045.         knownCreatureList.pop_front();
  1046.     }
  1047.     else // we can cache without problems :)
  1048.         removedKnown = 0;
  1049. }
  1050.  
  1051. bool ProtocolGame::canSee(const Creature* c) const
  1052. {
  1053.     return !c->isRemoved() && player->canSeeCreature(c) && canSee(c->getPosition());
  1054. }
  1055.  
  1056. bool ProtocolGame::canSee(const Position& pos) const
  1057. {
  1058.     return canSee(pos.x, pos.y, pos.z);
  1059. }
  1060.  
  1061. bool ProtocolGame::canSee(uint16_t x, uint16_t y, uint16_t z) const
  1062. {
  1063. #ifdef __DEBUG__
  1064.     if(z < 0 || z >= MAP_MAX_LAYERS)
  1065.         std::cout << "[Warning - ProtocolGame::canSee] Z-value is out of range!" << std::endl;
  1066. #endif
  1067.  
  1068.     const Position& myPos = player->getPosition();
  1069.     if(myPos.z <= 7)
  1070.     {
  1071.         //we are on ground level or above (7 -> 0), view is from 7 -> 0
  1072.         if(z > 7)
  1073.             return false;
  1074.     }
  1075.     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
  1076.         return false;
  1077.  
  1078.     //negative offset means that the action taken place is on a lower floor than ourself
  1079.     int32_t offsetz = myPos.z - z;
  1080.     return ((x >= myPos.x - Map::maxClientViewportX + offsetz) && (x <= myPos.x + (Map::maxClientViewportX+1) + offsetz) &&
  1081.         (y >= myPos.y - Map::maxClientViewportY + offsetz) && (y <= myPos.y + (Map::maxClientViewportY+1) + offsetz));
  1082. }
  1083.  
  1084. //********************** Parse methods *******************************//
  1085. void ProtocolGame::parseLogout(NetworkMessage& msg)
  1086. {
  1087.     Dispatcher::getInstance().addTask(createTask(boost::bind(&ProtocolGame::logout, this, true, false)));
  1088. }
  1089.  
  1090. void ProtocolGame::parseCreatePrivateChannel(NetworkMessage& msg)
  1091. {
  1092.     addGameTask(&Game::playerCreatePrivateChannel, player->getID());
  1093. }
  1094.  
  1095. void ProtocolGame::parseChannelInvite(NetworkMessage& msg)
  1096. {
  1097.     const std::string name = msg.GetString();
  1098.     addGameTask(&Game::playerChannelInvite, player->getID(), name);
  1099. }
  1100.  
  1101. void ProtocolGame::parseChannelExclude(NetworkMessage& msg)
  1102. {
  1103.     const std::string name = msg.GetString();
  1104.     addGameTask(&Game::playerChannelExclude, player->getID(), name);
  1105. }
  1106.  
  1107. void ProtocolGame::parseGetChannels(NetworkMessage& msg)
  1108. {
  1109.     addGameTask(&Game::playerRequestChannels, player->getID());
  1110. }
  1111.  
  1112. void ProtocolGame::parseOpenChannel(NetworkMessage& msg)
  1113. {
  1114.     uint16_t channelId = msg.GetU16();
  1115.     addGameTask(&Game::playerOpenChannel, player->getID(), channelId);
  1116. }
  1117.  
  1118. void ProtocolGame::parseCloseChannel(NetworkMessage& msg)
  1119. {
  1120.     uint16_t channelId = msg.GetU16();
  1121.     addGameTask(&Game::playerCloseChannel, player->getID(), channelId);
  1122. }
  1123.  
  1124. void ProtocolGame::parseOpenPriv(NetworkMessage& msg)
  1125. {
  1126.     const std::string receiver = msg.GetString();
  1127.     addGameTask(&Game::playerOpenPrivateChannel, player->getID(), receiver);
  1128. }
  1129.  
  1130. void ProtocolGame::parseProcessRuleViolation(NetworkMessage& msg)
  1131. {
  1132.     const std::string reporter = msg.GetString();
  1133.     addGameTask(&Game::playerProcessRuleViolation, player->getID(), reporter);
  1134. }
  1135.  
  1136. void ProtocolGame::parseCloseRuleViolation(NetworkMessage& msg)
  1137. {
  1138.     const std::string reporter = msg.GetString();
  1139.     addGameTask(&Game::playerCloseRuleViolation, player->getID(), reporter);
  1140. }
  1141.  
  1142. void ProtocolGame::parseCancelRuleViolation(NetworkMessage& msg)
  1143. {
  1144.     addGameTask(&Game::playerCancelRuleViolation, player->getID());
  1145. }
  1146.  
  1147. void ProtocolGame::parseCloseNpc(NetworkMessage& msg)
  1148. {
  1149.     addGameTask(&Game::playerCloseNpcChannel, player->getID());
  1150. }
  1151.  
  1152. void ProtocolGame::parseCancelMove(NetworkMessage& msg)
  1153. {
  1154.     addGameTask(&Game::playerCancelAttackAndFollow, player->getID());
  1155. }
  1156.  
  1157. void ProtocolGame::parseReceivePing(NetworkMessage& msg)
  1158. {
  1159.     addGameTask(&Game::playerReceivePing, player->getID());
  1160. }
  1161.  
  1162. void ProtocolGame::parseAutoWalk(NetworkMessage& msg)
  1163. {
  1164.     // first we get all directions...
  1165.     std::list<Direction> path;
  1166.     size_t dirCount = msg.GetByte();
  1167.     for(size_t i = 0; i < dirCount; ++i)
  1168.     {
  1169.         uint8_t rawDir = msg.GetByte();
  1170.         Direction dir = SOUTH;
  1171.         switch(rawDir)
  1172.         {
  1173.             case 1:
  1174.                 dir = EAST;
  1175.                 break;
  1176.             case 2:
  1177.                 dir = NORTHEAST;
  1178.                 break;
  1179.             case 3:
  1180.                 dir = NORTH;
  1181.                 break;
  1182.             case 4:
  1183.                 dir = NORTHWEST;
  1184.                 break;
  1185.             case 5:
  1186.                 dir = WEST;
  1187.                 break;
  1188.             case 6:
  1189.                 dir = SOUTHWEST;
  1190.                 break;
  1191.             case 7:
  1192.                 dir = SOUTH;
  1193.                 break;
  1194.             case 8:
  1195.                 dir = SOUTHEAST;
  1196.                 break;
  1197.             default:
  1198.                 continue;
  1199.         }
  1200.  
  1201.         path.push_back(dir);
  1202.     }
  1203.  
  1204.     addGameTask(&Game::playerAutoWalk, player->getID(), path);
  1205. }
  1206.  
  1207. void ProtocolGame::parseMove(NetworkMessage& msg, Direction dir)
  1208. {
  1209.     addGameTask(&Game::playerMove, player->getID(), dir);
  1210. }
  1211.  
  1212. void ProtocolGame::parseTurn(NetworkMessage& msg, Direction dir)
  1213. {
  1214.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), dir);
  1215. }
  1216.  
  1217. void ProtocolGame::parseRequestOutfit(NetworkMessage& msg)
  1218. {
  1219.     addGameTask(&Game::playerRequestOutfit, player->getID());
  1220. }
  1221.  
  1222. void ProtocolGame::parseSetOutfit(NetworkMessage& msg)
  1223. {
  1224.     Outfit_t newOutfit = player->defaultOutfit;
  1225.     if(g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT))
  1226.         newOutfit.lookType = msg.GetU16();
  1227.     else
  1228.         msg.SkipBytes(2);
  1229.  
  1230.     if(g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS))
  1231.     {
  1232.         newOutfit.lookHead = msg.GetByte();
  1233.         newOutfit.lookBody = msg.GetByte();
  1234.         newOutfit.lookLegs = msg.GetByte();
  1235.         newOutfit.lookFeet = msg.GetByte();
  1236.     }
  1237.     else
  1238.         msg.SkipBytes(4);
  1239.  
  1240.     if(g_config.getBool(ConfigManager::ALLOW_CHANGEADDONS))
  1241.         newOutfit.lookAddons = msg.GetByte();
  1242.     else
  1243.         msg.SkipBytes(1);
  1244.  
  1245.     addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit);
  1246. }
  1247.  
  1248. void ProtocolGame::parseUseItem(NetworkMessage& msg)
  1249. {
  1250.     Position pos = msg.GetPosition();
  1251.     uint16_t spriteId = msg.GetSpriteId();
  1252.     int16_t stackpos = msg.GetByte();
  1253.     uint8_t index = msg.GetByte();
  1254.     bool isHotkey = (pos.x == 0xFFFF && !pos.y && !pos.z);
  1255.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItem, player->getID(), pos, stackpos, index, spriteId, isHotkey);
  1256. }
  1257.  
  1258. void ProtocolGame::parseUseItemEx(NetworkMessage& msg)
  1259. {
  1260.     Position fromPos = msg.GetPosition();
  1261.     uint16_t fromSpriteId = msg.GetSpriteId();
  1262.     int16_t fromStackpos = msg.GetByte();
  1263.     Position toPos = msg.GetPosition();
  1264.     uint16_t toSpriteId = msg.GetU16();
  1265.     int16_t toStackpos = msg.GetByte();
  1266.     bool isHotkey = (fromPos.x == 0xFFFF && !fromPos.y && !fromPos.z);
  1267.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItemEx, player->getID(),
  1268.         fromPos, fromStackpos, fromSpriteId, toPos, toStackpos, toSpriteId, isHotkey);
  1269. }
  1270.  
  1271. void ProtocolGame::parseBattleWindow(NetworkMessage& msg)
  1272. {
  1273.     Position fromPos = msg.GetPosition();
  1274.     uint16_t spriteId = msg.GetSpriteId();
  1275.     int16_t fromStackpos = msg.GetByte();
  1276.     uint32_t creatureId = msg.GetU32();
  1277.     bool isHotkey = (fromPos.x == 0xFFFF && !fromPos.y && !fromPos.z);
  1278.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseBattleWindow, player->getID(), fromPos, fromStackpos, creatureId, spriteId, isHotkey);
  1279. }
  1280.  
  1281. void ProtocolGame::parseCloseContainer(NetworkMessage& msg)
  1282. {
  1283.     uint8_t cid = msg.GetByte();
  1284.     addGameTask(&Game::playerCloseContainer, player->getID(), cid);
  1285. }
  1286.  
  1287. void ProtocolGame::parseUpArrowContainer(NetworkMessage& msg)
  1288. {
  1289.     uint8_t cid = msg.GetByte();
  1290.     addGameTask(&Game::playerMoveUpContainer, player->getID(), cid);
  1291. }
  1292.  
  1293. void ProtocolGame::parseUpdateTile(NetworkMessage& msg)
  1294. {
  1295.     Position pos = msg.GetPosition();
  1296.     //addGameTask(&Game::playerUpdateTile, player->getID(), pos);
  1297. }
  1298.  
  1299. void ProtocolGame::parseUpdateContainer(NetworkMessage& msg)
  1300. {
  1301.     uint8_t cid = msg.GetByte();
  1302.     addGameTask(&Game::playerUpdateContainer, player->getID(), cid);
  1303. }
  1304.  
  1305. void ProtocolGame::parseThrow(NetworkMessage& msg)
  1306. {
  1307.     Position fromPos = msg.GetPosition();
  1308.     uint16_t spriteId = msg.GetSpriteId();
  1309.     int16_t fromStackpos = msg.GetByte();
  1310.     Position toPos = msg.GetPosition();
  1311.     uint8_t count = msg.GetByte();
  1312.     if(toPos != fromPos)
  1313.         addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerMoveThing,
  1314.             player->getID(), fromPos, spriteId, fromStackpos, toPos, count);
  1315. }
  1316.  
  1317. void ProtocolGame::parseLookAt(NetworkMessage& msg)
  1318. {
  1319.     Position pos = msg.GetPosition();
  1320.     uint16_t spriteId = msg.GetSpriteId();
  1321.     int16_t stackpos = msg.GetByte();
  1322.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookAt, player->getID(), pos, spriteId, stackpos);
  1323. }
  1324.  
  1325. void ProtocolGame::parseSay(NetworkMessage& msg)
  1326. {
  1327.     std::string receiver;
  1328.     uint16_t channelId = 0;
  1329.  
  1330.     SpeakClasses type = (SpeakClasses)msg.GetByte();
  1331.     switch(type)
  1332.     {
  1333.         case SPEAK_PRIVATE:
  1334.         case SPEAK_PRIVATE_RED:
  1335.         case SPEAK_RVR_ANSWER:
  1336.             receiver = msg.GetString();
  1337.             break;
  1338.  
  1339.         case SPEAK_CHANNEL_Y:
  1340.         case SPEAK_CHANNEL_RN:
  1341.         case SPEAK_CHANNEL_RA:
  1342.             channelId = msg.GetU16();
  1343.             break;
  1344.  
  1345.         default:
  1346.             break;
  1347.     }
  1348.  
  1349.     const std::string text = msg.GetString();
  1350.     if(text.length() > 255) //client limit
  1351.     {
  1352.         std::stringstream s;
  1353.         s << text.length();
  1354.  
  1355.         Logger::getInstance()->eFile("bots/" + player->getName() + ".log", "Attempt to send message with size " + s.str() + " - client is limited to 255 characters.", true);
  1356.         return;
  1357.     }
  1358.  
  1359.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSay, player->getID(), channelId, type, receiver, text);
  1360. }
  1361.  
  1362. void ProtocolGame::parseFightModes(NetworkMessage& msg)
  1363. {
  1364.     uint8_t rawFightMode = msg.GetByte(); //1 - offensive, 2 - balanced, 3 - defensive
  1365.     uint8_t rawChaseMode = msg.GetByte(); //0 - stand while fightning, 1 - chase opponent
  1366.     uint8_t rawSecureMode = msg.GetByte(); //0 - can't attack unmarked, 1 - can attack unmarked
  1367.  
  1368.     chaseMode_t chaseMode = CHASEMODE_STANDSTILL;
  1369.     if(rawChaseMode == 1)
  1370.         chaseMode = CHASEMODE_FOLLOW;
  1371.  
  1372.     fightMode_t fightMode = FIGHTMODE_ATTACK;
  1373.     if(rawFightMode == 2)
  1374.         fightMode = FIGHTMODE_BALANCED;
  1375.     else if(rawFightMode == 3)
  1376.         fightMode = FIGHTMODE_DEFENSE;
  1377.  
  1378.     secureMode_t secureMode = SECUREMODE_OFF;
  1379.     if(rawSecureMode == 1)
  1380.         secureMode = SECUREMODE_ON;
  1381.  
  1382.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSetFightModes, player->getID(), fightMode, chaseMode, secureMode);
  1383. }
  1384.  
  1385. void ProtocolGame::parseAttack(NetworkMessage& msg)
  1386. {
  1387.     uint32_t creatureId = msg.GetU32();
  1388.     addGameTask(&Game::playerSetAttackedCreature, player->getID(), creatureId);
  1389. }
  1390.  
  1391. void ProtocolGame::parseFollow(NetworkMessage& msg)
  1392. {
  1393.     uint32_t creatureId = msg.GetU32();
  1394.     addGameTask(&Game::playerFollowCreature, player->getID(), creatureId);
  1395. }
  1396.  
  1397. void ProtocolGame::parseTextWindow(NetworkMessage& msg)
  1398. {
  1399.     uint32_t windowTextId = msg.GetU32();
  1400.     const std::string newText = msg.GetString();
  1401.     addGameTask(&Game::playerWriteItem, player->getID(), windowTextId, newText);
  1402. }
  1403.  
  1404. void ProtocolGame::parseHouseWindow(NetworkMessage &msg)
  1405. {
  1406.     uint8_t doorId = msg.GetByte();
  1407.     uint32_t id = msg.GetU32();
  1408.     const std::string text = msg.GetString();
  1409.     addGameTask(&Game::playerUpdateHouseWindow, player->getID(), doorId, id, text);
  1410. }
  1411.  
  1412. void ProtocolGame::parseLookInShop(NetworkMessage &msg)
  1413. {
  1414.     // uint16_t id = msg.GetU16();
  1415.     // uint16_t count = msg.GetByte();
  1416.     // addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInShop, player->getID(), id, count);
  1417. }
  1418.  
  1419. void ProtocolGame::parsePlayerPurchase(NetworkMessage &msg)
  1420. {
  1421.     uint16_t id = msg.GetU16();
  1422.     uint16_t count = msg.GetByte();
  1423.     uint16_t amount = msg.GetByte();
  1424.     bool ignoreCap = msg.GetByte();
  1425.     bool inBackpacks = msg.GetByte();
  1426.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerPurchaseItem, player->getID(), id, count, amount, ignoreCap, inBackpacks);
  1427. }
  1428.  
  1429. void ProtocolGame::parsePlayerSale(NetworkMessage &msg)
  1430. {
  1431.     uint16_t id = msg.GetU16();
  1432.     uint16_t count = msg.GetByte();
  1433.     uint16_t amount = msg.GetByte();
  1434.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSellItem, player->getID(), id, count, amount);
  1435. }
  1436.  
  1437. void ProtocolGame::parseCloseShop(NetworkMessage &msg)
  1438. {
  1439.     addGameTask(&Game::playerCloseShop, player->getID());
  1440. }
  1441.  
  1442. void ProtocolGame::parseRequestTrade(NetworkMessage& msg)
  1443. {
  1444.     Position pos = msg.GetPosition();
  1445.     uint16_t spriteId = msg.GetSpriteId();
  1446.     int16_t stackpos = msg.GetByte();
  1447.     uint32_t playerId = msg.GetU32();
  1448.     addGameTask(&Game::playerRequestTrade, player->getID(), pos, stackpos, playerId, spriteId);
  1449. }
  1450.  
  1451. void ProtocolGame::parseAcceptTrade(NetworkMessage& msg)
  1452. {
  1453.     addGameTask(&Game::playerAcceptTrade, player->getID());
  1454. }
  1455.  
  1456. void ProtocolGame::parseLookInTrade(NetworkMessage& msg)
  1457. {
  1458.     bool counter = msg.GetByte();
  1459.     int32_t index = msg.GetByte();
  1460.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInTrade, player->getID(), counter, index);
  1461. }
  1462.  
  1463. void ProtocolGame::parseCloseTrade()
  1464. {
  1465.     addGameTask(&Game::playerCloseTrade, player->getID());
  1466. }
  1467.  
  1468. void ProtocolGame::parseAddVip(NetworkMessage& msg)
  1469. {
  1470.     const std::string name = msg.GetString();
  1471.     if(name.size() > 32)
  1472.         return;
  1473.  
  1474.     addGameTask(&Game::playerRequestAddVip, player->getID(), name);
  1475. }
  1476.  
  1477. void ProtocolGame::parseRemoveVip(NetworkMessage& msg)
  1478. {
  1479.     uint32_t guid = msg.GetU32();
  1480.     addGameTask(&Game::playerRequestRemoveVip, player->getID(), guid);
  1481. }
  1482.  
  1483. void ProtocolGame::parseRotateItem(NetworkMessage& msg)
  1484. {
  1485.     Position pos = msg.GetPosition();
  1486.     uint16_t spriteId = msg.GetSpriteId();
  1487.     int16_t stackpos = msg.GetByte();
  1488.     addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerRotateItem, player->getID(), pos, stackpos, spriteId);
  1489. }
  1490.  
  1491. void ProtocolGame::parseDebugAssert(NetworkMessage& msg)
  1492. {
  1493.     if(m_debugAssertSent)
  1494.         return;
  1495.  
  1496.     std::stringstream s;
  1497.     s << "----- " << formatDate() << " - " << player->getName() << " (" << convertIPAddress(getIP())
  1498.         << ") -----" << std::endl << msg.GetString() << std::endl << msg.GetString()
  1499.         << std::endl << msg.GetString() << std::endl << msg.GetString()
  1500.         << std::endl << std::endl;
  1501.  
  1502.     m_debugAssertSent = true;
  1503.     Logger::getInstance()->iFile(LOGFILE_CLIENT_ASSERTION, s.str(), false);
  1504. }
  1505.  
  1506. void ProtocolGame::parseBugReport(NetworkMessage& msg)
  1507. {
  1508.     std::string comment = msg.GetString();
  1509.     addGameTask(&Game::playerReportBug, player->getID(), comment);
  1510. }
  1511.  
  1512. void ProtocolGame::parseInviteToParty(NetworkMessage& msg)
  1513. {
  1514.     uint32_t targetId = msg.GetU32();
  1515.     addGameTask(&Game::playerInviteToParty, player->getID(), targetId);
  1516. }
  1517.  
  1518. void ProtocolGame::parseJoinParty(NetworkMessage& msg)
  1519. {
  1520.     uint32_t targetId = msg.GetU32();
  1521.     addGameTask(&Game::playerJoinParty, player->getID(), targetId);
  1522. }
  1523.  
  1524. void ProtocolGame::parseRevokePartyInvite(NetworkMessage& msg)
  1525. {
  1526.     uint32_t targetId = msg.GetU32();
  1527.     addGameTask(&Game::playerRevokePartyInvitation, player->getID(), targetId);
  1528. }
  1529.  
  1530. void ProtocolGame::parsePassPartyLeadership(NetworkMessage& msg)
  1531. {
  1532.     uint32_t targetId = msg.GetU32();
  1533.     addGameTask(&Game::playerPassPartyLeadership, player->getID(), targetId);
  1534. }
  1535.  
  1536. void ProtocolGame::parseLeaveParty(NetworkMessage& msg)
  1537. {
  1538.     addGameTask(&Game::playerLeaveParty, player->getID());
  1539. }
  1540.  
  1541. void ProtocolGame::parseSharePartyExperience(NetworkMessage& msg)
  1542. {
  1543.     bool activate = msg.GetByte();
  1544.     uint8_t unknown = msg.GetByte(); //TODO: find out what is this byte
  1545.     addGameTask(&Game::playerSharePartyExperience, player->getID(), activate, unknown);
  1546. }
  1547.  
  1548. void ProtocolGame::parseQuests(NetworkMessage& msg)
  1549. {
  1550.     addGameTask(&Game::playerQuests, player->getID());
  1551. }
  1552.  
  1553. void ProtocolGame::parseQuestInfo(NetworkMessage& msg)
  1554. {
  1555.     uint16_t questId = msg.GetU16();
  1556.     addGameTask(&Game::playerQuestInfo, player->getID(), questId);
  1557. }
  1558.  
  1559. void ProtocolGame::parseViolationWindow(NetworkMessage& msg)
  1560. {
  1561.     std::string target = msg.GetString();
  1562.     uint8_t reason = msg.GetByte();
  1563.     ViolationAction_t action = (ViolationAction_t)msg.GetByte();
  1564.     std::string comment = msg.GetString();
  1565.     std::string statement = msg.GetString();
  1566.     uint32_t statementId = (uint32_t)msg.GetU16();
  1567.     bool ipBanishment = msg.GetByte();
  1568.     addGameTask(&Game::playerViolationWindow, player->getID(), target, reason, action, comment, statement, statementId, ipBanishment);
  1569. }
  1570.  
  1571. //********************** Send methods *******************************//
  1572. void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver)
  1573. {
  1574.     NetworkMessage_ptr msg = getOutputBuffer();
  1575.     if(msg)
  1576.     {
  1577.         TRACK_MESSAGE(msg);
  1578.         msg->AddByte(0xAD);
  1579.         msg->AddString(receiver);
  1580.     }
  1581. }
  1582.  
  1583. void ProtocolGame::sendCreatureOutfit(const Creature* creature, const Outfit_t& outfit)
  1584. {
  1585.     if(!canSee(creature))
  1586.         return;
  1587.  
  1588.     NetworkMessage_ptr msg = getOutputBuffer();
  1589.     if(msg)
  1590.     {
  1591.         TRACK_MESSAGE(msg);
  1592.         msg->AddByte(0x8E);
  1593.         msg->AddU32(creature->getID());
  1594.         AddCreatureOutfit(msg, creature, outfit);
  1595.     }
  1596. }
  1597.  
  1598. void ProtocolGame::sendCreatureLight(const Creature* creature)
  1599. {
  1600.     if(!canSee(creature))
  1601.         return;
  1602.  
  1603.     NetworkMessage_ptr msg = getOutputBuffer();
  1604.     if(msg)
  1605.     {
  1606.         TRACK_MESSAGE(msg);
  1607.         AddCreatureLight(msg, creature);
  1608.     }
  1609. }
  1610.  
  1611. void ProtocolGame::sendWorldLight(const LightInfo& lightInfo)
  1612. {
  1613.     NetworkMessage_ptr msg = getOutputBuffer();
  1614.     if(msg)
  1615.     {
  1616.         TRACK_MESSAGE(msg);
  1617.         AddWorldLight(msg, lightInfo);
  1618.     }
  1619. }
  1620.  
  1621. void ProtocolGame::sendCreatureShield(const Creature* creature)
  1622. {
  1623.     if(!canSee(creature))
  1624.         return;
  1625.  
  1626.     NetworkMessage_ptr msg = getOutputBuffer();
  1627.     if(msg)
  1628.     {
  1629.         TRACK_MESSAGE(msg);
  1630.         msg->AddByte(0x91);
  1631.         msg->AddU32(creature->getID());
  1632.         msg->AddByte(player->getPartyShield(creature));
  1633.     }
  1634. }
  1635.  
  1636. void ProtocolGame::sendCreatureSkull(const Creature* creature)
  1637. {
  1638.     if(!canSee(creature))
  1639.         return;
  1640.  
  1641.     NetworkMessage_ptr msg = getOutputBuffer();
  1642.     if(msg)
  1643.     {
  1644.         TRACK_MESSAGE(msg);
  1645.         msg->AddByte(0x90);
  1646.         msg->AddU32(creature->getID());
  1647.         msg->AddByte(player->getSkullClient(creature));
  1648.     }
  1649. }
  1650.  
  1651. void ProtocolGame::sendCreatureSquare(const Creature* creature, SquareColor_t color)
  1652. {
  1653.     if(!canSee(creature))
  1654.         return;
  1655.  
  1656.     NetworkMessage_ptr msg = getOutputBuffer();
  1657.     if(msg)
  1658.     {
  1659.         TRACK_MESSAGE(msg);
  1660.         msg->AddByte(0x86);
  1661.         msg->AddU32(creature->getID());
  1662.         msg->AddByte((uint8_t)color);
  1663.     }
  1664. }
  1665.  
  1666. void ProtocolGame::sendTutorial(uint8_t tutorialId)
  1667. {
  1668.     NetworkMessage_ptr msg = getOutputBuffer();
  1669.     if(msg)
  1670.     {
  1671.         TRACK_MESSAGE(msg);
  1672.         msg->AddByte(0xDC);
  1673.         msg->AddByte(tutorialId);
  1674.     }
  1675. }
  1676.  
  1677. void ProtocolGame::sendAddMarker(const Position& pos, MapMarks_t markType, const std::string& desc)
  1678. {
  1679.     NetworkMessage_ptr msg = getOutputBuffer();
  1680.     if(msg)
  1681.     {
  1682.         TRACK_MESSAGE(msg);
  1683.         msg->AddByte(0xDD);
  1684.         msg->AddPosition(pos);
  1685.         msg->AddByte(markType);
  1686.         msg->AddString(desc);
  1687.     }
  1688. }
  1689.  
  1690. void ProtocolGame::sendReLoginWindow()
  1691. {
  1692.     NetworkMessage_ptr msg = getOutputBuffer();
  1693.     if(msg)
  1694.     {
  1695.         TRACK_MESSAGE(msg);
  1696.         msg->AddByte(0x28);
  1697.     }
  1698. }
  1699.  
  1700. void ProtocolGame::sendStats()
  1701. {
  1702.     NetworkMessage_ptr msg = getOutputBuffer();
  1703.     if(msg)
  1704.     {
  1705.         TRACK_MESSAGE(msg);
  1706.         AddPlayerStats(msg);
  1707.     }
  1708. }
  1709.  
  1710. void ProtocolGame::sendTextMessage(MessageClasses mClass, const std::string& message)
  1711. {
  1712.     NetworkMessage_ptr msg = getOutputBuffer();
  1713.     if(msg)
  1714.     {
  1715.         TRACK_MESSAGE(msg);
  1716.         AddTextMessage(msg, mClass, message);
  1717.     }
  1718. }
  1719.  
  1720. void ProtocolGame::sendClosePrivate(uint16_t channelId)
  1721. {
  1722.     NetworkMessage_ptr msg = getOutputBuffer();
  1723.     if(msg)
  1724.     {
  1725.         TRACK_MESSAGE(msg);
  1726.         if(channelId == CHANNEL_GUILD || channelId == CHANNEL_PARTY)
  1727.             g_chat.removeUserFromChannel(player, channelId);
  1728.  
  1729.         msg->AddByte(0xB3);
  1730.         msg->AddU16(channelId);
  1731.     }
  1732. }
  1733.  
  1734. void ProtocolGame::sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName)
  1735. {
  1736.     NetworkMessage_ptr msg = getOutputBuffer();
  1737.     if(msg)
  1738.     {
  1739.         TRACK_MESSAGE(msg);
  1740.         msg->AddByte(0xB2);
  1741.         msg->AddU16(channelId);
  1742.         msg->AddString(channelName);
  1743.     }
  1744. }
  1745.  
  1746. void ProtocolGame::sendChannelsDialog()
  1747. {
  1748.     NetworkMessage_ptr msg = getOutputBuffer();
  1749.     if(msg)
  1750.     {
  1751.         TRACK_MESSAGE(msg);
  1752.         msg->AddByte(0xAB);
  1753.         ChannelList list = g_chat.getChannelList(player);
  1754.         msg->AddByte(list.size());
  1755.         for(ChannelList::iterator it = list.begin(); it != list.end(); ++it)
  1756.         {
  1757.             if(ChatChannel* channel = (*it))
  1758.             {
  1759.                 msg->AddU16(channel->getId());
  1760.                 msg->AddString(channel->getName());
  1761.             }
  1762.         }
  1763.     }
  1764. }
  1765.  
  1766. void ProtocolGame::protocolSendDuelChannels(int channels)
  1767. {
  1768.     NetworkMessage_ptr msg = getOutputBuffer();
  1769.     if(msg)
  1770.     {
  1771.         TRACK_MESSAGE(msg);
  1772.         msg->AddByte(0xAB);
  1773.         ChannelList list = g_chat.getChannelList(player);
  1774.         if(channels == 0) // janelas de escolha de quantidade de players a duelar
  1775.            msg->AddByte((list.size() - (list.size() -3)));
  1776.         else if (channels == 1) // janelas de escolha de quantidade de pokemons para duelar
  1777.            msg->AddByte((list.size() - (list.size() -6)));
  1778.                      
  1779.                        
  1780.         for(ChannelList::iterator it = list.begin(); it != list.end(); ++it)
  1781.         {
  1782.             if(ChatChannel* channel = (*it))
  1783.             {
  1784.                 if(channels == 0){
  1785.                   if((channel->getId() >= 8 && channel->getId() <= 10)){
  1786.                      msg->AddU16(channel->getId());
  1787.                      msg->AddString(channel->getName());
  1788.                   }
  1789.                 }else if(channels == 1){
  1790.                   if((channel->getId() >= 11 && channel->getId() <= 16)){
  1791.                      msg->AddU16(channel->getId());
  1792.                      msg->AddString(channel->getName());
  1793.                   }
  1794.                 }
  1795.             }
  1796.         }
  1797.     }
  1798. }
  1799.  
  1800. void ProtocolGame::sendChannel(uint16_t channelId, const std::string& channelName)
  1801. {
  1802.     NetworkMessage_ptr msg = getOutputBuffer();
  1803.     if(msg)
  1804.     {
  1805.         TRACK_MESSAGE(msg);
  1806.         msg->AddByte(0xAC);
  1807.         msg->AddU16(channelId);
  1808.         msg->AddString(channelName);
  1809.     }
  1810. }
  1811.  
  1812. void ProtocolGame::sendCustomChannelsDialog(std::vector<std::string>& newList, std::vector<int>& newId)
  1813. {
  1814.     NetworkMessage_ptr msg = getOutputBuffer();
  1815.        
  1816.     int c = 0;
  1817.        
  1818.     if(msg)
  1819.     {
  1820.         ChannelList list;
  1821.         for(std::vector<std::string>::const_iterator it = newList.begin(); it != newList.end(); ++it)
  1822.         {
  1823.             if(ChatChannel* newChannel = new ChatChannel((newId[c]), (*it), CHANNELFLAG_ENABLED))
  1824.             {
  1825.                 list.push_back(newChannel);
  1826.             }
  1827.             c++;
  1828.         }
  1829.        
  1830.            
  1831.         TRACK_MESSAGE(msg);
  1832.         msg->AddByte(0xAB);
  1833.         msg->AddByte(list.size());
  1834.         for(ChannelList::iterator it = list.begin(); it != list.end(); ++it)
  1835.         {
  1836.             if(ChatChannel* channel = (*it))
  1837.             {
  1838.                 msg->AddU16(channel->getId());
  1839.                 msg->AddString(channel->getName());
  1840.             }
  1841.         }
  1842.     }
  1843. }
  1844.  
  1845. void ProtocolGame::sendRuleViolationsChannel(uint16_t channelId)
  1846. {
  1847.     NetworkMessage_ptr msg = getOutputBuffer();
  1848.     if(msg)
  1849.     {
  1850.         TRACK_MESSAGE(msg);
  1851.         msg->AddByte(0xAE);
  1852.         msg->AddU16(channelId);
  1853.         for(RuleViolationsMap::const_iterator it = g_game.getRuleViolations().begin(); it != g_game.getRuleViolations().end(); ++it)
  1854.         {
  1855.             RuleViolation& rvr = *it->second;
  1856.             if(rvr.isOpen && rvr.reporter)
  1857.                 AddCreatureSpeak(msg, rvr.reporter, SPEAK_RVR_CHANNEL, rvr.text, channelId, rvr.time);
  1858.         }
  1859.     }
  1860. }
  1861.  
  1862. void ProtocolGame::sendRemoveReport(const std::string& name)
  1863. {
  1864.     NetworkMessage_ptr msg = getOutputBuffer();
  1865.     if(msg)
  1866.     {
  1867.         TRACK_MESSAGE(msg);
  1868.         msg->AddByte(0xAF);
  1869.         msg->AddString(name);
  1870.     }
  1871. }
  1872.  
  1873. void ProtocolGame::sendRuleViolationCancel(const std::string& name)
  1874. {
  1875.     NetworkMessage_ptr msg = getOutputBuffer();
  1876.     if(msg)
  1877.     {
  1878.         TRACK_MESSAGE(msg);
  1879.         msg->AddByte(0xB0);
  1880.         msg->AddString(name);
  1881.     }
  1882. }
  1883.  
  1884. void ProtocolGame::sendLockRuleViolation()
  1885. {
  1886.     NetworkMessage_ptr msg = getOutputBuffer();
  1887.     if(msg)
  1888.     {
  1889.         TRACK_MESSAGE(msg);
  1890.         msg->AddByte(0xB1);
  1891.     }
  1892. }
  1893.  
  1894. void ProtocolGame::sendIcons(int32_t icons)
  1895. {
  1896.     NetworkMessage_ptr msg = getOutputBuffer();
  1897.     if(msg)
  1898.     {
  1899.         TRACK_MESSAGE(msg);
  1900.         msg->AddByte(0xA2);
  1901.         msg->AddU16(icons);
  1902.     }
  1903. }
  1904.  
  1905. void ProtocolGame::sendContainer(uint32_t cid, const Container* container, bool hasParent)
  1906. {
  1907.     NetworkMessage_ptr msg = getOutputBuffer();
  1908.     if(msg)
  1909.     {
  1910.         TRACK_MESSAGE(msg);
  1911.         msg->AddByte(0x6E);
  1912.         msg->AddByte(cid);
  1913.  
  1914.         msg->AddItemId(container);
  1915.         msg->AddString(container->getName());
  1916.         msg->AddByte(container->capacity());
  1917.  
  1918.         msg->AddByte(hasParent ? 0x01 : 0x00);
  1919.         msg->AddByte(std::min(container->size(), (uint32_t)255));
  1920.  
  1921.         ItemList::const_iterator cit = container->getItems();
  1922.         for(uint32_t i = 0; cit != container->getEnd() && i < 255; ++cit, ++i)
  1923.             msg->AddItem(*cit);
  1924.     }
  1925. }
  1926.  
  1927. void ProtocolGame::sendShop(const ShopInfoList& shop)
  1928. {
  1929.     NetworkMessage_ptr msg = getOutputBuffer();
  1930.     if(msg)
  1931.     {
  1932.         TRACK_MESSAGE(msg);
  1933.         msg->AddByte(0x7A);
  1934.         msg->AddByte(std::min(shop.size(), (size_t)255));
  1935.  
  1936.         ShopInfoList::const_iterator it = shop.begin();
  1937.         for(uint32_t i = 0; it != shop.end() && i < 255; ++it, ++i)
  1938.             AddShopItem(msg, (*it));
  1939.     }
  1940. }
  1941.  
  1942. void ProtocolGame::sendCloseShop()
  1943. {
  1944.     NetworkMessage_ptr msg = getOutputBuffer();
  1945.     if(msg)
  1946.     {
  1947.         TRACK_MESSAGE(msg);
  1948.         msg->AddByte(0x7C);
  1949.     }
  1950. }
  1951.  
  1952. void ProtocolGame::sendGoods(const ShopInfoList& shop)
  1953. {
  1954.     NetworkMessage_ptr msg = getOutputBuffer();
  1955.     if(msg)
  1956.     {
  1957.         TRACK_MESSAGE(msg);
  1958.         msg->AddByte(0x7B);
  1959.         msg->AddU32(g_game.getMoney(player));
  1960.  
  1961.         std::map<uint32_t, uint32_t> goodsMap;
  1962.         if(shop.size() >= 5)
  1963.         {
  1964.             for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit)
  1965.             {
  1966.                 if(sit->sellPrice < 0)
  1967.                     continue;
  1968.  
  1969.                 int8_t subType = -1;
  1970.                 if(sit->subType)
  1971.                 {
  1972.                     const ItemType& it = Item::items[sit->itemId];
  1973.                     if(it.hasSubType() && !it.stackable)
  1974.                         subType = sit->subType;
  1975.                 }
  1976.  
  1977.                 uint32_t count = player->__getItemTypeCount(sit->itemId, subType);
  1978.                 if(count > 0)
  1979.                     goodsMap[sit->itemId] = count;
  1980.             }
  1981.         }
  1982.         else
  1983.         {
  1984.             std::map<uint32_t, uint32_t> tmpMap;
  1985.             player->__getAllItemTypeCount(tmpMap);
  1986.             for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit)
  1987.             {
  1988.                 if(sit->sellPrice < 0)
  1989.                     continue;
  1990.  
  1991.                 int8_t subType = -1;
  1992.                 if(sit->subType)
  1993.                 {
  1994.                     const ItemType& it = Item::items[sit->itemId];
  1995.                     if(it.hasSubType() && !it.stackable)
  1996.                         subType = sit->subType;
  1997.                 }
  1998.  
  1999.                 if(subType != -1)
  2000.                 {
  2001.                     uint32_t count = player->__getItemTypeCount(sit->itemId, subType);
  2002.                     if(count > 0)
  2003.                         goodsMap[sit->itemId] = count;
  2004.                 }
  2005.                 else
  2006.                     goodsMap[sit->itemId] = tmpMap[sit->itemId];
  2007.             }
  2008.         }
  2009.  
  2010.         msg->AddByte(std::min(goodsMap.size(), (size_t)255));
  2011.         std::map<uint32_t, uint32_t>::const_iterator it = goodsMap.begin();
  2012.         for(uint32_t i = 0; it != goodsMap.end() && i < 255; ++it, ++i)
  2013.         {
  2014.             msg->AddItemId(it->first);
  2015.             msg->AddByte(std::min(it->second, (uint32_t)255));
  2016.         }
  2017.     }
  2018. }
  2019.  
  2020. void ProtocolGame::sendTradeItemRequest(const Player* player, const Item* item, bool ack)
  2021. {
  2022.     NetworkMessage_ptr msg = getOutputBuffer();
  2023.     if(msg)
  2024.     {
  2025.         TRACK_MESSAGE(msg);
  2026.         if(ack)
  2027.             msg->AddByte(0x7D);
  2028.         else
  2029.             msg->AddByte(0x7E);
  2030.  
  2031.         msg->AddString(player->getName());
  2032.         if(const Container* container = item->getContainer())
  2033.         {
  2034.             msg->AddByte(container->getItemHoldingCount() + 1);
  2035.             msg->AddItem(item);
  2036.             for(ContainerIterator it = container->begin(); it != container->end(); ++it)
  2037.                 msg->AddItem(*it);
  2038.         }
  2039.         else
  2040.         {
  2041.             msg->AddByte(1);
  2042.             msg->AddItem(item);
  2043.         }
  2044.     }
  2045. }
  2046.  
  2047. void ProtocolGame::sendCloseTrade()
  2048. {
  2049.     NetworkMessage_ptr msg = getOutputBuffer();
  2050.     if(msg)
  2051.     {
  2052.         TRACK_MESSAGE(msg);
  2053.         msg->AddByte(0x7F);
  2054.     }
  2055. }
  2056.  
  2057. void ProtocolGame::sendCloseContainer(uint32_t cid)
  2058. {
  2059.     NetworkMessage_ptr msg = getOutputBuffer();
  2060.     if(msg)
  2061.     {
  2062.         TRACK_MESSAGE(msg);
  2063.         msg->AddByte(0x6F);
  2064.         msg->AddByte(cid);
  2065.     }
  2066. }
  2067.  
  2068. void ProtocolGame::sendCreatureTurn(const Creature* creature, int16_t stackpos)
  2069. {
  2070.     if(stackpos >= 10 || !canSee(creature))
  2071.         return;
  2072.  
  2073.     NetworkMessage_ptr msg = getOutputBuffer();
  2074.     if(msg)
  2075.     {
  2076.         TRACK_MESSAGE(msg);
  2077.         msg->AddByte(0x6B);
  2078.         msg->AddPosition(creature->getPosition());
  2079.         msg->AddByte(stackpos);
  2080.         msg->AddU16(0x63); /*99*/
  2081.         msg->AddU32(creature->getID());
  2082.         msg->AddByte(creature->getDirection());
  2083.     }
  2084. }
  2085.  
  2086. void ProtocolGame::sendCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text, Position* pos/* = NULL*/)
  2087. {
  2088.     NetworkMessage_ptr msg = getOutputBuffer();
  2089.     if(msg)
  2090.     {
  2091.         TRACK_MESSAGE(msg);
  2092.         AddCreatureSpeak(msg, creature, type, text, 0, 0, pos);
  2093.     }
  2094. }
  2095.  
  2096. void ProtocolGame::sendToChannel(const Creature* creature, SpeakClasses type, const std::string& text, uint16_t channelId, uint32_t time /*= 0*/)
  2097. {
  2098.     NetworkMessage_ptr msg = getOutputBuffer();
  2099.     if(msg)
  2100.     {
  2101.         TRACK_MESSAGE(msg);
  2102.         AddCreatureSpeak(msg, creature, type, text, channelId, time);
  2103.     }
  2104. }
  2105.  
  2106. void ProtocolGame::sendCancel(const std::string& message)
  2107. {
  2108.     NetworkMessage_ptr msg = getOutputBuffer();
  2109.     if(msg)
  2110.     {
  2111.         TRACK_MESSAGE(msg);
  2112.         AddTextMessage(msg, MSG_STATUS_SMALL, message);
  2113.     }
  2114. }
  2115.  
  2116. void ProtocolGame::sendCancelTarget()
  2117. {
  2118.     NetworkMessage_ptr msg = getOutputBuffer();
  2119.     if(msg)
  2120.     {
  2121.         TRACK_MESSAGE(msg);
  2122.         msg->AddByte(0xA3);
  2123.     }
  2124. }
  2125.  
  2126. void ProtocolGame::sendChangeSpeed(const Creature* creature, uint32_t speed)
  2127. {
  2128.     if(!canSee(creature))
  2129.         return;
  2130.  
  2131.     NetworkMessage_ptr msg = getOutputBuffer();
  2132.     if(msg)
  2133.     {
  2134.         TRACK_MESSAGE(msg);
  2135.         msg->AddByte(0x8F);
  2136.         msg->AddU32(creature->getID());
  2137.         msg->AddU16(speed);
  2138.     }
  2139. }
  2140.  
  2141. void ProtocolGame::sendCancelWalk()
  2142. {
  2143.     NetworkMessage_ptr msg = getOutputBuffer();
  2144.     if(msg)
  2145.     {
  2146.         TRACK_MESSAGE(msg);
  2147.         msg->AddByte(0xB5);
  2148.         msg->AddByte(player->getDirection());
  2149.     }
  2150. }
  2151.  
  2152. void ProtocolGame::sendSkills()
  2153. {
  2154.     NetworkMessage_ptr msg = getOutputBuffer();
  2155.     if(msg)
  2156.     {
  2157.         TRACK_MESSAGE(msg);
  2158.         AddPlayerSkills(msg);
  2159.     }
  2160. }
  2161.  
  2162. void ProtocolGame::sendPing()
  2163. {
  2164.     NetworkMessage_ptr msg = getOutputBuffer();
  2165.     if(msg)
  2166.     {
  2167.         TRACK_MESSAGE(msg);
  2168.         msg->AddByte(0x1E);
  2169.     }
  2170. }
  2171.  
  2172. void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
  2173. {
  2174.     if(type > SHOOT_EFFECT_LAST || (!canSee(from) && !canSee(to)))
  2175.         return;
  2176.  
  2177.     NetworkMessage_ptr msg = getOutputBuffer();
  2178.     if(msg)
  2179.     {
  2180.         TRACK_MESSAGE(msg);
  2181.         AddDistanceShoot(msg, from, to, type);
  2182.     }
  2183. }
  2184.  
  2185. void ProtocolGame::sendMagicEffect(const Position& pos, uint16_t type)
  2186. {
  2187.     if(type > MAGIC_EFFECT_LAST || !canSee(pos))
  2188.         return;
  2189.  
  2190.     NetworkMessage_ptr msg = getOutputBuffer();
  2191.     if(msg)
  2192.     {
  2193.         TRACK_MESSAGE(msg);
  2194.         AddMagicEffect(msg, pos, type);
  2195.     }
  2196. }
  2197.  
  2198. void ProtocolGame::sendAnimatedText(const Position& pos, uint8_t color, std::string text)
  2199. {
  2200.     if(!canSee(pos))
  2201.         return;
  2202.  
  2203.     NetworkMessage_ptr msg = getOutputBuffer();
  2204.     if(msg)
  2205.     {
  2206.         TRACK_MESSAGE(msg);
  2207.         AddAnimatedText(msg, pos, color, text);
  2208.     }
  2209. }
  2210.  
  2211. void ProtocolGame::sendCreatureHealth(const Creature* creature)
  2212. {
  2213.     if(!canSee(creature))
  2214.         return;
  2215.  
  2216.     NetworkMessage_ptr msg = getOutputBuffer();
  2217.     if(msg)
  2218.     {
  2219.         TRACK_MESSAGE(msg);
  2220.         AddCreatureHealth(msg, creature);
  2221.     }
  2222. }
  2223.  
  2224. void ProtocolGame::sendFYIBox(const std::string& message)
  2225. {
  2226.     if(message.empty() || message.length() > 1018) //Prevent client debug when message is empty or length is > 1018 (not confirmed)
  2227.     {
  2228.         std::cout << "[Warning - ProtocolGame::sendFYIBox] Trying to send an empty or too huge message." << std::endl;
  2229.         return;
  2230.     }
  2231.  
  2232.     NetworkMessage_ptr msg = getOutputBuffer();
  2233.     if(msg)
  2234.     {
  2235.         TRACK_MESSAGE(msg);
  2236.         msg->AddByte(0x15);
  2237.         msg->AddString(message);
  2238.     }
  2239. }
  2240.  
  2241. //tile
  2242. void ProtocolGame::sendAddTileItem(const Tile* tile, const Position& pos, uint32_t stackpos, const Item* item)
  2243. {
  2244.     if(!canSee(pos))
  2245.         return;
  2246.  
  2247.     NetworkMessage_ptr msg = getOutputBuffer();
  2248.     if(msg)
  2249.     {
  2250.         TRACK_MESSAGE(msg);
  2251.         AddTileItem(msg, pos, stackpos, item);
  2252.     }
  2253. }
  2254.  
  2255. void ProtocolGame::sendUpdateTileItem(const Tile* tile, const Position& pos, uint32_t stackpos, const Item* item)
  2256. {
  2257.     if(!canSee(pos))
  2258.         return;
  2259.  
  2260.     NetworkMessage_ptr msg = getOutputBuffer();
  2261.     if(msg)
  2262.     {
  2263.         TRACK_MESSAGE(msg);
  2264.         UpdateTileItem(msg, pos, stackpos, item);
  2265.     }
  2266. }
  2267.  
  2268. void ProtocolGame::sendRemoveTileItem(const Tile* tile, const Position& pos, uint32_t stackpos)
  2269. {
  2270.     if(!canSee(pos))
  2271.         return;
  2272.  
  2273.     NetworkMessage_ptr msg = getOutputBuffer();
  2274.     if(msg)
  2275.     {
  2276.         TRACK_MESSAGE(msg);
  2277.         RemoveTileItem(msg, pos, stackpos);
  2278.     }
  2279. }
  2280.  
  2281. void ProtocolGame::sendUpdateTile(const Tile* tile, const Position& pos)
  2282. {
  2283.     if(!canSee(pos))
  2284.         return;
  2285.  
  2286.     NetworkMessage_ptr msg = getOutputBuffer();
  2287.     if(msg)
  2288.     {
  2289.         TRACK_MESSAGE(msg);
  2290.         msg->AddByte(0x69);
  2291.         msg->AddPosition(pos);
  2292.         if(tile)
  2293.         {
  2294.             GetTileDescription(tile, msg);
  2295.             msg->AddByte(0x00);
  2296.             msg->AddByte(0xFF);
  2297.         }
  2298.         else
  2299.         {
  2300.             msg->AddByte(0x01);
  2301.             msg->AddByte(0xFF);
  2302.         }
  2303.     }
  2304. }
  2305.  
  2306. void ProtocolGame::sendAddCreature(const Creature* creature, const Position& pos, uint32_t stackpos)
  2307. {
  2308.     if(!canSee(creature))
  2309.         return;
  2310.  
  2311.     NetworkMessage_ptr msg = getOutputBuffer();
  2312.     if(!msg)
  2313.         return;
  2314.  
  2315.     TRACK_MESSAGE(msg);
  2316.     if(creature != player)
  2317.     {
  2318.         AddTileCreature(msg, pos, stackpos, creature);
  2319.         return;
  2320.     }
  2321.  
  2322.     msg->AddByte(0x0A);
  2323.     msg->AddU32(player->getID());
  2324.     msg->AddU16(0x32);
  2325.  
  2326.     msg->AddByte(player->hasFlag(PlayerFlag_CanReportBugs));
  2327.     if(Group* group = player->getGroup())
  2328.     {
  2329.         int32_t reasons = group->getViolationReasons();
  2330.         if(reasons > 1)
  2331.         {
  2332.             msg->AddByte(0x0B);
  2333.             for(int32_t i = 0; i < 20; ++i)
  2334.             {
  2335.                 if(i < 4)
  2336.                     msg->AddByte(group->getNameViolationFlags());
  2337.                 else if(i < reasons)
  2338.                     msg->AddByte(group->getStatementViolationFlags());
  2339.                 else
  2340.                     msg->AddByte(0x00);
  2341.             }
  2342.         }
  2343.     }
  2344.  
  2345.     AddMapDescription(msg, pos);
  2346.     for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
  2347.         AddInventoryItem(msg, (slots_t)i, player->getInventoryItem((slots_t)i));
  2348.  
  2349.     AddPlayerStats(msg);
  2350.     AddPlayerSkills(msg);
  2351.  
  2352.     //gameworld light-settings
  2353.     LightInfo lightInfo;
  2354.     g_game.getWorldLightInfo(lightInfo);
  2355.     AddWorldLight(msg, lightInfo);
  2356.  
  2357.     //player light level
  2358.     AddCreatureLight(msg, creature);
  2359.     player->sendIcons();
  2360.     for(VIPListSet::iterator it = player->VIPList.begin(); it != player->VIPList.end(); it++)
  2361.     {
  2362.         std::string vipName;
  2363.         if(IOLoginData::getInstance()->getNameByGuid((*it), vipName))
  2364.         {
  2365.             Player* tmpPlayer = g_game.getPlayerByName(vipName);
  2366.             sendVIP((*it), vipName, (tmpPlayer && player->canSeeCreature(tmpPlayer)));
  2367.         }
  2368.     }
  2369. }
  2370.  
  2371. void ProtocolGame::sendRemoveCreature(const Creature* creature, const Position& pos, uint32_t stackpos)
  2372. {
  2373.     if(!canSee(pos))
  2374.         return;
  2375.  
  2376.     NetworkMessage_ptr msg = getOutputBuffer();
  2377.     if(msg)
  2378.     {
  2379.         TRACK_MESSAGE(msg);
  2380.         RemoveTileItem(msg, pos, stackpos);
  2381.     }
  2382. }
  2383.  
  2384. void ProtocolGame::sendMoveCreature(const Creature* creature, const Tile* newTile, const Position& newPos,
  2385.     uint32_t newStackpos, const Tile* oldTile, const Position& oldPos, uint32_t oldStackpos, bool teleport)
  2386. {
  2387.     if(creature == player)
  2388.     {
  2389.         NetworkMessage_ptr msg = getOutputBuffer();
  2390.         if(msg)
  2391.         {
  2392.             TRACK_MESSAGE(msg);
  2393.             if(teleport || oldStackpos >= 10)
  2394.             {
  2395.                 RemoveTileItem(msg, oldPos, oldStackpos);
  2396.                 AddMapDescription(msg, newPos);
  2397.             }
  2398.             else
  2399.             {
  2400.                 if(oldPos.z != 7 || newPos.z < 8)
  2401.                 {
  2402.                     msg->AddByte(0x6D);
  2403.                     msg->AddPosition(oldPos);
  2404.                     msg->AddByte(oldStackpos);
  2405.                     msg->AddPosition(newPos);
  2406.                 }
  2407.                 else
  2408.                     RemoveTileItem(msg, oldPos, oldStackpos);
  2409.  
  2410.                 if(newPos.z > oldPos.z)
  2411.                     MoveDownCreature(msg, creature, newPos, oldPos, oldStackpos);
  2412.                 else if(newPos.z < oldPos.z)
  2413.                     MoveUpCreature(msg, creature, newPos, oldPos, oldStackpos);
  2414.  
  2415.                 if(oldPos.y > newPos.y) // north, for old x
  2416.                 {
  2417.                     msg->AddByte(0x65);
  2418.                     GetMapDescription(oldPos.x - Map::maxClientViewportX, newPos.y - Map::maxClientViewportY, newPos.z, (Map::maxClientViewportX+1)*2, 1, msg);
  2419.                 }
  2420.                 else if(oldPos.y < newPos.y) // south, for old x
  2421.                 {
  2422.                     msg->AddByte(0x67);
  2423.                     //MoveUpCreatureGetMapDescription(oldPos.x - Map::maxClientViewportX, newPos.y + (Map::maxClientViewportY+1), newPos.z, 18, 1, msg);
  2424.                     GetMapDescription(oldPos.x - Map::maxClientViewportX, newPos.y + (Map::maxClientViewportY+1), newPos.z, (Map::maxClientViewportX+1)*2, 1, msg);
  2425.                 }
  2426.  
  2427.                 if(oldPos.x < newPos.x) // east, [with new y]
  2428.                 {
  2429.                     msg->AddByte(0x66);
  2430.                     //GetMapDescription(newPos.x + (Map::maxClientViewportX+1), newPos.y - Map::maxClientViewportY, newPos.z, 1, 14, msg);
  2431.                     GetMapDescription(newPos.x + (Map::maxClientViewportX+1), newPos.y - Map::maxClientViewportY, newPos.z, 1, (Map::maxClientViewportY+1)*2, msg);
  2432.                 }
  2433.                 else if(oldPos.x > newPos.x) // west, [with new y]
  2434.                 {
  2435.                     msg->AddByte(0x68);
  2436.                     GetMapDescription(newPos.x - Map::maxClientViewportX, newPos.y - Map::maxClientViewportY, newPos.z, 1, (Map::maxClientViewportY+1)*2, msg);
  2437.                 }
  2438.             }
  2439.         }
  2440.     }
  2441.     else if(canSee(oldPos) && canSee(newPos))
  2442.     {
  2443.         if(!player->canSeeCreature(creature))
  2444.             return;
  2445.  
  2446.         NetworkMessage_ptr msg = getOutputBuffer();
  2447.         if(msg)
  2448.         {
  2449.             TRACK_MESSAGE(msg);
  2450.             if(!teleport && (oldPos.z != 7 || newPos.z < 8) && oldStackpos < 10)
  2451.             {
  2452.                 msg->AddByte(0x6D);
  2453.                 msg->AddPosition(oldPos);
  2454.                 msg->AddByte(oldStackpos);
  2455.                 msg->AddPosition(newPos);
  2456.             }
  2457.             else
  2458.             {
  2459.                 RemoveTileItem(msg, oldPos, oldStackpos);
  2460.                 AddTileCreature(msg, newPos, newStackpos, creature);
  2461.             }
  2462.         }
  2463.     }
  2464.     else if(canSee(oldPos))
  2465.     {
  2466.         if(!player->canSeeCreature(creature))
  2467.             return;
  2468.  
  2469.         NetworkMessage_ptr msg = getOutputBuffer();
  2470.         if(msg)
  2471.         {
  2472.             TRACK_MESSAGE(msg);
  2473.             RemoveTileItem(msg, oldPos, oldStackpos);
  2474.         }
  2475.     }
  2476.     else if(canSee(newPos) && player->canSeeCreature(creature))
  2477.     {
  2478.         NetworkMessage_ptr msg = getOutputBuffer();
  2479.         if(msg)
  2480.         {
  2481.             TRACK_MESSAGE(msg);
  2482.             AddTileCreature(msg, newPos, newStackpos, creature);
  2483.         }
  2484.     }
  2485. }
  2486.  
  2487. //inventory
  2488. void ProtocolGame::sendAddInventoryItem(slots_t slot, const Item* item)
  2489. {
  2490.     NetworkMessage_ptr msg = getOutputBuffer();
  2491.     if(msg)
  2492.     {
  2493.         TRACK_MESSAGE(msg);
  2494.         AddInventoryItem(msg, slot, item);
  2495.     }
  2496. }
  2497.  
  2498. void ProtocolGame::sendUpdateInventoryItem(slots_t slot, const Item* item)
  2499. {
  2500.     NetworkMessage_ptr msg = getOutputBuffer();
  2501.     if(msg)
  2502.     {
  2503.         TRACK_MESSAGE(msg);
  2504.         UpdateInventoryItem(msg, slot, item);
  2505.     }
  2506. }
  2507.  
  2508. void ProtocolGame::sendRemoveInventoryItem(slots_t slot)
  2509. {
  2510.     NetworkMessage_ptr msg = getOutputBuffer();
  2511.     if(msg)
  2512.     {
  2513.         TRACK_MESSAGE(msg);
  2514.         RemoveInventoryItem(msg, slot);
  2515.     }
  2516. }
  2517.  
  2518. //containers
  2519. void ProtocolGame::sendAddContainerItem(uint8_t cid, const Item* item)
  2520. {
  2521.     NetworkMessage_ptr msg = getOutputBuffer();
  2522.     if(msg)
  2523.     {
  2524.         TRACK_MESSAGE(msg);
  2525.         AddContainerItem(msg, cid, item);
  2526.     }
  2527. }
  2528.  
  2529. void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint8_t slot, const Item* item)
  2530. {
  2531.     NetworkMessage_ptr msg = getOutputBuffer();
  2532.     if(msg)
  2533.     {
  2534.         TRACK_MESSAGE(msg);
  2535.         UpdateContainerItem(msg, cid, slot, item);
  2536.     }
  2537. }
  2538.  
  2539. void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint8_t slot)
  2540. {
  2541.     NetworkMessage_ptr msg = getOutputBuffer();
  2542.     if(msg)
  2543.     {
  2544.         TRACK_MESSAGE(msg);
  2545.         RemoveContainerItem(msg, cid, slot);
  2546.     }
  2547. }
  2548.  
  2549. void ProtocolGame::sendTextWindow(uint32_t windowTextId, Item* item, uint16_t maxLen, bool canWrite)
  2550. {
  2551.     NetworkMessage_ptr msg = getOutputBuffer();
  2552.     if(msg)
  2553.     {
  2554.         TRACK_MESSAGE(msg);
  2555.         msg->AddByte(0x96);
  2556.         msg->AddU32(windowTextId);
  2557.         msg->AddItemId(item);
  2558.         if(canWrite)
  2559.         {
  2560.             msg->AddU16(maxLen);
  2561.             msg->AddString(item->getText());
  2562.         }
  2563.         else
  2564.         {
  2565.             msg->AddU16(item->getText().size());
  2566.             msg->AddString(item->getText());
  2567.         }
  2568.  
  2569.         const std::string& writer = item->getWriter();
  2570.         if(writer.size())
  2571.             msg->AddString(writer);
  2572.         else
  2573.             msg->AddString("");
  2574.  
  2575.         time_t writtenDate = item->getDate();
  2576.         if(writtenDate > 0)
  2577.             msg->AddString(formatDate(writtenDate));
  2578.         else
  2579.             msg->AddString("");
  2580.     }
  2581. }
  2582.  
  2583. void ProtocolGame::sendTextWindow(uint32_t windowTextId, uint32_t itemId, const std::string& text)
  2584. {
  2585.     NetworkMessage_ptr msg = getOutputBuffer();
  2586.     if(msg)
  2587.     {
  2588.         TRACK_MESSAGE(msg);
  2589.         msg->AddByte(0x96);
  2590.         msg->AddU32(windowTextId);
  2591.         msg->AddItemId(itemId);
  2592.  
  2593.         msg->AddU16(text.size());
  2594.         msg->AddString(text);
  2595.  
  2596.         msg->AddString("");
  2597.         msg->AddString("");
  2598.     }
  2599. }
  2600.  
  2601. void ProtocolGame::sendHouseWindow(uint32_t windowTextId, House* _house,
  2602.     uint32_t listId, const std::string& text)
  2603. {
  2604.     NetworkMessage_ptr msg = getOutputBuffer();
  2605.     if(msg)
  2606.     {
  2607.         TRACK_MESSAGE(msg);
  2608.         msg->AddByte(0x97);
  2609.         msg->AddByte(0x00);
  2610.         msg->AddU32(windowTextId);
  2611.         msg->AddString(text);
  2612.     }
  2613. }
  2614.  
  2615. void ProtocolGame::sendOutfitWindow()
  2616. {
  2617.     NetworkMessage_ptr msg = getOutputBuffer();
  2618.     if(msg)
  2619.     {
  2620.         TRACK_MESSAGE(msg);
  2621.         msg->AddByte(0xC8);
  2622.         AddCreatureOutfit(msg, player, player->getDefaultOutfit(), true);
  2623.  
  2624.         std::list<Outfit> outfitList;
  2625.         for(OutfitMap::iterator it = player->outfits.begin(); it != player->outfits.end(); ++it)
  2626.         {
  2627.             if(player->canWearOutfit(it->first, it->second.addons))
  2628.                 outfitList.push_back(it->second);
  2629.         }
  2630.  
  2631.         if(outfitList.size())
  2632.         {
  2633.             msg->AddByte((size_t)std::min((size_t)OUTFITS_MAX_NUMBER, outfitList.size()));
  2634.             std::list<Outfit>::iterator it = outfitList.begin();
  2635.             for(int32_t i = 0; it != outfitList.end() && i < OUTFITS_MAX_NUMBER; ++it, ++i)
  2636.             {
  2637.                 msg->AddU16(it->lookType);
  2638.                 msg->AddString(it->name);
  2639.                 if(player->hasCustomFlag(PlayerCustomFlag_CanWearAllAddons))
  2640.                     msg->AddByte(0x03);
  2641.                 else if(!g_config.getBool(ConfigManager::ADDONS_PREMIUM) || player->isPremium())
  2642.                     msg->AddByte(it->addons);
  2643.                 else
  2644.                     msg->AddByte(0x00);
  2645.             }
  2646.         }
  2647.         else
  2648.         {
  2649.             msg->AddByte(1);
  2650.             msg->AddU16(player->getDefaultOutfit().lookType);
  2651.             msg->AddString("Outfit");
  2652.             msg->AddByte(player->getDefaultOutfit().lookAddons);
  2653.         }
  2654.  
  2655.         player->hasRequestedOutfit(true);
  2656.     }
  2657. }
  2658.  
  2659. void ProtocolGame::sendQuests()
  2660. {
  2661.     NetworkMessage_ptr msg = getOutputBuffer();
  2662.     if(msg)
  2663.     {
  2664.         TRACK_MESSAGE(msg);
  2665.         msg->AddByte(0xF0);
  2666.  
  2667.         msg->AddU16(Quests::getInstance()->getQuestCount(player));
  2668.         for(QuestList::const_iterator it = Quests::getInstance()->getFirstQuest(); it != Quests::getInstance()->getLastQuest(); ++it)
  2669.         {
  2670.             if(!(*it)->isStarted(player))
  2671.                 continue;
  2672.  
  2673.             msg->AddU16((*it)->getId());
  2674.             msg->AddString((*it)->getName());
  2675.             msg->AddByte((*it)->isCompleted(player));
  2676.         }
  2677.     }
  2678. }
  2679.  
  2680. void ProtocolGame::sendQuestInfo(Quest* quest)
  2681. {
  2682.     NetworkMessage_ptr msg = getOutputBuffer();
  2683.     if(msg)
  2684.     {
  2685.         TRACK_MESSAGE(msg);
  2686.         msg->AddByte(0xF1);
  2687.         msg->AddU16(quest->getId());
  2688.  
  2689.         msg->AddByte(quest->getMissionCount(player));
  2690.         for(MissionList::const_iterator it = quest->getFirstMission(); it != quest->getLastMission(); ++it)
  2691.         {
  2692.             if(!(*it)->isStarted(player))
  2693.                 continue;
  2694.  
  2695.             msg->AddString((*it)->getName(player));
  2696.             msg->AddString((*it)->getDescription(player));
  2697.         }
  2698.     }
  2699. }
  2700.  
  2701. void ProtocolGame::sendVIPLogIn(uint32_t guid)
  2702. {
  2703.     NetworkMessage_ptr msg = getOutputBuffer();
  2704.     if(msg)
  2705.     {
  2706.         TRACK_MESSAGE(msg);
  2707.         msg->AddByte(0xD3);
  2708.         msg->AddU32(guid);
  2709.     }
  2710. }
  2711.  
  2712. void ProtocolGame::sendVIPLogOut(uint32_t guid)
  2713. {
  2714.     NetworkMessage_ptr msg = getOutputBuffer();
  2715.     if(msg)
  2716.     {
  2717.         TRACK_MESSAGE(msg);
  2718.         msg->AddByte(0xD4);
  2719.         msg->AddU32(guid);
  2720.     }
  2721. }
  2722.  
  2723. void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, bool isOnline)
  2724. {
  2725.     NetworkMessage_ptr msg = getOutputBuffer();
  2726.     if(msg)
  2727.     {
  2728.         TRACK_MESSAGE(msg);
  2729.         msg->AddByte(0xD2);
  2730.         msg->AddU32(guid);
  2731.         msg->AddString(name);
  2732.         msg->AddByte(isOnline ? 1 : 0);
  2733.     }
  2734. }
  2735.  
  2736. ////////////// Add common messages
  2737. void ProtocolGame::AddMapDescription(NetworkMessage_ptr msg, const Position& pos)
  2738. {
  2739.     msg->AddByte(0x64);
  2740.     msg->AddPosition(player->getPosition());
  2741.     GetMapDescription(pos.x - Map::maxClientViewportX, pos.y - Map::maxClientViewportY, pos.z, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, msg);
  2742. }
  2743.  
  2744. void ProtocolGame::AddTextMessage(NetworkMessage_ptr msg, MessageClasses mclass, const std::string& message)
  2745. {
  2746.     msg->AddByte(0xB4);
  2747.     msg->AddByte(mclass);
  2748.     msg->AddString(message);
  2749. }
  2750.  
  2751. void ProtocolGame::AddAnimatedText(NetworkMessage_ptr msg, const Position& pos,
  2752.     uint8_t color, const std::string& text)
  2753. {
  2754.     msg->AddByte(0x84);
  2755.     msg->AddPosition(pos);
  2756.     msg->AddByte(color);
  2757.     msg->AddString(text);
  2758. }
  2759.  
  2760. void ProtocolGame::AddMagicEffect(NetworkMessage_ptr msg,const Position& pos, uint16_t type)
  2761. {
  2762. msg->AddByte(0x83);
  2763. msg->AddPosition(pos);
  2764. msg->AddU16(type + 1);
  2765. }
  2766.  
  2767. void ProtocolGame::AddDistanceShoot(NetworkMessage_ptr msg, const Position& from, const Position& to,
  2768.     uint8_t type)
  2769. {
  2770.     msg->AddByte(0x85);
  2771.     msg->AddPosition(from);
  2772.     msg->AddPosition(to);
  2773.     msg->AddByte(type + 1);
  2774. }
  2775.  
  2776. void ProtocolGame::AddCreature(NetworkMessage_ptr msg, const Creature* creature, bool known, uint32_t remove)
  2777. {
  2778.     if(!known)
  2779.     {
  2780.         msg->AddU16(0x61);
  2781.         msg->AddU32(remove);
  2782.         msg->AddU32(creature->getID());
  2783.         msg->AddString(creature->getHideName() ? "" : creature->getName());
  2784.     }
  2785.     else
  2786.     {
  2787.         msg->AddU16(0x62);
  2788.         msg->AddU32(creature->getID());
  2789.     }
  2790.  
  2791.     if(!creature->getHideHealth())
  2792.         msg->AddByte((int32_t)std::ceil(((float)creature->getHealth()) * 100 / std::max(creature->getMaxHealth(), (int32_t)1)));
  2793.     else
  2794.         msg->AddByte(0x00);
  2795.  
  2796.     msg->AddByte((uint8_t)creature->getDirection());
  2797.     AddCreatureOutfit(msg, creature, creature->getCurrentOutfit());
  2798.  
  2799.     LightInfo lightInfo;
  2800.     creature->getCreatureLight(lightInfo);
  2801.     msg->AddByte(player->hasCustomFlag(PlayerCustomFlag_HasFullLight) ? 0xFF : lightInfo.level);
  2802.     msg->AddByte(lightInfo.color);
  2803.  
  2804.     msg->AddU16(creature->getStepSpeed());
  2805.     msg->AddByte(player->getSkullClient(creature));
  2806.     msg->AddByte(player->getPartyShield(creature));
  2807.     if(!known)
  2808.         msg->AddByte(0x00); // war emblem
  2809.  
  2810.     msg->AddByte(!player->canWalkthrough(creature));
  2811. }
  2812.  
  2813. void ProtocolGame::AddPlayerStats(NetworkMessage_ptr msg)
  2814. {
  2815.     msg->AddByte(0xA0);
  2816.     msg->AddU16(player->getHealth());
  2817.     msg->AddU16(player->getPlayerInfo(PLAYERINFO_MAXHEALTH));
  2818.     msg->AddU32(uint32_t(player->getFreeCapacity() * 100));
  2819.     uint64_t experience = player->getExperience();
  2820.     if(experience > 0x7FFFFFFF) // client debugs after 2,147,483,647 exp
  2821.         msg->AddU32(0x7FFFFFFF);
  2822.     else
  2823.         msg->AddU32(experience);
  2824.  
  2825.     msg->AddU16(player->getPlayerInfo(PLAYERINFO_LEVEL));
  2826.     msg->AddByte(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT));
  2827.     msg->AddU16(player->getPlayerInfo(PLAYERINFO_MANA));
  2828.     msg->AddU16(player->getPlayerInfo(PLAYERINFO_MAXMANA));
  2829.     msg->AddByte(player->getPlayerInfo(PLAYERINFO_MAGICLEVEL));
  2830.     msg->AddByte(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT));
  2831.     msg->AddByte(player->getPlayerInfo(PLAYERINFO_SOUL));
  2832.     msg->AddU16(player->getStaminaMinutes());
  2833. }
  2834.  
  2835. void ProtocolGame::AddPlayerSkills(NetworkMessage_ptr msg)
  2836. {
  2837.     msg->AddByte(0xA1);
  2838.     msg->AddByte(player->getSkill(SKILL_FIST, SKILL_LEVEL));
  2839.     msg->AddByte(player->getSkill(SKILL_FIST, SKILL_PERCENT));
  2840.     msg->AddByte(player->getSkill(SKILL_CLUB, SKILL_LEVEL));
  2841.     msg->AddByte(player->getSkill(SKILL_CLUB, SKILL_PERCENT));
  2842.     msg->AddByte(player->getSkill(SKILL_SWORD, SKILL_LEVEL));
  2843.     msg->AddByte(player->getSkill(SKILL_SWORD, SKILL_PERCENT));
  2844.     msg->AddByte(player->getSkill(SKILL_AXE, SKILL_LEVEL));
  2845.     msg->AddByte(player->getSkill(SKILL_AXE, SKILL_PERCENT));
  2846.     msg->AddByte(player->getSkill(SKILL_DIST, SKILL_LEVEL));
  2847.     msg->AddByte(player->getSkill(SKILL_DIST, SKILL_PERCENT));
  2848.     msg->AddByte(player->getSkill(SKILL_SHIELD, SKILL_LEVEL));
  2849.     msg->AddByte(player->getSkill(SKILL_SHIELD, SKILL_PERCENT));
  2850.     msg->AddByte(player->getSkill(SKILL_FISH, SKILL_LEVEL));
  2851.     msg->AddByte(player->getSkill(SKILL_FISH, SKILL_PERCENT));
  2852. }
  2853.  
  2854. void ProtocolGame::AddCreatureSpeak(NetworkMessage_ptr msg, const Creature* creature, SpeakClasses type,
  2855.     std::string text, uint16_t channelId, uint32_t time/*= 0*/, Position* pos/* = NULL*/)
  2856. {
  2857.     msg->AddByte(0xAA);
  2858.     if(creature)
  2859.     {
  2860.         const Player* speaker = creature->getPlayer();
  2861.         if(speaker)
  2862.         {
  2863.             msg->AddU32(++g_chat.statement);
  2864.             g_chat.statementMap[g_chat.statement] = text;
  2865.         }
  2866.         else
  2867.             msg->AddU32(0x00);
  2868.  
  2869.         if(creature->getSpeakType() != SPEAK_CLASS_NONE)
  2870.             type = creature->getSpeakType();
  2871.  
  2872.         switch(type)
  2873.         {
  2874.             case SPEAK_CHANNEL_RA:
  2875.                 msg->AddString("");
  2876.                 break;
  2877.             case SPEAK_RVR_ANSWER:
  2878.                 msg->AddString("Gamemaster");
  2879.                 break;
  2880.             default:
  2881.                 msg->AddString(!creature->getHideName() ? creature->getName() : "");
  2882.                 break;
  2883.         }
  2884.  
  2885.         if(speaker && type != SPEAK_RVR_ANSWER && !speaker->isAccountManager()
  2886.             && !speaker->hasCustomFlag(PlayerCustomFlag_HideLevel))
  2887.             msg->AddU16(speaker->getPlayerInfo(PLAYERINFO_LEVEL));
  2888.         else
  2889.             msg->AddU16(0x00);
  2890.  
  2891.     }
  2892.     else
  2893.     {
  2894.         msg->AddU32(0x00);
  2895.         msg->AddString("");
  2896.         msg->AddU16(0x00);
  2897.     }
  2898.  
  2899.     msg->AddByte(type);
  2900.     switch(type)
  2901.     {
  2902.         case SPEAK_SAY:
  2903.         case SPEAK_WHISPER:
  2904.         case SPEAK_YELL:
  2905.         case SPEAK_MONSTER_SAY:
  2906.         case SPEAK_MONSTER_YELL:
  2907.         case SPEAK_PRIVATE_NP:
  2908.         {
  2909.             if(pos)
  2910.                 msg->AddPosition(*pos);
  2911.             else if(creature)
  2912.                 msg->AddPosition(creature->getPosition());
  2913.             else
  2914.                 msg->AddPosition(Position(0,0,7));
  2915.  
  2916.             break;
  2917.         }
  2918.  
  2919.         case SPEAK_CHANNEL_Y:
  2920.         case SPEAK_CHANNEL_RN:
  2921.         case SPEAK_CHANNEL_RA:
  2922.         case SPEAK_CHANNEL_O:
  2923.         case SPEAK_CHANNEL_W:
  2924.             msg->AddU16(channelId);
  2925.             break;
  2926.  
  2927.         case SPEAK_RVR_CHANNEL:
  2928.         {
  2929.             msg->AddU32(uint32_t(OTSYS_TIME() / 1000 & 0xFFFFFFFF) - time);
  2930.             break;
  2931.         }
  2932.  
  2933.         default:
  2934.             break;
  2935.     }
  2936.  
  2937.     msg->AddString(text);
  2938. }
  2939.  
  2940. void ProtocolGame::AddCreatureHealth(NetworkMessage_ptr msg,const Creature* creature)
  2941. {
  2942.     msg->AddByte(0x8C);
  2943.     msg->AddU32(creature->getID());
  2944.     if(!creature->getHideHealth())
  2945.         msg->AddByte((int32_t)std::ceil(((float)creature->getHealth()) * 100 / std::max(creature->getMaxHealth(), (int32_t)1)));
  2946.     else
  2947.         msg->AddByte(0x00);
  2948. }
  2949.  
  2950. void ProtocolGame::AddCreatureOutfit(NetworkMessage_ptr msg, const Creature* creature, const Outfit_t& outfit, bool outfitWindow/* = false*/)
  2951. {
  2952.     if(outfitWindow || !creature->getPlayer() || (!creature->isInvisible() && (!creature->isGhost()
  2953.         || !g_config.getBool(ConfigManager::GHOST_INVISIBLE_EFFECT))))
  2954.     {
  2955.         msg->AddU16(outfit.lookType);
  2956.         if(outfit.lookType)
  2957.         {
  2958.             msg->AddByte(outfit.lookHead);
  2959.             msg->AddByte(outfit.lookBody);
  2960.             msg->AddByte(outfit.lookLegs);
  2961.             msg->AddByte(outfit.lookFeet);
  2962.             msg->AddByte(outfit.lookAddons);
  2963.         }
  2964.         else if(outfit.lookTypeEx)
  2965.             msg->AddItemId(outfit.lookTypeEx);
  2966.         else
  2967.             msg->AddU16(outfit.lookTypeEx);
  2968.     }
  2969.     else
  2970.         msg->AddU32(0x00);
  2971. }
  2972.  
  2973. void ProtocolGame::AddWorldLight(NetworkMessage_ptr msg, const LightInfo& lightInfo)
  2974. {
  2975.     msg->AddByte(0x82);
  2976.     msg->AddByte((player->hasCustomFlag(PlayerCustomFlag_HasFullLight) ? 0xFF : lightInfo.level));
  2977.     msg->AddByte(lightInfo.color);
  2978. }
  2979.  
  2980. void ProtocolGame::AddCreatureLight(NetworkMessage_ptr msg, const Creature* creature)
  2981. {
  2982.     LightInfo lightInfo;
  2983.     creature->getCreatureLight(lightInfo);
  2984.     msg->AddByte(0x8D);
  2985.     msg->AddU32(creature->getID());
  2986.     msg->AddByte((player->hasCustomFlag(PlayerCustomFlag_HasFullLight) ? 0xFF : lightInfo.level));
  2987.     msg->AddByte(lightInfo.color);
  2988. }
  2989.  
  2990. //tile
  2991. void ProtocolGame::AddTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Item* item)
  2992. {
  2993.     if(stackpos >= 10)
  2994.         return;
  2995.  
  2996.     msg->AddByte(0x6A);
  2997.     msg->AddPosition(pos);
  2998.     msg->AddByte(stackpos);
  2999.     msg->AddItem(item);
  3000. }
  3001.  
  3002. void ProtocolGame::AddTileCreature(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Creature* creature)
  3003. {
  3004.     if(stackpos >= 10)
  3005.         return;
  3006.  
  3007.     msg->AddByte(0x6A);
  3008.     msg->AddPosition(pos);
  3009.     msg->AddByte(stackpos);
  3010.  
  3011.     bool known;
  3012.     uint32_t removedKnown;
  3013.     checkCreatureAsKnown(creature->getID(), known, removedKnown);
  3014.     AddCreature(msg, creature, known, removedKnown);
  3015. }
  3016.  
  3017. void ProtocolGame::UpdateTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Item* item)
  3018. {
  3019.     if(stackpos >= 10)
  3020.         return;
  3021.  
  3022.     msg->AddByte(0x6B);
  3023.     msg->AddPosition(pos);
  3024.     msg->AddByte(stackpos);
  3025.     msg->AddItem(item);
  3026. }
  3027.  
  3028. void ProtocolGame::RemoveTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos)
  3029. {
  3030.     if(stackpos >= 10)
  3031.         return;
  3032.  
  3033.     msg->AddByte(0x6C);
  3034.     msg->AddPosition(pos);
  3035.     msg->AddByte(stackpos);
  3036. }
  3037.  
  3038. void ProtocolGame::MoveUpCreature(NetworkMessage_ptr msg, const Creature* creature,
  3039.     const Position& newPos, const Position& oldPos, uint32_t oldStackpos)
  3040. {
  3041.     if(creature != player)
  3042.         return;
  3043.  
  3044.     msg->AddByte(0xBE); //floor change up
  3045.     if(newPos.z == 7) //going to surface
  3046.     {
  3047.         int32_t skip = -1;
  3048.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 5, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 3, skip); //(floor 7 and 6 already set)
  3049.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 4, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 4, skip);
  3050.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 3, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 5, skip);
  3051.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 2, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 6, skip);
  3052.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 1, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 7, skip);
  3053.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, 0, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 8, skip);
  3054.  
  3055.         if(skip >= 0)
  3056.         {
  3057.             msg->AddByte(skip);
  3058.             msg->AddByte(0xFF);
  3059.         }
  3060.     }
  3061.     else if(newPos.z > 7) //underground, going one floor up (still underground)
  3062.     {
  3063.         int32_t skip = -1;
  3064.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, oldPos.z- 3, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, 3, skip);
  3065.  
  3066.         if(skip >= 0)
  3067.         {
  3068.             msg->AddByte(skip);
  3069.             msg->AddByte(0xFF);
  3070.         }
  3071.     }
  3072.  
  3073.     //moving up a floor up makes us out of sync
  3074.     //west
  3075.     msg->AddByte(0x68);
  3076.     GetMapDescription(oldPos.x - Map::maxClientViewportX, oldPos.y - (Map::maxClientViewportY-1), newPos.z, 1, (Map::maxClientViewportY+1)*2, msg);
  3077.     //north
  3078.     msg->AddByte(0x65);
  3079.     GetMapDescription(oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z, (Map::maxClientViewportX+1)*2, 1, msg);
  3080.  
  3081. }
  3082.  
  3083. void ProtocolGame::MoveDownCreature(NetworkMessage_ptr msg, const Creature* creature,
  3084.     const Position& newPos, const Position& oldPos, uint32_t oldStackpos)
  3085. {
  3086.     if(creature != player)
  3087.         return;
  3088.  
  3089.     msg->AddByte(0xBF); //floor change down
  3090.     if(newPos.z == 8) //going from surface to underground
  3091.     {
  3092.         int32_t skip = -1;
  3093.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -1, skip);
  3094.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z + 1, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -2, skip);
  3095.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z + 2, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -3, skip);
  3096.  
  3097.         if(skip >= 0)
  3098.         {
  3099.             msg->AddByte(skip);
  3100.             msg->AddByte(0xFF);
  3101.         }
  3102.     }
  3103.     else if(newPos.z > oldPos.z && newPos.z > 8 && newPos.z < 14) //going further down
  3104.     {
  3105.         int32_t skip = -1;
  3106.         GetFloorDescription(msg, oldPos.x - Map::maxClientViewportX, oldPos.y - Map::maxClientViewportY, newPos.z + 2, (Map::maxClientViewportX+1)*2, (Map::maxClientViewportY+1)*2, -3, skip);
  3107.         if(skip >= 0)
  3108.         {
  3109.             msg->AddByte(skip);
  3110.             msg->AddByte(0xFF);
  3111.         }
  3112.     }
  3113.  
  3114.     //moving down a floor makes us out of sync
  3115.     //east
  3116.     msg->AddByte(0x66);
  3117.     GetMapDescription(oldPos.x + 9, oldPos.y - 1 - 6, newPos.z, 1, 14, msg);
  3118.  
  3119.     //south
  3120.     msg->AddByte(0x67);
  3121.     GetMapDescription(oldPos.x - 8, oldPos.y + 7, newPos.z, 18, 1, msg);
  3122. }
  3123.  
  3124. //inventory
  3125. void ProtocolGame::AddInventoryItem(NetworkMessage_ptr msg, slots_t slot, const Item* item)
  3126. {
  3127.     if(item)
  3128.     {
  3129.         msg->AddByte(0x78);
  3130.         msg->AddByte(slot);
  3131.         msg->AddItem(item);
  3132.     }
  3133.     else
  3134.         RemoveInventoryItem(msg, slot);
  3135. }
  3136.  
  3137. void ProtocolGame::RemoveInventoryItem(NetworkMessage_ptr msg, slots_t slot)
  3138. {
  3139.     msg->AddByte(0x79);
  3140.     msg->AddByte(slot);
  3141. }
  3142.  
  3143. void ProtocolGame::UpdateInventoryItem(NetworkMessage_ptr msg, slots_t slot, const Item* item)
  3144. {
  3145.     AddInventoryItem(msg, slot, item);
  3146. }
  3147.  
  3148. //containers
  3149. void ProtocolGame::AddContainerItem(NetworkMessage_ptr msg, uint8_t cid, const Item* item)
  3150. {
  3151.     msg->AddByte(0x70);
  3152.     msg->AddByte(cid);
  3153.     msg->AddItem(item);
  3154. }
  3155.  
  3156. void ProtocolGame::UpdateContainerItem(NetworkMessage_ptr msg, uint8_t cid, uint8_t slot, const Item* item)
  3157. {
  3158.     msg->AddByte(0x71);
  3159.     msg->AddByte(cid);
  3160.     msg->AddByte(slot);
  3161.     msg->AddItem(item);
  3162. }
  3163.  
  3164. void ProtocolGame::RemoveContainerItem(NetworkMessage_ptr msg, uint8_t cid, uint8_t slot)
  3165. {
  3166.     msg->AddByte(0x72);
  3167.     msg->AddByte(cid);
  3168.     msg->AddByte(slot);
  3169. }
  3170.  
  3171. void ProtocolGame::sendChannelMessage(std::string author, std::string text, SpeakClasses type, uint8_t channel)
  3172. {
  3173.     NetworkMessage_ptr msg = getOutputBuffer();
  3174.     if(msg)
  3175.     {
  3176.         TRACK_MESSAGE(msg);
  3177.         msg->AddByte(0xAA);
  3178.         msg->AddU32(0x00);
  3179.         msg->AddString(author);
  3180.         msg->AddU16(0x00);
  3181.         msg->AddByte(type);
  3182.         msg->AddU16(channel);
  3183.         msg->AddString(text);
  3184.     }
  3185. }
  3186.  
  3187. void ProtocolGame::AddShopItem(NetworkMessage_ptr msg, const ShopInfo item)
  3188. {
  3189.     const ItemType& it = Item::items[item.itemId];
  3190.     msg->AddU16(it.clientId);
  3191.     if(it.isSplash() || it.isFluidContainer())
  3192.         msg->AddByte(fluidMap[item.subType % 8]);
  3193.     else if(it.stackable || it.charges)
  3194.         msg->AddByte(item.subType);
  3195.     else
  3196.         msg->AddByte(0x01);
  3197.  
  3198.     msg->AddString(item.itemName);
  3199.     msg->AddU32(uint32_t(it.weight * 100));
  3200.     msg->AddU32(item.buyPrice);
  3201.     msg->AddU32(item.sellPrice);
  3202. }
  3203.  
  3204. void ProtocolGame::parseExtendedOpcode(NetworkMessage& msg)
  3205. {
  3206. uint8_t opcode = msg.GetByte();
  3207. std::string buffer = msg.GetString();
  3208.  
  3209. // process additional opcodes via lua script event
  3210. addGameTask(&Game::parsePlayerExtendedOpcode, player->getID(), opcode, buffer);
  3211. }
  3212.  
  3213. void ProtocolGame::sendExtendedOpcode(uint8_t opcode, const std::string& buffer)
  3214. {
  3215. // extended opcodes can only be send to players using otclient, cipsoft's tibia can't understand them
  3216.  
  3217.     NetworkMessage_ptr msg = getOutputBuffer();
  3218.     if(msg)
  3219.     {
  3220.         TRACK_MESSAGE(msg);
  3221.         msg->AddByte(0x32);
  3222.         msg->AddByte(opcode);
  3223.         msg->AddString(buffer);
  3224.     }
  3225. }
  3226.  
  3227. void ProtocolGame::parseMarketLeave()
  3228. {
  3229.     addGameTask(&Game::playerLeaveMarket, player->getID());
  3230. }
  3231.  
  3232. void ProtocolGame::parseMarketBrowse(NetworkMessage& msg)
  3233. {
  3234.     uint16_t browseId = msg.GetU16();
  3235.     if(browseId == MARKETREQUEST_OWN_OFFERS)
  3236.         addGameTask(&Game::playerBrowseMarketOwnOffers, player->getID());
  3237.     else if(browseId == MARKETREQUEST_OWN_HISTORY)
  3238.         addGameTask(&Game::playerBrowseMarketOwnHistory, player->getID());
  3239.     else
  3240.         addGameTask(&Game::playerBrowseMarket, player->getID(), browseId);
  3241. }
  3242.  
  3243. void ProtocolGame::parseMarketItemDesc(NetworkMessage& msg)
  3244. {
  3245.     uint32_t timestamp = msg.GetU32();
  3246.     uint16_t counter = msg.GetU16();
  3247.     addGameTask(&Game::playerItemDescMarket, player->getID(), timestamp, counter);
  3248. }
  3249.  
  3250. void ProtocolGame::parseMarketCreateOffer(NetworkMessage& msg)
  3251. {
  3252.     uint8_t type = msg.GetByte();
  3253.     Position pos = msg.GetPosition();
  3254.     uint16_t spriteId = msg.GetSpriteId();
  3255.     int16_t stackpos = msg.GetByte();
  3256.     uint16_t amount = msg.GetU16();
  3257.     uint32_t price = msg.GetU32();
  3258.     bool anonymous = (msg.GetByte() != 0);
  3259.     addGameTask(&Game::playerCreateMarketOffer, player->getID(), type, pos, spriteId, stackpos, amount, price, anonymous);
  3260. }
  3261.  
  3262. void ProtocolGame::parseMarketCancelOffer(NetworkMessage& msg)
  3263. {
  3264.     uint32_t timestamp = msg.GetU32();
  3265.     uint16_t counter = msg.GetU16();
  3266.     addGameTask(&Game::playerCancelMarketOffer, player->getID(), timestamp, counter);
  3267. }
  3268.  
  3269. void ProtocolGame::parseMarketAcceptOffer(NetworkMessage& msg)
  3270. {
  3271.     uint32_t timestamp = msg.GetU32();
  3272.     uint16_t counter = msg.GetU16();
  3273.     uint16_t amount = msg.GetU16();
  3274.     addGameTask(&Game::playerAcceptMarketOffer, player->getID(), timestamp, counter, amount);
  3275. }
  3276.  
  3277. void ProtocolGame::sendMarketEnter(uint32_t depotId)
  3278. {
  3279.     NetworkMessage_ptr msg = getOutputBuffer();
  3280.     if(msg)
  3281.     {
  3282.         TRACK_MESSAGE(msg);
  3283.         msg->AddByte(0xF6);
  3284.  
  3285.         msg->AddU32(g_game.getMoney(player));
  3286.         msg->AddByte(player->getVocationId());
  3287.         msg->AddByte(std::min<uint32_t>(IOMarket::getInstance()->getPlayerOfferCount(player->getGUID()),std::numeric_limits<uint8_t>::max()));
  3288.         Depot* depotChest = player->getDepot(depotId, false);
  3289.        
  3290.         if(!depotChest){
  3291.             msg->AddU16(0x00);
  3292.             return;
  3293.         }
  3294.        
  3295.         player->setMarketDepotId(depotId);
  3296.         player->setInMarket(true);
  3297.         std::map<uint16_t, uint32_t> depotItems;
  3298.         std::list<Container*> containerList;
  3299.         containerList.push_back(depotChest);
  3300.         do
  3301.         {
  3302.             Container* container = containerList.front();
  3303.             containerList.pop_front();
  3304.            
  3305.             for(ItemList::const_iterator it = container->getItems(); it != container->getEnd(); ++it)
  3306.             {
  3307.                 Item* item = *it;
  3308.                 if(item){
  3309.                     Container* c = item->getContainer();
  3310.                     if(c && !c->empty())
  3311.                     {
  3312.                        containerList.push_back(c);
  3313.                        continue;
  3314.                     }
  3315.                     if(item->getID() != ITEM_MARKET && item->getID() != ITEM_DEPOT ){
  3316.                        depotItems[item->getClientID()] += Item::countByType(item, -1);
  3317.                     }
  3318.                 }
  3319.             }
  3320.         }
  3321.         while(!containerList.empty());
  3322.  
  3323.         msg->AddU16(std::min<size_t>(depotItems.size(), std::numeric_limits<uint16_t>::max()));
  3324.         uint16_t i = 0;
  3325.         for(std::map<uint16_t, uint32_t>::const_iterator it = depotItems.begin(), end = depotItems.end(); it != end && i < 0xFFFF; ++it, ++i)
  3326.         {
  3327.             msg->AddU16(it->first);
  3328.             msg->AddU16(std::min<uint32_t>(0xFFFF, it->second));
  3329.         }
  3330.     }
  3331. }
  3332.  
  3333. void ProtocolGame::sendMarketLeave()
  3334. {
  3335.     NetworkMessage_ptr msg = getOutputBuffer();
  3336.     if(msg)
  3337.     {
  3338.         TRACK_MESSAGE(msg);
  3339.         msg->AddByte(0xF7);
  3340.     }
  3341.    
  3342. }
  3343.  
  3344. void ProtocolGame::sendMarketBrowseItem(uint16_t itemId, const MarketOfferList& buyOffers, const MarketOfferList& sellOffers)
  3345. {
  3346.     NetworkMessage_ptr msg = getOutputBuffer();
  3347.     if(msg)
  3348.     {
  3349.         TRACK_MESSAGE(msg);
  3350.         msg->AddByte(0xF9);
  3351.         msg->AddU16(2160);
  3352.         msg->AddU32(buyOffers.size());
  3353.         for(MarketOfferList::const_iterator it = buyOffers.begin(), end = buyOffers.end(); it != end; ++it)
  3354.         {
  3355.             msg->AddU32(it->timestamp);
  3356.             msg->AddU16(it->counter);
  3357.             msg->AddU16(it->amount);
  3358.             msg->AddItemId(it->itemId);
  3359.             msg->AddU32(it->price);
  3360.             msg->AddString(it->playerName);
  3361.             const ItemType& itt = Item::items[it->itemId];
  3362.             Item* item = Item::CreateItem(itt.id, 1);
  3363.             std::stringstream test(it->Attrs);
  3364.             std::string segment;
  3365.             std::vector<std::string> seglist;
  3366.             if(it->Attrs != "false"){
  3367.                 while(std::getline(test, segment, 'º'))
  3368.                 {
  3369.                     seglist.push_back(segment);
  3370.                 }
  3371.                 for(int i = 0; i < seglist.size(); i++) {
  3372.                     std::stringstream test2(seglist[i]);
  3373.                     std::string segment2;
  3374.                     std::vector<std::string> seglist2;
  3375.                     while(std::getline(test2, segment2, '#'))
  3376.                     {
  3377.                         seglist2.push_back(segment2);
  3378.                     }
  3379. if(seglist2.size() != 2){
  3380.     std::cout << "Error: seglist2 contains improper amount of segments (" << test2 << ")." << std::endl;
  3381.     continue;
  3382. }
  3383. else if(isNumbers(seglist2[1])){
  3384.     item->setAttribute(seglist2[0], atoi(seglist2[1].c_str()));
  3385. }
  3386. else {
  3387.     item->setAttribute(seglist2[0], seglist2[1]);
  3388. }
  3389.                 }
  3390.             }
  3391.             if(item->hasStringAttribute("poke")){
  3392.                 msg->AddString(item->getPoke());
  3393.             }else{
  3394.                 msg->AddString(item->getName());
  3395.             }
  3396.             delete item;
  3397.         }
  3398.  
  3399.         msg->AddU32(sellOffers.size());
  3400.         for(MarketOfferList::const_iterator it = sellOffers.begin(), end = sellOffers.end(); it != end; ++it)
  3401.         {
  3402.             msg->AddU32(it->timestamp);
  3403.             msg->AddU16(it->counter);
  3404.             msg->AddItemId(it->itemId);
  3405.             msg->AddU16(it->amount);
  3406.             msg->AddU32(it->price);
  3407.             msg->AddString(it->playerName);
  3408.             const ItemType& itt = Item::items[it->itemId];
  3409.             Item* item = Item::CreateItem(itt.id, 1);
  3410.             std::stringstream test(it->Attrs);
  3411.             std::string segment;
  3412.             std::vector<std::string> seglist;
  3413.             if(it->Attrs != "false"){
  3414.                 while(std::getline(test, segment, 'º'))
  3415.                 {
  3416.                     seglist.push_back(segment);
  3417.                 }
  3418.                 for(int i = 0; i < seglist.size(); i++) {
  3419.                     std::stringstream test2(seglist[i]);
  3420.                     std::string segment2;
  3421.                     std::vector<std::string> seglist2;
  3422.                     while(std::getline(test2, segment2, '#'))
  3423.                     {
  3424.                         seglist2.push_back(segment2);
  3425.                     }
  3426. if(seglist2.size() != 2){
  3427.     std::cout << "Error: seglist2 contains improper amount of segments (" << test2 << ")." << std::endl;
  3428.     continue;
  3429. }
  3430. else if(isNumbers(seglist2[1])){
  3431.     item->setAttribute(seglist2[0], atoi(seglist2[1].c_str()));
  3432. }
  3433. else {
  3434.     item->setAttribute(seglist2[0], seglist2[1]);
  3435. }
  3436.                 }
  3437.             }
  3438.             if(item->hasStringAttribute("poke")){
  3439.                 msg->AddString(item->getPoke());
  3440.             }else{
  3441.                 msg->AddString(item->getName());
  3442.             }
  3443.             delete item;
  3444.         }
  3445.     }
  3446. }
  3447.  
  3448. void ProtocolGame::sendMarketAcceptOffer(MarketOfferEx offer)
  3449. {
  3450.     NetworkMessage_ptr msg = getOutputBuffer();
  3451.     if(msg)
  3452.     {
  3453.         TRACK_MESSAGE(msg);
  3454.         msg->AddByte(0xF9);
  3455.         msg->AddItemId(offer.itemId);
  3456.         if(offer.type == MARKETACTION_BUY)
  3457.         {
  3458.             msg->AddU32(0x01);
  3459.             msg->AddU32(offer.timestamp);
  3460.             msg->AddU16(offer.counter);
  3461.             msg->AddU16(offer.amount);
  3462.             msg->AddItemId(offer.itemId);
  3463.             msg->AddU32(offer.price);
  3464.             msg->AddString(offer.playerName);
  3465.             msg->AddU32(0x00);
  3466.             const ItemType& itt = Item::items[offer.itemId];
  3467.             Item* item = Item::CreateItem(itt.id, 1);
  3468.             std::stringstream test(offer.Attrs);
  3469.             std::string segment;
  3470.             std::vector<std::string> seglist;
  3471.             if(offer.Attrs != "false"){
  3472.                 while(std::getline(test, segment, 'º'))
  3473.                 {
  3474.                     seglist.push_back(segment);
  3475.                 }
  3476.                 for(int i = 0; i < seglist.size(); i++) {
  3477.                     std::stringstream test2(seglist[i]);
  3478.                     std::string segment2;
  3479.                     std::vector<std::string> seglist2;
  3480.                     while(std::getline(test2, segment2, '#'))
  3481.                     {
  3482.                         seglist2.push_back(segment2);
  3483.                     }
  3484. if(seglist2.size() != 2){
  3485.     std::cout << "Error: seglist2 contains improper amount of segments (" << test2 << ")." << std::endl;
  3486.     continue;
  3487. }
  3488. else if(isNumbers(seglist2[1])){
  3489.     item->setAttribute(seglist2[0], atoi(seglist2[1].c_str()));
  3490. }
  3491. else {
  3492.     item->setAttribute(seglist2[0], seglist2[1]);
  3493. }
  3494.                 }
  3495.             }
  3496.             if(item->hasStringAttribute("poke")){
  3497.                 msg->AddString(item->getPoke());
  3498.             }else{
  3499.                 msg->AddString(item->getName());
  3500.             }
  3501.             delete item;
  3502.         }
  3503.         else
  3504.         {
  3505.             msg->AddU32(0x00);
  3506.             msg->AddU32(0x01);
  3507.             msg->AddU32(offer.timestamp);
  3508.             msg->AddU16(offer.counter);
  3509.             msg->AddU16(offer.amount);
  3510.             msg->AddItemId(offer.itemId);
  3511.             msg->AddU32(offer.price);
  3512.             msg->AddString(offer.playerName);
  3513.             const ItemType& itt = Item::items[offer.itemId];
  3514.             Item* item = Item::CreateItem(itt.id, 1);
  3515.             std::stringstream test(offer.Attrs);
  3516.             std::string segment;
  3517.             std::vector<std::string> seglist;
  3518.             if(offer.Attrs != "false"){
  3519.                 while(std::getline(test, segment, 'º'))
  3520.                 {
  3521.                     seglist.push_back(segment);
  3522.                 }
  3523.                 for(int i = 0; i < seglist.size(); i++) {
  3524.                     std::stringstream test2(seglist[i]);
  3525.                     std::string segment2;
  3526.                     std::vector<std::string> seglist2;
  3527.                     while(std::getline(test2, segment2, '#'))
  3528.                     {
  3529.                         seglist2.push_back(segment2);
  3530.                     }
  3531. if(seglist2.size() != 2){
  3532.     std::cout << "Error: seglist2 contains improper amount of segments (" << test2 << ")." << std::endl;
  3533.     continue;
  3534. }
  3535. else if(isNumbers(seglist2[1])){
  3536.     item->setAttribute(seglist2[0], atoi(seglist2[1].c_str()));
  3537. }
  3538. else {
  3539.     item->setAttribute(seglist2[0], seglist2[1]);
  3540. }
  3541.                 }
  3542.             }
  3543.             if(item->hasStringAttribute("poke")){
  3544.                 msg->AddString(item->getPoke());
  3545.             }else{
  3546.                 msg->AddString(item->getName());
  3547.             }
  3548.             delete item;
  3549.         }
  3550.     }
  3551. }
  3552.  
  3553. void ProtocolGame::sendMarketItemDesc(const std::string& desc, uint16_t itemId)
  3554. {
  3555.     NetworkMessage_ptr msg = getOutputBuffer();
  3556.     if(msg)
  3557.     {
  3558.         TRACK_MESSAGE(msg);
  3559.         msg->AddByte(0xFF);
  3560.         msg->AddString(desc);
  3561.         msg->AddItemId(itemId);
  3562.     }
  3563. }
  3564.  
  3565. void ProtocolGame::sendMarketBrowseOwnOffers(const MarketOfferList& buyOffers, const MarketOfferList& sellOffers)
  3566. {
  3567.     NetworkMessage_ptr msg = getOutputBuffer();
  3568.     if(msg)
  3569.     {
  3570.         TRACK_MESSAGE(msg);
  3571.         msg->AddByte(0xF9);
  3572.         msg->AddU16(MARKETREQUEST_OWN_OFFERS);
  3573.  
  3574.         msg->AddU32(buyOffers.size());
  3575.         for(MarketOfferList::const_iterator it = buyOffers.begin(), end = buyOffers.end(); it != end; ++it)
  3576.         {
  3577.             msg->AddU32(it->timestamp);
  3578.             msg->AddU16(it->counter);
  3579.             msg->AddItemId(it->itemId);
  3580.             msg->AddU16(it->amount);
  3581.             msg->AddU32(it->price);
  3582.             const ItemType& itt = Item::items[it->itemId];
  3583.             Item* item = Item::CreateItem(itt.id, 1);
  3584.             std::stringstream test(it->Attrs);
  3585.             std::string segment;
  3586.             std::vector<std::string> seglist;
  3587.             if(it->Attrs != "false"){
  3588.                 while(std::getline(test, segment, 'º'))
  3589.                 {
  3590.                     seglist.push_back(segment);
  3591.                 }
  3592.                 for(int i = 0; i < seglist.size(); i++) {
  3593.                     std::stringstream test2(seglist[i]);
  3594.                     std::string segment2;
  3595.                     std::vector<std::string> seglist2;
  3596.                     while(std::getline(test2, segment2, '#'))
  3597.                     {
  3598.                         seglist2.push_back(segment2);
  3599.                     }
  3600.                     if(std::isdigit(atoi((char*)seglist2[1].c_str())) || atoi((char*)seglist2[1].c_str()) >= 1){
  3601.                         item->setAttribute(seglist2[0], atoi((char*)seglist2[1].c_str()));
  3602.                     }else{
  3603.                         item->setAttribute(seglist2[0], seglist2[1]);
  3604.                     }
  3605.                 }
  3606.             }
  3607.             if(item->hasStringAttribute("poke")){
  3608.                 msg->AddString(item->getPoke());
  3609.             }else{
  3610.                 msg->AddString(item->getName());
  3611.             }
  3612.             delete item;
  3613.         }
  3614.  
  3615.         msg->AddU32(sellOffers.size());
  3616.         for(MarketOfferList::const_iterator it = sellOffers.begin(), end = sellOffers.end(); it != end; ++it)
  3617.         {
  3618.             msg->AddU32(it->timestamp);
  3619.             msg->AddU16(it->counter);
  3620.             msg->AddItemId(it->itemId);
  3621.             msg->AddU16(it->amount);
  3622.             msg->AddU32(it->price);
  3623.             const ItemType& itt = Item::items[it->itemId];
  3624.             Item* item = Item::CreateItem(itt.id, 1);
  3625.             std::stringstream test(it->Attrs);
  3626.             std::string segment;
  3627.             std::vector<std::string> seglist;
  3628.             if(it->Attrs != "false"){
  3629.                 while(std::getline(test, segment, 'º'))
  3630.                 {
  3631.                     seglist.push_back(segment);
  3632.                 }
  3633.                 for(int i = 0; i < seglist.size(); i++) {
  3634.                     std::stringstream test2(seglist[i]);
  3635.                     std::string segment2;
  3636.                     std::vector<std::string> seglist2;
  3637.                     while(std::getline(test2, segment2, '#'))
  3638.                     {
  3639.                         seglist2.push_back(segment2);
  3640.                     }
  3641.                     if(std::isdigit(atoi((char*)seglist2[1].c_str())) || atoi((char*)seglist2[1].c_str()) >= 1){
  3642.                         item->setAttribute(seglist2[0], atoi((char*)seglist2[1].c_str()));
  3643.                     }else{
  3644.                         item->setAttribute(seglist2[0], seglist2[1]);
  3645.                     }
  3646.                 }
  3647.             }
  3648.             if(item->hasStringAttribute("poke")){
  3649.                 msg->AddString(item->getPoke());
  3650.             }else{
  3651.                 msg->AddString(item->getName());
  3652.             }
  3653.             delete item;
  3654.         }
  3655.     }  
  3656. }
  3657.  
  3658. void ProtocolGame::sendMarketCancelOffer(MarketOfferEx offer)
  3659. {
  3660.     NetworkMessage_ptr msg = getOutputBuffer();
  3661.     if(msg)
  3662.     {
  3663.         TRACK_MESSAGE(msg);
  3664.         msg->AddByte(0xF9);
  3665.         msg->AddU16(MARKETREQUEST_OWN_OFFERS);
  3666.         if(offer.type == MARKETACTION_BUY)
  3667.         {
  3668.             msg->AddU32(0x01);
  3669.             msg->AddU32(offer.timestamp);
  3670.             msg->AddU16(offer.counter);
  3671.             msg->AddItemId(offer.itemId);
  3672.             msg->AddU16(offer.amount);
  3673.             msg->AddU32(offer.price);
  3674.             const ItemType& itt = Item::items[offer.itemId];
  3675.             Item* item = Item::CreateItem(itt.id, 1);
  3676.             std::stringstream test(offer.Attrs);
  3677.             std::string segment;
  3678.             std::vector<std::string> seglist;
  3679.             if(offer.Attrs != "false"){
  3680.                 while(std::getline(test, segment, 'º'))
  3681.                 {
  3682.                     seglist.push_back(segment);
  3683.                 }
  3684.                 for(int i = 0; i < seglist.size(); i++) {
  3685.                     std::stringstream test2(seglist[i]);
  3686.                     std::string segment2;
  3687.                     std::vector<std::string> seglist2;
  3688.                     while(std::getline(test2, segment2, '#'))
  3689.                     {
  3690.                         seglist2.push_back(segment2);
  3691.                     }
  3692.                     if(std::isdigit(atoi((char*)seglist2[1].c_str())) || atoi((char*)seglist2[1].c_str()) >= 1){
  3693.                         item->setAttribute(seglist2[0], atoi((char*)seglist2[1].c_str()));
  3694.                     }else{
  3695.                         item->setAttribute(seglist2[0], seglist2[1]);
  3696.                     }
  3697.                 }
  3698.             }
  3699.             if(item->hasStringAttribute("poke")){
  3700.                 msg->AddString(item->getPoke());
  3701.             }else{
  3702.                 msg->AddString(item->getName());
  3703.             }
  3704.             msg->AddU32(0x00);
  3705.             delete item;
  3706.         }
  3707.         else
  3708.         {
  3709.             msg->AddU32(0x00);
  3710.             msg->AddU32(0x01);
  3711.             msg->AddU32(offer.timestamp);
  3712.             msg->AddU16(offer.counter);
  3713.             msg->AddItemId(offer.itemId);
  3714.             msg->AddU16(offer.amount);
  3715.             msg->AddU32(offer.price);
  3716.             const ItemType& itt = Item::items[offer.itemId];
  3717.             Item* item = Item::CreateItem(itt.id, 1);
  3718.             std::stringstream test(offer.Attrs);
  3719.             std::string segment;
  3720.             std::vector<std::string> seglist;
  3721.             if(offer.Attrs != "false"){
  3722.                 while(std::getline(test, segment, 'º'))
  3723.                 {
  3724.                     seglist.push_back(segment);
  3725.                 }
  3726.                 for(int i = 0; i < seglist.size(); i++) {
  3727.                     std::stringstream test2(seglist[i]);
  3728.                     std::string segment2;
  3729.                     std::vector<std::string> seglist2;
  3730.                     while(std::getline(test2, segment2, '#'))
  3731.                     {
  3732.                         seglist2.push_back(segment2);
  3733.                     }
  3734.                     if(std::isdigit(atoi((char*)seglist2[1].c_str())) || atoi((char*)seglist2[1].c_str()) >= 1){
  3735.                         item->setAttribute(seglist2[0], atoi((char*)seglist2[1].c_str()));
  3736.                     }else{
  3737.                         item->setAttribute(seglist2[0], seglist2[1]);
  3738.                     }
  3739.                 }
  3740.             }
  3741.             if(item->hasStringAttribute("poke")){
  3742.                 msg->AddString(item->getPoke());
  3743.             }else{
  3744.                 msg->AddString(item->getName());
  3745.             }
  3746.             delete item;
  3747.         }
  3748.     }
  3749. }
  3750.  
  3751. void ProtocolGame::sendMarketBrowseOwnHistory(const HistoryMarketOfferList& buyOffers, const HistoryMarketOfferList& sellOffers)
  3752. {
  3753.     NetworkMessage_ptr msg = getOutputBuffer();
  3754.     if(msg)
  3755.     {
  3756.         TRACK_MESSAGE(msg);
  3757.         msg->AddByte(0xF9);
  3758.         msg->AddU16(MARKETREQUEST_OWN_HISTORY);
  3759.  
  3760.         std::map<uint32_t, uint16_t> counterMap;
  3761.  
  3762.         uint32_t i = 0;
  3763.         msg->AddU32(std::min<int32_t>(800, buyOffers.size()));
  3764.         for(HistoryMarketOfferList::const_iterator it = buyOffers.begin(), end = buyOffers.end(); it != end && i < 800; ++it, ++i)
  3765.         {
  3766.             msg->AddU32(it->timestamp);
  3767.             msg->AddU16(counterMap[it->timestamp]++);
  3768.             msg->AddItemId(it->itemId);
  3769.             msg->AddU16(it->amount);
  3770.             msg->AddU32(it->price);
  3771.             msg->AddByte(it->state);
  3772.             const ItemType& itt = Item::items[it->itemId];
  3773.             Item* item = Item::CreateItem(itt.id, 1);
  3774.             std::stringstream test(it->Attrs);
  3775.             std::string segment;
  3776.             std::vector<std::string> seglist;
  3777.             if(it->Attrs != "false"){
  3778.                 while(std::getline(test, segment, 'º'))
  3779.                 {
  3780.                     seglist.push_back(segment);
  3781.                 }
  3782.                 for(int i = 0; i < seglist.size(); i++) {
  3783.                     std::stringstream test2(seglist[i]);
  3784.                     std::string segment2;
  3785.                     std::vector<std::string> seglist2;
  3786.                     while(std::getline(test2, segment2, '#'))
  3787.                     {
  3788.                         seglist2.push_back(segment2);
  3789.                     }
  3790.                     if(std::isdigit(atoi((char*)seglist2[1].c_str())) || atoi((char*)seglist2[1].c_str()) >= 1){
  3791.                         item->setAttribute(seglist2[0], atoi((char*)seglist2[1].c_str()));
  3792.                     }else{
  3793.                         item->setAttribute(seglist2[0], seglist2[1]);
  3794.                     }
  3795.                 }
  3796.             }
  3797.             if(item->hasStringAttribute("poke")){
  3798.                 msg->AddString(item->getPoke());
  3799.             }else{
  3800.                 msg->AddString(item->getName());
  3801.             }
  3802.             delete item;
  3803.         }
  3804.  
  3805.         counterMap.clear();
  3806.         i = 0;
  3807.  
  3808.         msg->AddU32(std::min<int32_t>(800, sellOffers.size()));
  3809.         for(HistoryMarketOfferList::const_iterator it = sellOffers.begin(), end = sellOffers.end(); it != end && i < 800; ++it, ++i)
  3810.         {
  3811.             msg->AddU32(it->timestamp);
  3812.             msg->AddU16(counterMap[it->timestamp]++);
  3813.             msg->AddItemId(it->itemId);
  3814.             msg->AddU16(it->amount);
  3815.             msg->AddU32(it->price);
  3816.             msg->AddByte(it->state);
  3817.             const ItemType& itt = Item::items[it->itemId];
  3818.             Item* item = Item::CreateItem(itt.id, 1);
  3819.             std::stringstream test(it->Attrs);
  3820.             std::string segment;
  3821.             std::vector<std::string> seglist;
  3822.             if(it->Attrs != "false"){
  3823.                 while(std::getline(test, segment, 'º'))
  3824.                 {
  3825.                     seglist.push_back(segment);
  3826.                 }
  3827.                 for(int i = 0; i < seglist.size(); i++) {
  3828.                     std::stringstream test2(seglist[i]);
  3829.                     std::string segment2;
  3830.                     std::vector<std::string> seglist2;
  3831.                     while(std::getline(test2, segment2, '#'))
  3832.                     {
  3833.                         seglist2.push_back(segment2);
  3834.                     }
  3835.                     if(std::isdigit(atoi((char*)seglist2[1].c_str())) || atoi((char*)seglist2[1].c_str()) >= 1){
  3836.                         item->setAttribute(seglist2[0], atoi((char*)seglist2[1].c_str()));
  3837.                     }else{
  3838.                         item->setAttribute(seglist2[0], seglist2[1]);
  3839.                     }
  3840.                 }
  3841.             }
  3842.             if(item->hasStringAttribute("poke")){
  3843.                 msg->AddString(item->getPoke());
  3844.             }else{
  3845.                 msg->AddString(item->getName());
  3846.             }
  3847.             delete item;
  3848.         }
  3849.     }
  3850. }
  3851.  
  3852. void ProtocolGame::sendMarketDetail(uint16_t itemId)
  3853. {
  3854.     NetworkMessage_ptr msg = getOutputBuffer();
  3855.     if(msg)
  3856.     {
  3857.         TRACK_MESSAGE(msg);
  3858.     msg->AddByte(0xF8);
  3859.     msg->AddItemId(itemId);
  3860.  
  3861.     const ItemType& it = Item::items[itemId];
  3862.     std::ostringstream ss;
  3863.     if(it.armor != 0)
  3864.     {
  3865.         ss << it.armor;
  3866.         msg->AddString(ss.str());
  3867.     }
  3868.     else
  3869.         msg->AddU16(0x00);
  3870.  
  3871.     if(it.attack != 0)
  3872.     {
  3873.         ss.str("");
  3874.         ss << it.attack;
  3875.         if(it.abilities.elementType != COMBAT_NONE && it.decayTo > 0)
  3876.             ss << " physical +" << it.abilities.elementDamage << " " << getCombatName(it.abilities.elementType);
  3877.  
  3878.         // TODO: chance to hit, range
  3879.         // example:
  3880.         // "attack +x, chance to hit +y%, z fields"
  3881.  
  3882.         msg->AddString(ss.str());
  3883.     }
  3884.     else
  3885.         msg->AddU16(0x00);
  3886.  
  3887.     if(it.isContainer())
  3888.     {
  3889.         ss.str("");
  3890.         ss << it.maxItems;
  3891.         msg->AddString(ss.str());
  3892.     }
  3893.     else
  3894.         msg->AddU16(0x00);
  3895.  
  3896.     if(it.defense != 0)
  3897.     {
  3898.         ss.str("");
  3899.         ss << it.defense;
  3900.         if(it.extraDefense != 0)
  3901.             ss << " " << std::showpos << it.extraDefense << std::noshowpos;
  3902.  
  3903.         msg->AddString(ss.str());
  3904.     }
  3905.     else
  3906.         msg->AddU16(0x00);
  3907.  
  3908.     if(!it.description.empty())
  3909.     {
  3910.         std::string descr = it.description;
  3911.         if(descr[descr.length() - 1] == '.')
  3912.             descr.erase(descr.length() - 1);
  3913.  
  3914.         msg->AddString(descr);
  3915.     }
  3916.     else
  3917.         msg->AddU16(0x00);
  3918.  
  3919.     if(it.decayTime != 0)
  3920.     {
  3921.         ss.str("");
  3922.         ss << it.decayTime << " seconds";
  3923.         msg->AddString(ss.str());
  3924.     }
  3925.     else
  3926.         msg->AddU16(0x00);
  3927.  
  3928.     ss.str("");
  3929.     if(it.abilities.absorb)
  3930.     {
  3931.         bool separator = false;
  3932.         for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; ++i)
  3933.         {
  3934.             if(!it.abilities.absorb[i])
  3935.                 continue;
  3936.  
  3937.             if(separator)
  3938.                 ss << ", ";
  3939.             else
  3940.                 separator = true;
  3941.  
  3942.             ss << getCombatName(indexToCombatType(i)) << " " << std::showpos << it.abilities.absorb[i] << std::noshowpos << "%";
  3943.         }
  3944.     }
  3945.     msg->AddString(ss.str());
  3946.  
  3947.     if(it.minReqLevel != 0)
  3948.     {
  3949.         ss.str("");
  3950.         ss << it.minReqLevel;
  3951.         msg->AddString(ss.str());
  3952.     }
  3953.     else
  3954.         msg->AddU16(0x00);
  3955.  
  3956.     if(it.minReqMagicLevel != 0)
  3957.     {
  3958.         ss.str("");
  3959.         ss << it.minReqMagicLevel;
  3960.         msg->AddString(ss.str());
  3961.     }
  3962.     else
  3963.         msg->AddU16(0x00);
  3964.  
  3965.     msg->AddString(it.vocationString);
  3966.  
  3967.     msg->AddString(it.runeSpellName);
  3968.  
  3969.     ss.str("");
  3970.     if(it.abilities.skills)
  3971.     {
  3972.         bool separator = false;
  3973.         for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; i++)
  3974.         {
  3975.             if(!it.abilities.skills[i])
  3976.                 continue;
  3977.  
  3978.             if(separator)
  3979.                 ss << ", ";
  3980.             else
  3981.                 separator = true;
  3982.  
  3983.             ss << getSkillName(i) << " " << std::showpos << it.abilities.skills[i] << std::noshowpos;
  3984.         }
  3985.  
  3986.         if(it.abilities.stats[STAT_MAGICLEVEL] != 0)
  3987.         {
  3988.             if(separator)
  3989.                 ss << ", ";
  3990.             else
  3991.                 separator = true;
  3992.  
  3993.             ss << "magic level " << std::showpos << it.abilities.stats[STAT_MAGICLEVEL] << std::noshowpos;
  3994.         }
  3995.  
  3996.         if(it.abilities.speed != 0)
  3997.         {
  3998.             if(separator)
  3999.                 ss << ", ";
  4000.  
  4001.             ss << "speed" << " " << std::showpos << (int32_t)(it.abilities.speed / 2) << std::noshowpos;
  4002.         }
  4003.     }
  4004.     msg->AddString(ss.str());
  4005.  
  4006.     if(it.charges != 0)
  4007.     {
  4008.         ss.str("");
  4009.         ss << it.charges;
  4010.         msg->AddString(ss.str());
  4011.     }
  4012.     else
  4013.         msg->AddU16(0x00);
  4014.  
  4015.     std::string weaponName = getWeaponName(it.weaponType);
  4016.     if(it.slotPosition & SLOTP_TWO_HAND)
  4017.     {
  4018.         if(!weaponName.empty())
  4019.             weaponName += ", two-handed";
  4020.         else
  4021.             weaponName = "two-handed";
  4022.     }
  4023.     msg->AddString(weaponName);
  4024.  
  4025.     if(it.weight > 0)
  4026.     {
  4027.         ss.str("");
  4028.         ss << std::fixed << std::setprecision(2) << it.weight << " oz";
  4029.         msg->AddString(ss.str());
  4030.     }
  4031.     else
  4032.         msg->AddU16(0x00);
  4033.  
  4034.     MarketStatistics* statistics = IOMarket::getInstance()->getPurchaseStatistics(itemId);
  4035.     if(statistics)
  4036.     {
  4037.         msg->AddByte(0x01);
  4038.         msg->AddU32(statistics->numTransactions);
  4039.         msg->AddU32(std::min<uint64_t>(0xFFFFFFFF, statistics->totalPrice));
  4040.         msg->AddU32(statistics->highestPrice);
  4041.         msg->AddU32(statistics->lowestPrice);
  4042.     }
  4043.     else
  4044.         msg->AddByte(0x00);
  4045.  
  4046.     statistics = IOMarket::getInstance()->getSaleStatistics(itemId);
  4047.     if(statistics)
  4048.     {
  4049.         msg->AddByte(0x01);
  4050.         msg->AddU32(statistics->numTransactions);
  4051.         msg->AddU32(std::min<uint64_t>(0xFFFFFFFF, statistics->totalPrice));
  4052.         msg->AddU32(statistics->highestPrice);
  4053.         msg->AddU32(statistics->lowestPrice);
  4054.     }
  4055.     else
  4056.         msg->AddByte(0x00);
  4057.  
  4058.     }
  4059. }
  4060.  
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×