Advertisement
Guest User

Untitled

a guest
Mar 15th, 2016
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 53.29 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////
  2. // OpenTibia - an opensource roleplaying game
  3. //////////////////////////////////////////////////////////////////////
  4. // Implementation of tibia v7.8x 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.  
  21.  
  22. #include "definitions.h"
  23.  
  24. #include <string>
  25. #include <iostream>
  26. #include <sstream>
  27. #include <time.h>
  28. #include <list>
  29.  
  30. #include "networkmessage.h"
  31. #include "protocol78.h"
  32.  
  33. #include "items.h"
  34.  
  35. #include "tile.h"
  36. #include "creature.h"
  37. #include "player.h"
  38. #include "status.h"
  39. #include "chat.h"
  40.  
  41. #include <stdio.h>
  42.  
  43. #include "configmanager.h"
  44.  
  45. #include "otsystem.h"
  46. #include "actions.h"
  47. #include "game.h"
  48. #include "ioplayer.h"
  49. #include "house.h"
  50. #include "waitlist.h"
  51.  
  52. extern ConfigManager g_config;
  53. extern Actions actions;
  54. Chat g_chat;
  55.  
  56. Protocol78::Protocol78(SOCKET s)
  57. {
  58. OTSYS_THREAD_LOCKVARINIT(bufferLock);
  59. windowTextID = 0;
  60. readItem = NULL;
  61. maxTextLength = 0;
  62. this->s = s;
  63. }
  64.  
  65.  
  66. Protocol78::~Protocol78()
  67. {
  68. OTSYS_THREAD_LOCKVARRELEASE(bufferLock);
  69. }
  70.  
  71. void Protocol78::reinitializeProtocol(SOCKET _s)
  72. {
  73. windowTextID = 0;
  74. readItem = NULL;
  75. maxTextLength = 0;
  76. OutputBuffer.Reset();
  77. knownPlayers.clear();
  78. if(s)
  79. closesocket(s);
  80. s = _s;
  81. }
  82.  
  83. connectResult_t Protocol78::ConnectPlayer()
  84. {
  85. Waitlist* wait = Waitlist::instance();
  86.  
  87. if(player->access == 0 && !wait->clientLogin(player->getAccount(), player->getIP())){
  88. return CONNECT_TOMANYPLAYERS;
  89. }
  90. else{
  91. //last login position
  92. if(game->placeCreature(player->getLoginPosition(), player)){
  93. return CONNECT_SUCCESS;
  94. }
  95. //temple
  96. else if(game->placeCreature(player->masterPos, player, true)){
  97. return CONNECT_SUCCESS;
  98. }
  99. else
  100. return CONNECT_MASTERPOSERROR;
  101. }
  102.  
  103. return CONNECT_INTERNALERROR;
  104. }
  105.  
  106.  
  107. void Protocol78::ReceiveLoop()
  108. {
  109. NetworkMessage msg;
  110. msg.setEncryptionState(true);
  111. msg.setEncryptionKey(m_key);
  112. do{
  113. while(pendingLogout == false && msg.ReadFromSocket(s)){
  114. parsePacket(msg);
  115. }
  116.  
  117. if(s){
  118. closesocket(s);
  119. s = 0;
  120. }
  121. // logout by disconnect? -> kick
  122. if(pendingLogout == false){
  123. game->playerSetAttackedCreature(player, 0);
  124. while(player->inFightTicks >= 1000 && !player->isRemoved() && s == 0){
  125. OTSYS_SLEEP(250);
  126. }
  127.  
  128. OTSYS_THREAD_LOCK(game->gameLock, "Protocol78::ReceiveLoop()")
  129.  
  130. if(!player->isRemoved()){
  131. if(s == 0){
  132. game->removeCreature(player);
  133. }
  134. else{
  135. //set new key after reattaching
  136. msg.setEncryptionKey(m_key);
  137. }
  138. }
  139.  
  140. OTSYS_THREAD_UNLOCK(game->gameLock, "Protocol78::ReceiveLoop()")
  141. }
  142.  
  143. }while(s != 0 && !player->isRemoved());
  144. }
  145.  
  146.  
  147. void Protocol78::parsePacket(NetworkMessage &msg)
  148. {
  149. if(msg.getMessageLength() <= 0)
  150. return;
  151.  
  152. uint8_t recvbyte = msg.GetByte();
  153. //a dead player can not performs actions
  154. if(player->isRemoved() && recvbyte != 0x14){
  155. OTSYS_SLEEP(10);
  156. return;
  157. }
  158.  
  159. switch(recvbyte){
  160. case 0x14: // logout
  161. parseLogout(msg);
  162. break;
  163.  
  164. case 0x1E: // keep alive / ping response
  165. parseReceivePing(msg);
  166. break;
  167.  
  168. case 0x64: // move with steps
  169. parseAutoWalk(msg);
  170. break;
  171.  
  172. case 0x65: // move north
  173. parseMoveNorth(msg);
  174. break;
  175.  
  176. case 0x66: // move east
  177. parseMoveEast(msg);
  178. break;
  179.  
  180. case 0x67: // move south
  181. parseMoveSouth(msg);
  182. break;
  183.  
  184. case 0x68: // move west
  185. parseMoveWest(msg);
  186. break;
  187.  
  188. case 0x69: // stop-autowalk
  189. parseStopAutoWalk(msg);
  190. break;
  191.  
  192. case 0x6A:
  193. parseMoveNorthEast(msg);
  194. break;
  195.  
  196. case 0x6B:
  197. parseMoveSouthEast(msg);
  198. break;
  199.  
  200. case 0x6C:
  201. parseMoveSouthWest(msg);
  202. break;
  203.  
  204. case 0x6D:
  205. parseMoveNorthWest(msg);
  206. break;
  207.  
  208. case 0x6F: // turn north
  209. parseTurnNorth(msg);
  210. break;
  211.  
  212. case 0x70: // turn east
  213. parseTurnEast(msg);
  214. break;
  215.  
  216. case 0x71: // turn south
  217. parseTurnSouth(msg);
  218. break;
  219.  
  220. case 0x72: // turn west
  221. parseTurnWest(msg);
  222. break;
  223.  
  224. case 0x78: // throw item
  225. parseThrow(msg);
  226. break;
  227.  
  228. case 0x7D: // Request trade
  229. parseRequestTrade(msg);
  230. break;
  231.  
  232. case 0x7E: // Look at an item in trade
  233. parseLookInTrade(msg);
  234. break;
  235.  
  236. case 0x7F: // Accept trade
  237. parseAcceptTrade(msg);
  238. break;
  239.  
  240. case 0x80: // Close/cancel trade
  241. parseCloseTrade();
  242. break;
  243.  
  244. case 0x82: // use item
  245. parseUseItem(msg);
  246. break;
  247.  
  248. case 0x83: // use item
  249. parseUseItemEx(msg);
  250. break;
  251.  
  252. case 0x84: // battle window
  253. parseBattleWindow(msg);
  254. break;
  255.  
  256. case 0x85: //rotate item
  257. parseRotateItem(msg);
  258. break;
  259.  
  260. case 0x87: // close container
  261. parseCloseContainer(msg);
  262. break;
  263.  
  264. case 0x88: //"up-arrow" - container
  265. parseUpArrowContainer(msg);
  266. break;
  267.  
  268. case 0x89:
  269. parseTextWindow(msg);
  270. break;
  271.  
  272. case 0x8A:
  273. parseHouseWindow(msg);
  274. break;
  275.  
  276. case 0x8C: // throw item
  277. parseLookAt(msg);
  278. break;
  279.  
  280. case 0x96: // say something
  281. parseSay(msg);
  282. break;
  283.  
  284. case 0x97: // request Channels
  285. parseGetChannels(msg);
  286. break;
  287.  
  288. case 0x98: // open Channel
  289. parseOpenChannel(msg);
  290. break;
  291.  
  292. case 0x99: // close Channel
  293. parseCloseChannel(msg);
  294. break;
  295.  
  296. case 0x9A: // open priv
  297. parseOpenPriv(msg);
  298. break;
  299.  
  300. case 0xA0: // set attack and follow mode
  301. parseFightModes(msg);
  302. break;
  303.  
  304. case 0xA1: // attack
  305. parseAttack(msg);
  306. break;
  307.  
  308. case 0xA2: //follow
  309. parseFollow(msg);
  310. break;
  311.  
  312. case 0xAA:
  313. parseCreatePrivateChannel(msg);
  314. break;
  315.  
  316. case 0xAB:
  317. parseChannelInvite(msg);
  318. break;
  319.  
  320. case 0xAC:
  321. parseChannelExclude(msg);
  322. break;
  323.  
  324. case 0xBE: // cancel move
  325. parseCancelMove(msg);
  326. break;
  327.  
  328. case 0xC9: //client sends its position, unknown usage
  329. msg.GetPosition();
  330. break;
  331.  
  332. case 0xCA: //client request to resend the container (happens when you store more than container maxsize)
  333. parseUpdateContainer(msg);
  334. break;
  335.  
  336. case 0xD2: // request Outfit
  337. parseRequestOutfit(msg);
  338. break;
  339.  
  340. case 0xD3: // set outfit
  341. parseSetOutfit(msg);
  342. break;
  343.  
  344. case 0xDC:
  345. parseAddVip(msg);
  346. break;
  347.  
  348. case 0xDD:
  349. parseRemVip(msg);
  350. break;
  351.  
  352. default:
  353. #ifdef __DEBUG__
  354. printf("unknown packet header: %x \n", recvbyte);
  355. parseDebug(msg);
  356. #endif
  357. break;
  358. }
  359.  
  360. game->flushSendBuffers();
  361. }
  362.  
  363. void Protocol78::GetTileDescription(const Tile* tile, NetworkMessage &msg)
  364. {
  365. if(tile){
  366. int count = 0;
  367. if(tile->ground){
  368. msg.AddItem(tile->ground);
  369. count++;
  370. }
  371.  
  372. ItemVector::const_iterator it;
  373. for(it = tile->topItems.begin(); ((it != tile->topItems.end()) && (count < 10)); ++it){
  374. msg.AddItem(*it);
  375. count++;
  376. }
  377.  
  378. CreatureVector::const_iterator itc;
  379. for(itc = tile->creatures.begin(); ((itc != tile->creatures.end()) && (count < 10)); ++itc){
  380. bool known;
  381. unsigned long removedKnown;
  382. checkCreatureAsKnown((*itc)->getID(), known, removedKnown);
  383. AddCreature(msg,*itc, known, removedKnown);
  384. count++;
  385. }
  386.  
  387. for(it = tile->downItems.begin(); ((it != tile->downItems.end()) && (count < 10)); ++it){
  388. msg.AddItem(*it);
  389. count++;
  390. }
  391. }
  392. }
  393.  
  394. void Protocol78::GetMapDescription(unsigned short x, unsigned short y, unsigned char z,
  395. unsigned short width, unsigned short height, NetworkMessage &msg)
  396. {
  397. int skip = -1;
  398. int startz, endz, zstep = 0;
  399.  
  400. if (z > 7) {
  401. startz = z - 2;
  402. endz = std::min(MAP_MAX_LAYERS - 1, z + 2);
  403. zstep = 1;
  404. }
  405. else {
  406. startz = 7;
  407. endz = 0;
  408.  
  409. zstep = -1;
  410. }
  411.  
  412. for(int nz = startz; nz != endz + zstep; nz += zstep){
  413. GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip);
  414. }
  415.  
  416. if(skip >= 0){
  417. msg.AddByte(skip);
  418. msg.AddByte(0xFF);
  419. //cc += skip;
  420. }
  421.  
  422. #ifdef __DEBUG__
  423. //printf("tiles in total: %d \n", cc);
  424. #endif
  425. }
  426.  
  427. void Protocol78::GetFloorDescription(NetworkMessage& msg, int x, int y, int z, int width, int height, int offset, int& skip)
  428. {
  429. Tile* tile;
  430.  
  431. for(int nx = 0; nx < width; nx++){
  432. for(int ny = 0; ny < height; ny++){
  433. tile = game->getTile(x + nx + offset, y + ny + offset, z);
  434. if(tile){
  435. if(skip >= 0){
  436. msg.AddByte(skip);
  437. msg.AddByte(0xFF);
  438. }
  439. skip = 0;
  440.  
  441. GetTileDescription(tile, msg);
  442. }
  443. else {
  444. skip++;
  445. if(skip == 0xFF){
  446. msg.AddByte(0xFF);
  447. msg.AddByte(0xFF);
  448. skip = -1;
  449. }
  450. }
  451. }
  452. }
  453. }
  454.  
  455. void Protocol78::checkCreatureAsKnown(unsigned long id, bool &known, unsigned long &removedKnown)
  456. {
  457. // loop through the known player and check if the given player is in
  458. std::list<unsigned long>::iterator i;
  459. for(i = knownPlayers.begin(); i != knownPlayers.end(); ++i)
  460. {
  461. if((*i) == id)
  462. {
  463. // know... make the creature even more known...
  464. knownPlayers.erase(i);
  465. knownPlayers.push_back(id);
  466.  
  467. known = true;
  468. return;
  469. }
  470. }
  471.  
  472. // ok, he is unknown...
  473. known = false;
  474.  
  475. // ... but not in future
  476. knownPlayers.push_back(id);
  477.  
  478. // to many known players?
  479. if(knownPlayers.size() > 150) //150 for 7.4 clients, changed for 7.5?
  480. {
  481. // lets try to remove one from the end of the list
  482. for (int n = 0; n < 150; n++)
  483. {
  484. removedKnown = knownPlayers.front();
  485.  
  486. Creature *c = game->getCreatureByID(removedKnown);
  487. if ((!c) || (!CanSee(c)))
  488. break;
  489.  
  490. // this creature we can't remove, still in sight, so back to the end
  491. knownPlayers.pop_front();
  492. knownPlayers.push_back(removedKnown);
  493. }
  494.  
  495. // hopefully we found someone to remove :S, we got only 150 tries
  496. // if not... lets kick some players with debug errors :)
  497. knownPlayers.pop_front();
  498. }
  499. else
  500. {
  501. // we can cache without problems :)
  502. removedKnown = 0;
  503. }
  504. }
  505.  
  506. bool Protocol78::CanSee(const Position& pos) const
  507. {
  508. return CanSee(pos.x, pos.y, pos.z);
  509. }
  510.  
  511. bool Protocol78::CanSee(int x, int y, int z) const
  512. {
  513. #ifdef __DEBUG__
  514. if(z < 0 || z >= MAP_MAX_LAYERS) {
  515. std::cout << "WARNING! Protocol78::CanSee() Z-value is out of range!" << std::endl;
  516. }
  517. #endif
  518.  
  519. const Position& myPos = player->getPosition();
  520.  
  521. //we are on ground level or above (7 -> 0)
  522. if(myPos.z <= 7){
  523. //view is from 7 -> 0
  524. if(z > 7){
  525. return false;
  526. }
  527. }
  528. //we are underground (8 -> 15)
  529. else if(myPos.z >= 8){
  530. //view is +/- 2 from the floor we stand on
  531. if(std::abs(myPos.z - z) > 2){
  532. return false;
  533. }
  534. }
  535.  
  536. /*
  537. //underground 8->15
  538. if(myPos.z > 7 && z < 6){
  539. return false;
  540. }
  541. //ground level and above 7->0
  542. else if(myPos.z <= 7 && z > 7){
  543. return false;
  544. }
  545. */
  546.  
  547. //negative offset means that the action taken place is on a lower floor than ourself
  548. int offsetz = myPos.z - z;
  549.  
  550. if ((x >= myPos.x - 8 + offsetz) && (x <= myPos.x + 9 + offsetz) &&
  551. (y >= myPos.y - 6 + offsetz) && (y <= myPos.y + 7 + offsetz))
  552. return true;
  553.  
  554. return false;
  555. }
  556.  
  557. bool Protocol78::CanSee(const Creature* c) const
  558. {
  559. if(c->isRemoved())
  560. return false;
  561.  
  562. Position pos = c->getPosition();
  563. return CanSee(pos.x, pos.y, pos.z);
  564. }
  565.  
  566.  
  567. void Protocol78::logout()
  568. {
  569. // we ask the game to remove us
  570. if(!player->isRemoved()){
  571. if(game->removeCreature(player))
  572. pendingLogout = true;
  573. }
  574. else{
  575. pendingLogout = true;
  576. }
  577. }
  578.  
  579. // Parse methods
  580. void Protocol78::parseLogout(NetworkMessage& msg)
  581. {
  582. if(player->inFightTicks >=1000 && !player->isRemoved()){
  583. player->sendCancelMessage(RET_YOUMAYNOTLOGOUTDURINGAFIGHT);
  584. return;
  585. }
  586. else{
  587. logout();
  588. }
  589. }
  590.  
  591. void Protocol78::parseCreatePrivateChannel(NetworkMessage& msg)
  592. {
  593. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseCreatePrivateChannel()");
  594. if(player->isRemoved()){
  595. return;
  596. }
  597.  
  598. ChatChannel* channel = g_chat.createChannel(player, 0xFFFF);
  599.  
  600. if(channel){
  601. if(channel->addUser(player)){
  602. NetworkMessage msg;
  603. msg.AddByte(0xB2);
  604. msg.AddU16(channel->getId());
  605. msg.AddString(channel->getName());
  606.  
  607. WriteBuffer(msg);
  608. }
  609. }
  610. }
  611.  
  612. void Protocol78::parseChannelInvite(NetworkMessage& msg)
  613. {
  614. std::string name = msg.GetString();
  615.  
  616. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseChannelInvite()");
  617. if(player->isRemoved()){
  618. return;
  619. }
  620.  
  621. PrivateChatChannel* channel = g_chat.getPrivateChannel(player);
  622.  
  623. if(channel){
  624. Player* invitePlayer = game->getPlayerByName(name);
  625.  
  626. if(invitePlayer){
  627. channel->invitePlayer(player, invitePlayer);
  628. }
  629. }
  630. }
  631.  
  632. void Protocol78::parseChannelExclude(NetworkMessage& msg)
  633. {
  634. std::string name = msg.GetString();
  635.  
  636. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseChannelExclude()");
  637. if(player->isRemoved()){
  638. return;
  639. }
  640.  
  641. PrivateChatChannel* channel = g_chat.getPrivateChannel(player);
  642.  
  643. if(channel){
  644. Player* excludePlayer = game->getPlayerByName(name);
  645.  
  646. if(excludePlayer){
  647. channel->excludePlayer(player, excludePlayer);
  648. }
  649. }
  650. }
  651.  
  652. void Protocol78::parseGetChannels(NetworkMessage& msg)
  653. {
  654. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseGetChannels()");
  655. if(player->isRemoved()){
  656. return;
  657. }
  658.  
  659. sendChannelsDialog();
  660. }
  661.  
  662. void Protocol78::parseOpenChannel(NetworkMessage& msg)
  663. {
  664. unsigned short channelId = msg.GetU16();
  665. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseOpenChannel()");
  666. if(player->isRemoved()){
  667. return;
  668. }
  669.  
  670. if(g_chat.addUserToChannel(player, channelId)){
  671. sendChannel(channelId, g_chat.getChannelName(player, channelId));
  672. }
  673. }
  674.  
  675. void Protocol78::parseCloseChannel(NetworkMessage &msg)
  676. {
  677. unsigned short channelId = msg.GetU16();
  678. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseCloseChannel()");
  679. if(player->isRemoved()){
  680. return;
  681. }
  682.  
  683. g_chat.removeUserFromChannel(player, channelId);
  684. }
  685.  
  686. void Protocol78::parseOpenPriv(NetworkMessage& msg)
  687. {
  688. std::string receiver;
  689. receiver = msg.GetString();
  690.  
  691. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseOpenPriv()");
  692. if(player->isRemoved()){
  693. return;
  694. }
  695.  
  696. Player* playerPriv = game->getPlayerByName(receiver);
  697. if(playerPriv){
  698. sendOpenPriv(playerPriv->getName());
  699. }
  700. }
  701.  
  702. void Protocol78::parseCancelMove(NetworkMessage& msg)
  703. {
  704. game->playerSetAttackedCreature(player, 0);
  705. game->playerFollowCreature(player, 0);
  706. }
  707.  
  708. void Protocol78::parseDebug(NetworkMessage& msg)
  709. {
  710. int dataLength = msg.getMessageLength() - 3;
  711. if(dataLength != 0){
  712. printf("data: ");
  713. size_t data = msg.GetByte();
  714. while(dataLength > 0){
  715. printf("%d ", data);
  716. if(--dataLength > 0)
  717. data = msg.GetByte();
  718. }
  719. printf("\n");
  720. }
  721. }
  722.  
  723.  
  724. void Protocol78::parseReceivePing(NetworkMessage& msg)
  725. {
  726. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseReceivePing()");
  727. if(player->isRemoved()){
  728. return;
  729. }
  730.  
  731. player->receivePing();
  732. }
  733.  
  734. void Protocol78::parseAutoWalk(NetworkMessage& msg)
  735. {
  736. // first we get all directions...
  737. std::list<Direction> path;
  738. size_t numdirs = msg.GetByte();
  739. for (size_t i = 0; i < numdirs; ++i) {
  740. unsigned char rawdir = msg.GetByte();
  741. Direction dir = SOUTH;
  742.  
  743. switch(rawdir) {
  744. case 1: dir = EAST; break;
  745. case 2: dir = NORTHEAST; break;
  746. case 3: dir = NORTH; break;
  747. case 4: dir = NORTHWEST; break;
  748. case 5: dir = WEST; break;
  749. case 6: dir = SOUTHWEST; break;
  750. case 7: dir = SOUTH; break;
  751. case 8: dir = SOUTHEAST; break;
  752.  
  753. default:
  754. continue;
  755. };
  756.  
  757. /*
  758. #ifdef __DEBUG__
  759. std::cout << "Walk by mouse: Direction: " << dir << std::endl;
  760. #endif
  761. */
  762.  
  763. path.push_back(dir);
  764. }
  765.  
  766. game->playerAutoWalk(player, path);
  767. }
  768.  
  769. void Protocol78::parseStopAutoWalk(NetworkMessage& msg)
  770. {
  771. game->playerStopAutoWalk(player);
  772. }
  773.  
  774. void Protocol78::parseMoveNorth(NetworkMessage& msg)
  775. {
  776. sleepTillMove();
  777.  
  778. game->movePlayer(player, NORTH);
  779. }
  780.  
  781. void Protocol78::parseMoveEast(NetworkMessage& msg)
  782. {
  783. sleepTillMove();
  784.  
  785. game->movePlayer(player, EAST);
  786. }
  787.  
  788. void Protocol78::parseMoveSouth(NetworkMessage& msg)
  789. {
  790. sleepTillMove();
  791.  
  792. game->movePlayer(player, SOUTH);
  793. }
  794.  
  795. void Protocol78::parseMoveWest(NetworkMessage& msg)
  796. {
  797. sleepTillMove();
  798.  
  799. game->movePlayer(player, WEST);
  800. }
  801.  
  802. void Protocol78::parseMoveNorthEast(NetworkMessage& msg)
  803. {
  804. sleepTillMove();
  805. sleepTillMove();
  806.  
  807. game->movePlayer(player, NORTHEAST);
  808. }
  809.  
  810. void Protocol78::parseMoveSouthEast(NetworkMessage& msg)
  811. {
  812. sleepTillMove();
  813. sleepTillMove();
  814.  
  815. game->movePlayer(player, SOUTHEAST);
  816. }
  817.  
  818. void Protocol78::parseMoveSouthWest(NetworkMessage& msg)
  819. {
  820. sleepTillMove();
  821. sleepTillMove();
  822.  
  823. game->movePlayer(player, SOUTHWEST);
  824. }
  825.  
  826. void Protocol78::parseMoveNorthWest(NetworkMessage& msg)
  827. {
  828. sleepTillMove();
  829. sleepTillMove();
  830.  
  831. game->movePlayer(player, NORTHWEST);
  832. }
  833.  
  834. void Protocol78::parseTurnNorth(NetworkMessage& msg)
  835. {
  836. game->playerTurn(player, NORTH);
  837. }
  838.  
  839. void Protocol78::parseTurnEast(NetworkMessage& msg)
  840. {
  841. game->playerTurn(player, EAST);
  842. }
  843.  
  844. void Protocol78::parseTurnSouth(NetworkMessage& msg)
  845. {
  846. game->playerTurn(player, SOUTH);
  847. }
  848.  
  849. void Protocol78::parseTurnWest(NetworkMessage& msg)
  850. {
  851. game->playerTurn(player, WEST);
  852. }
  853.  
  854. void Protocol78::parseRequestOutfit(NetworkMessage& msg)
  855. {
  856. msg.Reset();
  857.  
  858. msg.AddByte(0xC8);
  859. msg.AddU16(player->looktype);
  860. msg.AddByte(player->lookhead); //head
  861. msg.AddByte(player->lookbody); //primary
  862. msg.AddByte(player->looklegs); //secondary
  863. msg.AddByte(player->lookfeet); //detail
  864. msg.AddByte(0); //addons
  865.  
  866. int first_outfit, last_outfit;
  867. switch (player->getSex()){
  868. case PLAYERSEX_FEMALE:
  869. first_outfit = PLAYER_FEMALE_1;
  870. last_outfit = PLAYER_FEMALE_7;
  871. break;
  872. case PLAYERSEX_MALE:
  873. first_outfit = PLAYER_MALE_1;
  874. last_outfit = PLAYER_MALE_7;
  875. break;
  876. default:
  877. first_outfit = PLAYER_MALE_1;
  878. last_outfit = PLAYER_MALE_7;
  879. break;
  880. }
  881. msg.AddByte(last_outfit - first_outfit + 1); //number of outfits
  882.  
  883. for(int i = first_outfit; i <= last_outfit; ++i){
  884. msg.AddU16(i);
  885. msg.AddByte(0); //addons
  886. }
  887. WriteBuffer(msg);
  888. }
  889.  
  890. void Protocol78::parseSetOutfit(NetworkMessage& msg)
  891. {
  892. int temp = msg.GetU16();
  893. if ( (player->getSex() == PLAYERSEX_FEMALE && temp >= PLAYER_FEMALE_1 && temp <= PLAYER_FEMALE_7) ||
  894. (player->getSex() == PLAYERSEX_MALE && temp >= PLAYER_MALE_1 && temp <= PLAYER_MALE_7))
  895. {
  896. player->looktype = temp;
  897. player->lookmaster = player->looktype;
  898. player->lookhead = msg.GetByte();
  899. player->lookbody = msg.GetByte();
  900. player->looklegs = msg.GetByte();
  901. player->lookfeet = msg.GetByte();
  902.  
  903. msg.GetByte(); //addons
  904.  
  905. game->playerChangeOutfit(player);
  906. }
  907. }
  908.  
  909. void Protocol78::parseUseItem(NetworkMessage& msg)
  910. {
  911. Position pos = msg.GetPosition();
  912. uint16_t itemId = msg.GetItemId();
  913. uint8_t stackpos = msg.GetByte();
  914. uint8_t index = msg.GetByte();
  915.  
  916. //std::cout << "parseUseItem: pos: " << pos << ", item: " << (int)itemId << ", stack: " << (int)stackpos << ", index: " << (int)index << std::endl;
  917.  
  918. game->playerUseItem(player, pos,stackpos, index, itemId);
  919. }
  920.  
  921. void Protocol78::parseUseItemEx(NetworkMessage& msg)
  922. {
  923. Position fromPos = msg.GetPosition();
  924. uint16_t fromItemId = msg.GetItemId();
  925. uint8_t fromStackpos = msg.GetByte();
  926. Position toPos = msg.GetPosition();
  927. uint16_t toItemId = msg.GetU16();
  928. uint8_t toStackpos = msg.GetByte();
  929.  
  930. //std::cout << "parseUseItemEx: fromPos: " << fromPos << ", item: " << (int)fromItemId << ", fromStack: " << (int)fromStackpos << ", toPos: " << toPos << ", toItemId: " << toItemId << ", toStack: " << (int)toStackpos << std::endl;
  931.  
  932. game->playerUseItemEx(player, fromPos, fromStackpos, fromItemId, toPos, toStackpos, toItemId);
  933. }
  934.  
  935. void Protocol78::parseBattleWindow(NetworkMessage &msg)
  936. {
  937. Position fromPos = msg.GetPosition();
  938. uint16_t itemId = msg.GetItemId();
  939. uint8_t fromStackPos = msg.GetByte();
  940. uint32_t creatureId = msg.GetU32();
  941.  
  942. //std::cout << "parseUseBattle: fromPos: " << fromPos << ", item: " << (int)itemId << ", fromStack: " << (int)fromStackPos << ", creature: " << creatureId << std::endl;
  943.  
  944. game->playerUseBattleWindow(player, fromPos, fromStackPos, creatureId, itemId);
  945. }
  946.  
  947. void Protocol78::parseCloseContainer(NetworkMessage& msg)
  948. {
  949. unsigned char containerid = msg.GetByte();
  950.  
  951. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseCloseContainer()");
  952. if(player->isRemoved()){
  953. return;
  954. }
  955.  
  956. player->closeContainer(containerid);
  957. sendCloseContainer(containerid);
  958. }
  959.  
  960. void Protocol78::parseUpArrowContainer(NetworkMessage& msg)
  961. {
  962. uint32_t cid = msg.GetByte();
  963. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseUpArrowContainer()");
  964. if(player->isRemoved()){
  965. return;
  966. }
  967.  
  968. Container* container = player->getContainer(cid);
  969. if(!container)
  970. return;
  971.  
  972. Container* parentcontainer = dynamic_cast<Container*>(container->getParent());
  973. if(parentcontainer){
  974. bool hasParent = (dynamic_cast<const Container*>(parentcontainer->getParent()) != NULL);
  975. player->addContainer(cid, parentcontainer);
  976. sendContainer(cid, parentcontainer, hasParent);
  977. }
  978. }
  979.  
  980. void Protocol78::parseUpdateContainer(NetworkMessage& msg)
  981. {
  982. uint32_t cid = msg.GetByte();
  983. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseUpdateContainer()");
  984. if(player->isRemoved()){
  985. return;
  986. }
  987.  
  988. Container* container = player->getContainer(cid);
  989. if(!container)
  990. return;
  991.  
  992. bool hasParent = (dynamic_cast<const Container*>(container->getParent()) != NULL);
  993. sendContainer(cid, container, hasParent);
  994. }
  995.  
  996. void Protocol78::parseThrow(NetworkMessage& msg)
  997. {
  998. Position fromPos = msg.GetPosition();
  999. uint16_t itemId = msg.GetItemId();
  1000. uint8_t fromStackpos = msg.GetByte();
  1001. Position toPos = msg.GetPosition();
  1002. uint8_t count = msg.GetByte();
  1003.  
  1004. /*
  1005. std::cout << "parseThrow: " << "from_x: " << (int)fromPos.x << ", from_y: " << (int)fromPos.y
  1006. << ", from_z: " << (int)fromPos.z << ", item: " << (int)itemId << ", fromStackpos: "
  1007. << (int)fromStackpos << " to_x: " << (int)toPos.x << ", to_y: " << (int)toPos.y
  1008. << ", to_z: " << (int)toPos.z
  1009. << ", count: " << (int)count << std::endl;
  1010. */
  1011.  
  1012. if(toPos == fromPos)
  1013. return;
  1014.  
  1015. game->thingMove(player, fromPos, itemId, fromStackpos, toPos, count);
  1016. }
  1017.  
  1018. void Protocol78::parseLookAt(NetworkMessage& msg)
  1019. {
  1020. Position pos = msg.GetPosition();
  1021. uint16_t itemId = msg.GetItemId();
  1022. uint8_t stackpos = msg.GetByte();
  1023.  
  1024. /*
  1025. #ifdef __DEBUG__
  1026. ss << "You look at x: " << x <<", y: " << y << ", z: " << z << " and see Item # " << itemId << ".";
  1027. #endif
  1028. */
  1029.  
  1030. game->playerLookAt(player, pos, itemId, stackpos);
  1031. }
  1032.  
  1033. void Protocol78::parseSay(NetworkMessage& msg)
  1034. {
  1035. SpeakClasses type = (SpeakClasses)msg.GetByte();
  1036.  
  1037. std::string receiver;
  1038. unsigned short channelId = 0;
  1039. if(type == SPEAK_PRIVATE ||
  1040. type == SPEAK_PRIVATE_RED)
  1041. receiver = msg.GetString();
  1042. if(type == SPEAK_CHANNEL_Y ||
  1043. type == SPEAK_CHANNEL_R1 ||
  1044. type == SPEAK_CHANNEL_R2)
  1045. channelId = msg.GetU16();
  1046. std::string text = msg.GetString();
  1047.  
  1048. if(game->playerSaySpell(player, text))
  1049. type = SPEAK_SAY;
  1050.  
  1051. switch (type)
  1052. {
  1053. case SPEAK_SAY:
  1054. game->playerSay(player, type, text);
  1055. break;
  1056. case SPEAK_WHISPER:
  1057. game->playerWhisper(player, text);
  1058. break;
  1059. case SPEAK_YELL:
  1060. game->playerYell(player, text);
  1061. break;
  1062. case SPEAK_PRIVATE:
  1063. case SPEAK_PRIVATE_RED:
  1064. game->playerSpeakTo(player, type, receiver, text);
  1065. break;
  1066. case SPEAK_CHANNEL_Y:
  1067. case SPEAK_CHANNEL_R1:
  1068. case SPEAK_CHANNEL_R2:
  1069. game->playerTalkToChannel(player, type, text, channelId);
  1070. break;
  1071. case SPEAK_BROADCAST:
  1072. game->playerBroadcastMessage(player, text);
  1073. break;
  1074. }
  1075. }
  1076.  
  1077. void Protocol78::parseFightModes(NetworkMessage& msg)
  1078. {
  1079. uint8_t fightMode = msg.GetByte(); //1 - offensive, 2 - balanced, 3 - defensive
  1080. uint8_t chaseMode = msg.GetByte(); // 0 - stand while fightning, 1 - chase opponent
  1081.  
  1082. game->playerSetFightModes(player, fightMode, chaseMode);
  1083. }
  1084.  
  1085. void Protocol78::parseAttack(NetworkMessage& msg)
  1086. {
  1087. unsigned long creatureid = msg.GetU32();
  1088. game->playerSetAttackedCreature(player, creatureid);
  1089. }
  1090.  
  1091. void Protocol78::parseFollow(NetworkMessage& msg)
  1092. {
  1093. unsigned long creatureId = msg.GetU32();
  1094. game->playerFollowCreature(player, creatureId);
  1095. }
  1096.  
  1097. void Protocol78::parseTextWindow(NetworkMessage& msg)
  1098. {
  1099. unsigned long id = msg.GetU32();
  1100. std::string new_text = msg.GetString();
  1101. if(new_text.length() > maxTextLength)
  1102. return;
  1103.  
  1104. if(readItem && windowTextID == id){
  1105. game->playerWriteItem(player, readItem, new_text);
  1106. readItem->releaseThing2();
  1107. readItem = NULL;
  1108. }
  1109. }
  1110.  
  1111. void Protocol78::parseHouseWindow(NetworkMessage &msg)
  1112. {
  1113. unsigned char _listid = msg.GetByte();
  1114. unsigned long id = msg.GetU32();
  1115. std::string new_list = msg.GetString();
  1116.  
  1117. OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "Protocol78::parseHouseWindow()");
  1118. if(player->isRemoved()){
  1119. return;
  1120. }
  1121.  
  1122. if(house && windowTextID == id && _listid == 0){
  1123. house->setAccessList(listId, new_list);
  1124. house = NULL;
  1125. listId = 0;
  1126. }
  1127. }
  1128.  
  1129. void Protocol78::parseRequestTrade(NetworkMessage& msg)
  1130. {
  1131. Position pos = msg.GetPosition();
  1132. uint16_t itemId = msg.GetItemId();
  1133. uint8_t stackpos = msg.GetByte();
  1134. uint32_t playerId = msg.GetU32();
  1135.  
  1136. game->playerRequestTrade(player, pos, stackpos, playerId, itemId);
  1137. }
  1138.  
  1139. void Protocol78::parseAcceptTrade(NetworkMessage& msg)
  1140. {
  1141. game->playerAcceptTrade(player);
  1142. }
  1143.  
  1144. void Protocol78::parseLookInTrade(NetworkMessage& msg)
  1145. {
  1146. bool counterOffer = (msg.GetByte() == 0x01);
  1147. int index = msg.GetByte();
  1148.  
  1149. game->playerLookInTrade(player, counterOffer, index);
  1150. }
  1151.  
  1152. void Protocol78::parseCloseTrade()
  1153. {
  1154. game->playerCloseTrade(player);
  1155. }
  1156.  
  1157. void Protocol78::parseAddVip(NetworkMessage& msg)
  1158. {
  1159. std::string vip_name = msg.GetString();
  1160. if(vip_name.size() > 32)
  1161. return;
  1162.  
  1163. game->playerRequestAddVip(player, vip_name);
  1164. }
  1165.  
  1166. void Protocol78::parseRemVip(NetworkMessage& msg)
  1167. {
  1168. unsigned long id = msg.GetU32();
  1169. player->removeVIP(id);
  1170. }
  1171.  
  1172. void Protocol78::parseRotateItem(NetworkMessage& msg)
  1173. {
  1174. Position pos = msg.GetPosition();
  1175. uint16_t itemId = msg.GetItemId();
  1176. uint8_t stackpos = msg.GetByte();
  1177.  
  1178. game->playerRotateItem(player, pos, stackpos, itemId);
  1179. }
  1180.  
  1181. // Send methods
  1182. void Protocol78::sendOpenPriv(const std::string& receiver)
  1183. {
  1184. NetworkMessage newmsg;
  1185. newmsg.AddByte(0xAD);
  1186. newmsg.AddString(receiver);
  1187. WriteBuffer(newmsg);
  1188. }
  1189.  
  1190. void Protocol78::sendSetOutfit(const Creature* creature)
  1191. {
  1192. if(CanSee(creature)){
  1193. NetworkMessage newmsg;
  1194. newmsg.AddByte(0x8E);
  1195. newmsg.AddU32(creature->getID());
  1196. newmsg.AddU16(creature->looktype);
  1197. newmsg.AddByte(creature->lookhead);
  1198. newmsg.AddByte(creature->lookbody);
  1199. newmsg.AddByte(creature->looklegs);
  1200. newmsg.AddByte(creature->lookfeet);
  1201.  
  1202. newmsg.AddByte(0); //addons
  1203.  
  1204. WriteBuffer(newmsg);
  1205. }
  1206. }
  1207.  
  1208. void Protocol78::sendCreatureLight(const Creature* creature)
  1209. {
  1210. if(CanSee(creature)){
  1211. NetworkMessage msg;
  1212. AddCreatureLight(msg, creature);
  1213. WriteBuffer(msg);
  1214. }
  1215. }
  1216.  
  1217. void Protocol78::sendWorldLight(const LightInfo& lightInfo)
  1218. {
  1219. NetworkMessage msg;
  1220. AddWorldLight(msg, lightInfo);
  1221. WriteBuffer(msg);
  1222. }
  1223.  
  1224. void Protocol78::sendCreatureSkull(const Creature* creature)
  1225. {
  1226. if(CanSee(creature)){
  1227. NetworkMessage msg;
  1228. msg.AddByte(0x90);
  1229. msg.AddU32(creature->getID());
  1230. #ifdef __SKULLSYSTEM__
  1231. if(const Player* playerSkull = creature->getPlayer()){
  1232. msg.AddByte(player->getSkullClient(playerSkull));
  1233. }
  1234. else{
  1235. msg.AddByte(0); //no skull
  1236. }
  1237. #else
  1238. msg.AddByte(0); //no skull
  1239. #endif
  1240.  
  1241. WriteBuffer(msg);
  1242. }
  1243. }
  1244.  
  1245. void Protocol78::sendCreatureShield(const Creature* creature)
  1246. {
  1247. if(CanSee(creature)){
  1248. NetworkMessage msg;
  1249. msg.AddByte(0x91);
  1250. msg.AddU32(creature->getID());
  1251. msg.AddByte(0); //no shield
  1252. WriteBuffer(msg);
  1253. }
  1254. }
  1255.  
  1256. void Protocol78::sendCreatureSquare(const Creature* creature, SquareColor color)
  1257. {
  1258. if(CanSee(creature)){
  1259. NetworkMessage msg;
  1260. msg.AddByte(0x86);
  1261. msg.AddU32(creature->getID());
  1262. msg.AddByte((unsigned char)color);
  1263. WriteBuffer(msg);
  1264. }
  1265. }
  1266.  
  1267. void Protocol78::sendStats()
  1268. {
  1269. NetworkMessage msg;
  1270. AddPlayerStats(msg);
  1271. WriteBuffer(msg);
  1272. }
  1273.  
  1274. void Protocol78::sendTextMessage(MessageClasses mclass, const char* message)
  1275. {
  1276. NetworkMessage msg;
  1277. AddTextMessage(msg,mclass, message);
  1278. WriteBuffer(msg);
  1279. }
  1280.  
  1281. void Protocol78::sendTextMessage(MessageClasses mclass, const char* message,
  1282. const Position &pos, unsigned char type)
  1283. {
  1284. NetworkMessage msg;
  1285. AddMagicEffect(msg,pos,type);
  1286. AddTextMessage(msg,mclass, message);
  1287. WriteBuffer(msg);
  1288. }
  1289.  
  1290. void Protocol78::sendClosePrivate(unsigned short channelId)
  1291. {
  1292. NetworkMessage msg;
  1293.  
  1294. msg.AddByte(0xB3);
  1295. msg.AddU16(channelId);
  1296.  
  1297. WriteBuffer(msg);
  1298. }
  1299.  
  1300. void Protocol78::sendChannelsDialog()
  1301. {
  1302. NetworkMessage newmsg;
  1303. ChannelList list;
  1304.  
  1305. list = g_chat.getChannelList(player);
  1306.  
  1307. newmsg.AddByte(0xAB);
  1308.  
  1309. newmsg.AddByte(list.size()); //how many
  1310.  
  1311. while(list.size()){
  1312. ChatChannel *channel;
  1313. channel = list.front();
  1314. list.pop_front();
  1315.  
  1316. newmsg.AddU16(channel->getId());
  1317. newmsg.AddString(channel->getName());
  1318. }
  1319.  
  1320. WriteBuffer(newmsg);
  1321. }
  1322.  
  1323. void Protocol78::sendChannel(unsigned short channelId, std::string channelName)
  1324. {
  1325. NetworkMessage newmsg;
  1326.  
  1327. newmsg.AddByte(0xAC);
  1328. newmsg.AddU16(channelId);
  1329. newmsg.AddString(channelName);
  1330.  
  1331. WriteBuffer(newmsg);
  1332. }
  1333.  
  1334. void Protocol78::sendIcons(int icons)
  1335. {
  1336. NetworkMessage newmsg;
  1337. newmsg.AddByte(0xA2);
  1338. newmsg.AddU16(icons);
  1339. WriteBuffer(newmsg);
  1340. }
  1341.  
  1342. void Protocol78::sendContainer(uint32_t cid, const Container* container, bool hasParent)
  1343. {
  1344. NetworkMessage msg;
  1345.  
  1346. msg.AddByte(0x6E);
  1347. msg.AddByte(cid);
  1348.  
  1349. msg.AddItemId(container);
  1350. msg.AddString(container->getName());
  1351. msg.AddByte(container->capacity());
  1352. msg.AddByte(hasParent ? 0x01 : 0x00);
  1353. msg.AddByte(container->size());
  1354.  
  1355. ItemList::const_iterator cit;
  1356. for(cit = container->getItems(); cit != container->getEnd(); ++cit){
  1357. msg.AddItem(*cit);
  1358. }
  1359.  
  1360. WriteBuffer(msg);
  1361. }
  1362.  
  1363. void Protocol78::sendTradeItemRequest(const Player* player, const Item* item, bool ack)
  1364. {
  1365. NetworkMessage msg;
  1366. if(ack){
  1367. msg.AddByte(0x7D);
  1368. }
  1369. else{
  1370. msg.AddByte(0x7E);
  1371. }
  1372.  
  1373. msg.AddString(player->getName());
  1374.  
  1375. if(const Container* tradeContainer = item->getContainer()){
  1376.  
  1377. std::list<const Container*> listContainer;
  1378. ItemList::const_iterator it;
  1379. Container* tmpContainer = NULL;
  1380.  
  1381. listContainer.push_back(tradeContainer);
  1382.  
  1383. std::list<const Item*> listItem;
  1384. listItem.push_back(tradeContainer);
  1385.  
  1386. while(listContainer.size() > 0) {
  1387. const Container* container = listContainer.front();
  1388. listContainer.pop_front();
  1389.  
  1390. for(it = container->getItems(); it != container->getEnd(); ++it){
  1391. if(tmpContainer = (*it)->getContainer()){
  1392. listContainer.push_back(tmpContainer);
  1393. }
  1394.  
  1395. listItem.push_back(*it);
  1396. }
  1397. }
  1398.  
  1399. msg.AddByte(listItem.size());
  1400. while(listItem.size() > 0) {
  1401. const Item* item = listItem.front();
  1402. listItem.pop_front();
  1403. msg.AddItem(item);
  1404. }
  1405. }
  1406. else {
  1407. msg.AddByte(1);
  1408. msg.AddItem(item);
  1409. }
  1410.  
  1411. WriteBuffer(msg);
  1412. }
  1413.  
  1414. void Protocol78::sendCloseTrade()
  1415. {
  1416. NetworkMessage msg;
  1417. msg.AddByte(0x7F);
  1418.  
  1419. WriteBuffer(msg);
  1420. }
  1421.  
  1422. void Protocol78::sendCloseContainer(uint32_t cid)
  1423. {
  1424. NetworkMessage msg;
  1425.  
  1426. msg.AddByte(0x6F);
  1427. msg.AddByte(cid);
  1428. WriteBuffer(msg);
  1429. }
  1430.  
  1431. void Protocol78::sendCreatureTurn(const Creature* creature, unsigned char stackPos)
  1432. {
  1433. if(CanSee(creature)){
  1434. NetworkMessage msg;
  1435.  
  1436. msg.AddByte(0x6B);
  1437. msg.AddPosition(creature->getPosition());
  1438. msg.AddByte(stackPos);
  1439.  
  1440. msg.AddU16(0x63);
  1441. msg.AddU32(creature->getID());
  1442. msg.AddByte(creature->getDirection());
  1443. WriteBuffer(msg);
  1444. }
  1445. }
  1446.  
  1447. void Protocol78::sendCreatureSay(const Creature *creature, SpeakClasses type, const std::string &text)
  1448. {
  1449. NetworkMessage msg;
  1450. AddCreatureSpeak(msg,creature, type, text, 0);
  1451. WriteBuffer(msg);
  1452. }
  1453.  
  1454. void Protocol78::sendToChannel(const Creature * creature, SpeakClasses type, const std::string &text, unsigned short channelId){
  1455. NetworkMessage msg;
  1456. AddCreatureSpeak(msg,creature, type, text, channelId);
  1457. WriteBuffer(msg);
  1458. }
  1459.  
  1460. void Protocol78::sendCancel(const char *msg)
  1461. {
  1462. NetworkMessage netmsg;
  1463. AddTextMessage(netmsg, MSG_STATUS_SMALL, msg);
  1464. WriteBuffer(netmsg);
  1465. }
  1466.  
  1467. void Protocol78::sendCancelTarget()
  1468. {
  1469. NetworkMessage netmsg;
  1470. netmsg.AddByte(0xa3);
  1471. WriteBuffer(netmsg);
  1472. }
  1473.  
  1474. void Protocol78::sendChangeSpeed(const Creature *creature)
  1475. {
  1476. NetworkMessage netmsg;
  1477. netmsg.AddByte(0x8F);
  1478.  
  1479. netmsg.AddU32(creature->getID());
  1480. netmsg.AddU16(creature->getSpeed());
  1481. WriteBuffer(netmsg);
  1482. }
  1483.  
  1484. void Protocol78::sendCancelWalk()
  1485. {
  1486. NetworkMessage netmsg;
  1487. netmsg.AddByte(0xB5);
  1488. netmsg.AddByte(player->getDirection()); // direction
  1489. WriteBuffer(netmsg);
  1490. }
  1491.  
  1492. void Protocol78::sendSkills()
  1493. {
  1494. NetworkMessage msg;
  1495. AddPlayerSkills(msg);
  1496. WriteBuffer(msg);
  1497. }
  1498.  
  1499. void Protocol78::sendPing()
  1500. {
  1501. NetworkMessage msg;
  1502. msg.AddByte(0x1E);
  1503. WriteBuffer(msg);
  1504. }
  1505.  
  1506. void Protocol78::sendDistanceShoot(const Position &from, const Position &to, unsigned char type)
  1507. {
  1508. NetworkMessage msg;
  1509. AddDistanceShoot(msg,from, to,type );
  1510. WriteBuffer(msg);
  1511. }
  1512.  
  1513. void Protocol78::sendMagicEffect(const Position &pos, unsigned char type)
  1514. {
  1515. NetworkMessage msg;
  1516. AddMagicEffect(msg, pos, type);
  1517. WriteBuffer(msg);
  1518. }
  1519.  
  1520. void Protocol78::sendAnimatedText(const Position &pos, unsigned char color, std::string text)
  1521. {
  1522. NetworkMessage msg;
  1523. AddAnimatedText(msg, pos, color, text);
  1524. WriteBuffer(msg);
  1525. }
  1526.  
  1527. void Protocol78::sendCreatureHealth(const Creature *creature)
  1528. {
  1529. NetworkMessage msg;
  1530. AddCreatureHealth(msg,creature);
  1531. WriteBuffer(msg);
  1532. }
  1533.  
  1534. //tile
  1535. void Protocol78::sendAddTileItem(const Position& pos, const Item* item)
  1536. {
  1537. if(CanSee(pos)){
  1538. NetworkMessage msg;
  1539. AddTileItem(msg, pos, item);
  1540. WriteBuffer(msg);
  1541. }
  1542. }
  1543.  
  1544. void Protocol78::sendUpdateTileItem(const Position& pos, uint32_t stackpos, const Item* item)
  1545. {
  1546. if(CanSee(pos)){
  1547. NetworkMessage msg;
  1548. UpdateTileItem(msg, pos, stackpos, item);
  1549. WriteBuffer(msg);
  1550. }
  1551. }
  1552.  
  1553. void Protocol78::sendRemoveTileItem(const Position& pos, uint32_t stackpos)
  1554. {
  1555. if(CanSee(pos)){
  1556. NetworkMessage msg;
  1557. RemoveTileItem(msg, pos, stackpos);
  1558. WriteBuffer(msg);
  1559. }
  1560. }
  1561.  
  1562. void Protocol78::UpdateTile(const Position& pos)
  1563. {
  1564. if(CanSee(pos)){
  1565. NetworkMessage msg;
  1566. UpdateTile(msg, pos);
  1567. WriteBuffer(msg);
  1568. }
  1569. }
  1570.  
  1571. void Protocol78::sendAddCreature(const Creature* creature, bool isLogin)
  1572. {
  1573. if(CanSee(creature->getPosition())){
  1574. NetworkMessage msg;
  1575.  
  1576. if(creature == player){
  1577. msg.AddByte(0x0A);
  1578. msg.AddU32(player->getID());
  1579.  
  1580. msg.AddByte(0x32);
  1581. msg.AddByte(0x00);
  1582.  
  1583. msg.AddByte(0x00); //can report bugs 0,1
  1584.  
  1585. //msg.AddByte(0x0B);//TODO?. GM actions
  1586. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1587. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1588. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1589. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1590. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1591. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1592. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1593. //msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);msg.AddByte(0xFF);
  1594.  
  1595. AddMapDescription(msg, player->getPosition());
  1596.  
  1597. if(isLogin){
  1598. AddMagicEffect(msg, player->getPosition(), NM_ME_ENERGY_AREA);
  1599. }
  1600.  
  1601. AddInventoryItem(msg, SLOT_HEAD, player->getInventoryItem(SLOT_HEAD));
  1602. AddInventoryItem(msg, SLOT_NECKLACE, player->getInventoryItem(SLOT_NECKLACE));
  1603. AddInventoryItem(msg, SLOT_BACKPACK, player->getInventoryItem(SLOT_BACKPACK));
  1604. AddInventoryItem(msg, SLOT_ARMOR, player->getInventoryItem(SLOT_ARMOR));
  1605. AddInventoryItem(msg, SLOT_RIGHT, player->getInventoryItem(SLOT_RIGHT));
  1606. AddInventoryItem(msg, SLOT_LEFT, player->getInventoryItem(SLOT_LEFT));
  1607. AddInventoryItem(msg, SLOT_LEGS, player->getInventoryItem(SLOT_LEGS));
  1608. AddInventoryItem(msg, SLOT_FEET, player->getInventoryItem(SLOT_FEET));
  1609. AddInventoryItem(msg, SLOT_RING, player->getInventoryItem(SLOT_RING));
  1610. AddInventoryItem(msg, SLOT_AMMO, player->getInventoryItem(SLOT_AMMO));
  1611.  
  1612. AddPlayerStats(msg);
  1613. AddPlayerSkills(msg);
  1614.  
  1615. //gameworld light-settings
  1616. LightInfo lightInfo;
  1617. game->getWorldLightInfo(lightInfo);
  1618. AddWorldLight(msg, lightInfo);
  1619.  
  1620. //player light level
  1621. AddCreatureLight(msg, creature);
  1622.  
  1623. std::string tempstring = g_config.getString(ConfigManager::LOGIN_MSG);
  1624. if(tempstring.size() > 0){
  1625. AddTextMessage(msg, MSG_STATUS_DEFAULT, tempstring.c_str());
  1626. }
  1627.  
  1628. tempstring = "Your last visit was on ";
  1629. time_t lastlogin = player->getLastLoginSaved();
  1630. tempstring += ctime(&lastlogin);
  1631. tempstring.erase(tempstring.length() -1);
  1632. tempstring += ".";
  1633. AddTextMessage(msg, MSG_STATUS_DEFAULT, tempstring.c_str());
  1634. WriteBuffer(msg);
  1635.  
  1636. for(VIPListSet::iterator it = player->VIPList.begin(); it != player->VIPList.end(); it++){
  1637. bool online;
  1638. std::string vip_name;
  1639. if(IOPlayer::instance()->getNameByGuid((*it), vip_name)){
  1640. online = (game->getPlayerByName(vip_name) != NULL);
  1641. sendVIP((*it), vip_name, online);
  1642. }
  1643. }
  1644.  
  1645. //force flush
  1646. flushOutputBuffer();
  1647. }
  1648. else{
  1649. AddTileCreature(msg, creature->getPosition(), creature);
  1650.  
  1651. if(isLogin){
  1652. AddMagicEffect(msg, creature->getPosition(), NM_ME_ENERGY_AREA);
  1653. }
  1654.  
  1655. WriteBuffer(msg);
  1656. }
  1657. }
  1658. }
  1659.  
  1660. void Protocol78::sendRemoveCreature(const Creature* creature, const Position& pos, uint32_t stackpos, bool isLogout)
  1661. {
  1662. if(CanSee(pos)){
  1663. NetworkMessage msg;
  1664. RemoveTileItem(msg, pos, stackpos);
  1665.  
  1666. if(isLogout){
  1667. AddMagicEffect(msg, pos, NM_ME_PUFF);
  1668. }
  1669.  
  1670. WriteBuffer(msg);
  1671. }
  1672. }
  1673.  
  1674. void Protocol78::sendMoveCreature(const Creature* creature, const Position& oldPos, uint32_t oldStackPos, bool teleport)
  1675. {
  1676. const Position& newPos = creature->getPosition();
  1677.  
  1678. if(creature == player){
  1679. NetworkMessage msg;
  1680.  
  1681. if(teleport){
  1682. RemoveTileItem(msg, oldPos, oldStackPos);
  1683. AddMapDescription(msg, player->getPosition());
  1684. }
  1685. else{
  1686. if(oldPos.z == 7 && newPos.z >= 8){
  1687. RemoveTileItem(msg, oldPos, oldStackPos);
  1688. }
  1689. else{
  1690. if(oldStackPos < 10){
  1691. msg.AddByte(0x6D);
  1692. msg.AddPosition(oldPos);
  1693. msg.AddByte(oldStackPos);
  1694. msg.AddPosition(creature->getPosition());
  1695. }
  1696. }
  1697.  
  1698. //floor change down
  1699. if(newPos.z > oldPos.z){
  1700. MoveDownCreature(msg, creature, newPos, oldPos, oldStackPos);
  1701. }
  1702. //floor change up
  1703. else if(newPos.z < oldPos.z){
  1704. MoveUpCreature(msg, creature, newPos, oldPos, oldStackPos);
  1705. }
  1706.  
  1707. if(oldPos.y > newPos.y){ // north, for old x
  1708. msg.AddByte(0x65);
  1709. GetMapDescription(oldPos.x - 8, newPos.y - 6, newPos.z, 18, 1, msg);
  1710. }
  1711. else if(oldPos.y < newPos.y){ // south, for old x
  1712. msg.AddByte(0x67);
  1713. GetMapDescription(oldPos.x - 8, newPos.y + 7, newPos.z, 18, 1, msg);
  1714. }
  1715.  
  1716. if(oldPos.x < newPos.x){ // east, [with new y]
  1717. msg.AddByte(0x66);
  1718. GetMapDescription(newPos.x + 9, newPos.y - 6, newPos.z, 1, 14, msg);
  1719. }
  1720. else if(oldPos.x > newPos.x){ // west, [with new y]
  1721. msg.AddByte(0x68);
  1722. GetMapDescription(newPos.x - 8, newPos.y - 6, newPos.z, 1, 14, msg);
  1723. }
  1724. }
  1725.  
  1726. WriteBuffer(msg);
  1727. }
  1728. else if(CanSee(oldPos) && CanSee(creature->getPosition())){
  1729. if(teleport || (oldPos.z == 7 && newPos.z >= 8)){
  1730. sendRemoveCreature(creature, oldPos, oldStackPos, false);
  1731. sendAddCreature(creature, false);
  1732. }
  1733. else{
  1734. if(oldStackPos < 10){
  1735. NetworkMessage msg;
  1736.  
  1737. msg.AddByte(0x6D);
  1738. msg.AddPosition(oldPos);
  1739. msg.AddByte(oldStackPos);
  1740. msg.AddPosition(creature->getPosition());
  1741. WriteBuffer(msg);
  1742. }
  1743. }
  1744. }
  1745. else if(CanSee(oldPos)){
  1746. sendRemoveCreature(creature, oldPos, oldStackPos, false);
  1747. }
  1748. else if(CanSee(creature->getPosition())){
  1749. sendAddCreature(creature, false);
  1750. }
  1751. }
  1752.  
  1753. //inventory
  1754. void Protocol78::sendAddInventoryItem(slots_t slot, const Item* item)
  1755. {
  1756. NetworkMessage msg;
  1757. AddInventoryItem(msg, slot, item);
  1758. WriteBuffer(msg);
  1759. }
  1760.  
  1761. void Protocol78::sendUpdateInventoryItem(slots_t slot, const Item* item)
  1762. {
  1763. NetworkMessage msg;
  1764. UpdateInventoryItem(msg, slot, item);
  1765. WriteBuffer(msg);
  1766. }
  1767.  
  1768. void Protocol78::sendRemoveInventoryItem(slots_t slot)
  1769. {
  1770. NetworkMessage msg;
  1771. RemoveInventoryItem(msg, slot);
  1772. WriteBuffer(msg);
  1773. }
  1774.  
  1775. //containers
  1776. void Protocol78::sendAddContainerItem(uint8_t cid, const Item* item)
  1777. {
  1778. NetworkMessage msg;
  1779. AddContainerItem(msg, cid, item);
  1780. WriteBuffer(msg);
  1781. }
  1782.  
  1783. void Protocol78::sendUpdateContainerItem(uint8_t cid, uint8_t slot, const Item* item)
  1784. {
  1785. NetworkMessage msg;
  1786. UpdateContainerItem(msg, cid, slot, item);
  1787. WriteBuffer(msg);
  1788. }
  1789.  
  1790. void Protocol78::sendRemoveContainerItem(uint8_t cid, uint8_t slot)
  1791. {
  1792. NetworkMessage msg;
  1793. RemoveContainerItem(msg, cid, slot);
  1794. WriteBuffer(msg);
  1795. }
  1796.  
  1797. void Protocol78::sendTextWindow(Item* item,const unsigned short maxlen, const bool canWrite)
  1798. {
  1799. NetworkMessage msg;
  1800. if(readItem){
  1801. readItem->releaseThing2();
  1802. }
  1803. windowTextID++;
  1804. msg.AddByte(0x96);
  1805. msg.AddU32(windowTextID);
  1806. msg.AddItemId(item);
  1807. if(canWrite){
  1808. msg.AddU16(maxlen);
  1809. msg.AddString(item->getText());
  1810. item->useThing2();
  1811. readItem = item;
  1812. maxTextLength = maxlen;
  1813. }
  1814. else{
  1815. msg.AddU16(item->getText().size());
  1816. msg.AddString(item->getText());
  1817. readItem = NULL;
  1818. maxTextLength = 0;
  1819. }
  1820. msg.AddString("unknown");
  1821. WriteBuffer(msg);
  1822. }
  1823.  
  1824. void Protocol78::sendHouseWindow(House* _house, unsigned long _listid, const std::string& text)
  1825. {
  1826. NetworkMessage msg;
  1827. windowTextID++;
  1828. house = _house;
  1829. listId = _listid;
  1830. msg.AddByte(0x97);
  1831. msg.AddByte(0);
  1832. msg.AddU32(windowTextID);
  1833. msg.AddString(text);
  1834. WriteBuffer(msg);
  1835. }
  1836.  
  1837. void Protocol78::sendVIPLogIn(unsigned long guid)
  1838. {
  1839. NetworkMessage msg;
  1840. msg.AddByte(0xD3);
  1841. msg.AddU32(guid);
  1842. WriteBuffer(msg);
  1843. }
  1844.  
  1845. void Protocol78::sendVIPLogOut(unsigned long guid)
  1846. {
  1847. NetworkMessage msg;
  1848. msg.AddByte(0xD4);
  1849. msg.AddU32(guid);
  1850. WriteBuffer(msg);
  1851. }
  1852.  
  1853. void Protocol78::sendVIP(unsigned long guid, const std::string &name, bool isOnline)
  1854. {
  1855. NetworkMessage msg;
  1856. msg.AddByte(0xD2);
  1857. msg.AddU32(guid);
  1858. msg.AddString(name);
  1859. msg.AddByte(isOnline == true ? 1 : 0);
  1860. WriteBuffer(msg);
  1861. }
  1862.  
  1863. ////////////// Add common messages
  1864. void Protocol78::AddMapDescription(NetworkMessage& msg, const Position& pos)
  1865. {
  1866. msg.AddByte(0x64);
  1867. msg.AddPosition(player->getPosition());
  1868. GetMapDescription(pos.x - 8, pos.y - 6, pos.z, 18, 14, msg);
  1869. }
  1870.  
  1871. void Protocol78::AddTextMessage(NetworkMessage &msg,MessageClasses mclass, const char* message)
  1872. {
  1873. msg.AddByte(0xB4);
  1874. msg.AddByte(mclass);
  1875. msg.AddString(message);
  1876. }
  1877.  
  1878. void Protocol78::AddAnimatedText(NetworkMessage &msg,const Position &pos, unsigned char color, std::string text)
  1879. {
  1880. #ifdef __DEBUG__
  1881. if(text.length() == 0) {
  1882. std::cout << "Warning: 0-Length string in AddAnimatedText()" << std::endl;
  1883. }
  1884. #endif
  1885.  
  1886. msg.AddByte(0x84);
  1887. msg.AddPosition(pos);
  1888. msg.AddByte(color);
  1889. msg.AddString(text);
  1890. }
  1891.  
  1892. void Protocol78::AddMagicEffect(NetworkMessage &msg,const Position &pos, unsigned char type)
  1893. {
  1894. msg.AddByte(0x83);
  1895. msg.AddPosition(pos);
  1896. msg.AddByte(type + 1);
  1897. }
  1898.  
  1899.  
  1900. void Protocol78::AddDistanceShoot(NetworkMessage &msg,const Position &from, const Position &to, unsigned char type)
  1901. {
  1902. msg.AddByte(0x85);
  1903. msg.AddPosition(from);
  1904. msg.AddPosition(to);
  1905. msg.AddByte(type + 1);
  1906. }
  1907.  
  1908. void Protocol78::AddCreature(NetworkMessage &msg,const Creature *creature, bool known, unsigned int remove)
  1909. {
  1910. if(known){
  1911. msg.AddU16(0x62);
  1912. msg.AddU32(creature->getID());
  1913. }
  1914. else{
  1915. msg.AddU16(0x61);
  1916. msg.AddU32(remove);
  1917. msg.AddU32(creature->getID());
  1918. msg.AddString(creature->getName());
  1919. }
  1920.  
  1921. msg.AddByte(std::max(1, creature->health*100/std::max(creature->healthmax,1)));
  1922.  
  1923. msg.AddByte((unsigned char)creature->getDirection());
  1924.  
  1925. msg.AddU16(creature->looktype);
  1926.  
  1927. msg.AddByte(creature->lookhead);
  1928. msg.AddByte(creature->lookbody);
  1929. msg.AddByte(creature->looklegs);
  1930. msg.AddByte(creature->lookfeet);
  1931. msg.AddByte(0); //addons
  1932.  
  1933. LightInfo lightInfo;
  1934. creature->getCreatureLight(lightInfo);
  1935. msg.AddByte(lightInfo.level);
  1936. msg.AddByte(lightInfo.color);
  1937.  
  1938. msg.AddU16(creature->getSpeed());
  1939.  
  1940. #ifdef __SKULLSYSTEM__
  1941. if(const Player* playerSkull = creature->getPlayer()){
  1942. msg.AddByte(player->getSkullClient(playerSkull));
  1943. }
  1944. else{
  1945. msg.AddByte(0); //no skull
  1946. }
  1947. #else
  1948. msg.AddByte(0); //no skull
  1949. #endif
  1950. msg.AddByte(0x00); // shield
  1951. }
  1952.  
  1953.  
  1954. void Protocol78::AddPlayerStats(NetworkMessage &msg)
  1955. {
  1956. msg.AddByte(0xA0);
  1957. msg.AddU16(player->getHealth());
  1958. msg.AddU16(player->getPlayerInfo(PLAYERINFO_MAXHEALTH));
  1959. msg.AddU16((unsigned short)std::floor(player->getFreeCapacity()));
  1960. msg.AddU32(player->getExperience());
  1961. msg.AddU16(player->getPlayerInfo(PLAYERINFO_LEVEL));
  1962. msg.AddByte(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT));
  1963. msg.AddU16(player->getMana());
  1964. msg.AddU16(player->getPlayerInfo(PLAYERINFO_MAXMANA));
  1965. msg.AddByte(player->getMagicLevel());
  1966. msg.AddByte(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT));
  1967. msg.AddByte(player->getPlayerInfo(PLAYERINFO_SOUL));
  1968. msg.AddU16(1440); //stamina(minutes)
  1969. }
  1970.  
  1971. void Protocol78::AddPlayerSkills(NetworkMessage& msg)
  1972. {
  1973. msg.AddByte(0xA1);
  1974.  
  1975. msg.AddByte(player->getSkill(SKILL_FIST, SKILL_LEVEL));
  1976. msg.AddByte(player->getSkill(SKILL_FIST, SKILL_PERCENT));
  1977. msg.AddByte(player->getSkill(SKILL_CLUB, SKILL_LEVEL));
  1978. msg.AddByte(player->getSkill(SKILL_CLUB, SKILL_PERCENT));
  1979. msg.AddByte(player->getSkill(SKILL_SWORD, SKILL_LEVEL));
  1980. msg.AddByte(player->getSkill(SKILL_SWORD, SKILL_PERCENT));
  1981. msg.AddByte(player->getSkill(SKILL_AXE, SKILL_LEVEL));
  1982. msg.AddByte(player->getSkill(SKILL_AXE, SKILL_PERCENT));
  1983. msg.AddByte(player->getSkill(SKILL_DIST, SKILL_LEVEL));
  1984. msg.AddByte(player->getSkill(SKILL_DIST, SKILL_PERCENT));
  1985. msg.AddByte(player->getSkill(SKILL_SHIELD, SKILL_LEVEL));
  1986. msg.AddByte(player->getSkill(SKILL_SHIELD, SKILL_PERCENT));
  1987. msg.AddByte(player->getSkill(SKILL_FISH, SKILL_LEVEL));
  1988. msg.AddByte(player->getSkill(SKILL_FISH, SKILL_PERCENT));
  1989. }
  1990.  
  1991. void Protocol78::AddCreatureSpeak(NetworkMessage &msg,const Creature *creature, SpeakClasses type, std::string text, unsigned short channelId)
  1992. {
  1993. msg.AddByte(0xAA);
  1994. msg.AddU32(0);
  1995. msg.AddString(creature->getName());
  1996. if(const Player* player = creature->getPlayer()){
  1997. msg.AddU16(player->getPlayerInfo(PLAYERINFO_LEVEL));
  1998. }
  1999. else{
  2000. msg.AddU16(0);
  2001. }
  2002. msg.AddByte(type);
  2003. switch(type){
  2004. case SPEAK_SAY:
  2005. case SPEAK_WHISPER:
  2006. case SPEAK_YELL:
  2007. case SPEAK_MONSTER1:
  2008. case SPEAK_MONSTER2:
  2009. msg.AddPosition(creature->getPosition());
  2010. break;
  2011. case SPEAK_CHANNEL_Y:
  2012. case SPEAK_CHANNEL_R1:
  2013. case SPEAK_CHANNEL_R2:
  2014. case SPEAK_CHANNEL_O:
  2015. msg.AddU16(channelId);
  2016. break;
  2017. }
  2018. msg.AddString(text);
  2019. }
  2020.  
  2021. void Protocol78::AddCreatureHealth(NetworkMessage &msg,const Creature *creature)
  2022. {
  2023. msg.AddByte(0x8C);
  2024. msg.AddU32(creature->getID());
  2025. msg.AddByte(std::max(1, creature->health*100/std::max(creature->healthmax,1)));
  2026. }
  2027.  
  2028. void Protocol78::AddWorldLight(NetworkMessage &msg, const LightInfo& lightInfo)
  2029. {
  2030. msg.AddByte(0x82);
  2031. msg.AddByte(lightInfo.level);
  2032. msg.AddByte(lightInfo.color);
  2033. }
  2034.  
  2035. void Protocol78::AddCreatureLight(NetworkMessage &msg, const Creature* creature)
  2036. {
  2037. LightInfo lightInfo;
  2038. creature->getCreatureLight(lightInfo);
  2039. msg.AddByte(0x8D);
  2040. msg.AddU32(creature->getID());
  2041. msg.AddByte(lightInfo.level);
  2042. msg.AddByte(lightInfo.color);
  2043. }
  2044.  
  2045. //tile
  2046. void Protocol78::AddTileItem(NetworkMessage& msg, const Position& pos, const Item* item)
  2047. {
  2048. msg.AddByte(0x6A);
  2049. msg.AddPosition(pos);
  2050. msg.AddItem(item);
  2051. }
  2052.  
  2053. void Protocol78::AddTileCreature(NetworkMessage& msg, const Position& pos, const Creature* creature)
  2054. {
  2055. msg.AddByte(0x6A);
  2056. msg.AddPosition(pos);
  2057.  
  2058. bool known;
  2059. unsigned long removedKnown;
  2060. checkCreatureAsKnown(creature->getID(), known, removedKnown);
  2061. AddCreature(msg, creature, known, removedKnown);
  2062. }
  2063.  
  2064. void Protocol78::UpdateTileItem(NetworkMessage& msg, const Position& pos, uint32_t stackpos, const Item* item)
  2065. {
  2066. if(stackpos < 10){
  2067. msg.AddByte(0x6B);
  2068. msg.AddPosition(pos);
  2069. msg.AddByte(stackpos);
  2070. msg.AddItem(item);
  2071. }
  2072. }
  2073.  
  2074. void Protocol78::RemoveTileItem(NetworkMessage& msg, const Position& pos, uint32_t stackpos)
  2075. {
  2076. if(stackpos < 10){
  2077. msg.AddByte(0x6C);
  2078. msg.AddPosition(pos);
  2079. msg.AddByte(stackpos);
  2080. }
  2081. }
  2082.  
  2083. void Protocol78::UpdateTile(NetworkMessage& msg, const Position& pos)
  2084. {
  2085. msg.AddByte(0x69);
  2086. msg.AddPosition(pos);
  2087.  
  2088. Tile* tile = game->getTile(pos.x, pos.y, pos.z);
  2089. if(tile){
  2090. GetTileDescription(tile, msg);
  2091. msg.AddByte(0);
  2092. msg.AddByte(0xFF);
  2093. }
  2094. else{
  2095. msg.AddByte(0x01);
  2096. msg.AddByte(0xFF);
  2097. }
  2098. }
  2099.  
  2100. void Protocol78::MoveUpCreature(NetworkMessage& msg, const Creature* creature,
  2101. const Position& newPos, const Position& oldPos, uint32_t oldStackPos)
  2102. {
  2103. if(creature == player){
  2104. //floor change up
  2105. msg.AddByte(0xBE);
  2106.  
  2107. //going to surface
  2108. if(newPos.z == 7){
  2109. int skip = -1;
  2110. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 5, 18, 14, 3, skip); //(floor 7 and 6 already set)
  2111. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 4, 18, 14, 4, skip);
  2112. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 3, 18, 14, 5, skip);
  2113. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 2, 18, 14, 6, skip);
  2114. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 1, 18, 14, 7, skip);
  2115. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 0, 18, 14, 8, skip);
  2116.  
  2117. if(skip >= 0){
  2118. msg.AddByte(skip);
  2119. msg.AddByte(0xFF);
  2120. }
  2121. }
  2122. //underground, going one floor up (still underground)
  2123. else if(newPos.z > 7){
  2124. int skip = -1;
  2125. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, oldPos.z - 3, 18, 14, 3, skip);
  2126.  
  2127. if(skip >= 0){
  2128. msg.AddByte(skip);
  2129. msg.AddByte(0xFF);
  2130. }
  2131. }
  2132.  
  2133. //moving up a floor up makes us out of sync
  2134. //west
  2135. msg.AddByte(0x68);
  2136. GetMapDescription(oldPos.x - 8, oldPos.y + 1 - 6, newPos.z, 1, 14, msg);
  2137.  
  2138. //north
  2139. msg.AddByte(0x65);
  2140. GetMapDescription(oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 1, msg);
  2141. }
  2142. }
  2143.  
  2144. void Protocol78::MoveDownCreature(NetworkMessage& msg, const Creature* creature,
  2145. const Position& newPos, const Position& oldPos, uint32_t oldStackPos)
  2146. {
  2147. if(creature == player){
  2148. //floor change down
  2149. msg.AddByte(0xBF);
  2150.  
  2151. //going from surface to underground
  2152. if(newPos.z == 8){
  2153. int skip = -1;
  2154.  
  2155. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 14, -1, skip);
  2156. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 1, 18, 14, -2, skip);
  2157. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);
  2158.  
  2159. if(skip >= 0){
  2160. msg.AddByte(skip);
  2161. msg.AddByte(0xFF);
  2162. }
  2163. }
  2164. //going further down
  2165. else if(newPos.z > oldPos.z && newPos.z > 8 && newPos.z < 14){
  2166. int skip = -1;
  2167. GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip);
  2168.  
  2169. if(skip >= 0){
  2170. msg.AddByte(skip);
  2171. msg.AddByte(0xFF);
  2172. }
  2173. }
  2174.  
  2175. //moving down a floor makes us out of sync
  2176. //east
  2177. msg.AddByte(0x66);
  2178. GetMapDescription(oldPos.x + 9, oldPos.y - 1 - 6, newPos.z, 1, 14, msg);
  2179.  
  2180. //south
  2181. msg.AddByte(0x67);
  2182. GetMapDescription(oldPos.x - 8, oldPos.y + 7, newPos.z, 18, 1, msg);
  2183. }
  2184. }
  2185.  
  2186.  
  2187. //inventory
  2188. void Protocol78::AddInventoryItem(NetworkMessage& msg, slots_t slot, const Item* item)
  2189. {
  2190. if(item == NULL){
  2191. msg.AddByte(0x79);
  2192. msg.AddByte(slot);
  2193. }
  2194. else{
  2195. msg.AddByte(0x78);
  2196. msg.AddByte(slot);
  2197. msg.AddItem(item);
  2198. }
  2199. }
  2200.  
  2201. void Protocol78::UpdateInventoryItem(NetworkMessage& msg, slots_t slot, const Item* item)
  2202. {
  2203. if(item == NULL){
  2204. msg.AddByte(0x79);
  2205. msg.AddByte(slot);
  2206. }
  2207. else{
  2208. msg.AddByte(0x78);
  2209. msg.AddByte(slot);
  2210. msg.AddItem(item);
  2211. }
  2212. }
  2213.  
  2214. void Protocol78::RemoveInventoryItem(NetworkMessage& msg, slots_t slot)
  2215. {
  2216. msg.AddByte(0x79);
  2217. msg.AddByte(slot);
  2218. }
  2219.  
  2220. //containers
  2221. void Protocol78::AddContainerItem(NetworkMessage& msg, uint8_t cid, const Item *item)
  2222. {
  2223. msg.AddByte(0x70);
  2224. msg.AddByte(cid);
  2225. msg.AddItem(item);
  2226. }
  2227.  
  2228. void Protocol78::UpdateContainerItem(NetworkMessage& msg, uint8_t cid, uint8_t slot, const Item* item)
  2229. {
  2230. msg.AddByte(0x71);
  2231. msg.AddByte(cid);
  2232. msg.AddByte(slot);
  2233. msg.AddItem(item);
  2234. }
  2235.  
  2236. void Protocol78::RemoveContainerItem(NetworkMessage& msg, uint8_t cid, uint8_t slot)
  2237. {
  2238. msg.AddByte(0x72);
  2239. msg.AddByte(cid);
  2240. msg.AddByte(slot);
  2241. }
  2242.  
  2243. //////////////////////////
  2244.  
  2245. void Protocol78::flushOutputBuffer()
  2246. {
  2247. OTSYS_THREAD_LOCK_CLASS lockClass(bufferLock, "Protocol78::flushOutputBuffer()");
  2248. //force writetosocket
  2249. OutputBuffer.WriteToSocket(s);
  2250. OutputBuffer.Reset();
  2251.  
  2252. return;
  2253. }
  2254.  
  2255. void Protocol78::WriteBuffer(NetworkMessage& add)
  2256. {
  2257. game->addPlayerBuffer(player);
  2258.  
  2259. OTSYS_THREAD_LOCK(bufferLock, "Protocol78::WriteBuffer")
  2260.  
  2261. if(OutputBuffer.getMessageLength() + add.getMessageLength() >= NETWORKMESSAGE_MAXSIZE - 16){
  2262. this->flushOutputBuffer();
  2263. }
  2264.  
  2265. OutputBuffer.JoinMessages(add);
  2266. OTSYS_THREAD_UNLOCK(bufferLock, "Protocol78::WriteBuffer")
  2267. return;
  2268. }
  2269.  
  2270. void Protocol78::setKey(const unsigned long* key)
  2271. {
  2272. memcpy(m_key, key, 16);
  2273. OutputBuffer.setEncryptionState(true);
  2274. OutputBuffer.setEncryptionKey(key);
  2275. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement