Advertisement
Guest User

protocolgame.cpp

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