Advertisement
Guest User

Protocolgame.cpp

a guest
Mar 12th, 2015
344
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 64.00 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. bool gamemaster = msg.GetByte();
  427. std::string name = msg.GetString(), character = msg.GetString(), password = msg.GetString();
  428.  
  429. msg.SkipBytes(6); //841- wtf?
  430. if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX)
  431. {
  432. disconnectClient(0x14, CLIENT_VERSION_STRING);
  433. return false;
  434. }
  435.  
  436. if(name.empty())
  437. {
  438. if(!g_config.getBool(ConfigManager::ACCOUNT_MANAGER))
  439. {
  440. disconnectClient(0x14, "Invalid account name.");
  441. return false;
  442. }
  443.  
  444. name = "1";
  445. password = "1";
  446. }
  447.  
  448. if(g_game.getGameState() < GAME_STATE_NORMAL)
  449. {
  450. disconnectClient(0x14, "Gameworld is just starting up, please wait.");
  451. return false;
  452. }
  453.  
  454. if(g_game.getGameState() == GAME_STATE_MAINTAIN)
  455. {
  456. disconnectClient(0x14, "Gameworld is under maintenance, please re-connect in a while.");
  457. return false;
  458. }
  459.  
  460. if(ConnectionManager::getInstance()->isDisabled(getIP(), protocolId))
  461. {
  462. disconnectClient(0x14, "Too many connections attempts from your IP address, please try again later.");
  463. return false;
  464. }
  465.  
  466. if(IOBan::getInstance()->isIpBanished(getIP()))
  467. {
  468. disconnectClient(0x14, "Your IP is banished!");
  469. return false;
  470. }
  471.  
  472. uint32_t id = 1;
  473. if(!IOLoginData::getInstance()->getAccountId(name, id))
  474. {
  475. ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, false);
  476. disconnectClient(0x14, "Invalid account name.");
  477. return false;
  478. }
  479.  
  480. std::string hash;
  481. if(!IOLoginData::getInstance()->getPassword(id, hash, character) || !encryptTest(password, hash))
  482. {
  483. ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, false);
  484. disconnectClient(0x14, "Invalid password.");
  485. return false;
  486. }
  487.  
  488. Ban ban;
  489. ban.value = id;
  490.  
  491. ban.type = BAN_ACCOUNT;
  492. if(IOBan::getInstance()->getData(ban) && !IOLoginData::getInstance()->hasFlag(id, PlayerFlag_CannotBeBanned))
  493. {
  494. bool deletion = ban.expires < 0;
  495. std::string name_ = "Automatic ";
  496. if(!ban.adminId)
  497. name_ += (deletion ? "deletion" : "banishment");
  498. else
  499. IOLoginData::getInstance()->getNameByGuid(ban.adminId, name_, true);
  500.  
  501. char buffer[500 + ban.comment.length()];
  502. 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.",
  503. (deletion ? "deleted" : "banished"), formatDateShort(ban.added).c_str(), name_.c_str(),
  504. getReason(ban.reason).c_str(), getAction(ban.action, false).c_str(), ban.comment.c_str(),
  505. (deletion ? "account won't be undeleted" : "banishment will be lifted at:\n"),
  506. (deletion ? "." : formatDateShort(ban.expires, true).c_str()));
  507.  
  508. disconnectClient(0x14, buffer);
  509. return false;
  510. }
  511.  
  512. ConnectionManager::getInstance()->addAttempt(getIP(), protocolId, true);
  513. Dispatcher::getInstance().addTask(createTask(boost::bind(
  514. &ProtocolGame::login, this, character, id, password, operatingSystem, version, gamemaster)));
  515. return true;
  516. }
  517.  
  518. void ProtocolGame::parsePacket(NetworkMessage &msg)
  519. {
  520. if(!player || !m_acceptPackets || g_game.getGameState() == GAME_STATE_SHUTDOWN
  521. || msg.getMessageLength() <= 0)
  522. return;
  523.  
  524. uint8_t recvbyte = msg.GetByte();
  525. //a dead player cannot performs actions
  526. if(player->isRemoved() && recvbyte != 0x14)
  527. return;
  528.  
  529. if(player->isAccountManager())
  530. {
  531. switch(recvbyte)
  532. {
  533. case 0x14:
  534. parseLogout(msg);
  535. break;
  536.  
  537. case 0x96:
  538. parseSay(msg);
  539. break;
  540.  
  541. default:
  542. sendCancelWalk();
  543. break;
  544. }
  545. }
  546. else
  547. {
  548. switch(recvbyte)
  549. {
  550. case 0x14: // logout
  551. parseLogout(msg);
  552. break;
  553.  
  554. case 0x1E: // keep alive / ping response
  555. parseReceivePing(msg);
  556. break;
  557.  
  558. case 0x64: // move with steps
  559. parseAutoWalk(msg);
  560. break;
  561.  
  562. case 0x65: // move north
  563. case 0x66: // move east
  564. case 0x67: // move south
  565. case 0x68: // move west
  566. parseMove(msg, (Direction)(recvbyte - 0x65));
  567. break;
  568.  
  569. case 0x69: // stop-autowalk
  570. addGameTask(&Game::playerStopAutoWalk, player->getID());
  571. break;
  572.  
  573. case 0x6A:
  574. parseMove(msg, NORTHEAST);
  575. break;
  576.  
  577. case 0x6B:
  578. parseMove(msg, SOUTHEAST);
  579. break;
  580.  
  581. case 0x6C:
  582. parseMove(msg, SOUTHWEST);
  583. break;
  584.  
  585. case 0x6D:
  586. parseMove(msg, NORTHWEST);
  587. break;
  588.  
  589. case 0x6F: // turn north
  590. case 0x70: // turn east
  591. case 0x71: // turn south
  592. case 0x72: // turn west
  593. parseTurn(msg, (Direction)(recvbyte - 0x6F));
  594. break;
  595.  
  596. case 0x78: // throw item
  597. parseThrow(msg);
  598. break;
  599.  
  600. case 0x79: // description in shop window
  601. parseLookInShop(msg);
  602. break;
  603.  
  604. case 0x7A: // player bought from shop
  605. parsePlayerPurchase(msg);
  606. break;
  607.  
  608. case 0x7B: // player sold to shop
  609. parsePlayerSale(msg);
  610. break;
  611.  
  612. case 0x7C: // player closed shop window
  613. parseCloseShop(msg);
  614. break;
  615.  
  616. case 0x7D: // Request trade
  617. parseRequestTrade(msg);
  618. break;
  619.  
  620. case 0x7E: // Look at an item in trade
  621. parseLookInTrade(msg);
  622. break;
  623.  
  624. case 0x7F: // Accept trade
  625. parseAcceptTrade(msg);
  626. break;
  627.  
  628. case 0x80: // close/cancel trade
  629. parseCloseTrade();
  630. break;
  631.  
  632. case 0x82: // use item
  633. parseUseItem(msg);
  634. break;
  635.  
  636. case 0x83: // use item
  637. parseUseItemEx(msg);
  638. break;
  639.  
  640. case 0x84: // battle window
  641. parseBattleWindow(msg);
  642. break;
  643.  
  644. case 0x85: //rotate item
  645. parseRotateItem(msg);
  646. break;
  647.  
  648. case 0x87: // close container
  649. parseCloseContainer(msg);
  650. break;
  651.  
  652. case 0x88: //"up-arrow" - container
  653. parseUpArrowContainer(msg);
  654. break;
  655.  
  656. case 0x89:
  657. parseTextWindow(msg);
  658. break;
  659.  
  660. case 0x8A:
  661. parseHouseWindow(msg);
  662. break;
  663.  
  664. case 0x8C: // throw item
  665. parseLookAt(msg);
  666. break;
  667.  
  668. case 0x96: // say something
  669. parseSay(msg);
  670. break;
  671.  
  672. case 0x97: // request channels
  673. parseGetChannels(msg);
  674. break;
  675.  
  676. case 0x98: // open channel
  677. parseOpenChannel(msg);
  678. break;
  679.  
  680. case 0x99: // close channel
  681. parseCloseChannel(msg);
  682. break;
  683.  
  684. case 0x9A: // open priv
  685. parseOpenPriv(msg);
  686. break;
  687.  
  688. case 0x9B: //process report
  689. parseProcessRuleViolation(msg);
  690. break;
  691.  
  692. case 0x9C: //gm closes report
  693. parseCloseRuleViolation(msg);
  694. break;
  695.  
  696. case 0x9D: //player cancels report
  697. parseCancelRuleViolation(msg);
  698. break;
  699.  
  700. case 0x9E: // close NPC
  701. parseCloseNpc(msg);
  702. break;
  703.  
  704. case 0xA0: // set attack and follow mode
  705. parseFightModes(msg);
  706. break;
  707.  
  708. case 0xA1: // attack
  709. parseAttack(msg);
  710. break;
  711.  
  712. case 0xA2: //follow
  713. parseFollow(msg);
  714. break;
  715.  
  716. case 0xA3: // invite party
  717. parseInviteToParty(msg);
  718. break;
  719.  
  720. case 0xA4: // join party
  721. parseJoinParty(msg);
  722. break;
  723.  
  724. case 0xA5: // revoke party
  725. parseRevokePartyInvite(msg);
  726. break;
  727.  
  728. case 0xA6: // pass leadership
  729. parsePassPartyLeadership(msg);
  730. break;
  731.  
  732. case 0xA7: // leave party
  733. parseLeaveParty(msg);
  734. break;
  735.  
  736. case 0xA8: // share exp
  737. parseSharePartyExperience(msg);
  738. break;
  739.  
  740. case 0xAA:
  741. parseCreatePrivateChannel(msg);
  742. break;
  743.  
  744. case 0xAB:
  745. parseChannelInvite(msg);
  746. break;
  747.  
  748. case 0xAC:
  749. parseChannelExclude(msg);
  750. break;
  751.  
  752. case 0xBE: // cancel move
  753. parseCancelMove(msg);
  754. break;
  755.  
  756. case 0xC9: //client request to resend the tile
  757. parseUpdateTile(msg);
  758. break;
  759.  
  760. case 0xCA: //client request to resend the container (happens when you store more than container maxsize)
  761. parseUpdateContainer(msg);
  762. break;
  763.  
  764. case 0xD2: // request outfit
  765. if((!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || !g_config.getBool(
  766. ConfigManager::DISABLE_OUTFITS_PRIVILEGED)) && (g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT)
  767. || g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS) || g_config.getBool(ConfigManager::ALLOW_CHANGEADDONS)))
  768. parseRequestOutfit(msg);
  769. break;
  770.  
  771. case 0xD3: // set outfit
  772. if((!player->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges) || !g_config.getBool(ConfigManager::DISABLE_OUTFITS_PRIVILEGED))
  773. && (g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS) || g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT)))
  774. parseSetOutfit(msg);
  775. break;
  776.  
  777. case 0xDC:
  778. parseAddVip(msg);
  779. break;
  780.  
  781. case 0xDD:
  782. parseRemoveVip(msg);
  783. break;
  784.  
  785. case 0xE6:
  786. parseBugReport(msg);
  787. break;
  788.  
  789. case 0xE7:
  790. parseViolationWindow(msg);
  791. break;
  792.  
  793. case 0xE8:
  794. parseDebugAssert(msg);
  795. break;
  796.  
  797. case 0xF0:
  798. parseQuests(msg);
  799. break;
  800.  
  801. case 0xF1:
  802. parseQuestInfo(msg);
  803. break;
  804.  
  805. default:
  806. {
  807. if(g_config.getBool(ConfigManager::BAN_UNKNOWN_BYTES))
  808. {
  809. int64_t banTime = -1;
  810. ViolationAction_t action = ACTION_BANISHMENT;
  811. Account tmp = IOLoginData::getInstance()->loadAccount(player->getAccount(), true);
  812.  
  813. tmp.warnings++;
  814. if(tmp.warnings >= g_config.getNumber(ConfigManager::WARNINGS_TO_DELETION))
  815. action = ACTION_DELETION;
  816. else if(tmp.warnings >= g_config.getNumber(ConfigManager::WARNINGS_TO_FINALBAN))
  817. {
  818. banTime = time(NULL) + g_config.getNumber(ConfigManager::FINALBAN_LENGTH);
  819. action = ACTION_BANFINAL;
  820. }
  821. else
  822. banTime = time(NULL) + g_config.getNumber(ConfigManager::BAN_LENGTH);
  823.  
  824. if(IOBan::getInstance()->addAccountBanishment(tmp.number, banTime, 13, action,
  825. "Sending unknown packets to the server.", 0, player->getGUID()))
  826. {
  827. IOLoginData::getInstance()->saveAccount(tmp);
  828. player->sendTextMessage(MSG_INFO_DESCR, "You have been banished.");
  829.  
  830. g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_GREEN);
  831. Scheduler::getInstance().addEvent(createSchedulerTask(1000, boost::bind(
  832. &Game::kickPlayer, &g_game, player->getID(), false)));
  833. }
  834. }
  835.  
  836. std::stringstream hex, s;
  837. hex << "0x" << std::hex << (int16_t)recvbyte << std::dec;
  838. s << player->getName() << " sent unknown byte: " << hex << std::endl;
  839.  
  840. LOG_MESSAGE(LOGTYPE_NOTICE, s.str(), "PLAYER")
  841. Logger::getInstance()->eFile(getFilePath(FILE_TYPE_LOG, "bots/" + player->getName() + ".log").c_str(),
  842. "[" + formatDate() + "] Received byte " + hex.str(), false);
  843. break;
  844. }
  845. }
  846. }
  847. }
  848.  
  849. void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage_ptr msg)
  850. {
  851. if(!tile)
  852. return;
  853.  
  854. int32_t count = 0;
  855. if(tile->ground)
  856. {
  857. msg->AddItem(tile->ground);
  858. count++;
  859. }
  860.  
  861. const TileItemVector* items = tile->getItemList();
  862. const CreatureVector* creatures = tile->getCreatures();
  863.  
  864. ItemVector::const_iterator it;
  865. if(items)
  866. {
  867. for(it = items->getBeginTopItem(); (it != items->getEndTopItem() && count < 10); ++it, ++count)
  868. msg->AddItem(*it);
  869. }
  870.  
  871. if(creatures)
  872. {
  873. for(CreatureVector::const_reverse_iterator cit = creatures->rbegin(); (cit != creatures->rend() && count < 10); ++cit)
  874. {
  875. if(!player->canSeeCreature(*cit))
  876. continue;
  877.  
  878. bool known;
  879. uint32_t removedKnown;
  880. checkCreatureAsKnown((*cit)->getID(), known, removedKnown);
  881.  
  882. AddCreature(msg, (*cit), known, removedKnown);
  883. count++;
  884. }
  885. }
  886.  
  887. if(items)
  888. {
  889. for(it = items->getBeginDownItem(); (it != items->getEndDownItem() && count < 10); ++it, ++count)
  890. msg->AddItem(*it);
  891. }
  892. }
  893.  
  894. void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z,
  895. int32_t width, int32_t height, NetworkMessage_ptr msg)
  896. {
  897. int32_t skip = -1, startz, endz, zstep = 0;
  898. if(z > 7)
  899. {
  900. startz = z - 2;
  901. endz = std::min((int32_t)MAP_MAX_LAYERS - 1, z + 2);
  902. zstep = 1;
  903. }
  904. else
  905. {
  906. startz = 7;
  907. endz = 0;
  908. zstep = -1;
  909. }
  910.  
  911. for(int32_t nz = startz; nz != endz + zstep; nz += zstep)
  912. GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip);
  913.  
  914. if(skip >= 0)
  915. {
  916. msg->AddByte(skip);
  917. msg->AddByte(0xFF);
  918. //cc += skip;
  919. }
  920. }
  921.  
  922. void ProtocolGame::GetFloorDescription(NetworkMessage_ptr msg, int32_t x, int32_t y, int32_t z,
  923. int32_t width, int32_t height, int32_t offset, int32_t& skip)
  924. {
  925. Tile* tile = NULL;
  926. for(int32_t nx = 0; nx < width; nx++)
  927. {
  928. for(int32_t ny = 0; ny < height; ny++)
  929. {
  930. if((tile = g_game.getTile(Position(x + nx + offset, y + ny + offset, z))))
  931. {
  932. if(skip >= 0)
  933. {
  934. msg->AddByte(skip);
  935. msg->AddByte(0xFF);
  936. }
  937.  
  938. skip = 0;
  939. GetTileDescription(tile, msg);
  940. }
  941. else
  942. {
  943. ++skip;
  944. if(skip == 0xFF)
  945. {
  946. msg->AddByte(0xFF);
  947. msg->AddByte(0xFF);
  948. skip = -1;
  949. }
  950. }
  951. }
  952. }
  953. }
  954.  
  955. void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool& known, uint32_t& removedKnown)
  956. {
  957. // loop through the known creature list and check if the given creature is in
  958. for(std::list<uint32_t>::iterator it = knownCreatureList.begin(); it != knownCreatureList.end(); ++it)
  959. {
  960. if((*it) != id)
  961. continue;
  962.  
  963. // know... make the creature even more known...
  964. knownCreatureList.erase(it);
  965. knownCreatureList.push_back(id);
  966.  
  967. known = true;
  968. return;
  969. }
  970.  
  971. // ok, he is unknown...
  972. known = false;
  973. // ... but not in future
  974. knownCreatureList.push_back(id);
  975. // too many known creatures?
  976. if(knownCreatureList.size() > 250)
  977. {
  978. // lets try to remove one from the end of the list
  979. Creature* c = NULL;
  980. for(int32_t n = 0; n < 250; n++)
  981. {
  982. removedKnown = knownCreatureList.front();
  983. if(!(c = g_game.getCreatureByID(removedKnown)) || !canSee(c))
  984. break;
  985.  
  986. // this creature we can't remove, still in sight, so back to the end
  987. knownCreatureList.pop_front();
  988. knownCreatureList.push_back(removedKnown);
  989. }
  990.  
  991. // hopefully we found someone to remove :S, we got only 250 tries
  992. // if not... lets kick some players with debug errors :)
  993. knownCreatureList.pop_front();
  994. }
  995. else // we can cache without problems :)
  996. removedKnown = 0;
  997. }
  998.  
  999. bool ProtocolGame::canSee(const Creature* c) const
  1000. {
  1001. return !c->isRemoved() && player->canSeeCreature(c) && canSee(c->getPosition());
  1002. }
  1003.  
  1004. bool ProtocolGame::canSee(const Position& pos) const
  1005. {
  1006. return canSee(pos.x, pos.y, pos.z);
  1007. }
  1008.  
  1009. bool ProtocolGame::canSee(uint16_t x, uint16_t y, uint16_t z) const
  1010. {
  1011. #ifdef __DEBUG__
  1012. if(z < 0 || z >= MAP_MAX_LAYERS)
  1013. std::cout << "[Warning - ProtocolGame::canSee] Z-value is out of range!" << std::endl;
  1014. #endif
  1015.  
  1016. const Position& myPos = player->getPosition();
  1017. if(myPos.z <= 7)
  1018. {
  1019. //we are on ground level or above (7 -> 0), view is from 7 -> 0
  1020. if(z > 7)
  1021. return false;
  1022. }
  1023. 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
  1024. return false;
  1025.  
  1026. //negative offset means that the action taken place is on a lower floor than ourself
  1027. int32_t offsetz = myPos.z - z;
  1028. return ((x >= myPos.x - 8 + offsetz) && (x <= myPos.x + 9 + offsetz) &&
  1029. (y >= myPos.y - 6 + offsetz) && (y <= myPos.y + 7 + offsetz));
  1030. }
  1031.  
  1032. //********************** Parse methods *******************************//
  1033. void ProtocolGame::parseLogout(NetworkMessage& msg)
  1034. {
  1035. Dispatcher::getInstance().addTask(createTask(boost::bind(&ProtocolGame::logout, this, true, false)));
  1036. }
  1037.  
  1038. void ProtocolGame::parseCreatePrivateChannel(NetworkMessage& msg)
  1039. {
  1040. addGameTask(&Game::playerCreatePrivateChannel, player->getID());
  1041. }
  1042.  
  1043. void ProtocolGame::parseChannelInvite(NetworkMessage& msg)
  1044. {
  1045. const std::string name = msg.GetString();
  1046. addGameTask(&Game::playerChannelInvite, player->getID(), name);
  1047. }
  1048.  
  1049. void ProtocolGame::parseChannelExclude(NetworkMessage& msg)
  1050. {
  1051. const std::string name = msg.GetString();
  1052. addGameTask(&Game::playerChannelExclude, player->getID(), name);
  1053. }
  1054.  
  1055. void ProtocolGame::parseGetChannels(NetworkMessage& msg)
  1056. {
  1057. addGameTask(&Game::playerRequestChannels, player->getID());
  1058. }
  1059.  
  1060. void ProtocolGame::parseOpenChannel(NetworkMessage& msg)
  1061. {
  1062. uint16_t channelId = msg.GetU16();
  1063. addGameTask(&Game::playerOpenChannel, player->getID(), channelId);
  1064. }
  1065.  
  1066. void ProtocolGame::parseCloseChannel(NetworkMessage& msg)
  1067. {
  1068. uint16_t channelId = msg.GetU16();
  1069. addGameTask(&Game::playerCloseChannel, player->getID(), channelId);
  1070. }
  1071.  
  1072. void ProtocolGame::parseOpenPriv(NetworkMessage& msg)
  1073. {
  1074. const std::string receiver = msg.GetString();
  1075. addGameTask(&Game::playerOpenPrivateChannel, player->getID(), receiver);
  1076. }
  1077.  
  1078. void ProtocolGame::parseProcessRuleViolation(NetworkMessage& msg)
  1079. {
  1080. const std::string reporter = msg.GetString();
  1081. addGameTask(&Game::playerProcessRuleViolation, player->getID(), reporter);
  1082. }
  1083.  
  1084. void ProtocolGame::parseCloseRuleViolation(NetworkMessage& msg)
  1085. {
  1086. const std::string reporter = msg.GetString();
  1087. addGameTask(&Game::playerCloseRuleViolation, player->getID(), reporter);
  1088. }
  1089.  
  1090. void ProtocolGame::parseCancelRuleViolation(NetworkMessage& msg)
  1091. {
  1092. addGameTask(&Game::playerCancelRuleViolation, player->getID());
  1093. }
  1094.  
  1095. void ProtocolGame::parseCloseNpc(NetworkMessage& msg)
  1096. {
  1097. addGameTask(&Game::playerCloseNpcChannel, player->getID());
  1098. }
  1099.  
  1100. void ProtocolGame::parseCancelMove(NetworkMessage& msg)
  1101. {
  1102. addGameTask(&Game::playerCancelAttackAndFollow, player->getID());
  1103. }
  1104.  
  1105. void ProtocolGame::parseReceivePing(NetworkMessage& msg)
  1106. {
  1107. addGameTask(&Game::playerReceivePing, player->getID());
  1108. }
  1109.  
  1110. void ProtocolGame::parseAutoWalk(NetworkMessage& msg)
  1111. {
  1112. // first we get all directions...
  1113. std::list<Direction> path;
  1114. size_t dirCount = msg.GetByte();
  1115. for(size_t i = 0; i < dirCount; ++i)
  1116. {
  1117. uint8_t rawDir = msg.GetByte();
  1118. Direction dir = SOUTH;
  1119. switch(rawDir)
  1120. {
  1121. case 1:
  1122. dir = EAST;
  1123. break;
  1124. case 2:
  1125. dir = NORTHEAST;
  1126. break;
  1127. case 3:
  1128. dir = NORTH;
  1129. break;
  1130. case 4:
  1131. dir = NORTHWEST;
  1132. break;
  1133. case 5:
  1134. dir = WEST;
  1135. break;
  1136. case 6:
  1137. dir = SOUTHWEST;
  1138. break;
  1139. case 7:
  1140. dir = SOUTH;
  1141. break;
  1142. case 8:
  1143. dir = SOUTHEAST;
  1144. break;
  1145. default:
  1146. continue;
  1147. }
  1148.  
  1149. path.push_back(dir);
  1150. }
  1151.  
  1152. addGameTask(&Game::playerAutoWalk, player->getID(), path);
  1153. }
  1154.  
  1155. void ProtocolGame::parseMove(NetworkMessage& msg, Direction dir)
  1156. {
  1157. addGameTask(&Game::playerMove, player->getID(), dir);
  1158. }
  1159.  
  1160. void ProtocolGame::parseTurn(NetworkMessage& msg, Direction dir)
  1161. {
  1162. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), dir);
  1163. }
  1164.  
  1165. void ProtocolGame::parseRequestOutfit(NetworkMessage& msg)
  1166. {
  1167. addGameTask(&Game::playerRequestOutfit, player->getID());
  1168. }
  1169.  
  1170. void ProtocolGame::parseSetOutfit(NetworkMessage& msg)
  1171. {
  1172. Outfit_t newOutfit = player->defaultOutfit;
  1173. if(g_config.getBool(ConfigManager::ALLOW_CHANGEOUTFIT))
  1174. newOutfit.lookType = msg.GetU16();
  1175. else
  1176. msg.SkipBytes(2);
  1177.  
  1178. if(g_config.getBool(ConfigManager::ALLOW_CHANGECOLORS))
  1179. {
  1180. newOutfit.lookHead = msg.GetByte();
  1181. newOutfit.lookBody = msg.GetByte();
  1182. newOutfit.lookLegs = msg.GetByte();
  1183. newOutfit.lookFeet = msg.GetByte();
  1184. }
  1185. else
  1186. msg.SkipBytes(4);
  1187.  
  1188. if(g_config.getBool(ConfigManager::ALLOW_CHANGEADDONS))
  1189. newOutfit.lookAddons = msg.GetByte();
  1190. else
  1191. msg.SkipBytes(1);
  1192.  
  1193. addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit);
  1194. }
  1195.  
  1196. void ProtocolGame::parseUseItem(NetworkMessage& msg)
  1197. {
  1198. Position pos = msg.GetPosition();
  1199. uint16_t spriteId = msg.GetSpriteId();
  1200. int16_t stackpos = msg.GetByte();
  1201. uint8_t index = msg.GetByte();
  1202. bool isHotkey = (pos.x == 0xFFFF && !pos.y && !pos.z);
  1203. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItem, player->getID(), pos, stackpos, index, spriteId, isHotkey);
  1204. }
  1205.  
  1206. void ProtocolGame::parseUseItemEx(NetworkMessage& msg)
  1207. {
  1208. Position fromPos = msg.GetPosition();
  1209. uint16_t fromSpriteId = msg.GetSpriteId();
  1210. int16_t fromStackpos = msg.GetByte();
  1211. Position toPos = msg.GetPosition();
  1212. uint16_t toSpriteId = msg.GetU16();
  1213. int16_t toStackpos = msg.GetByte();
  1214. bool isHotkey = (fromPos.x == 0xFFFF && !fromPos.y && !fromPos.z);
  1215. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItemEx, player->getID(),
  1216. fromPos, fromStackpos, fromSpriteId, toPos, toStackpos, toSpriteId, isHotkey);
  1217. }
  1218.  
  1219. void ProtocolGame::parseBattleWindow(NetworkMessage& msg)
  1220. {
  1221. Position fromPos = msg.GetPosition();
  1222. uint16_t spriteId = msg.GetSpriteId();
  1223. int16_t fromStackpos = msg.GetByte();
  1224. uint32_t creatureId = msg.GetU32();
  1225. bool isHotkey = (fromPos.x == 0xFFFF && !fromPos.y && !fromPos.z);
  1226. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseBattleWindow, player->getID(), fromPos, fromStackpos, creatureId, spriteId, isHotkey);
  1227. }
  1228.  
  1229. void ProtocolGame::parseCloseContainer(NetworkMessage& msg)
  1230. {
  1231. uint8_t cid = msg.GetByte();
  1232. addGameTask(&Game::playerCloseContainer, player->getID(), cid);
  1233. }
  1234.  
  1235. void ProtocolGame::parseUpArrowContainer(NetworkMessage& msg)
  1236. {
  1237. uint8_t cid = msg.GetByte();
  1238. addGameTask(&Game::playerMoveUpContainer, player->getID(), cid);
  1239. }
  1240.  
  1241. void ProtocolGame::parseUpdateTile(NetworkMessage& msg)
  1242. {
  1243. Position pos = msg.GetPosition();
  1244. //addGameTask(&Game::playerUpdateTile, player->getID(), pos);
  1245. }
  1246.  
  1247. void ProtocolGame::parseUpdateContainer(NetworkMessage& msg)
  1248. {
  1249. uint8_t cid = msg.GetByte();
  1250. addGameTask(&Game::playerUpdateContainer, player->getID(), cid);
  1251. }
  1252.  
  1253. void ProtocolGame::parseThrow(NetworkMessage& msg)
  1254. {
  1255. Position fromPos = msg.GetPosition();
  1256. uint16_t spriteId = msg.GetSpriteId();
  1257. int16_t fromStackpos = msg.GetByte();
  1258. Position toPos = msg.GetPosition();
  1259. uint8_t count = msg.GetByte();
  1260. if(toPos != fromPos)
  1261. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerMoveThing,
  1262. player->getID(), fromPos, spriteId, fromStackpos, toPos, count);
  1263. }
  1264.  
  1265. void ProtocolGame::parseLookAt(NetworkMessage& msg)
  1266. {
  1267. Position pos = msg.GetPosition();
  1268. uint16_t spriteId = msg.GetSpriteId();
  1269. int16_t stackpos = msg.GetByte();
  1270. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookAt, player->getID(), pos, spriteId, stackpos);
  1271. }
  1272.  
  1273. void ProtocolGame::parseSay(NetworkMessage& msg)
  1274. {
  1275. std::string receiver;
  1276. uint16_t channelId = 0;
  1277.  
  1278. SpeakClasses type = (SpeakClasses)msg.GetByte();
  1279. switch(type)
  1280. {
  1281. case SPEAK_PRIVATE:
  1282. case SPEAK_PRIVATE_RED:
  1283. case SPEAK_RVR_ANSWER:
  1284. receiver = msg.GetString();
  1285. break;
  1286.  
  1287. case SPEAK_CHANNEL_Y:
  1288. case SPEAK_CHANNEL_RN:
  1289. case SPEAK_CHANNEL_RA:
  1290. channelId = msg.GetU16();
  1291. break;
  1292.  
  1293. default:
  1294. break;
  1295. }
  1296.  
  1297. const std::string text = msg.GetString();
  1298. if(text.length() > 255) //client limit
  1299. {
  1300. std::stringstream s;
  1301. s << text.length();
  1302.  
  1303. Logger::getInstance()->eFile("bots/" + player->getName() + ".log", "Attempt to send message with size " + s.str() + " - client is limited to 255 characters.", true);
  1304. return;
  1305. }
  1306.  
  1307. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSay, player->getID(), channelId, type, receiver, text);
  1308. }
  1309.  
  1310. void ProtocolGame::parseFightModes(NetworkMessage& msg)
  1311. {
  1312. uint8_t rawFightMode = msg.GetByte(); //1 - offensive, 2 - balanced, 3 - defensive
  1313. uint8_t rawChaseMode = msg.GetByte(); //0 - stand while fightning, 1 - chase opponent
  1314. uint8_t rawSecureMode = msg.GetByte(); //0 - can't attack unmarked, 1 - can attack unmarked
  1315.  
  1316. chaseMode_t chaseMode = CHASEMODE_STANDSTILL;
  1317. if(rawChaseMode == 1)
  1318. chaseMode = CHASEMODE_FOLLOW;
  1319.  
  1320. fightMode_t fightMode = FIGHTMODE_ATTACK;
  1321. if(rawFightMode == 2)
  1322. fightMode = FIGHTMODE_BALANCED;
  1323. else if(rawFightMode == 3)
  1324. fightMode = FIGHTMODE_DEFENSE;
  1325.  
  1326. secureMode_t secureMode = SECUREMODE_OFF;
  1327. if(rawSecureMode == 1)
  1328. secureMode = SECUREMODE_ON;
  1329.  
  1330. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSetFightModes, player->getID(), fightMode, chaseMode, secureMode);
  1331. }
  1332.  
  1333. void ProtocolGame::parseAttack(NetworkMessage& msg)
  1334. {
  1335. uint32_t creatureId = msg.GetU32();
  1336. addGameTask(&Game::playerSetAttackedCreature, player->getID(), creatureId);
  1337. }
  1338.  
  1339. void ProtocolGame::parseFollow(NetworkMessage& msg)
  1340. {
  1341. uint32_t creatureId = msg.GetU32();
  1342. addGameTask(&Game::playerFollowCreature, player->getID(), creatureId);
  1343. }
  1344.  
  1345. void ProtocolGame::parseTextWindow(NetworkMessage& msg)
  1346. {
  1347. uint32_t windowTextId = msg.GetU32();
  1348. const std::string newText = msg.GetString();
  1349. addGameTask(&Game::playerWriteItem, player->getID(), windowTextId, newText);
  1350. }
  1351.  
  1352. void ProtocolGame::parseHouseWindow(NetworkMessage &msg)
  1353. {
  1354. uint8_t doorId = msg.GetByte();
  1355. uint32_t id = msg.GetU32();
  1356. const std::string text = msg.GetString();
  1357. addGameTask(&Game::playerUpdateHouseWindow, player->getID(), doorId, id, text);
  1358. }
  1359.  
  1360. void ProtocolGame::parseLookInShop(NetworkMessage &msg)
  1361. {
  1362. uint16_t id = msg.GetU16();
  1363. uint16_t count = msg.GetByte();
  1364. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInShop, player->getID(), id, count);
  1365. }
  1366.  
  1367. void ProtocolGame::parsePlayerPurchase(NetworkMessage &msg)
  1368. {
  1369. uint16_t id = msg.GetU16();
  1370. uint16_t count = msg.GetByte();
  1371. uint16_t amount = msg.GetByte();
  1372. bool ignoreCap = msg.GetByte();
  1373. bool inBackpacks = msg.GetByte();
  1374. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerPurchaseItem, player->getID(), id, count, amount, ignoreCap, inBackpacks);
  1375. }
  1376.  
  1377. void ProtocolGame::parsePlayerSale(NetworkMessage &msg)
  1378. {
  1379. uint16_t id = msg.GetU16();
  1380. uint16_t count = msg.GetByte();
  1381. uint16_t amount = msg.GetByte();
  1382. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSellItem, player->getID(), id, count, amount);
  1383. }
  1384.  
  1385. void ProtocolGame::parseCloseShop(NetworkMessage &msg)
  1386. {
  1387. addGameTask(&Game::playerCloseShop, player->getID());
  1388. }
  1389.  
  1390. void ProtocolGame::parseRequestTrade(NetworkMessage& msg)
  1391. {
  1392. Position pos = msg.GetPosition();
  1393. uint16_t spriteId = msg.GetSpriteId();
  1394. int16_t stackpos = msg.GetByte();
  1395. uint32_t playerId = msg.GetU32();
  1396. addGameTask(&Game::playerRequestTrade, player->getID(), pos, stackpos, playerId, spriteId);
  1397. }
  1398.  
  1399. void ProtocolGame::parseAcceptTrade(NetworkMessage& msg)
  1400. {
  1401. addGameTask(&Game::playerAcceptTrade, player->getID());
  1402. }
  1403.  
  1404. void ProtocolGame::parseLookInTrade(NetworkMessage& msg)
  1405. {
  1406. bool counter = msg.GetByte();
  1407. int32_t index = msg.GetByte();
  1408. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInTrade, player->getID(), counter, index);
  1409. }
  1410.  
  1411. void ProtocolGame::parseCloseTrade()
  1412. {
  1413. addGameTask(&Game::playerCloseTrade, player->getID());
  1414. }
  1415.  
  1416. void ProtocolGame::parseAddVip(NetworkMessage& msg)
  1417. {
  1418. const std::string name = msg.GetString();
  1419. if(name.size() > 32)
  1420. return;
  1421.  
  1422. addGameTask(&Game::playerRequestAddVip, player->getID(), name);
  1423. }
  1424.  
  1425. void ProtocolGame::parseRemoveVip(NetworkMessage& msg)
  1426. {
  1427. uint32_t guid = msg.GetU32();
  1428. addGameTask(&Game::playerRequestRemoveVip, player->getID(), guid);
  1429. }
  1430.  
  1431. void ProtocolGame::parseRotateItem(NetworkMessage& msg)
  1432. {
  1433. Position pos = msg.GetPosition();
  1434. uint16_t spriteId = msg.GetSpriteId();
  1435. int16_t stackpos = msg.GetByte();
  1436. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerRotateItem, player->getID(), pos, stackpos, spriteId);
  1437. }
  1438.  
  1439. void ProtocolGame::parseDebugAssert(NetworkMessage& msg)
  1440. {
  1441. if(m_debugAssertSent)
  1442. return;
  1443.  
  1444. std::stringstream s;
  1445. s << "----- " << formatDate() << " - " << player->getName() << " (" << convertIPAddress(getIP())
  1446. << ") -----" << std::endl << msg.GetString() << std::endl << msg.GetString()
  1447. << std::endl << msg.GetString() << std::endl << msg.GetString()
  1448. << std::endl << std::endl;
  1449.  
  1450. m_debugAssertSent = true;
  1451. Logger::getInstance()->iFile(LOGFILE_CLIENT_ASSERTION, s.str(), false);
  1452. }
  1453.  
  1454. void ProtocolGame::parseBugReport(NetworkMessage& msg)
  1455. {
  1456. std::string comment = msg.GetString();
  1457. addGameTask(&Game::playerReportBug, player->getID(), comment);
  1458. }
  1459.  
  1460. void ProtocolGame::parseInviteToParty(NetworkMessage& msg)
  1461. {
  1462. uint32_t targetId = msg.GetU32();
  1463. addGameTask(&Game::playerInviteToParty, player->getID(), targetId);
  1464. }
  1465.  
  1466. void ProtocolGame::parseJoinParty(NetworkMessage& msg)
  1467. {
  1468. uint32_t targetId = msg.GetU32();
  1469. addGameTask(&Game::playerJoinParty, player->getID(), targetId);
  1470. }
  1471.  
  1472. void ProtocolGame::parseRevokePartyInvite(NetworkMessage& msg)
  1473. {
  1474. uint32_t targetId = msg.GetU32();
  1475. addGameTask(&Game::playerRevokePartyInvitation, player->getID(), targetId);
  1476. }
  1477.  
  1478. void ProtocolGame::parsePassPartyLeadership(NetworkMessage& msg)
  1479. {
  1480. uint32_t targetId = msg.GetU32();
  1481. addGameTask(&Game::playerPassPartyLeadership, player->getID(), targetId);
  1482. }
  1483.  
  1484. void ProtocolGame::parseLeaveParty(NetworkMessage& msg)
  1485. {
  1486. addGameTask(&Game::playerLeaveParty, player->getID());
  1487. }
  1488.  
  1489. void ProtocolGame::parseSharePartyExperience(NetworkMessage& msg)
  1490. {
  1491. bool activate = msg.GetByte();
  1492. uint8_t unknown = msg.GetByte(); //TODO: find out what is this byte
  1493. addGameTask(&Game::playerSharePartyExperience, player->getID(), activate, unknown);
  1494. }
  1495.  
  1496. void ProtocolGame::parseQuests(NetworkMessage& msg)
  1497. {
  1498. addGameTask(&Game::playerQuests, player->getID());
  1499. }
  1500.  
  1501. void ProtocolGame::parseQuestInfo(NetworkMessage& msg)
  1502. {
  1503. uint16_t questId = msg.GetU16();
  1504. addGameTask(&Game::playerQuestInfo, player->getID(), questId);
  1505. }
  1506.  
  1507. void ProtocolGame::parseViolationWindow(NetworkMessage& msg)
  1508. {
  1509. std::string target = msg.GetString();
  1510. uint8_t reason = msg.GetByte();
  1511. ViolationAction_t action = (ViolationAction_t)msg.GetByte();
  1512. std::string comment = msg.GetString();
  1513. std::string statement = msg.GetString();
  1514. uint32_t statementId = (uint32_t)msg.GetU16();
  1515. bool ipBanishment = msg.GetByte();
  1516. addGameTask(&Game::playerViolationWindow, player->getID(), target, reason, action, comment, statement, statementId, ipBanishment);
  1517. }
  1518.  
  1519. //********************** Send methods *******************************//
  1520. void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver)
  1521. {
  1522. NetworkMessage_ptr msg = getOutputBuffer();
  1523. if(msg)
  1524. {
  1525. TRACK_MESSAGE(msg);
  1526. msg->AddByte(0xAD);
  1527. msg->AddString(receiver);
  1528. }
  1529. }
  1530.  
  1531. void ProtocolGame::sendCreatureOutfit(const Creature* creature, const Outfit_t& outfit)
  1532. {
  1533. if(!canSee(creature))
  1534. return;
  1535.  
  1536. NetworkMessage_ptr msg = getOutputBuffer();
  1537. if(msg)
  1538. {
  1539. TRACK_MESSAGE(msg);
  1540. msg->AddByte(0x8E);
  1541. msg->AddU32(creature->getID());
  1542. AddCreatureOutfit(msg, creature, outfit);
  1543. }
  1544. }
  1545.  
  1546. void ProtocolGame::sendCreatureLight(const Creature* creature)
  1547. {
  1548. if(!canSee(creature))
  1549. return;
  1550.  
  1551. NetworkMessage_ptr msg = getOutputBuffer();
  1552. if(msg)
  1553. {
  1554. TRACK_MESSAGE(msg);
  1555. AddCreatureLight(msg, creature);
  1556. }
  1557. }
  1558.  
  1559. void ProtocolGame::sendWorldLight(const LightInfo& lightInfo)
  1560. {
  1561. NetworkMessage_ptr msg = getOutputBuffer();
  1562. if(msg)
  1563. {
  1564. TRACK_MESSAGE(msg);
  1565. AddWorldLight(msg, lightInfo);
  1566. }
  1567. }
  1568.  
  1569. void ProtocolGame::sendCreatureShield(const Creature* creature)
  1570. {
  1571. if(!canSee(creature))
  1572. return;
  1573.  
  1574. NetworkMessage_ptr msg = getOutputBuffer();
  1575. if(msg)
  1576. {
  1577. TRACK_MESSAGE(msg);
  1578. msg->AddByte(0x91);
  1579. msg->AddU32(creature->getID());
  1580. msg->AddByte(player->getPartyShield(creature));
  1581. }
  1582. }
  1583.  
  1584. void ProtocolGame::sendCreatureSkull(const Creature* creature)
  1585. {
  1586. if(!canSee(creature))
  1587. return;
  1588.  
  1589. NetworkMessage_ptr msg = getOutputBuffer();
  1590. if(msg)
  1591. {
  1592. TRACK_MESSAGE(msg);
  1593. msg->AddByte(0x90);
  1594. msg->AddU32(creature->getID());
  1595. msg->AddByte(player->getSkullClient(creature));
  1596. }
  1597. }
  1598.  
  1599. void ProtocolGame::sendCreatureSquare(const Creature* creature, SquareColor_t color)
  1600. {
  1601. if(!canSee(creature))
  1602. return;
  1603.  
  1604. NetworkMessage_ptr msg = getOutputBuffer();
  1605. if(msg)
  1606. {
  1607. TRACK_MESSAGE(msg);
  1608. msg->AddByte(0x86);
  1609. msg->AddU32(creature->getID());
  1610. msg->AddByte((uint8_t)color);
  1611. }
  1612. }
  1613.  
  1614. void ProtocolGame::sendTutorial(uint8_t tutorialId)
  1615. {
  1616. NetworkMessage_ptr msg = getOutputBuffer();
  1617. if(msg)
  1618. {
  1619. TRACK_MESSAGE(msg);
  1620. msg->AddByte(0xDC);
  1621. msg->AddByte(tutorialId);
  1622. }
  1623. }
  1624.  
  1625. void ProtocolGame::sendAddMarker(const Position& pos, MapMarks_t markType, const std::string& desc)
  1626. {
  1627. NetworkMessage_ptr msg = getOutputBuffer();
  1628. if(msg)
  1629. {
  1630. TRACK_MESSAGE(msg);
  1631. msg->AddByte(0xDD);
  1632. msg->AddPosition(pos);
  1633. msg->AddByte(markType);
  1634. msg->AddString(desc);
  1635. }
  1636. }
  1637.  
  1638. void ProtocolGame::sendReLoginWindow()
  1639. {
  1640. NetworkMessage_ptr msg = getOutputBuffer();
  1641. if(msg)
  1642. {
  1643. TRACK_MESSAGE(msg);
  1644. msg->AddByte(0x28);
  1645. }
  1646. }
  1647.  
  1648. void ProtocolGame::sendStats()
  1649. {
  1650. NetworkMessage_ptr msg = getOutputBuffer();
  1651. if(msg)
  1652. {
  1653. TRACK_MESSAGE(msg);
  1654. AddPlayerStats(msg);
  1655. }
  1656. }
  1657.  
  1658. void ProtocolGame::sendTextMessage(MessageClasses mClass, const std::string& message)
  1659. {
  1660. NetworkMessage_ptr msg = getOutputBuffer();
  1661. if(msg)
  1662. {
  1663. TRACK_MESSAGE(msg);
  1664. AddTextMessage(msg, mClass, message);
  1665. }
  1666. }
  1667.  
  1668. void ProtocolGame::sendClosePrivate(uint16_t channelId)
  1669. {
  1670. NetworkMessage_ptr msg = getOutputBuffer();
  1671. if(msg)
  1672. {
  1673. TRACK_MESSAGE(msg);
  1674. if(channelId == CHANNEL_GUILD || channelId == CHANNEL_PARTY)
  1675. g_chat.removeUserFromChannel(player, channelId);
  1676.  
  1677. msg->AddByte(0xB3);
  1678. msg->AddU16(channelId);
  1679. }
  1680. }
  1681.  
  1682. void ProtocolGame::sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName)
  1683. {
  1684. NetworkMessage_ptr msg = getOutputBuffer();
  1685. if(msg)
  1686. {
  1687. TRACK_MESSAGE(msg);
  1688. msg->AddByte(0xB2);
  1689. msg->AddU16(channelId);
  1690. msg->AddString(channelName);
  1691. }
  1692. }
  1693.  
  1694. void ProtocolGame::sendChannelsDialog()
  1695. {
  1696. NetworkMessage_ptr msg = getOutputBuffer();
  1697. if(msg)
  1698. {
  1699. TRACK_MESSAGE(msg);
  1700. msg->AddByte(0xAB);
  1701. ChannelList list = g_chat.getChannelList(player);
  1702. msg->AddByte(list.size());
  1703. for(ChannelList::iterator it = list.begin(); it != list.end(); ++it)
  1704. {
  1705. if(ChatChannel* channel = (*it))
  1706. {
  1707. msg->AddU16(channel->getId());
  1708. msg->AddString(channel->getName());
  1709. }
  1710. }
  1711. }
  1712. }
  1713.  
  1714. void ProtocolGame::sendChannel(uint16_t channelId, const std::string& channelName)
  1715. {
  1716. NetworkMessage_ptr msg = getOutputBuffer();
  1717. if(msg)
  1718. {
  1719. TRACK_MESSAGE(msg);
  1720. msg->AddByte(0xAC);
  1721. msg->AddU16(channelId);
  1722. msg->AddString(channelName);
  1723. }
  1724. }
  1725.  
  1726. void ProtocolGame::sendRuleViolationsChannel(uint16_t channelId)
  1727. {
  1728. NetworkMessage_ptr msg = getOutputBuffer();
  1729. if(msg)
  1730. {
  1731. TRACK_MESSAGE(msg);
  1732. msg->AddByte(0xAE);
  1733. msg->AddU16(channelId);
  1734. for(RuleViolationsMap::const_iterator it = g_game.getRuleViolations().begin(); it != g_game.getRuleViolations().end(); ++it)
  1735. {
  1736. RuleViolation& rvr = *it->second;
  1737. if(rvr.isOpen && rvr.reporter)
  1738. AddCreatureSpeak(msg, rvr.reporter, SPEAK_RVR_CHANNEL, rvr.text, channelId, rvr.time);
  1739. }
  1740. }
  1741. }
  1742.  
  1743. void ProtocolGame::sendRemoveReport(const std::string& name)
  1744. {
  1745. NetworkMessage_ptr msg = getOutputBuffer();
  1746. if(msg)
  1747. {
  1748. TRACK_MESSAGE(msg);
  1749. msg->AddByte(0xAF);
  1750. msg->AddString(name);
  1751. }
  1752. }
  1753.  
  1754. void ProtocolGame::sendRuleViolationCancel(const std::string& name)
  1755. {
  1756. NetworkMessage_ptr msg = getOutputBuffer();
  1757. if(msg)
  1758. {
  1759. TRACK_MESSAGE(msg);
  1760. msg->AddByte(0xB0);
  1761. msg->AddString(name);
  1762. }
  1763. }
  1764.  
  1765. void ProtocolGame::sendLockRuleViolation()
  1766. {
  1767. NetworkMessage_ptr msg = getOutputBuffer();
  1768. if(msg)
  1769. {
  1770. TRACK_MESSAGE(msg);
  1771. msg->AddByte(0xB1);
  1772. }
  1773. }
  1774.  
  1775. void ProtocolGame::sendIcons(int32_t icons)
  1776. {
  1777. NetworkMessage_ptr msg = getOutputBuffer();
  1778. if(msg)
  1779. {
  1780. TRACK_MESSAGE(msg);
  1781. msg->AddByte(0xA2);
  1782. msg->AddU16(icons);
  1783. }
  1784. }
  1785.  
  1786. void ProtocolGame::sendContainer(uint32_t cid, const Container* container, bool hasParent)
  1787. {
  1788. NetworkMessage_ptr msg = getOutputBuffer();
  1789. if(msg)
  1790. {
  1791. TRACK_MESSAGE(msg);
  1792. msg->AddByte(0x6E);
  1793. msg->AddByte(cid);
  1794.  
  1795. msg->AddItemId(container);
  1796. msg->AddString(container->getName());
  1797. msg->AddByte(container->capacity());
  1798.  
  1799. msg->AddByte(hasParent ? 0x01 : 0x00);
  1800. msg->AddByte(std::min(container->size(), (uint32_t)255));
  1801.  
  1802. ItemList::const_iterator cit = container->getItems();
  1803. for(uint32_t i = 0; cit != container->getEnd() && i < 255; ++cit, ++i)
  1804. msg->AddItem(*cit);
  1805. }
  1806. }
  1807.  
  1808. void ProtocolGame::sendShop(const ShopInfoList& shop)
  1809. {
  1810. NetworkMessage_ptr msg = getOutputBuffer();
  1811. if(msg)
  1812. {
  1813. TRACK_MESSAGE(msg);
  1814. msg->AddByte(0x7A);
  1815. msg->AddByte(std::min(shop.size(), (size_t)255));
  1816.  
  1817. ShopInfoList::const_iterator it = shop.begin();
  1818. for(uint32_t i = 0; it != shop.end() && i < 255; ++it, ++i)
  1819. AddShopItem(msg, (*it));
  1820. }
  1821. }
  1822.  
  1823. void ProtocolGame::sendCloseShop()
  1824. {
  1825. NetworkMessage_ptr msg = getOutputBuffer();
  1826. if(msg)
  1827. {
  1828. TRACK_MESSAGE(msg);
  1829. msg->AddByte(0x7C);
  1830. }
  1831. }
  1832.  
  1833. void ProtocolGame::sendGoods(const ShopInfoList& shop)
  1834. {
  1835. NetworkMessage_ptr msg = getOutputBuffer();
  1836. if(msg)
  1837. {
  1838. TRACK_MESSAGE(msg);
  1839. msg->AddByte(0x7B);
  1840. msg->AddU32(g_game.getMoney(player));
  1841.  
  1842. std::map<uint32_t, uint32_t> goodsMap;
  1843. if(shop.size() >= 5)
  1844. {
  1845. for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit)
  1846. {
  1847. if(sit->sellPrice < 0)
  1848. continue;
  1849.  
  1850. int8_t subType = -1;
  1851. if(sit->subType)
  1852. {
  1853. const ItemType& it = Item::items[sit->itemId];
  1854. if(it.hasSubType() && !it.stackable)
  1855. subType = sit->subType;
  1856. }
  1857.  
  1858. uint32_t count = player->__getItemTypeCount(sit->itemId, subType);
  1859. if(count > 0)
  1860. goodsMap[sit->itemId] = count;
  1861. }
  1862. }
  1863. else
  1864. {
  1865. std::map<uint32_t, uint32_t> tmpMap;
  1866. player->__getAllItemTypeCount(tmpMap);
  1867. for(ShopInfoList::const_iterator sit = shop.begin(); sit != shop.end(); ++sit)
  1868. {
  1869. if(sit->sellPrice < 0)
  1870. continue;
  1871.  
  1872. int8_t subType = -1;
  1873. if(sit->subType)
  1874. {
  1875. const ItemType& it = Item::items[sit->itemId];
  1876. if(it.hasSubType() && !it.stackable)
  1877. subType = sit->subType;
  1878. }
  1879.  
  1880. if(subType != -1)
  1881. {
  1882. uint32_t count = player->__getItemTypeCount(sit->itemId, subType);
  1883. if(count > 0)
  1884. goodsMap[sit->itemId] = count;
  1885. }
  1886. else
  1887. goodsMap[sit->itemId] = tmpMap[sit->itemId];
  1888. }
  1889. }
  1890.  
  1891. msg->AddByte(std::min(goodsMap.size(), (size_t)255));
  1892. std::map<uint32_t, uint32_t>::const_iterator it = goodsMap.begin();
  1893. for(uint32_t i = 0; it != goodsMap.end() && i < 255; ++it, ++i)
  1894. {
  1895. msg->AddItemId(it->first);
  1896. msg->AddByte(std::min(it->second, (uint32_t)255));
  1897. }
  1898. }
  1899. }
  1900.  
  1901. void ProtocolGame::sendTradeItemRequest(const Player* player, const Item* item, bool ack)
  1902. {
  1903. NetworkMessage_ptr msg = getOutputBuffer();
  1904. if(msg)
  1905. {
  1906. TRACK_MESSAGE(msg);
  1907. if(ack)
  1908. msg->AddByte(0x7D);
  1909. else
  1910. msg->AddByte(0x7E);
  1911.  
  1912. msg->AddString(player->getName());
  1913. if(const Container* container = item->getContainer())
  1914. {
  1915. msg->AddByte(container->getItemHoldingCount() + 1);
  1916. msg->AddItem(item);
  1917. for(ContainerIterator it = container->begin(); it != container->end(); ++it)
  1918. msg->AddItem(*it);
  1919. }
  1920. else
  1921. {
  1922. msg->AddByte(1);
  1923. msg->AddItem(item);
  1924. }
  1925. }
  1926. }
  1927.  
  1928. void ProtocolGame::sendCloseTrade()
  1929. {
  1930. NetworkMessage_ptr msg = getOutputBuffer();
  1931. if(msg)
  1932. {
  1933. TRACK_MESSAGE(msg);
  1934. msg->AddByte(0x7F);
  1935. }
  1936. }
  1937.  
  1938. void ProtocolGame::sendCloseContainer(uint32_t cid)
  1939. {
  1940. NetworkMessage_ptr msg = getOutputBuffer();
  1941. if(msg)
  1942. {
  1943. TRACK_MESSAGE(msg);
  1944. msg->AddByte(0x6F);
  1945. msg->AddByte(cid);
  1946. }
  1947. }
  1948.  
  1949. void ProtocolGame::sendCreatureTurn(const Creature* creature, int16_t stackpos)
  1950. {
  1951. if(stackpos >= 10 || !canSee(creature))
  1952. return;
  1953.  
  1954. NetworkMessage_ptr msg = getOutputBuffer();
  1955. if(msg)
  1956. {
  1957. TRACK_MESSAGE(msg);
  1958. msg->AddByte(0x6B);
  1959. msg->AddPosition(creature->getPosition());
  1960. msg->AddByte(stackpos);
  1961. msg->AddU16(0x63); /*99*/
  1962. msg->AddU32(creature->getID());
  1963. msg->AddByte(creature->getDirection());
  1964. }
  1965. }
  1966.  
  1967. void ProtocolGame::sendCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text, Position* pos/* = NULL*/)
  1968. {
  1969. NetworkMessage_ptr msg = getOutputBuffer();
  1970. if(msg)
  1971. {
  1972. TRACK_MESSAGE(msg);
  1973. AddCreatureSpeak(msg, creature, type, text, 0, 0, pos);
  1974. }
  1975. }
  1976.  
  1977. void ProtocolGame::sendToChannel(const Creature* creature, SpeakClasses type, const std::string& text, uint16_t channelId, uint32_t time /*= 0*/)
  1978. {
  1979. NetworkMessage_ptr msg = getOutputBuffer();
  1980. if(msg)
  1981. {
  1982. TRACK_MESSAGE(msg);
  1983. AddCreatureSpeak(msg, creature, type, text, channelId, time);
  1984. }
  1985. }
  1986.  
  1987. void ProtocolGame::sendCancel(const std::string& message)
  1988. {
  1989. NetworkMessage_ptr msg = getOutputBuffer();
  1990. if(msg)
  1991. {
  1992. TRACK_MESSAGE(msg);
  1993. AddTextMessage(msg, MSG_STATUS_SMALL, message);
  1994. }
  1995. }
  1996.  
  1997. void ProtocolGame::sendCancelTarget()
  1998. {
  1999. NetworkMessage_ptr msg = getOutputBuffer();
  2000. if(msg)
  2001. {
  2002. TRACK_MESSAGE(msg);
  2003. msg->AddByte(0xA3);
  2004. }
  2005. }
  2006.  
  2007. void ProtocolGame::sendChangeSpeed(const Creature* creature, uint32_t speed)
  2008. {
  2009. if(!canSee(creature))
  2010. return;
  2011.  
  2012. NetworkMessage_ptr msg = getOutputBuffer();
  2013. if(msg)
  2014. {
  2015. TRACK_MESSAGE(msg);
  2016. msg->AddByte(0x8F);
  2017. msg->AddU32(creature->getID());
  2018. msg->AddU16(speed);
  2019. }
  2020. }
  2021.  
  2022. void ProtocolGame::sendCancelWalk()
  2023. {
  2024. NetworkMessage_ptr msg = getOutputBuffer();
  2025. if(msg)
  2026. {
  2027. TRACK_MESSAGE(msg);
  2028. msg->AddByte(0xB5);
  2029. msg->AddByte(player->getDirection());
  2030. }
  2031. }
  2032.  
  2033. void ProtocolGame::sendSkills()
  2034. {
  2035. NetworkMessage_ptr msg = getOutputBuffer();
  2036. if(msg)
  2037. {
  2038. TRACK_MESSAGE(msg);
  2039. AddPlayerSkills(msg);
  2040. }
  2041. }
  2042.  
  2043. void ProtocolGame::sendPing()
  2044. {
  2045. NetworkMessage_ptr msg = getOutputBuffer();
  2046. if(msg)
  2047. {
  2048. TRACK_MESSAGE(msg);
  2049. msg->AddByte(0x1E);
  2050. }
  2051. }
  2052.  
  2053. void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
  2054. {
  2055. if(type > SHOOT_EFFECT_LAST || (!canSee(from) && !canSee(to)))
  2056. return;
  2057.  
  2058. NetworkMessage_ptr msg = getOutputBuffer();
  2059. if(msg)
  2060. {
  2061. TRACK_MESSAGE(msg);
  2062. AddDistanceShoot(msg, from, to, type);
  2063. }
  2064. }
  2065.  
  2066. void ProtocolGame::sendMagicEffect(const Position& pos, uint8_t type)
  2067. {
  2068. if(type > MAGIC_EFFECT_LAST || !canSee(pos))
  2069. return;
  2070.  
  2071. NetworkMessage_ptr msg = getOutputBuffer();
  2072. if(msg)
  2073. {
  2074. TRACK_MESSAGE(msg);
  2075. AddMagicEffect(msg, pos, type);
  2076. }
  2077. }
  2078.  
  2079. void ProtocolGame::sendAnimatedText(const Position& pos, uint8_t color, std::string text)
  2080. {
  2081. if(!canSee(pos))
  2082. return;
  2083.  
  2084. NetworkMessage_ptr msg = getOutputBuffer();
  2085. if(msg)
  2086. {
  2087. TRACK_MESSAGE(msg);
  2088. AddAnimatedText(msg, pos, color, text);
  2089. }
  2090. }
  2091.  
  2092. void ProtocolGame::sendCreatureHealth(const Creature* creature)
  2093. {
  2094. if(!canSee(creature))
  2095. return;
  2096.  
  2097. NetworkMessage_ptr msg = getOutputBuffer();
  2098. if(msg)
  2099. {
  2100. TRACK_MESSAGE(msg);
  2101. AddCreatureHealth(msg, creature);
  2102. }
  2103. }
  2104.  
  2105. void ProtocolGame::sendFYIBox(const std::string& message)
  2106. {
  2107. if(message.empty() || message.length() > 1018) //Prevent client debug when message is empty or length is > 1018 (not confirmed)
  2108. {
  2109. std::cout << "[Warning - ProtocolGame::sendFYIBox] Trying to send an empty or too huge message." << std::endl;
  2110. return;
  2111. }
  2112.  
  2113. NetworkMessage_ptr msg = getOutputBuffer();
  2114. if(msg)
  2115. {
  2116. TRACK_MESSAGE(msg);
  2117. msg->AddByte(0x15);
  2118. msg->AddString(message);
  2119. }
  2120. }
  2121.  
  2122. //tile
  2123. void ProtocolGame::sendAddTileItem(const Tile* tile, const Position& pos, uint32_t stackpos, const Item* item)
  2124. {
  2125. if(!canSee(pos))
  2126. return;
  2127.  
  2128. NetworkMessage_ptr msg = getOutputBuffer();
  2129. if(msg)
  2130. {
  2131. TRACK_MESSAGE(msg);
  2132. AddTileItem(msg, pos, stackpos, item);
  2133. }
  2134. }
  2135.  
  2136. void ProtocolGame::sendUpdateTileItem(const Tile* tile, const Position& pos, uint32_t stackpos, const Item* item)
  2137. {
  2138. if(!canSee(pos))
  2139. return;
  2140.  
  2141. NetworkMessage_ptr msg = getOutputBuffer();
  2142. if(msg)
  2143. {
  2144. TRACK_MESSAGE(msg);
  2145. UpdateTileItem(msg, pos, stackpos, item);
  2146. }
  2147. }
  2148.  
  2149. void ProtocolGame::sendRemoveTileItem(const Tile* tile, const Position& pos, uint32_t stackpos)
  2150. {
  2151. if(!canSee(pos))
  2152. return;
  2153.  
  2154. NetworkMessage_ptr msg = getOutputBuffer();
  2155. if(msg)
  2156. {
  2157. TRACK_MESSAGE(msg);
  2158. RemoveTileItem(msg, pos, stackpos);
  2159. }
  2160. }
  2161.  
  2162. void ProtocolGame::sendUpdateTile(const Tile* tile, const Position& pos)
  2163. {
  2164. if(!canSee(pos))
  2165. return;
  2166.  
  2167. NetworkMessage_ptr msg = getOutputBuffer();
  2168. if(msg)
  2169. {
  2170. TRACK_MESSAGE(msg);
  2171. msg->AddByte(0x69);
  2172. msg->AddPosition(pos);
  2173. if(tile)
  2174. {
  2175. GetTileDescription(tile, msg);
  2176. msg->AddByte(0x00);
  2177. msg->AddByte(0xFF);
  2178. }
  2179. else
  2180. {
  2181. msg->AddByte(0x01);
  2182. msg->AddByte(0xFF);
  2183. }
  2184. }
  2185. }
  2186.  
  2187. void ProtocolGame::sendAddCreature(const Creature* creature, const Position& pos, uint32_t stackpos)
  2188. {
  2189. if(!canSee(creature))
  2190. return;
  2191.  
  2192. NetworkMessage_ptr msg = getOutputBuffer();
  2193. if(!msg)
  2194. return;
  2195.  
  2196. TRACK_MESSAGE(msg);
  2197. if(creature != player)
  2198. {
  2199. AddTileCreature(msg, pos, stackpos, creature);
  2200. return;
  2201. }
  2202.  
  2203. msg->AddByte(0x0A);
  2204. msg->AddU32(player->getID());
  2205. msg->AddU16(0x32);
  2206.  
  2207. msg->AddByte(player->hasFlag(PlayerFlag_CanReportBugs));
  2208. if(Group* group = player->getGroup())
  2209. {
  2210. int32_t reasons = group->getViolationReasons();
  2211. if(reasons > 1)
  2212. {
  2213. msg->AddByte(0x0B);
  2214. for(int32_t i = 0; i < 20; ++i)
  2215. {
  2216. if(i < 4)
  2217. msg->AddByte(group->getNameViolationFlags());
  2218. else if(i < reasons)
  2219. msg->AddByte(group->getStatementViolationFlags());
  2220. else
  2221. msg->AddByte(0x00);
  2222. }
  2223. }
  2224. }
  2225.  
  2226. AddMapDescription(msg, pos);
  2227. for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
  2228. AddInventoryItem(msg, (slots_t)i, player->getInventoryItem((slots_t)i));
  2229.  
  2230. AddPlayerStats(msg);
  2231. AddPlayerSkills(msg);
  2232.  
  2233. //gameworld light-settings
  2234. LightInfo lightInfo;
  2235. g_game.getWorldLightInfo(lightInfo);
  2236. AddWorldLight(msg, lightInfo);
  2237.  
  2238. //player light level
  2239. AddCreatureLight(msg, creature);
  2240. player->sendIcons();
  2241. for(VIPListSet::iterator it = player->VIPList.begin(); it != player->VIPList.end(); it++)
  2242. {
  2243. std::string vipName;
  2244. if(IOLoginData::getInstance()->getNameByGuid((*it), vipName))
  2245. {
  2246. Player* tmpPlayer = g_game.getPlayerByName(vipName);
  2247. sendVIP((*it), vipName, (tmpPlayer && player->canSeeCreature(tmpPlayer)));
  2248. }
  2249. }
  2250. }
  2251.  
  2252. void ProtocolGame::sendRemoveCreature(const Creature* creature, const Position& pos, uint32_t stackpos)
  2253. {
  2254. if(!canSee(pos))
  2255. return;
  2256.  
  2257. NetworkMessage_ptr msg = getOutputBuffer();
  2258. if(msg)
  2259. {
  2260. TRACK_MESSAGE(msg);
  2261. RemoveTileItem(msg, pos, stackpos);
  2262. }
  2263. }
  2264.  
  2265. void ProtocolGame::sendMoveCreature(const Creature* creature, const Tile* newTile, const Position& newPos,
  2266. uint32_t newStackpos, const Tile* oldTile, const Position& oldPos, uint32_t oldStackpos, bool teleport)
  2267. {
  2268. if(creature == player)
  2269. {
  2270. NetworkMessage_ptr msg = getOutputBuffer();
  2271. if(msg)
  2272. {
  2273. TRACK_MESSAGE(msg);
  2274. if(teleport || oldStackpos >= 10)
  2275. {
  2276. RemoveTileItem(msg, oldPos, oldStackpos);
  2277. AddMapDescription(msg, newPos);
  2278. }
  2279. else
  2280. {
  2281. if(oldPos.z != 7 || newPos.z < 8)
  2282. {
  2283. msg->AddByte(0x6D);
  2284. msg->AddPosition(oldPos);
  2285. msg->AddByte(oldStackpos);
  2286. msg->AddPosition(newPos);
  2287. }
  2288. else
  2289. RemoveTileItem(msg, oldPos, oldStackpos);
  2290.  
  2291. if(newPos.z > oldPos.z)
  2292. MoveDownCreature(msg, creature, newPos, oldPos, oldStackpos);
  2293. else if(newPos.z < oldPos.z)
  2294. MoveUpCreature(msg, creature, newPos, oldPos, oldStackpos);
  2295.  
  2296. if(oldPos.y > newPos.y) // north, for old x
  2297. {
  2298. msg->AddByte(0x65);
  2299. GetMapDescription(oldPos.x - 8, newPos.y - 6, newPos.z, 18, 1, msg);
  2300. }
  2301. else if(oldPos.y < newPos.y) // south, for old x
  2302. {
  2303. msg->AddByte(0x67);
  2304. GetMapDescription(oldPos.x - 8, newPos.y + 7, newPos.z, 18, 1, msg);
  2305. }
  2306.  
  2307. if(oldPos.x < newPos.x) // east, [with new y]
  2308. {
  2309. msg->AddByte(0x66);
  2310. GetMapDescription(newPos.x + 9, newPos.y - 6, newPos.z, 1, 14, msg);
  2311. }
  2312. else if(oldPos.x > newPos.x) // west, [with new y]
  2313. {
  2314. msg->AddByte(0x68);
  2315. GetMapDescription(newPos.x - 8, newPos.y - 6, newPos.z, 1, 14, msg);
  2316. }
  2317. }
  2318. }
  2319. }
  2320. else if(canSee(oldPos) && canSee(newPos))
  2321. {
  2322. if(!player->canSeeCreature(creature))
  2323. return;
  2324.  
  2325. NetworkMessage_ptr msg = getOutputBuffer();
  2326. if(msg)
  2327. {
  2328. TRACK_MESSAGE(msg);
  2329. if(!teleport && (oldPos.z != 7 || newPos.z < 8) && oldStackpos < 10)
  2330. {
  2331. msg->AddByte(0x6D);
  2332. msg->AddPosition(oldPos);
  2333. msg->AddByte(oldStackpos);
  2334. msg->AddPosition(newPos);
  2335. }
  2336. else
  2337. {
  2338. RemoveTileItem(msg, oldPos, oldStackpos);
  2339. AddTileCreature(msg, newPos, newStackpos, creature);
  2340. }
  2341. }
  2342. }
  2343. else if(canSee(oldPos))
  2344. {
  2345. if(!player->canSeeCreature(creature))
  2346. return;
  2347.  
  2348. NetworkMessage_ptr msg = getOutputBuffer();
  2349. if(msg)
  2350. {
  2351. TRACK_MESSAGE(msg);
  2352. RemoveTileItem(msg, oldPos, oldStackpos);
  2353. }
  2354. }
  2355. else if(canSee(newPos) && player->canSeeCreature(creature))
  2356. {
  2357. NetworkMessage_ptr msg = getOutputBuffer();
  2358. if(msg)
  2359. {
  2360. TRACK_MESSAGE(msg);
  2361. AddTileCreature(msg, newPos, newStackpos, creature);
  2362. }
  2363. }
  2364. }
  2365.  
  2366. //inventory
  2367. void ProtocolGame::sendAddInventoryItem(slots_t slot, const Item* item)
  2368. {
  2369. NetworkMessage_ptr msg = getOutputBuffer();
  2370. if(msg)
  2371. {
  2372. TRACK_MESSAGE(msg);
  2373. AddInventoryItem(msg, slot, item);
  2374. }
  2375. }
  2376.  
  2377. void ProtocolGame::sendUpdateInventoryItem(slots_t slot, const Item* item)
  2378. {
  2379. NetworkMessage_ptr msg = getOutputBuffer();
  2380. if(msg)
  2381. {
  2382. TRACK_MESSAGE(msg);
  2383. UpdateInventoryItem(msg, slot, item);
  2384. }
  2385. }
  2386.  
  2387. void ProtocolGame::sendRemoveInventoryItem(slots_t slot)
  2388. {
  2389. NetworkMessage_ptr msg = getOutputBuffer();
  2390. if(msg)
  2391. {
  2392. TRACK_MESSAGE(msg);
  2393. RemoveInventoryItem(msg, slot);
  2394. }
  2395. }
  2396.  
  2397. //containers
  2398. void ProtocolGame::sendAddContainerItem(uint8_t cid, const Item* item)
  2399. {
  2400. NetworkMessage_ptr msg = getOutputBuffer();
  2401. if(msg)
  2402. {
  2403. TRACK_MESSAGE(msg);
  2404. AddContainerItem(msg, cid, item);
  2405. }
  2406. }
  2407.  
  2408. void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint8_t slot, const Item* item)
  2409. {
  2410. NetworkMessage_ptr msg = getOutputBuffer();
  2411. if(msg)
  2412. {
  2413. TRACK_MESSAGE(msg);
  2414. UpdateContainerItem(msg, cid, slot, item);
  2415. }
  2416. }
  2417.  
  2418. void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint8_t slot)
  2419. {
  2420. NetworkMessage_ptr msg = getOutputBuffer();
  2421. if(msg)
  2422. {
  2423. TRACK_MESSAGE(msg);
  2424. RemoveContainerItem(msg, cid, slot);
  2425. }
  2426. }
  2427.  
  2428. void ProtocolGame::sendTextWindow(uint32_t windowTextId, Item* item, uint16_t maxLen, bool canWrite)
  2429. {
  2430. NetworkMessage_ptr msg = getOutputBuffer();
  2431. if(msg)
  2432. {
  2433. TRACK_MESSAGE(msg);
  2434. msg->AddByte(0x96);
  2435. msg->AddU32(windowTextId);
  2436. msg->AddItemId(item);
  2437. if(canWrite)
  2438. {
  2439. msg->AddU16(maxLen);
  2440. msg->AddString(item->getText());
  2441. }
  2442. else
  2443. {
  2444. msg->AddU16(item->getText().size());
  2445. msg->AddString(item->getText());
  2446. }
  2447.  
  2448. const std::string& writer = item->getWriter();
  2449. if(writer.size())
  2450. msg->AddString(writer);
  2451. else
  2452. msg->AddString("");
  2453.  
  2454. time_t writtenDate = item->getDate();
  2455. if(writtenDate > 0)
  2456. msg->AddString(formatDate(writtenDate));
  2457. else
  2458. msg->AddString("");
  2459. }
  2460. }
  2461.  
  2462. void ProtocolGame::sendTextWindow(uint32_t windowTextId, uint32_t itemId, const std::string& text)
  2463. {
  2464. NetworkMessage_ptr msg = getOutputBuffer();
  2465. if(msg)
  2466. {
  2467. TRACK_MESSAGE(msg);
  2468. msg->AddByte(0x96);
  2469. msg->AddU32(windowTextId);
  2470. msg->AddItemId(itemId);
  2471.  
  2472. msg->AddU16(text.size());
  2473. msg->AddString(text);
  2474.  
  2475. msg->AddString("");
  2476. msg->AddString("");
  2477. }
  2478. }
  2479.  
  2480. void ProtocolGame::sendHouseWindow(uint32_t windowTextId, House* _house,
  2481. uint32_t listId, const std::string& text)
  2482. {
  2483. NetworkMessage_ptr msg = getOutputBuffer();
  2484. if(msg)
  2485. {
  2486. TRACK_MESSAGE(msg);
  2487. msg->AddByte(0x97);
  2488. msg->AddByte(0x00);
  2489. msg->AddU32(windowTextId);
  2490. msg->AddString(text);
  2491. }
  2492. }
  2493.  
  2494. void ProtocolGame::sendOutfitWindow()
  2495. {
  2496. NetworkMessage_ptr msg = getOutputBuffer();
  2497. if(msg)
  2498. {
  2499. TRACK_MESSAGE(msg);
  2500. msg->AddByte(0xC8);
  2501. AddCreatureOutfit(msg, player, player->getDefaultOutfit(), true);
  2502.  
  2503. std::list<Outfit> outfitList;
  2504. for(OutfitMap::iterator it = player->outfits.begin(); it != player->outfits.end(); ++it)
  2505. {
  2506. if(player->canWearOutfit(it->first, it->second.addons))
  2507. outfitList.push_back(it->second);
  2508. }
  2509.  
  2510. if(outfitList.size())
  2511. {
  2512. msg->AddByte((size_t)std::min((size_t)OUTFITS_MAX_NUMBER, outfitList.size()));
  2513. std::list<Outfit>::iterator it = outfitList.begin();
  2514. for(int32_t i = 0; it != outfitList.end() && i < OUTFITS_MAX_NUMBER; ++it, ++i)
  2515. {
  2516. msg->AddU16(it->lookType);
  2517. msg->AddString(it->name);
  2518. if(player->hasCustomFlag(PlayerCustomFlag_CanWearAllAddons))
  2519. msg->AddByte(0x03);
  2520. else if(!g_config.getBool(ConfigManager::ADDONS_PREMIUM) || player->isPremium())
  2521. msg->AddByte(it->addons);
  2522. else
  2523. msg->AddByte(0x00);
  2524. }
  2525. }
  2526. else
  2527. {
  2528. msg->AddByte(1);
  2529. msg->AddU16(player->getDefaultOutfit().lookType);
  2530. msg->AddString("Outfit");
  2531. msg->AddByte(player->getDefaultOutfit().lookAddons);
  2532. }
  2533.  
  2534. player->hasRequestedOutfit(true);
  2535. }
  2536. }
  2537.  
  2538. void ProtocolGame::sendQuests()
  2539. {
  2540. NetworkMessage_ptr msg = getOutputBuffer();
  2541. if(msg)
  2542. {
  2543. TRACK_MESSAGE(msg);
  2544. msg->AddByte(0xF0);
  2545.  
  2546. msg->AddU16(Quests::getInstance()->getQuestCount(player));
  2547. for(QuestList::const_iterator it = Quests::getInstance()->getFirstQuest(); it != Quests::getInstance()->getLastQuest(); ++it)
  2548. {
  2549. if(!(*it)->isStarted(player))
  2550. continue;
  2551.  
  2552. msg->AddU16((*it)->getId());
  2553. msg->AddString((*it)->getName());
  2554. msg->AddByte((*it)->isCompleted(player));
  2555. }
  2556. }
  2557. }
  2558.  
  2559. void ProtocolGame::sendQuestInfo(Quest* quest)
  2560. {
  2561. NetworkMessage_ptr msg = getOutputBuffer();
  2562. if(msg)
  2563. {
  2564. TRACK_MESSAGE(msg);
  2565. msg->AddByte(0xF1);
  2566. msg->AddU16(quest->getId());
  2567.  
  2568. msg->AddByte(quest->getMissionCount(player));
  2569. for(MissionList::const_iterator it = quest->getFirstMission(); it != quest->getLastMission(); ++it)
  2570. {
  2571. if(!(*it)->isStarted(player))
  2572. continue;
  2573.  
  2574. msg->AddString((*it)->getName(player));
  2575. msg->AddString((*it)->getDescription(player));
  2576. }
  2577. }
  2578. }
  2579.  
  2580. void ProtocolGame::sendVIPLogIn(uint32_t guid)
  2581. {
  2582. NetworkMessage_ptr msg = getOutputBuffer();
  2583. if(msg)
  2584. {
  2585. TRACK_MESSAGE(msg);
  2586. msg->AddByte(0xD3);
  2587. msg->AddU32(guid);
  2588. }
  2589. }
  2590.  
  2591. void ProtocolGame::sendVIPLogOut(uint32_t guid)
  2592. {
  2593. NetworkMessage_ptr msg = getOutputBuffer();
  2594. if(msg)
  2595. {
  2596. TRACK_MESSAGE(msg);
  2597. msg->AddByte(0xD4);
  2598. msg->AddU32(guid);
  2599. }
  2600. }
  2601.  
  2602. void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, bool isOnline)
  2603. {
  2604. NetworkMessage_ptr msg = getOutputBuffer();
  2605. if(msg)
  2606. {
  2607. TRACK_MESSAGE(msg);
  2608. msg->AddByte(0xD2);
  2609. msg->AddU32(guid);
  2610. msg->A
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement