Advertisement
Guest User

Untitled

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