Advertisement
Guest User

Untitled

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