void ProtocolGameBase::sendInventory() { std::map<uint16_t, uint16_t> items = player->getAllItemsClientId(); NetworkMessage msg; msg.addByte(0xF5); msg.add<uint16_t>(items.size() + 11); for (uint16_t i = 1; i <= 11; i++) { msg.add<uint16_t>(i); msg.addByte(0); msg.add<uint16_t>(1); } for (const auto& it : items) { msg.add<uint16_t>(it.first); msg.addByte(0); msg.add<uint16_t>(it.second); } writeToOutputBuffer(msg); }
void ProtocolGameBase::sendCancelWalk() { NetworkMessage msg; msg.addByte(0xB5); msg.addByte(player->getDirection()); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendChannel(uint16_t channelId, const std::string& channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers) { NetworkMessage msg; msg.addByte(0xAC); msg.add<uint16_t>(channelId); msg.addString(channelName); if (channelUsers) { msg.add<uint16_t>(channelUsers->size()); for (const auto& it : *channelUsers) { msg.addString(it.second->getName()); } } else { msg.add<uint16_t>(0x00); } if (invitedUsers) { msg.add<uint16_t>(invitedUsers->size()); for (const auto& it : *invitedUsers) { msg.addString(it.second->getName()); } } else { msg.add<uint16_t>(0x00); } writeToOutputBuffer(msg); }
void ProtocolGameBase::sendMapDescription(const Position& pos) { NetworkMessage msg; msg.addByte(0x64); msg.addPosition(player->getPosition()); GetMapDescription(pos.x - 8, pos.y - 6, pos.z, 18, 14, msg); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendBasicData() { NetworkMessage msg; msg.addByte(0x9F); msg.addByte(player->isPremium() ? 0x01 : 0x00); msg.add<uint32_t>(std::numeric_limits<uint32_t>::max()); msg.addByte(player->getVocation()->getClientId()); msg.add<uint16_t>(0x00); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendCreatureLight(const Creature* creature) { if (!canSee(creature)) { return; } NetworkMessage msg; AddCreatureLight(msg, creature); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendVIP(uint32_t guid, const std::string& name, const std::string& description, uint32_t icon, bool notify, VipStatus_t status) { NetworkMessage msg; msg.addByte(0xD2); msg.add<uint32_t>(guid); msg.addString(name); msg.addString(description); msg.add<uint32_t>(std::min<uint32_t>(10, icon)); msg.addByte(notify ? 0x01 : 0x00); msg.addByte(status); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendMagicEffect(const Position& pos, uint8_t type) { if (!canSee(pos)) { return; } NetworkMessage msg; msg.addByte(0x83); msg.addPosition(pos); msg.addByte(type); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendInventoryItem(slots_t slot, const Item* item) { NetworkMessage msg; if (item) { msg.addByte(0x78); msg.addByte(slot); msg.addItem(item); } else { msg.addByte(0x79); msg.addByte(slot); } writeToOutputBuffer(msg); }
void ProtocolSpectator::sendEmptyTileOnPlayerPos(const Tile* tile, const Position& playerPos) { NetworkMessage msg; msg.addByte(0x69); msg.addPosition(playerPos); msg.add<uint16_t>(0x00); msg.addItem(tile->getGround()); msg.addByte(0x00); msg.addByte(0xFF); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendUpdateTile(const Tile* tile, const Position& pos) { if (!canSee(pos)) { return; } NetworkMessage msg; msg.addByte(0x69); msg.addPosition(pos); if (tile) { GetTileDescription(tile, msg); msg.addByte(0x00); msg.addByte(0xFF); } else { msg.addByte(0x01); msg.addByte(0xFF); } writeToOutputBuffer(msg); }
void ProtocolSpectator::syncKnownCreatureSets() { const auto& casterKnownCreatures = client->getKnownCreatures(); const auto playerPos = player->getPosition(); const auto tile = player->getTile(); if (!tile || !tile->getGround()) { disconnectSpectator("A sync error has occured."); return; } sendEmptyTileOnPlayerPos(tile, playerPos); bool known; uint32_t removedKnown; for (const auto creatureID : casterKnownCreatures) { if (knownCreatureSet.find(creatureID) != knownCreatureSet.end()) { continue; } NetworkMessage msg; const auto creature = g_game.getCreatureByID(creatureID); if (creature && !creature->isRemoved()) { msg.addByte(0x6A); msg.addPosition(playerPos); msg.addByte(1); //stackpos checkCreatureAsKnown(creature->getID(), known, removedKnown); AddCreature(msg, creature, known, removedKnown); RemoveTileThing(msg, playerPos, 1); } else if (operatingSystem <= CLIENTOS_FLASH) { // otclient freeze with huge amount of creature add, but do not debug if there are unknown creatures, best solution for now :( addDummyCreature(msg, creatureID, playerPos); RemoveTileThing(msg, playerPos, 1); } writeToOutputBuffer(msg); } sendUpdateTile(tile, playerPos); }
void ProtocolGameBase::sendContainer(uint8_t cid, const Container* container, bool hasParent, uint16_t firstIndex) { NetworkMessage msg; msg.addByte(0x6E); msg.addByte(cid); if (container->getID() == ITEM_BROWSEFIELD) { msg.addItem(1987, 1); msg.addString("Browse Field"); } else { msg.addItem(container); msg.addString(container->getName()); } msg.addByte(container->capacity()); msg.addByte(hasParent ? 0x01 : 0x00); msg.addByte(container->isUnlocked() ? 0x01 : 0x00); // Drag and drop msg.addByte(container->hasPagination() ? 0x01 : 0x00); // Pagination uint32_t containerSize = container->size(); msg.add<uint16_t>(containerSize); msg.add<uint16_t>(firstIndex); if (firstIndex < containerSize) { uint8_t itemsToSend = std::min<uint32_t>(std::min<uint32_t>(container->capacity(), containerSize - firstIndex), std::numeric_limits<uint8_t>::max()); msg.addByte(itemsToSend); for (ItemDeque::const_iterator it = container->getItemList().begin() + firstIndex, end = it + itemsToSend; it != end; ++it) { msg.addItem(*it); } } else { msg.addByte(0x00); } writeToOutputBuffer(msg); }
void ProtocolSpectator::onRecvFirstMessage(NetworkMessage& msg) { if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { getConnection()->close(); return; } operatingSystem = (OperatingSystem_t)msg.get<uint16_t>(); version = msg.get<uint16_t>(); msg.skipBytes(7); // U32 clientVersion, U8 clientType if (!RSA_decrypt(msg)) { getConnection()->close(); return; } uint32_t key[4]; key[0] = msg.get<uint32_t>(); key[1] = msg.get<uint32_t>(); key[2] = msg.get<uint32_t>(); key[3] = msg.get<uint32_t>(); enableXTEAEncryption(); setXTEAKey(key); if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { NetworkMessage opcodeMessage; opcodeMessage.addByte(0x32); opcodeMessage.addByte(0x00); opcodeMessage.add<uint16_t>(0x00); writeToOutputBuffer(opcodeMessage); } msg.skipBytes(1); // gamemaster flag std::string password = msg.getString(); std::string characterName = msg.getString(); uint32_t timeStamp = msg.get<uint32_t>(); uint8_t randNumber = msg.getByte(); if (m_challengeTimestamp != timeStamp || m_challengeRandom != randNumber) { getConnection()->close(); return; } auto dispatchDisconnectClient = [this](const std::string& msg) { g_dispatcher.addTask(createTask( std::bind(&ProtocolSpectator::disconnectSpectator, this, msg))); }; if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { dispatchDisconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!"); return; } if (g_game.getGameState() == GAME_STATE_STARTUP) { dispatchDisconnectClient("Gameworld is starting up. Please wait."); return; } if (g_game.getGameState() == GAME_STATE_MAINTAIN) { dispatchDisconnectClient("Gameworld is under maintenance. Please re-connect in a while."); return; } BanInfo banInfo; if (IOBan::isIpBanned(getIP(), banInfo)) { if (banInfo.reason.empty()) { banInfo.reason = "(none)"; } std::ostringstream ss; ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason; dispatchDisconnectClient(ss.str()); return; } password.erase(password.begin()); g_dispatcher.addTask(createTask(std::bind(&ProtocolSpectator::login, this, characterName, password))); }
void ProtocolGameBase::sendPingBack() { NetworkMessage msg; msg.addByte(0x1E); writeToOutputBuffer(msg, false); }
void ProtocolGameBase::sendAddCreature(const Creature* creature, const Position& pos, int32_t stackpos, bool isLogin) { if (!canSee(pos)) { return; } if (creature != player) { if (stackpos != -1) { NetworkMessage msg; msg.addByte(0x6A); msg.addPosition(pos); msg.addByte(stackpos); bool known; uint32_t removedKnown; checkCreatureAsKnown(creature->getID(), known, removedKnown); AddCreature(msg, creature, known, removedKnown); writeToOutputBuffer(msg); } if (isLogin) { sendMagicEffect(pos, CONST_ME_TELEPORT); } return; } NetworkMessage msg; msg.addByte(0x17); msg.add<uint32_t>(player->getID()); msg.add<uint16_t>(0x32); // beat duration (50) msg.addDouble(Creature::speedA, 3); msg.addDouble(Creature::speedB, 3); msg.addDouble(Creature::speedC, 3); // can report bugs? if (player->getAccountType() >= ACCOUNT_TYPE_TUTOR) { msg.addByte(0x01); } else { msg.addByte(0x00); } msg.addByte(0x00); // can change pvp framing option msg.addByte(0x00); // expert mode button enabled msg.addString("http://static.tibia.com/images/store/"); msg.addByte(3); writeToOutputBuffer(msg); sendPendingStateEntered(); sendEnterWorld(); sendMapDescription(pos); if (isLogin) { sendMagicEffect(pos, CONST_ME_TELEPORT); } sendInventoryItem(CONST_SLOT_HEAD, player->getInventoryItem(CONST_SLOT_HEAD)); sendInventoryItem(CONST_SLOT_NECKLACE, player->getInventoryItem(CONST_SLOT_NECKLACE)); sendInventoryItem(CONST_SLOT_BACKPACK, player->getInventoryItem(CONST_SLOT_BACKPACK)); sendInventoryItem(CONST_SLOT_ARMOR, player->getInventoryItem(CONST_SLOT_ARMOR)); sendInventoryItem(CONST_SLOT_RIGHT, player->getInventoryItem(CONST_SLOT_RIGHT)); sendInventoryItem(CONST_SLOT_LEFT, player->getInventoryItem(CONST_SLOT_LEFT)); sendInventoryItem(CONST_SLOT_LEGS, player->getInventoryItem(CONST_SLOT_LEGS)); sendInventoryItem(CONST_SLOT_FEET, player->getInventoryItem(CONST_SLOT_FEET)); sendInventoryItem(CONST_SLOT_RING, player->getInventoryItem(CONST_SLOT_RING)); sendInventoryItem(CONST_SLOT_AMMO, player->getInventoryItem(CONST_SLOT_AMMO)); sendStats(); sendSkills(); //gameworld light-settings LightInfo lightInfo; g_game.getWorldLightInfo(lightInfo); sendWorldLight(lightInfo); //player light level sendCreatureLight(creature); const std::forward_list<VIPEntry>& vipEntries = IOLoginData::getVIPEntries(player->getAccount()); if (player->isAccessPlayer()) { for (const VIPEntry& entry : vipEntries) { VipStatus_t vipStatus; Player* vipPlayer = g_game.getPlayerByGUID(entry.guid); if (!vipPlayer) { vipStatus = VIPSTATUS_OFFLINE; } else { vipStatus = VIPSTATUS_ONLINE; } sendVIP(entry.guid, entry.name, entry.description, entry.icon, entry.notify, vipStatus); } } else { for (const VIPEntry& entry : vipEntries) { VipStatus_t vipStatus; Player* vipPlayer = g_game.getPlayerByGUID(entry.guid); if (!vipPlayer || vipPlayer->isInGhostMode()) { vipStatus = VIPSTATUS_OFFLINE; } else { vipStatus = VIPSTATUS_ONLINE; } sendVIP(entry.guid, entry.name, entry.description, entry.icon, entry.notify, vipStatus); } } sendBasicData(); sendInventory(); player->sendIcons(); }
void ProtocolGameBase::sendPendingStateEntered() { NetworkMessage msg; msg.addByte(0x0A); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendEnterWorld() { NetworkMessage msg; msg.addByte(0x0F); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendWorldLight(const LightInfo& lightInfo) { NetworkMessage msg; AddWorldLight(msg, lightInfo); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendSkills() { NetworkMessage msg; AddPlayerSkills(msg); writeToOutputBuffer(msg); }