diff --git a/src/core.hpp b/src/core.hpp index ad64df77646..6352118840f 100644 --- a/src/core.hpp +++ b/src/core.hpp @@ -15,7 +15,7 @@ static constexpr auto AUTHENTICATOR_PERIOD = 30U; // SERVER_MAJOR_VERSION is the actual full version of the server, including minor and patch numbers. // This is intended for internal use to identify the exact state of the server (release) software. static constexpr auto SERVER_RELEASE_VERSION = "3.1.2"; -static constexpr auto CLIENT_VERSION = 1332; +static constexpr auto CLIENT_VERSION = 1340; #define CLIENT_VERSION_UPPER (CLIENT_VERSION / 100) #define CLIENT_VERSION_LOWER (CLIENT_VERSION % 100) diff --git a/src/creatures/players/wheel/player_wheel.cpp b/src/creatures/players/wheel/player_wheel.cpp index 2a3e1366430..eff54689f94 100644 --- a/src/creatures/players/wheel/player_wheel.cpp +++ b/src/creatures/players/wheel/player_wheel.cpp @@ -889,7 +889,7 @@ void PlayerWheel::revealGem(WheelGemQuality_t quality) { sendOpenWheelWindow(m_player.getID()); } -PlayerWheelGem PlayerWheel::getGem(uint8_t index) const { +PlayerWheelGem PlayerWheel::getGem(uint16_t index) const { auto gems = getRevealedGems(); if (gems.size() <= index) { g_logger().error("[{}] Player {} trying to get gem with index {} but has only {} gems", __FUNCTION__, m_player.getName(), index, gems.size()); @@ -907,9 +907,9 @@ PlayerWheelGem PlayerWheel::getGem(const std::string &uuid) const { return gem; } -uint8_t PlayerWheel::getGemIndex(const std::string &uuid) const { +uint16_t PlayerWheel::getGemIndex(const std::string &uuid) const { auto gems = getRevealedGems(); - for (uint8_t i = 0; i < gems.size(); ++i) { + for (uint16_t i = 0; i < gems.size(); ++i) { if (gems[i].uuid == uuid) { return i; } @@ -918,7 +918,7 @@ uint8_t PlayerWheel::getGemIndex(const std::string &uuid) const { return 0xFF; } -void PlayerWheel::destroyGem(uint8_t index) { +void PlayerWheel::destroyGem(uint16_t index) { auto gem = getGem(index); if (gem.locked) { g_logger().error("[{}] Player {} trying to destroy locked gem with index {}", __FUNCTION__, m_player.getName(), index); @@ -928,7 +928,7 @@ void PlayerWheel::destroyGem(uint8_t index) { sendOpenWheelWindow(m_player.getID()); } -void PlayerWheel::switchGemDomain(uint8_t index) { +void PlayerWheel::switchGemDomain(uint16_t index) { auto gem = getGem(index); if (gem.locked) { g_logger().error("[{}] Player {} trying to destroy locked gem with index {}", __FUNCTION__, m_player.getName(), index); @@ -946,14 +946,14 @@ void PlayerWheel::switchGemDomain(uint8_t index) { sendOpenWheelWindow(m_player.getID()); } -void PlayerWheel::toggleGemLock(uint8_t index) { +void PlayerWheel::toggleGemLock(uint16_t index) { auto gem = getGem(index); gem.locked = !gem.locked; gem.save(gemsKV()); sendOpenWheelWindow(m_player.getID()); } -void PlayerWheel::setActiveGem(WheelGemAffinity_t affinity, uint8_t index) { +void PlayerWheel::setActiveGem(WheelGemAffinity_t affinity, uint16_t index) { auto gem = getGem(index); if (gem.uuid.empty()) { g_logger().error("[{}] Failed to load gem with index {}", __FUNCTION__, index); @@ -979,19 +979,15 @@ void PlayerWheel::addGems(NetworkMessage &msg) const { for (const auto &gem : activeGems) { auto index = getGemIndex(gem.uuid); g_logger().debug("[{}] Adding active gem: {} with index {}", __FUNCTION__, gem.toString(), index); - msg.addByte(getGemIndex(gem.uuid)); + msg.add(getGemIndex(gem.uuid)); } auto revealedGems = getRevealedGems(); - if (revealedGems.size() > 225) { - g_logger().error("[{}] Player {} has more than 225 gems unlocked", __FUNCTION__, m_player.getName()); - revealedGems.resize(225); - } - msg.addByte(revealedGems.size()); - int index = 0; + msg.add(revealedGems.size()); + uint16_t index = 0; for (const auto &gem : revealedGems) { g_logger().debug("[{}] Adding revealed gem: {}", __FUNCTION__, gem.toString()); - msg.addByte(index++); + msg.add(index++); msg.addByte(gem.locked); msg.addByte(static_cast(gem.affinity)); msg.addByte(static_cast(gem.quality)); @@ -1161,7 +1157,7 @@ void PlayerWheel::saveSlotPointsOnPressSaveButton(NetworkMessage &msg) { removeActiveGem(affinity); continue; } - uint8_t gemIndex = msg.getByte(); + uint16_t gemIndex = msg.get(); setActiveGem(affinity, gemIndex); } diff --git a/src/creatures/players/wheel/player_wheel.hpp b/src/creatures/players/wheel/player_wheel.hpp index 14f922e9597..e94f605930c 100644 --- a/src/creatures/players/wheel/player_wheel.hpp +++ b/src/creatures/players/wheel/player_wheel.hpp @@ -386,14 +386,14 @@ class PlayerWheel { * @return The calculated mitigation value. */ float calculateMitigation() const; - PlayerWheelGem getGem(uint8_t index) const; + PlayerWheelGem getGem(uint16_t index) const; PlayerWheelGem getGem(const std::string &uuid) const; - uint8_t getGemIndex(const std::string &uuid) const; + uint16_t getGemIndex(const std::string &uuid) const; void revealGem(WheelGemQuality_t quality); - void destroyGem(uint8_t index); - void switchGemDomain(uint8_t index); - void toggleGemLock(uint8_t index); - void setActiveGem(WheelGemAffinity_t affinity, uint8_t index); + void destroyGem(uint16_t index); + void switchGemDomain(uint16_t index); + void toggleGemLock(uint16_t index); + void setActiveGem(WheelGemAffinity_t affinity, uint16_t index); void removeActiveGem(WheelGemAffinity_t affinity); void addRevelationBonus(WheelGemAffinity_t affinity, uint16_t points) { m_bonusRevelationPoints[static_cast(affinity)] += points; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 133f0335ff1..6df5d758ad2 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -708,6 +708,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { OperatingSystem_t operatingSystem = static_cast(msg.get()); version = msg.get(); // Protocol version + g_logger().trace("Protocol version: {}", version); // Old protocol support oldProtocol = g_configManager().getBoolean(OLD_PROTOCOL, __FUNCTION__) && version <= 1100; @@ -721,10 +722,21 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { clientVersion = static_cast(msg.get()); if (!oldProtocol) { - msg.getString(); // Client version (String) + auto clientVersionString = msg.getString(); // Client version (String) + g_logger().trace("Client version: {}", clientVersionString); + if (version >= 1334) { + auto assetHashIdentifier = msg.getString(); // Assets hash identifier + g_logger().trace("Client asset hash identifier: {}", assetHashIdentifier); + } + } + + if (version < 1334) { + auto datRevision = msg.get(); // Dat revision + g_logger().trace("Dat revision: {}", datRevision); } - msg.skipBytes(3); // U16 dat revision, U8 game preview state + auto gamePreviewState = msg.getByte(); // U8 game preview state + g_logger().trace("Game preview state: {}", gamePreviewState); if (!Protocol::RSA_decrypt(msg)) { g_logger().warn("[ProtocolGame::onRecvFirstMessage] - RSA Decrypt Failed"); @@ -736,7 +748,8 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) { enableXTEAEncryption(); setXTEAKey(key.data()); - msg.skipBytes(1); // gamemaster flag + auto isGameMaster = static_cast(msg.getByte()); // gamemaster flag + g_logger().trace("Is Game Master: {}", isGameMaster); std::string authType = g_configManager().getString(AUTH_TYPE, __FUNCTION__); std::ostringstream ss; @@ -1668,8 +1681,11 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) { newOutfit.lookMountBody = std::min(132, msg.getByte()); newOutfit.lookMountLegs = std::min(132, msg.getByte()); newOutfit.lookMountFeet = std::min(132, msg.getByte()); + bool isMounted = msg.getByte(); newOutfit.lookFamiliarsType = msg.get(); + g_logger().debug("Bool isMounted: {}", isMounted); } + uint8_t isMountRandomized = msg.getByte(); g_game().playerChangeOutfit(player->getID(), newOutfit, isMountRandomized); } else if (outfitType == 1) { @@ -1789,11 +1805,23 @@ void ProtocolGame::parseQuickLoot(NetworkMessage &msg) { return; } - Position pos = msg.getPosition(); - uint16_t itemId = msg.get(); - uint8_t stackpos = msg.getByte(); - bool lootAllCorpses = msg.getByte(); - bool autoLoot = msg.getByte(); + uint8_t variant = msg.getByte(); + const Position pos = msg.getPosition(); + uint16_t itemId = 0; + uint8_t stackpos = 0; + bool lootAllCorpses = true; + bool autoLoot = true; + + if (variant == 2) { + // Loot player nearby (13.40) + } else { + itemId = msg.get(); + stackpos = msg.getByte(); + lootAllCorpses = variant == 1; + autoLoot = false; + } + g_logger().debug("[{}] variant {}, pos {}, itemId {}, stackPos {}", __FUNCTION__, variant, pos.toString(), itemId, stackpos); + g_game().playerQuickLoot(player->getID(), pos, itemId, stackpos, nullptr, lootAllCorpses, autoLoot); } @@ -2348,6 +2376,10 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) { newmsg.addString(Class, "ProtocolGame::parseBestiarysendMonsterData - Class"); newmsg.addByte(currentLevel); + + newmsg.add(0); // Animus Mastery Bonus + newmsg.add(0); // Animus Mastery Points + newmsg.add(killCounter); newmsg.add(mtype->info.bestiaryFirstUnlock); @@ -2980,7 +3012,12 @@ void ProtocolGame::parseBestiarysendCreatures(NetworkMessage &msg) { } else { newmsg.addByte(0); } + + newmsg.add(0); // Creature Animous Bonus } + + newmsg.add(0); // Animus Mastery Points + writeToOutputBuffer(newmsg); } @@ -4665,6 +4702,19 @@ void ProtocolGame::sendContainer(uint8_t cid, std::shared_ptr contain msg.addByte(0x00); } + // New container menu options + if (container->isMovable()) { // Pickupable/Moveable (?) + msg.addByte(1); + } else { + msg.addByte(0); + } + + if (container->getHoldingPlayer()) { // Player holding the item (?) + msg.addByte(1); + } else { + msg.addByte(0); + } + writeToOutputBuffer(msg); } @@ -4861,9 +4911,9 @@ void ProtocolGame::sendSaleItemList(const std::vector &shopVector, co msg.add(player->getMoney() + player->getBankBalance()); } - uint8_t itemsToSend = 0; + uint16_t itemsToSend = 0; auto msgPosition = msg.getBufferPosition(); - msg.skipBytes(1); + msg.skipBytes(2); for (const ShopBlock &shopBlock : shopVector) { if (shopBlock.itemSellPrice == 0) { @@ -4878,14 +4928,14 @@ void ProtocolGame::sendSaleItemList(const std::vector &shopVector, co } else { msg.add(std::min(it->second, std::numeric_limits::max())); } - if (++itemsToSend >= 0xFF) { + if (++itemsToSend >= 0xFFFF) { break; } } } msg.setBufferPosition(msgPosition); - msg.addByte(itemsToSend); + msg.add(itemsToSend); writeToOutputBuffer(msg); }