Advertisement
Guest User

Untitled

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