Advertisement
Guest User

protocolgame.cpp

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