Advertisement
Guest User

Untitled

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