Guest User

Untitled

a guest
Mar 15th, 2016
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 63.77 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. //////////////////////////////////////////////////////////////////////
  4. // Implementation of tibia v8.0 protocol
  5. //////////////////////////////////////////////////////////////////////
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 2
  9. // of the License, or (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software Foundation,
  18. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. //////////////////////////////////////////////////////////////////////
  20. #include "otpch.h"
  21.  
  22. #include "protocolgame.h"
  23. #include "networkmessage.h"
  24. #include "outputmessage.h"
  25. #include "items.h"
  26. #include "tile.h"
  27. #include "player.h"
  28. #include "chat.h"
  29. #include "configmanager.h"
  30. #include "actions.h"
  31. #include "game.h"
  32. #include "ioplayer.h"
  33. #include "house.h"
  34. #include "waitlist.h"
  35. #include "ban.h"
  36. #include "ioaccount.h"
  37. #include "connection.h"
  38. #include "creatureevent.h"
  39. #include <boost/function.hpp>
  40. #include <string>
  41. #include <iostream>
  42. #include <sstream>
  43. #include <ctime>
  44. #include <list>
  45. #include <fstream>
  46.  
  47. extern Game g_game;
  48. extern ConfigManager g_config;
  49. extern Actions actions;
  50. extern BanManager g_bans;
  51. extern CreatureEvents* g_creatureEvents;
  52. Chat g_chat;
  53.  
  54. #ifdef __ENABLE_SERVER_DIAGNOSTIC__
  55. uint32_t ProtocolGame::protocolGameCount = 0;
  56. #endif
  57.  
  58. // Helping templates to add dispatcher tasks
  59.  
  60. template<class FunctionType>
  61. void ProtocolGame::addGameTaskInternal(bool droppable, uint32_t delay, const FunctionType& func)
  62. {
  63. if(droppable)
  64. g_dispatcher.addTask(createTask(delay, func));
  65. else
  66. g_dispatcher.addTask(createTask(func));
  67. }
  68.  
  69. ProtocolGame::ProtocolGame(Connection_ptr connection) :
  70. Protocol(connection)
  71. {
  72. player = NULL;
  73. m_debugAssertSent = false;
  74. m_acceptPackets = false;
  75. eventConnect = 0;
  76.  
  77. #ifdef __ENABLE_SERVER_DIAGNOSTIC__
  78. protocolGameCount++;
  79. #endif
  80. }
  81.  
  82. ProtocolGame::~ProtocolGame()
  83. {
  84. player = NULL;
  85.  
  86. #ifdef __ENABLE_SERVER_DIAGNOSTIC__
  87. protocolGameCount--;
  88. #endif
  89. }
  90.  
  91. void ProtocolGame::setPlayer(Player* p)
  92. {
  93. player = p;
  94. }
  95.  
  96. void ProtocolGame::releaseProtocol()
  97. {
  98. //dispatcher thread
  99. if(player){
  100. if(player->client == this){
  101. player->client = NULL;
  102. }
  103. }
  104.  
  105. Protocol::releaseProtocol();
  106. }
  107.  
  108. void ProtocolGame::deleteProtocolTask()
  109. {
  110. //dispatcher thread
  111. if(player){
  112. #ifdef __DEBUG_NET_DETAIL__
  113. std::cout << "Deleting ProtocolGame - Protocol:" << this << ", Player: " << player << std::endl;
  114. #endif
  115.  
  116. g_game.FreeThing(player);
  117. player = NULL;
  118. }
  119.  
  120. Protocol::deleteProtocolTask();
  121. }
  122.  
  123. bool ProtocolGame::login(const std::string& name, bool isSetGM)
  124. {
  125. //dispatcher thread
  126. Player* _player = g_game.getPlayerByName(name);
  127. if(!_player || g_config.getNumber(ConfigManager::ALLOW_CLONES)){
  128. player = new Player(name, this);
  129. player->useThing2();
  130. player->setID();
  131.  
  132. if(!IOPlayer::instance()->loadPlayer(player, name, true)){
  133. #ifdef __DEBUG__
  134. std::cout << "ProtocolGame::login - preloading loadPlayer failed - " << name << std::endl;
  135. #endif
  136. disconnectClient(0x14, "Your character could not be loaded.");
  137. return false;
  138. }
  139.  
  140. if(g_bans.isPlayerBanished(name) && !player->hasFlag(PlayerFlag_CannotBeBanned)){
  141. disconnectClient(0x14, "Your character is locked!");
  142. return false;
  143. }
  144.  
  145. if(g_bans.isAccountBanished(player->getAccountId()) && !player->hasFlag(PlayerFlag_CannotBeBanned)){
  146. disconnectClient(0x14, "Your account is banished!");
  147. return false;
  148. }
  149.  
  150. if(isSetGM && !player->hasFlag(PlayerFlag_CanAlwaysLogin) &&
  151. !g_config.getNumber(ConfigManager::ALLOW_GAMEMASTER_MULTICLIENT))
  152. {
  153. disconnectClient(0x14, "You may only login with a Gamemaster account.");
  154. return false;
  155. }
  156.  
  157. if(g_game.getGameState() == GAME_STATE_CLOSING && !player->hasFlag(PlayerFlag_CanAlwaysLogin)){
  158. disconnectClient(0x14, "The game is just going down.\nPlease try again later.");
  159. return false;
  160. }
  161.  
  162. if(g_game.getGameState() == GAME_STATE_CLOSED && !player->hasFlag(PlayerFlag_CanAlwaysLogin)){
  163. disconnectClient(0x14, "Server is closed.");
  164. return false;
  165. }
  166.  
  167. if(g_config.getNumber(ConfigManager::CHECK_ACCOUNTS) && !player->hasFlag(PlayerFlag_CanAlwaysLogin)
  168. && g_game.getPlayerByAccount(player->getAccountId())){
  169. disconnectClient(0x14, "You may only login with one character per account.");
  170. return false;
  171. }
  172.  
  173. if(!WaitingList::getInstance()->clientLogin(player)){
  174. int32_t currentSlot = WaitingList::getInstance()->getClientSlot(player);
  175. int32_t retryTime = WaitingList::getTime(currentSlot);
  176. std::stringstream ss;
  177.  
  178. ss << "Too many players online.\n" << "You are at place "
  179. << currentSlot << " on the waiting list.";
  180.  
  181. OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
  182. if(output){
  183. TRACK_MESSAGE(output);
  184. output->AddByte(0x16);
  185. output->AddString(ss.str());
  186. output->AddByte(retryTime);
  187. OutputMessagePool::getInstance()->send(output);
  188. }
  189. getConnection()->closeConnection();
  190. return false;
  191. }
  192.  
  193. if(!IOPlayer::instance()->loadPlayer(player, name)){
  194. #ifdef __DEBUG__
  195. std::cout << "ProtocolGame::login - loadPlayer failed - " << name << std::endl;
  196. #endif
  197. disconnectClient(0x14, "Your character could not be loaded.");
  198. return false;
  199. }
  200.  
  201. if(!g_game.placeCreature(player, player->getLoginPosition())){
  202. if(!g_game.placeCreature(player, player->getTemplePosition(), false, true)){
  203. disconnectClient(0x14, "Temple position is wrong. Contact the administrator.");
  204. return false;
  205. }
  206. }
  207.  
  208. player->lastip = player->getIP();
  209. player->lastLoginSaved = std::max(time(NULL), player->lastLoginSaved + 1);
  210. player->lastLoginMs = OTSYS_TIME();
  211. IOPlayer::instance()->updateLoginInfo(player);
  212. m_acceptPackets = true;
  213.  
  214. return true;
  215. }
  216. else{
  217. if(eventConnect != 0){
  218. //A task has already been scheduled just bail out (should not be overriden)
  219. disconnectClient(0x14, "You are already logged in.");
  220. return false;
  221. }
  222.  
  223. if(_player->client){
  224. g_chat.removeUserFromAllChannels(_player);
  225. _player->disconnect();
  226. _player->isConnecting = true;
  227. addRef();
  228. eventConnect = g_scheduler.addEvent(
  229. createSchedulerTask(1000, boost::bind(&ProtocolGame::connect, this, _player->getID(), true)));
  230. return true;
  231. }
  232.  
  233. addRef();
  234. return connect(_player->getID());
  235. }
  236.  
  237. return false;
  238. }
  239.  
  240. bool ProtocolGame::connect(uint32_t playerId, const bool isLoggingIn)
  241. {
  242. unRef();
  243. eventConnect = 0;
  244. Player* _player = g_game.getPlayerByID(playerId);
  245. if(!_player || _player->isRemoved() || _player->client){
  246. disconnectClient(0x14, "You are already logged in.");
  247. return false;
  248. }
  249.  
  250. player = _player;
  251. player->useThing2();
  252. player->isConnecting = false;
  253. player->client = this;
  254. player->client->sendAddCreature(player, player->getPosition(),
  255. player->getTile()->__getIndexOfThing(player), isLoggingIn);
  256. player->lastip = player->getIP();
  257. IOPlayer::instance()->updateLoginInfo(player);
  258. m_acceptPackets = true;
  259.  
  260. return true;
  261. }
  262.  
  263. bool ProtocolGame::logout(bool forced)
  264. {
  265. //dispatcher thread
  266. if(!player)
  267. return false;
  268.  
  269. if(!player->isRemoved()){
  270. if(!forced){
  271. if(player->getTile()->hasFlag(TILESTATE_NOLOGOUT)){
  272. player->sendCancelMessage(RET_YOUCANNOTLOGOUTHERE);
  273. return false;
  274. }
  275.  
  276. if(player->hasCondition(CONDITION_INFIGHT)){
  277. player->sendCancelMessage(RET_YOUMAYNOTLOGOUTDURINGAFIGHT);
  278. return false;
  279. }
  280.  
  281. //scripting event - onLogOut
  282. if(!g_creatureEvents->playerLogOut(player)){
  283. //Let the script handle the error message
  284. return false;
  285. }
  286. }
  287. }
  288.  
  289. if(Connection_ptr connection = getConnection()){
  290. connection->closeConnection();
  291. }
  292.  
  293. return g_game.removeCreature(player);
  294. }
  295.  
  296. bool ProtocolGame::parseFirstPacket(NetworkMessage& msg)
  297. {
  298. if(g_game.getGameState() == GAME_STATE_SHUTDOWN){
  299. getConnection()->closeConnection();
  300. return false;
  301. }
  302.  
  303. /*uint16_t clientos =*/ msg.GetU16();
  304. uint16_t version = msg.GetU16();
  305.  
  306. if(!RSA_decrypt(msg)){
  307. getConnection()->closeConnection();
  308. return false;
  309. }
  310.  
  311. uint32_t key[4];
  312. key[0] = msg.GetU32();
  313. key[1] = msg.GetU32();
  314. key[2] = msg.GetU32();
  315. key[3] = msg.GetU32();
  316. enableXTEAEncryption();
  317. setXTEAKey(key);
  318.  
  319. bool isSetGM = (msg.GetByte() == 1);
  320. uint32_t accnumber = msg.GetU32();
  321. const std::string name = msg.GetString();
  322. const std::string password = msg.GetString();
  323.  
  324. if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX){
  325. disconnectClient(0x0A, STRING_CLIENT_VERSION);
  326. return false;
  327. }
  328.  
  329. if(g_game.getGameState() == GAME_STATE_STARTUP){
  330. std::string clientMessage = g_config.getString(ConfigManager::WORLD_NAME) + " is starting up. Please wait.";
  331. disconnectClient(0x14, clientMessage.c_str());
  332. return false;
  333. }
  334.  
  335. if(g_bans.isIpDisabled(getIP())){
  336. disconnectClient(0x14, "Too many connections attempts from this IP. Try again later.");
  337. return false;
  338. }
  339.  
  340. if(g_bans.isIpBanished(getIP())){
  341. disconnectClient(0x14, "Your IP is banished!");
  342. return false;
  343. }
  344.  
  345. std::string acc_pass;
  346. if (!(IOAccount::instance()->getPassword(accnumber, name, acc_pass) && passwordTest(password, acc_pass))){
  347. g_bans.addLoginAttempt(getIP(), false);
  348. getConnection()->closeConnection();
  349. return false;
  350. }
  351.  
  352. g_bans.addLoginAttempt(getIP(), true);
  353.  
  354. g_dispatcher.addTask(
  355. createTask(boost::bind(&ProtocolGame::login, this, name, isSetGM)));
  356.  
  357. return true;
  358. }
  359.  
  360. void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
  361. {
  362. parseFirstPacket(msg);
  363. }
  364.  
  365. void ProtocolGame::onConnect()
  366. {
  367. OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
  368.  
  369. OutputMessagePool::getInstance()->send(output);
  370. }
  371.  
  372. void ProtocolGame::disconnectClient(uint8_t error, const char* message)
  373. {
  374. OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
  375. if(output){
  376. TRACK_MESSAGE(output);
  377. output->AddByte(error);
  378. output->AddString(message);
  379. OutputMessagePool::getInstance()->send(output);
  380. }
  381. disconnect();
  382. }
  383.  
  384. void ProtocolGame::disconnect()
  385. {
  386. if(getConnection()){
  387. getConnection()->closeConnection();
  388. }
  389. }
  390.  
  391. void ProtocolGame::parsePacket(NetworkMessage &msg)
  392. {
  393. if(!player || !m_acceptPackets || g_game.getGameState() == GAME_STATE_SHUTDOWN || msg.getMessageLength() <= 0)
  394. return;
  395.  
  396. uint8_t recvbyte = msg.GetByte();
  397. //a dead player can not performs actions
  398. if((player->isRemoved() || player->getHealth() <= 0) && recvbyte != 0x14){
  399. return;
  400. }
  401.  
  402. bool kickPlayer = false;
  403.  
  404. switch(recvbyte){
  405. case 0x14: // logout
  406. g_dispatcher.addTask(createTask(boost::bind(&ProtocolGame::logout, this, false)));
  407. break;
  408.  
  409. case 0x1E: // keep alive / ping response
  410. g_dispatcher.addTask(createTask(boost::bind(&Game::playerReceivePing, &g_game, player->getID())));
  411. break;
  412.  
  413. case 0x64: // move with steps
  414. parseAutoWalk(msg);
  415. break;
  416.  
  417. case 0x65: // move north
  418. addGameTask(&Game::playerMove, player->getID(), NORTH);
  419. break;
  420.  
  421. case 0x66: // move east
  422. addGameTask(&Game::playerMove, player->getID(), EAST);
  423. break;
  424.  
  425. case 0x67: // move south
  426. addGameTask(&Game::playerMove, player->getID(), SOUTH);
  427. break;
  428.  
  429. case 0x68: // move west
  430. addGameTask(&Game::playerMove, player->getID(), WEST);
  431. break;
  432.  
  433. case 0x69: // stop-autowalk
  434. addGameTask(&Game::playerStopAutoWalk, player->getID());
  435. break;
  436.  
  437. case 0x6A:
  438. addGameTask(&Game::playerMove, player->getID(), NORTHEAST);
  439. break;
  440.  
  441. case 0x6B:
  442. addGameTask(&Game::playerMove, player->getID(), SOUTHEAST);
  443. break;
  444.  
  445. case 0x6C:
  446. addGameTask(&Game::playerMove, player->getID(), SOUTHWEST);
  447. break;
  448.  
  449. case 0x6D:
  450. addGameTask(&Game::playerMove, player->getID(), NORTHWEST);
  451. break;
  452.  
  453. case 0x6F: // turn north
  454. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), NORTH);
  455. break;
  456.  
  457. case 0x70: // turn east
  458. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), EAST);
  459. break;
  460.  
  461. case 0x71: // turn south
  462. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), SOUTH);
  463. break;
  464.  
  465. case 0x72: // turn west
  466. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), WEST);
  467. break;
  468.  
  469. case 0x78: // throw item
  470. parseThrow(msg);
  471. break;
  472.  
  473. case 0x7D: // Request trade
  474. parseRequestTrade(msg);
  475. break;
  476.  
  477. case 0x7E: // Look at an item in trade
  478. parseLookInTrade(msg);
  479. break;
  480.  
  481. case 0x7F: // Accept trade
  482. addGameTask(&Game::playerAcceptTrade, player->getID());
  483. break;
  484.  
  485. case 0x80: // Close/cancel trade
  486. parseCloseTrade();
  487. break;
  488.  
  489. case 0x82: // use item
  490. parseUseItem(msg);
  491. break;
  492.  
  493. case 0x83: // use item
  494. parseUseItemEx(msg);
  495. break;
  496.  
  497. case 0x84: // battle window
  498. parseBattleWindow(msg);
  499. break;
  500.  
  501. case 0x85: //rotate item
  502. parseRotateItem(msg);
  503. break;
  504.  
  505. case 0x87: // close container
  506. parseCloseContainer(msg);
  507. break;
  508.  
  509. case 0x88: //"up-arrow" - container
  510. parseUpArrowContainer(msg);
  511. break;
  512.  
  513. case 0x89:
  514. parseTextWindow(msg);
  515. break;
  516.  
  517. case 0x8A:
  518. parseHouseWindow(msg);
  519. break;
  520.  
  521. case 0x8C: // throw item
  522. parseLookAt(msg);
  523. break;
  524.  
  525. case 0x96: // say something
  526. parseSay(msg);
  527. break;
  528.  
  529. case 0x97: // request Channels
  530. addGameTask(&Game::playerRequestChannels, player->getID());
  531. break;
  532.  
  533. case 0x98: // open Channel
  534. parseOpenChannel(msg);
  535. break;
  536.  
  537. case 0x99: // close Channel
  538. parseCloseChannel(msg);
  539. break;
  540.  
  541. case 0x9A: // open priv
  542. parseOpenPriv(msg);
  543. break;
  544.  
  545. case 0x9B: //process report
  546. parseProcessRuleViolation(msg);
  547. break;
  548.  
  549. case 0x9C: //gm closes report
  550. parseCloseRuleViolation(msg);
  551. break;
  552.  
  553. case 0x9D: //player cancels report
  554. addGameTask(&Game::playerCancelRuleViolation, player->getID());
  555. break;
  556.  
  557. case 0xA0: // set attack and follow mode
  558. parseFightModes(msg);
  559. break;
  560.  
  561. case 0xA1: // attack
  562. parseAttack(msg);
  563. break;
  564.  
  565. case 0xA2: //follow
  566. parseFollow(msg);
  567. break;
  568.  
  569. case 0xA3:
  570. parseInviteToParty(msg);
  571. break;
  572.  
  573. case 0xA4:
  574. parseJoinParty(msg);
  575. break;
  576.  
  577. case 0xA5:
  578. parseRevokePartyInvitation(msg);
  579. break;
  580.  
  581. case 0xA6:
  582. parsePassPartyLeadership(msg);
  583. break;
  584.  
  585. case 0xA7:
  586. addGameTask(&Game::playerLeaveParty, player->getID());
  587. break;
  588.  
  589. case 0xAA:
  590. addGameTask(&Game::playerCreatePrivateChannel, player->getID());
  591. break;
  592.  
  593. case 0xAB:
  594. parseChannelInvite(msg);
  595. break;
  596.  
  597. case 0xAC:
  598. parseChannelExclude(msg);
  599. break;
  600.  
  601. case 0xBE: // cancel move
  602. addGameTask(&Game::playerCancelAttackAndFollow, player->getID());
  603. break;
  604.  
  605. case 0xC9: //client request to resend the tile
  606. parseUpdateTile(msg);
  607. break;
  608.  
  609. case 0xCA: //client request to resend the container (happens when you store more than container maxsize)
  610. parseUpdateContainer(msg);
  611. break;
  612.  
  613. case 0xD2: // request outfit
  614. addGameTask(&Game::playerRequestOutfit, player->getID());
  615. break;
  616.  
  617. case 0xD3: // set outfit
  618. parseSetOutfit(msg);
  619. break;
  620.  
  621. case 0xDC:
  622. parseAddVip(msg);
  623. break;
  624.  
  625. case 0xDD:
  626. parseRemoveVip(msg);
  627. break;
  628.  
  629. case 0xE6:
  630. parseBugReport(msg);
  631. break;
  632.  
  633. case 0xE7:
  634. parseViolationWindow(msg);
  635. break;
  636.  
  637. case 0xE8:
  638. parseDebugAssert(msg);
  639. break;
  640.  
  641. default:
  642. std::cout << "Unknown packet header: " << std::hex << (int)recvbyte << std::dec << ", player " << player->getName() << std::endl;
  643. kickPlayer = true;
  644. break;
  645. }
  646.  
  647. if(msg.isOverrun()){ //we've got a badass over here
  648. std::cout << "msg.isOvverrun() == true, player " << player->getName() << std::endl;
  649. kickPlayer = true;
  650. }
  651.  
  652. if(kickPlayer){
  653. player->kickPlayer();
  654. }
  655. }
  656.  
  657. void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage_ptr msg)
  658. {
  659. if(tile){
  660. int count = 0;
  661. if(tile->ground){
  662. msg->AddItem(tile->ground);
  663. count++;
  664. }
  665.  
  666. const TileItemVector* items = tile->getItemList();
  667. const CreatureVector* creatures = tile->getCreatures();
  668.  
  669. ItemVector::const_iterator it;
  670. if(items){
  671. for(it = items->getBeginTopItem(); ((it != items->getEndTopItem()) && (count < 10)); ++it){
  672. msg->AddItem(*it);
  673. count++;
  674. }
  675. }
  676.  
  677. if(creatures){
  678. CreatureVector::const_reverse_iterator cit;
  679. for(cit = creatures->rbegin(); ((cit != creatures->rend()) && (count < 10)); ++cit){
  680. if(player->canSeeCreature(*cit)){
  681. bool known;
  682. uint32_t removedKnown;
  683. checkCreatureAsKnown((*cit)->getID(), known, removedKnown);
  684. AddCreature(msg, *cit, known, removedKnown);
  685. count++;
  686. }
  687. }
  688. }
  689.  
  690. if(items){
  691. for(it = items->getBeginDownItem(); ((it != items->getEndDownItem()) && (count < 10)); ++it){
  692. msg->AddItem(*it);
  693. count++;
  694. }
  695. }
  696. }
  697. }
  698.  
  699. void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z,
  700. int32_t width, int32_t height, NetworkMessage_ptr msg)
  701. {
  702. int32_t skip = -1;
  703. int32_t startz, endz, zstep = 0;
  704.  
  705. if(z > 7){
  706. startz = z - 2;
  707. endz = std::min((int32_t)MAP_MAX_LAYERS - 1, (int32_t)z + 2);
  708. zstep = 1;
  709. }
  710. else{
  711. startz = 7;
  712. endz = 0;
  713.  
  714. zstep = -1;
  715. }
  716.  
  717. for(int32_t nz = startz; nz != endz + zstep; nz += zstep){
  718. GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip);
  719. }
  720.  
  721. if(skip >= 0){
  722. msg->AddByte(skip);
  723. msg->AddByte(0xFF);
  724. }
  725.  
  726. #ifdef __DEBUG__
  727. //printf("tiles in total: %d \n", cc);
  728. #endif
  729. }
  730.  
  731. void ProtocolGame::GetFloorDescription(NetworkMessage_ptr msg, int32_t x, int32_t y, int32_t z,
  732. int32_t width, int32_t height, int32_t offset, int32_t& skip)
  733. {
  734. Tile* tile;
  735.  
  736. for(int32_t nx = 0; nx < width; ++nx){
  737. for(int32_t ny = 0; ny < height; ++ny){
  738. tile = g_game.getTile(x + nx + offset, y + ny + offset, z);
  739.  
  740. if(tile){
  741. if(skip >= 0){
  742. msg->AddByte(skip);
  743. msg->AddByte(0xFF);
  744. }
  745. skip = 0;
  746.  
  747.  
  748. GetTileDescription(tile, msg);
  749. }
  750. else {
  751. skip++;
  752. if(skip == 0xFF){
  753. msg->AddByte(0xFF);
  754. msg->AddByte(0xFF);
  755. skip = -1;
  756. }
  757. }
  758. }
  759. }
  760. }
  761.  
  762. void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool &known, uint32_t &removedKnown)
  763. {
  764. // loop through the known player and check if the given player is in
  765. std::list<uint32_t>::iterator i;
  766. for(i = knownCreatureList.begin(); i != knownCreatureList.end(); ++i){
  767. if((*i) == id){
  768. // know... make the creature even more known...
  769. knownCreatureList.erase(i);
  770. knownCreatureList.push_back(id);
  771.  
  772. known = true;
  773. return;
  774. }
  775. }
  776.  
  777. // ok, he is unknown...
  778. known = false;
  779.  
  780. // ... but not in future
  781. knownCreatureList.push_back(id);
  782.  
  783. // to many known creatures?
  784. if(knownCreatureList.size() > 150){
  785. // lets try to remove one from the end of the list
  786. for (int n = 0; n < 150; ++n){
  787. removedKnown = knownCreatureList.front();
  788.  
  789. Creature* c = g_game.getCreatureByID(removedKnown);
  790. if ((!c) || (!canSee(c)))
  791. break;
  792.  
  793. // this creature we can't remove, still in sight, so back to the end
  794. knownCreatureList.pop_front();
  795. knownCreatureList.push_back(removedKnown);
  796. }
  797.  
  798. // hopefully we found someone to remove :S, we got only 150 tries
  799. // if not... lets kick some players with debug errors :)
  800. knownCreatureList.pop_front();
  801. }
  802. else{
  803. // we can cache without problems :)
  804. removedKnown = 0;
  805. }
  806. }
  807.  
  808. bool ProtocolGame::canSee(const Creature* c) const
  809. {
  810. if(c->isRemoved())
  811. return false;
  812.  
  813. if(!player->canSeeCreature(c))
  814. return false;
  815.  
  816. return canSee(c->getPosition());
  817. }
  818.  
  819. bool ProtocolGame::canSee(const Position& pos) const
  820. {
  821. return canSee(pos.x, pos.y, pos.z);
  822. }
  823.  
  824. bool ProtocolGame::canSee(int x, int y, int z) const
  825. {
  826. #ifdef __DEBUG__
  827. if(z < 0 || z >= MAP_MAX_LAYERS) {
  828. std::cout << "WARNING! ProtocolGame::canSee() Z-value is out of range!" << std::endl;
  829. }
  830. #endif
  831.  
  832. const Position& myPos = player->getPosition();
  833.  
  834. if(myPos.z <= 7){
  835. //we are on ground level or above (7 -> 0)
  836. //view is from 7 -> 0
  837. if(z > 7){
  838. return false;
  839. }
  840. }
  841. else if(myPos.z >= 8){
  842. //we are underground (8 -> 15)
  843. //view is +/- 2 from the floor we stand on
  844. if(std::abs(myPos.z - z) > 2){
  845. return false;
  846. }
  847. }
  848.  
  849. //negative offset means that the action taken place is on a lower floor than ourself
  850. int offsetz = myPos.z - z;
  851.  
  852. if ((x >= myPos.x - 8 + offsetz) && (x <= myPos.x + 9 + offsetz) &&
  853. (y >= myPos.y - 6 + offsetz) && (y <= myPos.y + 7 + offsetz))
  854. return true;
  855.  
  856. return false;
  857. }
  858.  
  859. //********************** Parse methods *******************************
  860. void ProtocolGame::parseChannelInvite(NetworkMessage& msg)
  861. {
  862. const std::string name = msg.GetString();
  863.  
  864. addGameTask(&Game::playerChannelInvite, player->getID(), name);
  865. }
  866.  
  867. void ProtocolGame::parseChannelExclude(NetworkMessage& msg)
  868. {
  869. const std::string name = msg.GetString();
  870.  
  871. addGameTask(&Game::playerChannelExclude, player->getID(), name);
  872. }
  873.  
  874. void ProtocolGame::parseOpenChannel(NetworkMessage& msg)
  875. {
  876. uint16_t channelId = msg.GetU16();
  877.  
  878. addGameTask(&Game::playerOpenChannel, player->getID(), channelId);
  879. }
  880.  
  881. void ProtocolGame::parseCloseChannel(NetworkMessage &msg)
  882. {
  883. uint16_t channelId = msg.GetU16();
  884.  
  885. addGameTask(&Game::playerCloseChannel, player->getID(), channelId);
  886. }
  887.  
  888. void ProtocolGame::parseOpenPriv(NetworkMessage& msg)
  889. {
  890. const std::string receiver = msg.GetString();
  891.  
  892. addGameTask(&Game::playerOpenPrivateChannel, player->getID(), receiver);
  893. }
  894.  
  895. void ProtocolGame::parseProcessRuleViolation(NetworkMessage& msg)
  896. {
  897. const std::string reporter = msg.GetString();
  898.  
  899. addGameTask(&Game::playerProcessRuleViolation, player->getID(), reporter);
  900. }
  901.  
  902. void ProtocolGame::parseCloseRuleViolation(NetworkMessage& msg)
  903. {
  904. const std::string reporter = msg.GetString();
  905.  
  906. addGameTask(&Game::playerCloseRuleViolation, player->getID(), reporter);
  907. }
  908.  
  909. void ProtocolGame::parseDebug(NetworkMessage& msg)
  910. {
  911. int dataLength = msg.getMessageLength() - 1;
  912. if(dataLength != 0){
  913. printf("data: ");
  914. int data = msg.GetByte();
  915. while(dataLength > 0){
  916. printf("%d ", data);
  917. if(--dataLength > 0)
  918. data = msg.GetByte();
  919. }
  920. printf("\n");
  921. }
  922. }
  923.  
  924. void ProtocolGame::parseAutoWalk(NetworkMessage& msg)
  925. {
  926. std::list<Direction> path;
  927.  
  928. size_t numdirs = msg.GetByte();
  929. for (size_t i = 0; i < numdirs; ++i) {
  930. uint8_t rawdir = msg.GetByte();
  931. switch(rawdir) {
  932. case 1: path.push_back(EAST); break;
  933. case 2: path.push_back(NORTHEAST); break;
  934. case 3: path.push_back(NORTH); break;
  935. case 4: path.push_back(NORTHWEST); break;
  936. case 5: path.push_back(WEST); break;
  937. case 6: path.push_back(SOUTHWEST); break;
  938. case 7: path.push_back(SOUTH); break;
  939. case 8: path.push_back(SOUTHEAST); break;
  940. default: break;
  941. };
  942. }
  943.  
  944. if (path.empty())
  945. return;
  946.  
  947. addGameTask(&Game::playerAutoWalk, player->getID(), path);
  948. }
  949.  
  950. void ProtocolGame::parseSetOutfit(NetworkMessage& msg)
  951. {
  952. uint16_t lookType = msg.GetU16();
  953.  
  954. Outfit_t newOutfit;
  955.  
  956. // only first 4 outfits
  957. uint8_t lastFemaleOutfit = 0x8B;
  958. uint8_t lastMaleOutfit = 0x83;
  959.  
  960. // if premium then all 7 outfits
  961. if (player->getSex() == PLAYERSEX_FEMALE && player->isPremium())
  962. lastFemaleOutfit = 0x8E;
  963. else if (player->getSex() == PLAYERSEX_MALE && player->isPremium())
  964. lastMaleOutfit = 0x86;
  965.  
  966. if ((player->getSex() == PLAYERSEX_FEMALE &&
  967. lookType >= 136 &&
  968. lookType <= lastFemaleOutfit) ||
  969. (player->getSex() == PLAYERSEX_MALE &&
  970. lookType >= 128 &&
  971. lookType <= lastMaleOutfit))
  972. {
  973. newOutfit.lookType = lookType;
  974. newOutfit.lookHead = msg.GetByte();
  975. newOutfit.lookBody = msg.GetByte();
  976. newOutfit.lookLegs = msg.GetByte();
  977. newOutfit.lookFeet = msg.GetByte();
  978. }
  979.  
  980. addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit);
  981. }
  982.  
  983. void ProtocolGame::parseUseItem(NetworkMessage& msg)
  984. {
  985. Position pos = msg.GetPosition();
  986. uint16_t spriteId = msg.GetSpriteId();
  987. uint8_t stackpos = msg.GetByte();
  988. uint8_t index = msg.GetByte();
  989.  
  990. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItem, player->getID(), pos, stackpos, index, spriteId);
  991. }
  992.  
  993. void ProtocolGame::parseUseItemEx(NetworkMessage& msg)
  994. {
  995. Position fromPos = msg.GetPosition();
  996. uint16_t fromSpriteId = msg.GetSpriteId();
  997. uint8_t fromStackPos = msg.GetByte();
  998. Position toPos = msg.GetPosition();
  999. uint16_t toSpriteId = msg.GetU16();
  1000. uint8_t toStackPos = msg.GetByte();
  1001.  
  1002. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItemEx, player->getID(), fromPos, fromStackPos, fromSpriteId, toPos, toStackPos, toSpriteId);
  1003. }
  1004.  
  1005. void ProtocolGame::parseBattleWindow(NetworkMessage &msg)
  1006. {
  1007. Position fromPos = msg.GetPosition();
  1008. uint16_t spriteId = msg.GetSpriteId();
  1009. uint8_t fromStackPos = msg.GetByte();
  1010. uint32_t creatureId = msg.GetU32();
  1011.  
  1012. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseBattleWindow, player->getID(), fromPos, fromStackPos, creatureId, spriteId);
  1013. }
  1014.  
  1015. void ProtocolGame::parseCloseContainer(NetworkMessage& msg)
  1016. {
  1017. uint8_t cid = msg.GetByte();
  1018.  
  1019. addGameTask(&Game::playerCloseContainer, player->getID(), cid);
  1020. }
  1021.  
  1022. void ProtocolGame::parseUpArrowContainer(NetworkMessage& msg)
  1023. {
  1024. uint8_t cid = msg.GetByte();
  1025.  
  1026. addGameTask(&Game::playerMoveUpContainer, player->getID(), cid);
  1027. }
  1028.  
  1029. void ProtocolGame::parseUpdateTile(NetworkMessage& msg)
  1030. {
  1031. Position pos = msg.GetPosition();
  1032.  
  1033. //addGameTask(&Game::playerUpdateTile, player->getID(), pos);
  1034. }
  1035.  
  1036. void ProtocolGame::parseUpdateContainer(NetworkMessage& msg)
  1037. {
  1038. uint8_t cid = msg.GetByte();
  1039.  
  1040. addGameTask(&Game::playerUpdateContainer, player->getID(), cid);
  1041. }
  1042.  
  1043. void ProtocolGame::parseThrow(NetworkMessage& msg)
  1044. {
  1045. Position fromPos = msg.GetPosition();
  1046. uint16_t spriteId = msg.GetSpriteId();
  1047. uint8_t fromStackpos = msg.GetByte();
  1048. Position toPos = msg.GetPosition();
  1049. uint8_t count = msg.GetByte();
  1050.  
  1051. /*
  1052. std::cout << "parseThrow: " << "from_x: " << (int)fromPos.x << ", from_y: " << (int)fromPos.y
  1053. << ", from_z: " << (int)fromPos.z << ", item: " << (int)itemId << ", fromStackpos: "
  1054. << (int)fromStackpos << " to_x: " << (int)toPos.x << ", to_y: " << (int)toPos.y
  1055. << ", to_z: " << (int)toPos.z
  1056. << ", count: " << (int)count << std::endl;
  1057. */
  1058.  
  1059. if(toPos != fromPos){
  1060. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION,
  1061. &Game::playerMoveThing, player->getID(), fromPos, spriteId,
  1062. fromStackpos, toPos, count);
  1063. }
  1064. }
  1065.  
  1066. void ProtocolGame::parseLookAt(NetworkMessage& msg)
  1067. {
  1068. Position pos = msg.GetPosition();
  1069. uint16_t spriteId = msg.GetSpriteId();
  1070. uint8_t stackpos = msg.GetByte();
  1071.  
  1072. /*
  1073. #ifdef __DEBUG__
  1074. ss << "You look at x: " << x <<", y: " << y << ", z: " << z << " and see Item # " << itemId << ".";
  1075. #endif
  1076. */
  1077.  
  1078. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookAt, player->getID(), pos, spriteId, stackpos);
  1079. }
  1080.  
  1081. void ProtocolGame::parseSay(NetworkMessage& msg)
  1082. {
  1083. SpeakClasses type = (SpeakClasses)msg.GetByte();
  1084.  
  1085. std::string receiver;
  1086. uint16_t channelId = 0;
  1087. switch(type){
  1088. case SPEAK_PRIVATE:
  1089. case SPEAK_PRIVATE_RED:
  1090. case SPEAK_RVR_ANSWER:
  1091. receiver = msg.GetString();
  1092. break;
  1093. case SPEAK_CHANNEL_Y:
  1094. case SPEAK_CHANNEL_R1:
  1095. case SPEAK_CHANNEL_R2:
  1096. channelId = msg.GetU16();
  1097. break;
  1098. default:
  1099. break;
  1100. }
  1101.  
  1102. const std::string text = msg.GetString();
  1103. if(text.length() > 255)
  1104. return;
  1105. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSay, player->getID(), channelId, type, receiver, text);
  1106. }
  1107.  
  1108. void ProtocolGame::parseFightModes(NetworkMessage& msg)
  1109. {
  1110. uint8_t rawFightMode = msg.GetByte(); //1 - offensive, 2 - balanced, 3 - defensive
  1111. uint8_t rawChaseMode = msg.GetByte(); // 0 - stand while fightning, 1 - chase opponent
  1112. uint8_t rawSafeMode = msg.GetByte();
  1113.  
  1114. bool safeMode = (rawSafeMode == 1);
  1115. chaseMode_t chaseMode = CHASEMODE_STANDSTILL;
  1116.  
  1117. if(rawChaseMode == 0){
  1118. chaseMode = CHASEMODE_STANDSTILL;
  1119. }
  1120. else if(rawChaseMode == 1){
  1121. chaseMode = CHASEMODE_FOLLOW;
  1122. }
  1123.  
  1124. fightMode_t fightMode = FIGHTMODE_ATTACK;
  1125.  
  1126. if(rawFightMode == 1){
  1127. fightMode = FIGHTMODE_ATTACK;
  1128. }
  1129. else if(rawFightMode == 2){
  1130. fightMode = FIGHTMODE_BALANCED;
  1131. }
  1132. else if(rawFightMode == 3){
  1133. fightMode = FIGHTMODE_DEFENSE;
  1134. }
  1135.  
  1136. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSetFightModes, player->getID(), fightMode, chaseMode, safeMode);
  1137. }
  1138.  
  1139. void ProtocolGame::parseAttack(NetworkMessage& msg)
  1140. {
  1141. uint32_t creatureId = msg.GetU32();
  1142.  
  1143. addGameTask(&Game::playerSetAttackedCreature, player->getID(), creatureId);
  1144. }
  1145.  
  1146. void ProtocolGame::parseFollow(NetworkMessage& msg)
  1147. {
  1148. uint32_t creatureId = msg.GetU32();
  1149.  
  1150. addGameTask(&Game::playerFollowCreature, player->getID(), creatureId);
  1151. }
  1152.  
  1153. void ProtocolGame::parseInviteToParty(NetworkMessage& msg)
  1154. {
  1155. uint32_t creatureId = msg.GetU32();
  1156.  
  1157. addGameTask(&Game::playerInviteToParty, player->getID(), creatureId);
  1158. }
  1159.  
  1160. void ProtocolGame::parseJoinParty(NetworkMessage& msg)
  1161. {
  1162. uint32_t creatureId = msg.GetU32();
  1163.  
  1164. addGameTask(&Game::playerJoinParty, player->getID(), creatureId);
  1165. }
  1166.  
  1167. void ProtocolGame::parseRevokePartyInvitation(NetworkMessage& msg)
  1168. {
  1169. uint32_t creatureId = msg.GetU32();
  1170.  
  1171. addGameTask(&Game::playerRevokePartyInvitation, player->getID(), creatureId);
  1172. }
  1173.  
  1174. void ProtocolGame::parsePassPartyLeadership(NetworkMessage& msg)
  1175. {
  1176. uint32_t creatureId = msg.GetU32();
  1177.  
  1178. addGameTask(&Game::playerPassPartyLeadership, player->getID(), creatureId);
  1179. }
  1180.  
  1181. void ProtocolGame::parseTextWindow(NetworkMessage& msg)
  1182. {
  1183. uint32_t windowTextId = msg.GetU32();
  1184. const std::string newText = msg.GetString();
  1185.  
  1186. addGameTask(&Game::playerWriteItem, player->getID(), windowTextId, newText);
  1187. }
  1188.  
  1189. void ProtocolGame::parseHouseWindow(NetworkMessage &msg)
  1190. {
  1191. uint8_t doorId = msg.GetByte();
  1192. uint32_t id = msg.GetU32();
  1193. const std::string text = msg.GetString();
  1194.  
  1195. addGameTask(&Game::playerUpdateHouseWindow, player->getID(), doorId, id, text);
  1196. }
  1197.  
  1198. void ProtocolGame::parseRequestTrade(NetworkMessage& msg)
  1199. {
  1200. Position pos = msg.GetPosition();
  1201. uint16_t spriteId = msg.GetSpriteId();
  1202. uint8_t stackpos = msg.GetByte();
  1203. uint32_t playerId = msg.GetU32();
  1204.  
  1205. addGameTask(&Game::playerRequestTrade, player->getID(), pos, stackpos, playerId, spriteId);
  1206. }
  1207.  
  1208. void ProtocolGame::parseLookInTrade(NetworkMessage& msg)
  1209. {
  1210. bool counterOffer = (msg.GetByte() == 0x01);
  1211. uint8_t index = msg.GetByte();
  1212.  
  1213. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInTrade, player->getID(), counterOffer, index);
  1214. }
  1215.  
  1216. void ProtocolGame::parseCloseTrade()
  1217. {
  1218. addGameTask(&Game::playerCloseTrade, player->getID());
  1219. }
  1220.  
  1221. void ProtocolGame::parseAddVip(NetworkMessage& msg)
  1222. {
  1223. const std::string name = msg.GetString();
  1224. if(name.size() > 32)
  1225. return;
  1226.  
  1227. addGameTask(&Game::playerRequestAddVip, player->getID(), name);
  1228. }
  1229.  
  1230. void ProtocolGame::parseRemoveVip(NetworkMessage& msg)
  1231. {
  1232. uint32_t guid = msg.GetU32();
  1233.  
  1234. addGameTask(&Game::playerRequestRemoveVip, player->getID(), guid);
  1235. }
  1236.  
  1237. void ProtocolGame::parseRotateItem(NetworkMessage& msg)
  1238. {
  1239. Position pos = msg.GetPosition();
  1240. uint16_t spriteId = msg.GetSpriteId();
  1241. uint8_t stackpos = msg.GetByte();
  1242.  
  1243. addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerRotateItem, player->getID(), pos, stackpos, spriteId);
  1244. }
  1245.  
  1246. void ProtocolGame::parseViolationWindow(NetworkMessage& msg)
  1247. {
  1248. std::string target = msg.GetString();
  1249. uint8_t reason = msg.GetByte();
  1250. violationAction_t action = (violationAction_t)msg.GetByte();
  1251. std::string comment = msg.GetString();
  1252.  
  1253. uint16_t statementId = msg.GetU16();
  1254. uint16_t channelId = msg.GetU16();
  1255. bool ipBanishment = msg.GetByte() != 0;
  1256. addGameTask(&Game::playerViolationWindow, player->getID(), target, reason, action, comment, statementId, channelId, ipBanishment);
  1257. }
  1258.  
  1259. void ProtocolGame::parseBugReport(NetworkMessage& msg)
  1260. {
  1261. std::string comment = msg.GetString();
  1262. addGameTask(&Game::playerReportBug, player->getID(), comment);
  1263. }
  1264.  
  1265. void ProtocolGame::parseDebugAssert(NetworkMessage& msg)
  1266. {
  1267. if(!g_config.getNumber(ConfigManager::SAVE_CLIENT_DEBUG_ASSERTIONS)){
  1268. return;
  1269. }
  1270.  
  1271. //only accept 1 report each time
  1272. if(m_debugAssertSent){
  1273. return;
  1274. }
  1275. m_debugAssertSent = true;
  1276.  
  1277. std::string assertLine = msg.GetString();
  1278. std::string report_date = msg.GetString();
  1279. std::string description = msg.GetString();
  1280. std::string comment = msg.GetString();
  1281.  
  1282. //write it in the assertions file
  1283. std::ofstream of("client_assertions.txt", std::ios_base::app);
  1284. if(of){
  1285. char today[32];
  1286. formatDate(time(NULL), today);
  1287.  
  1288. of <<
  1289. "-----" << today << " - " << player->getName() << " (" << convertIPToString(player->getIP()) <<
  1290. assertLine << std::endl <<
  1291. report_date << std::endl <<
  1292. description << std::endl <<
  1293. comment << std::endl;
  1294. }
  1295. }
  1296.  
  1297. //********************** Send methods *******************************
  1298. void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver)
  1299. {
  1300. NetworkMessage_ptr msg = getOutputBuffer();
  1301. if(msg){
  1302. TRACK_MESSAGE(msg);
  1303. msg->AddByte(0xAD);
  1304. msg->AddString(receiver);
  1305. }
  1306. }
  1307.  
  1308. void ProtocolGame::sendCreatureOutfit(const Creature* creature, const Outfit_t& outfit)
  1309. {
  1310. if(canSee(creature)){
  1311. NetworkMessage_ptr msg = getOutputBuffer();
  1312. if(msg){
  1313. TRACK_MESSAGE(msg);
  1314. msg->AddByte(0x8E);
  1315. msg->AddU32(creature->getID());
  1316. AddCreatureOutfit(msg, creature, outfit);
  1317. }
  1318. }
  1319. }
  1320.  
  1321. void ProtocolGame::sendCreatureLight(const Creature* creature)
  1322. {
  1323. if(canSee(creature)){
  1324. NetworkMessage_ptr msg = getOutputBuffer();
  1325. if(msg){
  1326. TRACK_MESSAGE(msg);
  1327. AddCreatureLight(msg, creature);
  1328. }
  1329. }
  1330. }
  1331.  
  1332. void ProtocolGame::sendWorldLight(const LightInfo& lightInfo)
  1333. {
  1334. NetworkMessage_ptr msg = getOutputBuffer();
  1335. if(msg){
  1336. TRACK_MESSAGE(msg);
  1337. AddWorldLight(msg, lightInfo);
  1338. }
  1339. }
  1340.  
  1341. void ProtocolGame::sendCreatureSkull(const Creature* creature)
  1342. {
  1343. if(canSee(creature)){
  1344. NetworkMessage_ptr msg = getOutputBuffer();
  1345. if(msg){
  1346. TRACK_MESSAGE(msg);
  1347. msg->AddByte(0x90);
  1348. msg->AddU32(creature->getID());
  1349. #ifdef __SKULLSYSTEM__
  1350. msg->AddByte(player->getSkullClient(creature->getPlayer()));
  1351. #else
  1352. msg->AddByte(SKULL_NONE);
  1353. #endif
  1354. }
  1355. }
  1356. }
  1357.  
  1358. void ProtocolGame::sendCreatureShield(const Creature* creature)
  1359. {
  1360. if(canSee(creature)){
  1361. NetworkMessage_ptr msg = getOutputBuffer();
  1362. if(msg){
  1363. TRACK_MESSAGE(msg);
  1364. msg->AddByte(0x91);
  1365. msg->AddU32(creature->getID());
  1366. msg->AddByte(player->getPartyShield(creature->getPlayer()));
  1367. }
  1368. }
  1369. }
  1370.  
  1371. void ProtocolGame::sendCreatureSquare(const Creature* creature, SquareColor_t color)
  1372. {
  1373. if(canSee(creature)){
  1374. NetworkMessage_ptr msg = getOutputBuffer();
  1375. if(msg){
  1376. TRACK_MESSAGE(msg);
  1377. msg->AddByte(0x86);
  1378. msg->AddU32(creature->getID());
  1379. msg->AddByte((uint8_t)color);
  1380. }
  1381. }
  1382. }
  1383.  
  1384. void ProtocolGame::sendStats()
  1385. {
  1386. NetworkMessage_ptr msg = getOutputBuffer();
  1387. if(msg){
  1388. TRACK_MESSAGE(msg);
  1389. AddPlayerStats(msg);
  1390. }
  1391. }
  1392.  
  1393. void ProtocolGame::sendTextMessage(MessageClasses mclass, const std::string& message)
  1394. {
  1395. NetworkMessage_ptr msg = getOutputBuffer();
  1396. if(msg){
  1397. TRACK_MESSAGE(msg);
  1398. AddTextMessage(msg, mclass, message);
  1399. }
  1400. }
  1401.  
  1402. void ProtocolGame::sendClosePrivate(uint16_t channelId)
  1403. {
  1404. NetworkMessage_ptr msg = getOutputBuffer();
  1405. if(msg){
  1406. TRACK_MESSAGE(msg);
  1407. msg->AddByte(0xB3);
  1408. msg->AddU16(channelId);
  1409. }
  1410. }
  1411.  
  1412. void ProtocolGame::sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName)
  1413. {
  1414. NetworkMessage_ptr msg = getOutputBuffer();
  1415. if(msg){
  1416. TRACK_MESSAGE(msg);
  1417. msg->AddByte(0xB2);
  1418. msg->AddU16(channelId);
  1419. msg->AddString(channelName);
  1420. }
  1421. }
  1422.  
  1423. void ProtocolGame::sendChannelsDialog()
  1424. {
  1425. NetworkMessage_ptr msg = getOutputBuffer();
  1426. if(msg){
  1427. TRACK_MESSAGE(msg);
  1428. ChannelList list;
  1429. list = g_chat.getChannelList(player);
  1430.  
  1431. msg->AddByte(0xAB);
  1432. msg->AddByte(list.size());
  1433.  
  1434. while(list.size()){
  1435. ChatChannel *channel;
  1436. channel = list.front();
  1437. list.pop_front();
  1438.  
  1439. msg->AddU16(channel->getId());
  1440. msg->AddString(channel->getName());
  1441. }
  1442. }
  1443. }
  1444.  
  1445. void ProtocolGame::sendChannel(uint16_t channelId, const std::string& channelName)
  1446. {
  1447. NetworkMessage_ptr msg = getOutputBuffer();
  1448. if(msg){
  1449. TRACK_MESSAGE(msg);
  1450. msg->AddByte(0xAC);
  1451. msg->AddU16(channelId);
  1452. msg->AddString(channelName);
  1453. }
  1454. }
  1455.  
  1456. void ProtocolGame::sendRuleViolationsChannel(uint16_t channelId)
  1457. {
  1458. NetworkMessage_ptr msg = getOutputBuffer();
  1459. if(msg){
  1460. TRACK_MESSAGE(msg);
  1461. msg->AddByte(0xAE);
  1462. msg->AddU16(channelId);
  1463. RuleViolationsMap::const_iterator it = g_game.getRuleViolations().begin();
  1464. for( ; it != g_game.getRuleViolations().end(); ++it){
  1465. RuleViolation& rvr = *it->second;
  1466. if(rvr.isOpen && rvr.reporter){
  1467. AddCreatureSpeak(msg, rvr.reporter, SPEAK_RVR_CHANNEL, rvr.text, channelId, rvr.time);
  1468. }
  1469. }
  1470. }
  1471. }
  1472.  
  1473. void ProtocolGame::sendRemoveReport(const std::string& name)
  1474. {
  1475. NetworkMessage_ptr msg = getOutputBuffer();
  1476. if(msg){
  1477. TRACK_MESSAGE(msg);
  1478. msg->AddByte(0xAF);
  1479. msg->AddString(name);
  1480. }
  1481. }
  1482.  
  1483. void ProtocolGame::sendRuleViolationCancel(const std::string& name)
  1484. {
  1485. NetworkMessage_ptr msg = getOutputBuffer();
  1486. if(msg){
  1487. TRACK_MESSAGE(msg);
  1488. msg->AddByte(0xB0);
  1489. msg->AddString(name);
  1490. }
  1491. }
  1492.  
  1493. void ProtocolGame::sendLockRuleViolation()
  1494. {
  1495. NetworkMessage_ptr msg = getOutputBuffer();
  1496. if(msg){
  1497. TRACK_MESSAGE(msg);
  1498. msg->AddByte(0xB1);
  1499. }
  1500. }
  1501.  
  1502. void ProtocolGame::sendIcons(uint16_t icons)
  1503. {
  1504. NetworkMessage_ptr msg = getOutputBuffer();
  1505. if(msg){
  1506. TRACK_MESSAGE(msg);
  1507. msg->AddByte(0xA2);
  1508. msg->AddByte(icons);
  1509. }
  1510. }
  1511.  
  1512. void ProtocolGame::sendContainer(uint32_t cid, const Container* container, bool hasParent)
  1513. {
  1514. NetworkMessage_ptr msg = getOutputBuffer();
  1515. if(msg){
  1516. TRACK_MESSAGE(msg);
  1517. msg->AddByte(0x6E);
  1518. msg->AddByte(cid);
  1519. msg->AddItemId(container);
  1520. msg->AddString(container->getName());
  1521. msg->AddByte(container->capacity());
  1522. msg->AddByte(hasParent ? 0x01 : 0x00);
  1523. if(container->size() > 255){
  1524. msg->AddByte(255);
  1525. }
  1526. else{
  1527. msg->AddByte(container->size());
  1528. }
  1529.  
  1530. ItemList::const_iterator cit;
  1531. uint32_t i = 0;
  1532. for(cit = container->getItems(); cit != container->getEnd() && i < 255; ++cit, ++i){
  1533. msg->AddItem(*cit);
  1534. }
  1535. }
  1536. }
  1537.  
  1538. void ProtocolGame::sendTradeItemRequest(const Player* player, const Item* item, bool ack)
  1539. {
  1540. NetworkMessage_ptr msg = getOutputBuffer();
  1541. if(msg){
  1542. TRACK_MESSAGE(msg);
  1543. if(ack){
  1544. msg->AddByte(0x7D);
  1545. }
  1546. else{
  1547. msg->AddByte(0x7E);
  1548. }
  1549.  
  1550. msg->AddString(player->getName());
  1551.  
  1552. if(const Container* tradeContainer = item->getContainer()){
  1553. std::list<const Container*> listContainer;
  1554. ItemList::const_iterator it;
  1555. Container* tmpContainer = NULL;
  1556.  
  1557. listContainer.push_back(tradeContainer);
  1558.  
  1559. std::list<const Item*> listItem;
  1560. listItem.push_back(tradeContainer);
  1561.  
  1562. while(!listContainer.empty()) {
  1563. const Container* container = listContainer.front();
  1564. listContainer.pop_front();
  1565.  
  1566. for(it = container->getItems(); it != container->getEnd(); ++it){
  1567. if((tmpContainer = (*it)->getContainer())){
  1568. listContainer.push_back(tmpContainer);
  1569. }
  1570.  
  1571. listItem.push_back(*it);
  1572. }
  1573. }
  1574.  
  1575. msg->AddByte(listItem.size());
  1576. while(!listItem.empty()) {
  1577. const Item* item = listItem.front();
  1578. listItem.pop_front();
  1579. msg->AddItem(item);
  1580. }
  1581. }
  1582. else {
  1583. msg->AddByte(1);
  1584. msg->AddItem(item);
  1585. }
  1586. }
  1587. }
  1588.  
  1589. void ProtocolGame::sendCloseTrade()
  1590. {
  1591. NetworkMessage_ptr msg = getOutputBuffer();
  1592. if(msg){
  1593. TRACK_MESSAGE(msg);
  1594. msg->AddByte(0x7F);
  1595. }
  1596. }
  1597.  
  1598. void ProtocolGame::sendCloseContainer(uint32_t cid)
  1599. {
  1600. NetworkMessage_ptr msg = getOutputBuffer();
  1601. if(msg){
  1602. TRACK_MESSAGE(msg);
  1603. msg->AddByte(0x6F);
  1604. msg->AddByte(cid);
  1605. }
  1606. }
  1607.  
  1608. void ProtocolGame::sendCreatureTurn(const Creature* creature, uint32_t stackpos)
  1609. {
  1610. if(stackpos < 10){
  1611. if(canSee(creature)){
  1612. NetworkMessage_ptr msg = getOutputBuffer();
  1613. if(msg){
  1614. TRACK_MESSAGE(msg);
  1615. msg->AddByte(0x6B);
  1616. msg->AddPosition(creature->getPosition());
  1617. msg->AddByte(stackpos);
  1618. msg->AddU16(0x63); /*99*/
  1619. msg->AddU32(creature->getID());
  1620. msg->AddByte(creature->getDirection());
  1621. }
  1622. }
  1623. }
  1624. }
  1625.  
  1626. void ProtocolGame::sendCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text)
  1627. {
  1628. NetworkMessage_ptr msg = getOutputBuffer();
  1629. if(msg){
  1630. TRACK_MESSAGE(msg);
  1631. AddCreatureSpeak(msg, creature, type, text, 0);
  1632. }
  1633. }
  1634.  
  1635. void ProtocolGame::sendToChannel(const Creature * creature, SpeakClasses type, const std::string& text, uint16_t channelId, uint32_t time /*= 0*/)
  1636. {
  1637. NetworkMessage_ptr msg = getOutputBuffer();
  1638. if(msg){
  1639. TRACK_MESSAGE(msg);
  1640. AddCreatureSpeak(msg, creature, type, text, channelId, time);
  1641. }
  1642. }
  1643.  
  1644. void ProtocolGame::sendCancel(const std::string& message)
  1645. {
  1646. NetworkMessage_ptr msg = getOutputBuffer();
  1647. if(msg){
  1648. TRACK_MESSAGE(msg);
  1649. AddTextMessage(msg, MSG_STATUS_SMALL, message);
  1650. }
  1651. }
  1652.  
  1653. void ProtocolGame::sendCancelTarget()
  1654. {
  1655. NetworkMessage_ptr msg = getOutputBuffer();
  1656. if(msg){
  1657. TRACK_MESSAGE(msg);
  1658. msg->AddByte(0xA3);
  1659. }
  1660. }
  1661.  
  1662. void ProtocolGame::sendChangeSpeed(const Creature* creature, uint32_t speed)
  1663. {
  1664. if(canSee(creature)){
  1665. NetworkMessage_ptr msg = getOutputBuffer();
  1666. if(msg){
  1667. TRACK_MESSAGE(msg);
  1668. msg->AddByte(0x8F);
  1669. msg->AddU32(creature->getID());
  1670. msg->AddU16(speed);
  1671. }
  1672. }
  1673. }
  1674.  
  1675. void ProtocolGame::sendCancelWalk()
  1676. {
  1677. NetworkMessage_ptr msg = getOutputBuffer();
  1678. if(msg){
  1679. TRACK_MESSAGE(msg);
  1680. msg->AddByte(0xB5);
  1681. msg->AddByte(player->getDirection());
  1682. }
  1683. }
  1684.  
  1685. void ProtocolGame::sendSkills()
  1686. {
  1687. NetworkMessage_ptr msg = getOutputBuffer();
  1688. if(msg){
  1689. TRACK_MESSAGE(msg);
  1690. AddPlayerSkills(msg);
  1691. }
  1692. }
  1693.  
  1694. void ProtocolGame::sendPing()
  1695. {
  1696. NetworkMessage_ptr msg = getOutputBuffer();
  1697. if(msg){
  1698. TRACK_MESSAGE(msg);
  1699. msg->AddByte(0x1E);
  1700. }
  1701. }
  1702.  
  1703. void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type)
  1704. {
  1705. if(canSee(from) || canSee(to)){
  1706. NetworkMessage_ptr msg = getOutputBuffer();
  1707. if(msg){
  1708. TRACK_MESSAGE(msg);
  1709. AddDistanceShoot(msg, from, to, type);
  1710. }
  1711. }
  1712. }
  1713.  
  1714. void ProtocolGame::sendMagicEffect(const Position& pos, uint8_t type)
  1715. {
  1716. if(canSee(pos)){
  1717. NetworkMessage_ptr msg = getOutputBuffer();
  1718. if(msg){
  1719. TRACK_MESSAGE(msg);
  1720. AddMagicEffect(msg, pos, type);
  1721. }
  1722. }
  1723. }
  1724.  
  1725. void ProtocolGame::sendAnimatedText(const Position& pos, uint8_t color, std::string text)
  1726. {
  1727. if(canSee(pos)){
  1728. NetworkMessage_ptr msg = getOutputBuffer();
  1729. if(msg){
  1730. TRACK_MESSAGE(msg);
  1731. AddAnimatedText(msg, pos, color, text);
  1732. }
  1733. }
  1734. }
  1735.  
  1736. void ProtocolGame::sendCreatureHealth(const Creature* creature)
  1737. {
  1738. if(canSee(creature)){
  1739. NetworkMessage_ptr msg = getOutputBuffer();
  1740. if(msg){
  1741. TRACK_MESSAGE(msg);
  1742. AddCreatureHealth(msg, creature);
  1743. }
  1744. }
  1745. }
  1746.  
  1747. //tile
  1748. void ProtocolGame::sendAddTileItem(const Tile* tile, const Position& pos, uint32_t stackpos, const Item* item)
  1749. {
  1750. if(canSee(pos)){
  1751. NetworkMessage_ptr msg = getOutputBuffer();
  1752. if(msg){
  1753. TRACK_MESSAGE(msg);
  1754. AddTileItem(msg, pos, stackpos, item);
  1755. }
  1756. }
  1757. }
  1758.  
  1759. void ProtocolGame::sendUpdateTileItem(const Tile* tile, const Position& pos, uint32_t stackpos, const Item* item)
  1760. {
  1761. if(canSee(pos)){
  1762. NetworkMessage_ptr msg = getOutputBuffer();
  1763. if(msg){
  1764. TRACK_MESSAGE(msg);
  1765. UpdateTileItem(msg, pos, stackpos, item);
  1766. }
  1767. }
  1768. }
  1769.  
  1770. void ProtocolGame::sendRemoveTileItem(const Tile* tile, const Position& pos, uint32_t stackpos)
  1771. {
  1772. if(canSee(pos)){
  1773. NetworkMessage_ptr msg = getOutputBuffer();
  1774. if(msg){
  1775. TRACK_MESSAGE(msg);
  1776. RemoveTileItem(msg, pos, stackpos);
  1777. }
  1778. }
  1779. }
  1780.  
  1781. void ProtocolGame::sendUpdateTile(const Tile* tile, const Position& pos)
  1782. {
  1783. if(canSee(pos)){
  1784. NetworkMessage_ptr msg = getOutputBuffer();
  1785. if(msg){
  1786. TRACK_MESSAGE(msg);
  1787. msg->AddByte(0x69);
  1788. msg->AddPosition(pos);
  1789.  
  1790. if(tile){
  1791. GetTileDescription(tile, msg);
  1792. msg->AddByte(0);
  1793. msg->AddByte(0xFF);
  1794. }
  1795. else{
  1796. msg->AddByte(0x01);
  1797. msg->AddByte(0xFF);
  1798. }
  1799. }
  1800. }
  1801. }
  1802.  
  1803. void ProtocolGame::sendAddCreature(const Creature* creature, const Position& pos, uint32_t stackpos, bool isLoggingIn)
  1804. {
  1805. if(canSee(creature)){
  1806. NetworkMessage_ptr msg = getOutputBuffer();
  1807. if(msg){
  1808. TRACK_MESSAGE(msg);
  1809. if(creature == player){
  1810. msg->AddByte(0x0A);
  1811. msg->AddU32(player->getID());
  1812. msg->AddU16(0x0032); // Related to client-side drawing speed
  1813. msg->AddByte(player->hasFlag(PlayerFlag_CanReportBugs));
  1814.  
  1815. if (player->hasFlag(PlayerFlag_CanAnswerRuleViolations)){
  1816. msg->AddByte(0x0B);
  1817. for (uint8_t i = 0; i < 32; i++) {
  1818. msg->AddByte(0xFF);
  1819. }
  1820. }
  1821.  
  1822. AddMapDescription(msg, pos);
  1823.  
  1824. if (isLoggingIn){
  1825. AddMagicEffect(msg, player->getPosition(), NM_ME_TELEPORT);
  1826. }
  1827.  
  1828. AddInventoryItem(msg, SLOT_HEAD, player->getInventoryItem(SLOT_HEAD));
  1829. AddInventoryItem(msg, SLOT_NECKLACE, player->getInventoryItem(SLOT_NECKLACE));
  1830. AddInventoryItem(msg, SLOT_BACKPACK, player->getInventoryItem(SLOT_BACKPACK));
  1831. AddInventoryItem(msg, SLOT_ARMOR, player->getInventoryItem(SLOT_ARMOR));
  1832. AddInventoryItem(msg, SLOT_RIGHT, player->getInventoryItem(SLOT_RIGHT));
  1833. AddInventoryItem(msg, SLOT_LEFT, player->getInventoryItem(SLOT_LEFT));
  1834. AddInventoryItem(msg, SLOT_LEGS, player->getInventoryItem(SLOT_LEGS));
  1835. AddInventoryItem(msg, SLOT_FEET, player->getInventoryItem(SLOT_FEET));
  1836. AddInventoryItem(msg, SLOT_RING, player->getInventoryItem(SLOT_RING));
  1837. AddInventoryItem(msg, SLOT_AMMO, player->getInventoryItem(SLOT_AMMO));
  1838.  
  1839. AddPlayerStats(msg);
  1840. AddPlayerSkills(msg);
  1841.  
  1842. //gameworld light-settings
  1843. LightInfo lightInfo;
  1844. g_game.getWorldLightInfo(lightInfo);
  1845. AddWorldLight(msg, lightInfo);
  1846.  
  1847. //player light level
  1848. AddCreatureLight(msg, creature);
  1849.  
  1850. for(VIPListSet::iterator it = player->VIPList.begin(); it != player->VIPList.end(); ++it){
  1851. std::string vip_name;
  1852. if(IOPlayer::instance()->getNameByGuid((*it), vip_name)){
  1853. Player *p = g_game.getPlayerByName(vip_name);
  1854. bool online = (p && (!p->isGmInvisible() || player->canSeeGmInvisible(p)));
  1855. sendVIP((*it), vip_name, online);
  1856. }
  1857. }
  1858.  
  1859. sendIcons(player->getIcons());
  1860. }
  1861. else{
  1862. AddTileCreature(msg, pos, stackpos, creature);
  1863.  
  1864. if (isLoggingIn){
  1865. AddMagicEffect(msg, creature->getPosition(), NM_ME_TELEPORT);
  1866. }
  1867. }
  1868. }
  1869. }
  1870. }
  1871.  
  1872. void ProtocolGame::sendRemoveCreature(const Creature* creature, const Position& pos, uint32_t stackpos, bool isLogout)
  1873. {
  1874. if(canSee(pos)){
  1875. NetworkMessage_ptr msg = getOutputBuffer();
  1876. if(msg){
  1877. TRACK_MESSAGE(msg);
  1878. RemoveTileItem(msg, pos, stackpos);
  1879.  
  1880. if(isLogout){
  1881. AddMagicEffect(msg, pos, NM_ME_PUFF);
  1882. }
  1883. }
  1884. }
  1885. }
  1886.  
  1887. void ProtocolGame::sendMoveCreature(const Creature* creature, const Tile* newTile, const Position& newPos,
  1888. uint32_t newStackPos, const Tile* oldTile, const Position& oldPos, uint32_t oldStackPos, bool teleport)
  1889. {
  1890. if(creature == player){
  1891. NetworkMessage_ptr msg = getOutputBuffer();
  1892. if(msg){
  1893. TRACK_MESSAGE(msg);
  1894. if(teleport || oldStackPos >= 10){
  1895. RemoveTileItem(msg, oldPos, oldStackPos);
  1896. AddMapDescription(msg, newPos);
  1897. }
  1898. else{
  1899. if(oldPos.z == 7 && newPos.z >= 8){
  1900. RemoveTileItem(msg, oldPos, oldStackPos);
  1901. }
  1902. else{
  1903. msg->AddByte(0x6D);
  1904. msg->AddPosition(oldPos);
  1905. msg->AddByte(oldStackPos);
  1906. msg->AddPosition(newPos);
  1907. }
  1908.  
  1909. //floor change down
  1910. if(newPos.z > oldPos.z){
  1911. MoveDownCreature(msg, creature, newPos, oldPos, oldStackPos);
  1912. }
  1913. //floor change up
  1914. else if(newPos.z < oldPos.z){
  1915. MoveUpCreature(msg, creature, newPos, oldPos, oldStackPos);
  1916. }
  1917.  
  1918. if(oldPos.y > newPos.y){ // north, for old x
  1919. msg->AddByte(0x65);
  1920. GetMapDescription(oldPos.x - 8, newPos.y - 6, newPos.z, 18, 1, msg);
  1921. }
  1922. else if(oldPos.y < newPos.y){ // south, for old x
  1923. msg->AddByte(0x67);
  1924. GetMapDescription(oldPos.x - 8, newPos.y + 7, newPos.z, 18, 1, msg);
  1925. }
  1926.  
  1927. if(oldPos.x < newPos.x){ // east, [with new y]
  1928. msg->AddByte(0x66);
  1929. GetMapDescription(newPos.x + 9, newPos.y - 6, newPos.z, 1, 14, msg);
  1930. }
  1931. else if(oldPos.x > newPos.x){ // west, [with new y]
  1932. msg->AddByte(0x68);
  1933. GetMapDescription(newPos.x - 8, newPos.y - 6, newPos.z, 1, 14, msg);
  1934. }
  1935. }
  1936. }
  1937. }
  1938. else if(canSee(oldPos) && canSee(newPos)){
  1939. if(player->canSeeCreature(creature)){
  1940. NetworkMessage_ptr msg = getOutputBuffer();
  1941. if(msg){
  1942. TRACK_MESSAGE(msg);
  1943. if(teleport || (oldPos.z == 7 && newPos.z >= 8) || oldStackPos >= 10){
  1944. RemoveTileItem(msg, oldPos, oldStackPos);
  1945. AddTileCreature(msg, newPos, newStackPos, creature);
  1946. }
  1947. else{
  1948. msg->AddByte(0x6D);
  1949. msg->AddPosition(oldPos);
  1950. msg->AddByte(oldStackPos);
  1951. msg->AddPosition(newPos);
  1952. }
  1953. }
  1954. }
  1955. }
  1956. else if(canSee(oldPos)){
  1957. if(player->canSeeCreature(creature)){
  1958. NetworkMessage_ptr msg = getOutputBuffer();
  1959. if(msg){
  1960. TRACK_MESSAGE(msg);
  1961. RemoveTileItem(msg, oldPos, oldStackPos);
  1962. }
  1963. }
  1964. }
  1965. else if(canSee(newPos)){
  1966. if(player->canSeeCreature(creature)){
  1967. NetworkMessage_ptr msg = getOutputBuffer();
  1968. if(msg){
  1969. TRACK_MESSAGE(msg);
  1970. AddTileCreature(msg, newPos, newStackPos, creature);
  1971. }
  1972. }
  1973. }
  1974. }
  1975.  
  1976. //inventory
  1977. void ProtocolGame::sendAddInventoryItem(slots_t slot, const Item* item)
  1978. {
  1979. NetworkMessage_ptr msg = getOutputBuffer();
  1980. if(msg){
  1981. TRACK_MESSAGE(msg);
  1982. AddInventoryItem(msg, slot, item);
  1983. }
  1984. }
  1985.  
  1986. void ProtocolGame::sendUpdateInventoryItem(slots_t slot, const Item* item)
  1987. {
  1988. NetworkMessage_ptr msg = getOutputBuffer();
  1989. if(msg){
  1990. TRACK_MESSAGE(msg);
  1991. UpdateInventoryItem(msg, slot, item);
  1992. }
  1993. }
  1994.  
  1995. void ProtocolGame::sendRemoveInventoryItem(slots_t slot)
  1996. {
  1997. NetworkMessage_ptr msg = getOutputBuffer();
  1998. if(msg){
  1999. TRACK_MESSAGE(msg);
  2000. RemoveInventoryItem(msg, slot);
  2001. }
  2002. }
  2003.  
  2004. //containers
  2005. void ProtocolGame::sendAddContainerItem(uint8_t cid, const Item* item)
  2006. {
  2007. NetworkMessage_ptr msg = getOutputBuffer();
  2008. if(msg){
  2009. TRACK_MESSAGE(msg);
  2010. AddContainerItem(msg, cid, item);
  2011. }
  2012. }
  2013.  
  2014. void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint8_t slot, const Item* item)
  2015. {
  2016. NetworkMessage_ptr msg = getOutputBuffer();
  2017. if(msg){
  2018. TRACK_MESSAGE(msg);
  2019. UpdateContainerItem(msg, cid, slot, item);
  2020. }
  2021. }
  2022.  
  2023. void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint8_t slot)
  2024. {
  2025. NetworkMessage_ptr msg = getOutputBuffer();
  2026. if(msg){
  2027. TRACK_MESSAGE(msg);
  2028. RemoveContainerItem(msg, cid, slot);
  2029. }
  2030. }
  2031.  
  2032. void ProtocolGame::sendTextWindow(uint32_t windowTextId, Item* item, uint16_t maxlen, bool canWrite)
  2033. {
  2034. NetworkMessage_ptr msg = getOutputBuffer();
  2035. if(msg){
  2036. TRACK_MESSAGE(msg);
  2037. msg->AddByte(0x96);
  2038. msg->AddU32(windowTextId);
  2039. msg->AddItemId(item);
  2040. if(canWrite){
  2041. msg->AddU16(maxlen);
  2042. msg->AddString(item->getText());
  2043. }
  2044. else{
  2045. msg->AddU16(item->getText().size());
  2046. msg->AddString(item->getText());
  2047. }
  2048.  
  2049. const std::string& writer = item->getWriter();
  2050. if(writer.size()){
  2051. msg->AddString(writer);
  2052. }
  2053. else{
  2054. msg->AddString("");
  2055. }
  2056. }
  2057. }
  2058.  
  2059. void ProtocolGame::sendTextWindow(uint32_t windowTextId, uint32_t itemId, const std::string& text)
  2060. {
  2061. NetworkMessage_ptr msg = getOutputBuffer();
  2062. if(msg){
  2063. TRACK_MESSAGE(msg);
  2064. msg->AddByte(0x96);
  2065. msg->AddU32(windowTextId);
  2066. msg->AddItemId(itemId);
  2067.  
  2068. msg->AddU16(text.size());
  2069. msg->AddString(text);
  2070.  
  2071. msg->AddString("");
  2072. }
  2073. }
  2074.  
  2075. void ProtocolGame::sendHouseWindow(uint32_t windowTextId, House* _house,
  2076. uint32_t listId, const std::string& text)
  2077. {
  2078. NetworkMessage_ptr msg = getOutputBuffer();
  2079. if(msg){
  2080. TRACK_MESSAGE(msg);
  2081. msg->AddByte(0x97);
  2082. msg->AddByte(0);
  2083. msg->AddU32(windowTextId);
  2084. msg->AddString(text);
  2085. }
  2086. }
  2087.  
  2088. void ProtocolGame::sendOutfitWindow()
  2089. {
  2090. NetworkMessage_ptr msg = getOutputBuffer();
  2091. if (msg){
  2092. msg->AddByte(0xC8);
  2093. AddCreatureOutfit(msg, player, player->getDefaultOutfit());
  2094.  
  2095. switch (player->getSex()) {
  2096. case PLAYERSEX_FEMALE:
  2097. msg->AddU16(136);
  2098. if (player->isPremium())
  2099. msg->AddU16(142);
  2100. else
  2101. msg->AddU16(139);
  2102.  
  2103. break;
  2104. case PLAYERSEX_MALE:
  2105. msg->AddU16(128);
  2106. if (player->isPremium())
  2107. msg->AddU16(134);
  2108. else
  2109. msg->AddU16(131);
  2110.  
  2111. break;
  2112. case 2:
  2113. msg->AddU16(160);
  2114. msg->AddU16(160);
  2115.  
  2116. break;
  2117. default:
  2118. msg->AddU16(128);
  2119. msg->AddU16(134);
  2120. }
  2121. }
  2122. }
  2123.  
  2124. void ProtocolGame::sendVIPLogIn(uint32_t guid)
  2125. {
  2126. NetworkMessage_ptr msg = getOutputBuffer();
  2127. if(msg){
  2128. TRACK_MESSAGE(msg);
  2129. msg->AddByte(0xD3);
  2130. msg->AddU32(guid);
  2131. }
  2132. }
  2133.  
  2134. void ProtocolGame::sendVIPLogOut(uint32_t guid)
  2135. {
  2136. NetworkMessage_ptr msg = getOutputBuffer();
  2137. if(msg){
  2138. TRACK_MESSAGE(msg);
  2139. msg->AddByte(0xD4);
  2140. msg->AddU32(guid);
  2141. }
  2142. }
  2143.  
  2144. void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, bool isOnline)
  2145. {
  2146. NetworkMessage_ptr msg = getOutputBuffer();
  2147. if(msg){
  2148. TRACK_MESSAGE(msg);
  2149. msg->AddByte(0xD2);
  2150. msg->AddU32(guid);
  2151. msg->AddString(name);
  2152. msg->AddByte(isOnline ? 1 : 0);
  2153. }
  2154. }
  2155.  
  2156. ////////////// Add common messages
  2157. void ProtocolGame::AddMapDescription(NetworkMessage_ptr msg, const Position& pos)
  2158. {
  2159. msg->AddByte(0x64);
  2160. msg->AddPosition(player->getPosition());
  2161. GetMapDescription(pos.x - 8, pos.y - 6, pos.z, 18, 14, msg);
  2162. }
  2163.  
  2164. void ProtocolGame::AddTextMessage(NetworkMessage_ptr msg, MessageClasses mclass, const std::string& message)
  2165. {
  2166. msg->AddByte(0xB4);
  2167. msg->AddByte(mclass);
  2168. msg->AddString(message);
  2169. }
  2170.  
  2171. void ProtocolGame::AddAnimatedText(NetworkMessage_ptr msg, const Position& pos,
  2172. uint8_t color, const std::string& text)
  2173. {
  2174. msg->AddByte(0x84);
  2175. msg->AddPosition(pos);
  2176. msg->AddByte(color);
  2177. msg->AddString(text);
  2178. }
  2179.  
  2180. void ProtocolGame::AddMagicEffect(NetworkMessage_ptr msg,const Position& pos, uint8_t type)
  2181. {
  2182. msg->AddByte(0x83);
  2183. msg->AddPosition(pos);
  2184. msg->AddByte(type + 1);
  2185. }
  2186.  
  2187. void ProtocolGame::AddDistanceShoot(NetworkMessage_ptr msg, const Position& from, const Position& to,
  2188. uint8_t type)
  2189. {
  2190. msg->AddByte(0x85);
  2191. msg->AddPosition(from);
  2192. msg->AddPosition(to);
  2193. msg->AddByte(type + 1);
  2194. }
  2195.  
  2196. void ProtocolGame::AddCreature(NetworkMessage_ptr msg,const Creature* creature, bool known, uint32_t remove)
  2197. {
  2198. if(known){
  2199. msg->AddU16(0x62);
  2200. msg->AddU32(creature->getID());
  2201. }
  2202. else{
  2203. msg->AddU16(0x61);
  2204. msg->AddU32(remove);
  2205. msg->AddU32(creature->getID());
  2206. msg->AddString(creature->getName());
  2207. }
  2208.  
  2209. msg->AddByte((int32_t)std::ceil(((float)creature->getHealth()) * 100 / std::max(creature->getMaxHealth(), (int32_t)1)));
  2210. msg->AddByte((uint8_t)creature->getDirection());
  2211.  
  2212. if(creature->isInvisible() ||
  2213. (creature->getPlayer() && creature->getPlayer()->isGmInvisible()))
  2214. {
  2215. if (player->canSeeInvisibility() && player != creature)
  2216. {
  2217. AddCreatureOutfit(msg, creature, creature->getCurrentOutfit());
  2218. }
  2219. else {
  2220. msg->AddU16(0);
  2221. msg->AddU16(0);
  2222. }
  2223. /*static Outfit_t outfit;
  2224. AddCreatureOutfit(msg, creature, outfit);*/
  2225. }
  2226. else{
  2227. AddCreatureOutfit(msg, creature, creature->getCurrentOutfit());
  2228. }
  2229.  
  2230. LightInfo lightInfo;
  2231. creature->getCreatureLight(lightInfo);
  2232. msg->AddByte(lightInfo.level);
  2233. msg->AddByte(lightInfo.color);
  2234.  
  2235. msg->AddU16(creature->getStepSpeed());
  2236. #ifdef __SKULLSYSTEM__
  2237. msg->AddByte(player->getSkullClient(creature->getPlayer()));
  2238. #else
  2239. msg->AddByte(SKULL_NONE);
  2240. #endif
  2241. msg->AddByte(player->getPartyShield(creature->getPlayer()));
  2242. }
  2243.  
  2244. void ProtocolGame::AddPlayerStats(NetworkMessage_ptr msg)
  2245. {
  2246. msg->AddByte(0xA0);
  2247. msg->AddU16(player->getHealth());
  2248. msg->AddU16(player->getPlayerInfo(PLAYERINFO_MAXHEALTH));
  2249. msg->AddU16((uint32_t)(player->getFreeCapacity()));
  2250. uint64_t experience = player->getExperience();
  2251. if(experience <= 0x7FFFFFFF){
  2252. msg->AddU32(player->getExperience());
  2253. }
  2254. else{
  2255. msg->AddU32(0x00); //Client debugs after 2,147,483,647 exp
  2256. }
  2257. msg->AddU16(player->getPlayerInfo(PLAYERINFO_LEVEL));
  2258. msg->AddByte(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT));
  2259.  
  2260. msg->AddU16(player->getMana());
  2261. msg->AddU16(player->getPlayerInfo(PLAYERINFO_MAXMANA));
  2262.  
  2263. msg->AddByte(player->getMagicLevel());
  2264. msg->AddByte(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT));
  2265.  
  2266. msg->AddByte(player->getPlayerInfo(PLAYERINFO_SOUL));
  2267. }
  2268.  
  2269. void ProtocolGame::AddPlayerSkills(NetworkMessage_ptr msg)
  2270. {
  2271. msg->AddByte(0xA1);
  2272. msg->AddByte(player->getSkill(SKILL_FIST, SKILL_LEVEL));
  2273. msg->AddByte(player->getSkill(SKILL_FIST, SKILL_PERCENT));
  2274. msg->AddByte(player->getSkill(SKILL_CLUB, SKILL_LEVEL));
  2275. msg->AddByte(player->getSkill(SKILL_CLUB, SKILL_PERCENT));
  2276. msg->AddByte(player->getSkill(SKILL_SWORD, SKILL_LEVEL));
  2277. msg->AddByte(player->getSkill(SKILL_SWORD, SKILL_PERCENT));
  2278. msg->AddByte(player->getSkill(SKILL_AXE, SKILL_LEVEL));
  2279. msg->AddByte(player->getSkill(SKILL_AXE, SKILL_PERCENT));
  2280. msg->AddByte(player->getSkill(SKILL_DIST, SKILL_LEVEL));
  2281. msg->AddByte(player->getSkill(SKILL_DIST, SKILL_PERCENT));
  2282. msg->AddByte(player->getSkill(SKILL_SHIELD, SKILL_LEVEL));
  2283. msg->AddByte(player->getSkill(SKILL_SHIELD, SKILL_PERCENT));
  2284. msg->AddByte(player->getSkill(SKILL_FISH, SKILL_LEVEL));
  2285. msg->AddByte(player->getSkill(SKILL_FISH, SKILL_PERCENT));
  2286. }
  2287.  
  2288. void ProtocolGame::AddCreatureSpeak(NetworkMessage_ptr msg, const Creature* creature,
  2289. SpeakClasses type, std::string text, uint16_t channelId, uint32_t time /*= 0*/)
  2290. {
  2291. msg->AddByte(0xAA);
  2292. msg->AddU32(++Player::channelStatementGuid);
  2293.  
  2294. Player::channelStatementMap[Player::channelStatementGuid] = text;
  2295.  
  2296. if (type != SPEAK_CHANNEL_R2){
  2297. if (type != SPEAK_RVR_ANSWER){
  2298. msg->AddString(creature->getName());
  2299. }
  2300. else {
  2301. msg->AddString("Gamemaster");
  2302. }
  2303. }
  2304. else {
  2305. msg->AddString("");
  2306. }
  2307.  
  2308. msg->AddByte(type);
  2309. switch(type){
  2310. case SPEAK_SAY:
  2311. case SPEAK_WHISPER:
  2312. case SPEAK_YELL:
  2313. case SPEAK_MONSTER_SAY:
  2314. case SPEAK_MONSTER_YELL:
  2315. assert(creature);
  2316. msg->AddPosition(creature->getPosition());
  2317. break;
  2318. case SPEAK_CHANNEL_Y:
  2319. case SPEAK_CHANNEL_R1:
  2320. case SPEAK_CHANNEL_R2:
  2321. case SPEAK_CHANNEL_O:
  2322. msg->AddU16(channelId);
  2323. break;
  2324. case SPEAK_RVR_CHANNEL: {
  2325. uint32_t t = (OTSYS_TIME() / 1000) & 0xFFFFFFFF;
  2326. msg->AddU32(t - time);
  2327. } break;
  2328. default:
  2329. break;
  2330. }
  2331.  
  2332. msg->AddString(text);
  2333. }
  2334.  
  2335. void ProtocolGame::AddCreatureHealth(NetworkMessage_ptr msg,const Creature* creature)
  2336. {
  2337. msg->AddByte(0x8C);
  2338. msg->AddU32(creature->getID());
  2339. msg->AddByte((int32_t)std::ceil(((float)creature->getHealth()) * 100 / std::max(creature->getMaxHealth(), (int32_t)1)));
  2340. }
  2341.  
  2342. void ProtocolGame::AddCreatureOutfit(NetworkMessage_ptr msg, const Creature* creature, const Outfit_t& outfit)
  2343. {
  2344. msg->AddU16(outfit.lookType);
  2345. if(outfit.lookType != 0){
  2346. msg->AddByte(outfit.lookHead);
  2347. msg->AddByte(outfit.lookBody);
  2348. msg->AddByte(outfit.lookLegs);
  2349. msg->AddByte(outfit.lookFeet);
  2350. }
  2351. else if(outfit.lookTypeEx != 0){
  2352. msg->AddItemId(outfit.lookTypeEx);
  2353. }
  2354. else{
  2355. msg->AddU16(outfit.lookTypeEx);
  2356. }
  2357. }
  2358.  
  2359. void ProtocolGame::AddWorldLight(NetworkMessage_ptr msg, const LightInfo& lightInfo)
  2360. {
  2361. msg->AddByte(0x82);
  2362. msg->AddByte(lightInfo.level);
  2363. msg->AddByte(lightInfo.color);
  2364. }
  2365.  
  2366. void ProtocolGame::AddCreatureLight(NetworkMessage_ptr msg, const Creature* creature)
  2367. {
  2368. LightInfo lightInfo;
  2369. creature->getCreatureLight(lightInfo);
  2370. msg->AddByte(0x8D);
  2371. msg->AddU32(creature->getID());
  2372. msg->AddByte(lightInfo.level);
  2373. msg->AddByte(lightInfo.color);
  2374. }
  2375.  
  2376. //tile
  2377. void ProtocolGame::AddTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Item* item)
  2378. {
  2379. if(stackpos < 10){
  2380. msg->AddByte(0x6A);
  2381. msg->AddPosition(pos);
  2382. msg->AddItem(item);
  2383. }
  2384. }
  2385.  
  2386. void ProtocolGame::AddTileCreature(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos,
  2387. const Creature* creature)
  2388. {
  2389. //if(stackpos < 10){
  2390. msg->AddByte(0x6A);
  2391. msg->AddPosition(pos);
  2392.  
  2393. bool known;
  2394. uint32_t removedKnown;
  2395. checkCreatureAsKnown(creature->getID(), known, removedKnown);
  2396. AddCreature(msg, creature, known, removedKnown);
  2397. //}
  2398. }
  2399.  
  2400. void ProtocolGame::UpdateTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos, const Item* item)
  2401. {
  2402. if(stackpos < 10){
  2403. msg->AddByte(0x6B);
  2404. msg->AddPosition(pos);
  2405. msg->AddByte(stackpos);
  2406. msg->AddItem(item);
  2407. }
  2408. }
  2409.  
  2410. void ProtocolGame::RemoveTileItem(NetworkMessage_ptr msg, const Position& pos, uint32_t stackpos)
  2411. {
  2412. if(stackpos < 10){
  2413. msg->AddByte(0x6C);
  2414. msg->AddPosition(pos);
  2415. msg->AddByte(stackpos);
  2416. }
  2417. }
  2418.  
  2419. void ProtocolGame::MoveUpCreature(NetworkMessage_ptr msg, const Creature* creature,
  2420. const Position& newPos, const Position& oldPos, uint32_t oldStackPos)
  2421. {
  2422. if(creature == player){
  2423. //floor change up
  2424. msg->AddByte(0xBE);
  2425.  
  2426. //going to surface
  2427. if(newPos.z == 7){
  2428. int32_t skip = -1;
  2429. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 5, 18, 14, 3, skip); //(floor 7 and 6 already set)
  2430. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 4, 18, 14, 4, skip);
  2431. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 3, 18, 14, 5, skip);
  2432. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 2, 18, 14, 6, skip);
  2433. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 1, 18, 14, 7, skip);
  2434. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 0, 18, 14, 8, skip);
  2435.  
  2436. if(skip >= 0){
  2437. msg->AddByte(skip);
  2438. msg->AddByte(0xFF);
  2439. }
  2440. }
  2441. //underground, going one floor up (still underground)
  2442. else if(newPos.z > 7){
  2443. int32_t skip = -1;
  2444. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, oldPos.z - 3, 18, 14, 3, skip);
  2445.  
  2446. if(skip >= 0){
  2447. msg->AddByte(skip);
  2448. msg->AddByte(0xFF);
  2449. }
  2450. }
  2451.  
  2452. //moving up a floor up makes us out of sync
  2453. //west
  2454. msg->AddByte(0x68);
  2455. GetMapDescription(oldPos.x - 8, oldPos.y + 1 - 6, newPos.z, 1, 14, msg);
  2456.  
  2457. //north
  2458. msg->AddByte(0x65);
  2459. GetMapDescription(oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 1, msg);
  2460. }
  2461. }
  2462.  
  2463. void ProtocolGame::MoveDownCreature(NetworkMessage_ptr msg, const Creature* creature,
  2464. const Position& newPos, const Position& oldPos, uint32_t oldStackPos)
  2465. {
  2466. if(creature == player){
  2467. //floor change down
  2468. msg->AddByte(0xBF);
  2469.  
  2470. //going from surface to underground
  2471. if(newPos.z == 8){
  2472. int32_t skip = -1;
  2473. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 14, -1, skip);
  2474. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 1, 18, 14, -2, skip);
  2475. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);
  2476.  
  2477. if(skip >= 0){
  2478. msg->AddByte(skip);
  2479. msg->AddByte(0xFF);
  2480. }
  2481. }
  2482. //going further down
  2483. else if(newPos.z > oldPos.z && newPos.z > 8 && newPos.z < 14){
  2484. int32_t skip = -1;
  2485. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);
  2486.  
  2487. if(skip >= 0){
  2488. msg->AddByte(skip);
  2489. msg->AddByte(0xFF);
  2490. }
  2491. }
  2492.  
  2493. //moving down a floor makes us out of sync
  2494. //east
  2495. msg->AddByte(0x66);
  2496. GetMapDescription(oldPos.x + 9, oldPos.y - 1 - 6, newPos.z, 1, 14, msg);
  2497.  
  2498. //south
  2499. msg->AddByte(0x67);
  2500. GetMapDescription(oldPos.x - 8, oldPos.y + 7, newPos.z, 18, 1, msg);
  2501. }
  2502. }
  2503.  
  2504. //inventory
  2505. void ProtocolGame::AddInventoryItem(NetworkMessage_ptr msg, slots_t slot, const Item* item)
  2506. {
  2507. if(item == NULL){
  2508. msg->AddByte(0x79);
  2509. msg->AddByte(slot);
  2510. }
  2511. else{
  2512. msg->AddByte(0x78);
  2513. msg->AddByte(slot);
  2514. msg->AddItem(item);
  2515. }
  2516. }
  2517.  
  2518. void ProtocolGame::UpdateInventoryItem(NetworkMessage_ptr msg, slots_t slot, const Item* item)
  2519. {
  2520. if(item == NULL){
  2521. msg->AddByte(0x79);
  2522. msg->AddByte(slot);
  2523. }
  2524. else{
  2525. msg->AddByte(0x78);
  2526. msg->AddByte(slot);
  2527. msg->AddItem(item);
  2528. }
  2529. }
  2530.  
  2531. void ProtocolGame::RemoveInventoryItem(NetworkMessage_ptr msg, slots_t slot)
  2532. {
  2533. msg->AddByte(0x79);
  2534. msg->AddByte(slot);
  2535. }
  2536.  
  2537. //containers
  2538. void ProtocolGame::AddContainerItem(NetworkMessage_ptr msg, uint8_t cid, const Item* item)
  2539. {
  2540. msg->AddByte(0x70);
  2541. msg->AddByte(cid);
  2542. msg->AddItem(item);
  2543. }
  2544.  
  2545. void ProtocolGame::UpdateContainerItem(NetworkMessage_ptr msg, uint8_t cid, uint8_t slot, const Item* item)
  2546. {
  2547. msg->AddByte(0x71);
  2548. msg->AddByte(cid);
  2549. msg->AddByte(slot);
  2550. msg->AddItem(item);
  2551. }
  2552.  
  2553. void ProtocolGame::RemoveContainerItem(NetworkMessage_ptr msg, uint8_t cid, uint8_t slot)
  2554. {
  2555. msg->AddByte(0x72);
  2556. msg->AddByte(cid);
  2557. msg->AddByte(slot);
  2558. }
Add Comment
Please, Sign In to add comment