Skip to content

Commit

Permalink
feat: support to protocol 13.40 (#2802)
Browse files Browse the repository at this point in the history
NOTE: just the bytes, no features.

Client to test:
https://github.com/dudantas/tibia-client/releases/tag/13.34.93b0a1

---------

Co-authored-by: Marcos <[email protected]>
  • Loading branch information
dudantas and marcosvf132 authored Aug 9, 2024
1 parent 8521d69 commit 7766a1d
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
28 changes: 12 additions & 16 deletions src/creatures/players/wheel/player_wheel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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;
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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<uint16_t>(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<uint16_t>(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<uint16_t>(index++);
msg.addByte(gem.locked);
msg.addByte(static_cast<uint8_t>(gem.affinity));
msg.addByte(static_cast<uint8_t>(gem.quality));
Expand Down Expand Up @@ -1161,7 +1157,7 @@ void PlayerWheel::saveSlotPointsOnPressSaveButton(NetworkMessage &msg) {
removeActiveGem(affinity);
continue;
}
uint8_t gemIndex = msg.getByte();
uint16_t gemIndex = msg.get<uint16_t>();
setActiveGem(affinity, gemIndex);
}

Expand Down
12 changes: 6 additions & 6 deletions src/creatures/players/wheel/player_wheel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<size_t>(affinity)] += points;
Expand Down
74 changes: 62 additions & 12 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) {

OperatingSystem_t operatingSystem = static_cast<OperatingSystem_t>(msg.get<uint16_t>());
version = msg.get<uint16_t>(); // Protocol version
g_logger().trace("Protocol version: {}", version);

// Old protocol support
oldProtocol = g_configManager().getBoolean(OLD_PROTOCOL, __FUNCTION__) && version <= 1100;
Expand All @@ -721,10 +722,21 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) {
clientVersion = static_cast<int32_t>(msg.get<uint32_t>());

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<uint16_t>(); // 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");
Expand All @@ -736,7 +748,8 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) {
enableXTEAEncryption();
setXTEAKey(key.data());

msg.skipBytes(1); // gamemaster flag
auto isGameMaster = static_cast<bool>(msg.getByte()); // gamemaster flag
g_logger().trace("Is Game Master: {}", isGameMaster);

std::string authType = g_configManager().getString(AUTH_TYPE, __FUNCTION__);
std::ostringstream ss;
Expand Down Expand Up @@ -1668,8 +1681,11 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) {
newOutfit.lookMountBody = std::min<uint8_t>(132, msg.getByte());
newOutfit.lookMountLegs = std::min<uint8_t>(132, msg.getByte());
newOutfit.lookMountFeet = std::min<uint8_t>(132, msg.getByte());
bool isMounted = msg.getByte();
newOutfit.lookFamiliarsType = msg.get<uint16_t>();
g_logger().debug("Bool isMounted: {}", isMounted);
}

uint8_t isMountRandomized = msg.getByte();
g_game().playerChangeOutfit(player->getID(), newOutfit, isMountRandomized);
} else if (outfitType == 1) {
Expand Down Expand Up @@ -1789,11 +1805,23 @@ void ProtocolGame::parseQuickLoot(NetworkMessage &msg) {
return;
}

Position pos = msg.getPosition();
uint16_t itemId = msg.get<uint16_t>();
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<uint16_t>();
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);
}

Expand Down Expand Up @@ -2348,6 +2376,10 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) {
newmsg.addString(Class, "ProtocolGame::parseBestiarysendMonsterData - Class");

newmsg.addByte(currentLevel);

newmsg.add<uint16_t>(0); // Animus Mastery Bonus
newmsg.add<uint16_t>(0); // Animus Mastery Points

newmsg.add<uint32_t>(killCounter);

newmsg.add<uint16_t>(mtype->info.bestiaryFirstUnlock);
Expand Down Expand Up @@ -2980,7 +3012,12 @@ void ProtocolGame::parseBestiarysendCreatures(NetworkMessage &msg) {
} else {
newmsg.addByte(0);
}

newmsg.add<uint16_t>(0); // Creature Animous Bonus
}

newmsg.add<uint16_t>(0); // Animus Mastery Points

writeToOutputBuffer(newmsg);
}

Expand Down Expand Up @@ -4665,6 +4702,19 @@ void ProtocolGame::sendContainer(uint8_t cid, std::shared_ptr<Container> 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);
}

Expand Down Expand Up @@ -4861,9 +4911,9 @@ void ProtocolGame::sendSaleItemList(const std::vector<ShopBlock> &shopVector, co
msg.add<uint64_t>(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) {
Expand All @@ -4878,14 +4928,14 @@ void ProtocolGame::sendSaleItemList(const std::vector<ShopBlock> &shopVector, co
} else {
msg.add<uint16_t>(std::min<uint16_t>(it->second, std::numeric_limits<uint16_t>::max()));
}
if (++itemsToSend >= 0xFF) {
if (++itemsToSend >= 0xFFFF) {
break;
}
}
}

msg.setBufferPosition(msgPosition);
msg.addByte(itemsToSend);
msg.add<uint16_t>(itemsToSend);
writeToOutputBuffer(msg);
}

Expand Down

0 comments on commit 7766a1d

Please sign in to comment.