Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support to protocol 14.05 #3164

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ jobs:
uses: gittools/actions/gitversion/[email protected]

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3.7.1
with:
install: true

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
Expand All @@ -73,6 +73,8 @@ jobs:
tags: ghcr.io/${{ github.repository }}:${{ steps.gitversion.outputs.semVer }}
cache-from: type=gha, scope=${{ github.workflow }}
cache-to: type=gha, scope=${{ github.workflow }}
secrets: |
DEBUG=1

- name: Image digest
if: ${{ github.event_name == 'push' }}
Expand All @@ -97,7 +99,7 @@ jobs:
uses: gittools/actions/gitversion/[email protected]

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3.7.1
with:
install: true

Expand Down
2 changes: 1 addition & 1 deletion data-otservbr-global/monster/magicals/burning_book.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Burning Book")
local monster = {}

monster.description = "a burning book"
monster.experience = 11934
monster.experience = 13200
monster.outfit = {
lookType = 1061,
lookHead = 79,
Expand Down
2 changes: 1 addition & 1 deletion data-otservbr-global/monster/magicals/forest_fury.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Forest Fury")
local monster = {}

monster.description = "a forest fury"
monster.experience = 235
monster.experience = 330
monster.outfit = {
lookType = 569,
lookHead = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Guardian of Tales")
local monster = {}

monster.description = "a guardian of tales"
monster.experience = 9204
monster.experience = 10600
monster.outfit = {
lookType = 1063,
lookHead = 92,
Expand Down
2 changes: 1 addition & 1 deletion data-otservbr-global/monster/magicals/rage_squid.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Rage Squid")
local monster = {}

monster.description = "a rage squid"
monster.experience = 14820
monster.experience = 16300
monster.outfit = {
lookType = 1059,
lookHead = 94,
Expand Down
2 changes: 1 addition & 1 deletion data-otservbr-global/monster/plants/wilting_leaf_golem.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local mType = Game.createMonsterType("Wilting Leaf Golem")
local monster = {}

monster.description = "a wilting leaf golem"
monster.experience = 145
monster.experience = 225
monster.outfit = {
lookType = 573,
lookHead = 0,
Expand Down
Binary file modified data/items/appearances.dat
Binary file not shown.
8 changes: 4 additions & 4 deletions data/scripts/talkactions/god/icons_functions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ end
function Player:sendNormalIcons(icons)
local msg = NetworkMessage()
msg:addByte(0xA2)
msg:addU32(icons)
msg:addU64(icons)
msg:addByte(0)
msg:sendToPlayer(self)
end

function Player:sendIconBakragore(specialIcon)
local msg = NetworkMessage()
msg:addByte(0xA3)
msg:addU32(specialIcon)
msg:addByte(0)
msg:addByte(0xA2)
msg:addU64(0)
msg:addByte(specialIcon)
msg:sendToPlayer(self)
end

Expand Down
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 = 1340;
static constexpr auto CLIENT_VERSION = 1405;

#define CLIENT_VERSION_UPPER (CLIENT_VERSION / 100)
#define CLIENT_VERSION_LOWER (CLIENT_VERSION % 100)
13 changes: 9 additions & 4 deletions src/server/network/connection/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "server/network/protocol/protocol.hpp"
#include "game/scheduling/dispatcher.hpp"
#include "server/network/message/networkmessage.hpp"
#include "server/network/protocol/protocolgame.hpp"
#include "server/server.hpp"
#include "utils/tools.hpp"

Expand Down Expand Up @@ -105,7 +106,7 @@ void Connection::closeSocket() {
void Connection::accept(Protocol_ptr protocolPtr) {
connectionState = CONNECTION_STATE_IDENTIFYING;
protocol = std::move(protocolPtr);
g_dispatcher().addEvent([protocol = protocol] { protocol->onConnect(); }, __FUNCTION__, std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count());
g_dispatcher().addEvent([eventProtocol = protocol] { eventProtocol->sendLoginChallenge(); }, __FUNCTION__, std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count());

acceptInternal(false);
}
Expand Down Expand Up @@ -134,7 +135,7 @@ void Connection::parseProxyIdentification(const std::error_code &error) {

if (error || connectionState == CONNECTION_STATE_CLOSED) {
if (error != asio::error::operation_aborted && error != asio::error::eof && error != asio::error::connection_reset) {
g_logger().error("[Connection::parseProxyIdentification] - Read error: {}", error.message());
g_logger().debug("[Connection::parseProxyIdentification] - Read error: {}", error.message());
}
close(FORCE_CLOSE);
return;
Expand Down Expand Up @@ -209,6 +210,10 @@ void Connection::parseHeader(const std::error_code &error) {
}

uint16_t size = m_msg.getLengthHeader();
if (std::dynamic_pointer_cast<ProtocolGame>(protocol)) {
size = (size * 8) + 4;
}

if (size == 0 || size > INPUTMESSAGE_MAXSIZE) {
close(FORCE_CLOSE);
return;
Expand All @@ -234,7 +239,7 @@ void Connection::parsePacket(const std::error_code &error) {

if (error || connectionState == CONNECTION_STATE_CLOSED) {
if (error) {
g_logger().error("[Connection::parsePacket] - Read error: {}", error.message());
g_logger().debug("[Connection::parsePacket] - Read error: {}", error.message());
}
close(FORCE_CLOSE);
return;
Expand Down Expand Up @@ -272,7 +277,7 @@ void Connection::parsePacket(const std::error_code &error) {
// it doesn't generate any problem because olders protocol don't use 'server sends first' feature
m_msg.get<uint32_t>();
// Skip protocol ID
m_msg.skipBytes(1);
m_msg.skipBytes(2);
}

protocol->onRecvFirstMessage(m_msg);
Expand Down
2 changes: 2 additions & 0 deletions src/server/network/connection/connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ static constexpr int32_t CONNECTION_READ_TIMEOUT = 30;

class Protocol;
using Protocol_ptr = std::shared_ptr<Protocol>;
class ProtocolGame;
using ProtocolGame_ptr = std::shared_ptr<ProtocolGame>;
class OutputMessage;
using OutputMessage_ptr = std::shared_ptr<OutputMessage>;
class Connection;
Expand Down
4 changes: 2 additions & 2 deletions src/server/network/message/networkmessage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class NetworkMessage {
// Headers:
// 2 bytes for unencrypted message size
// 4 bytes for checksum
// 2 bytes for encrypted message size
static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 8;
// 1 byte for padding message size
static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 7;

int32_t decodeHeader();

Expand Down
8 changes: 7 additions & 1 deletion src/server/network/message/outputmessage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,14 @@ class OutputMessage : public NetworkMessage {
return buffer.data() + outputBufferStart;
}

void writePaddingAmount() {
uint8_t paddingAmount = 8 - (info.length % 8) - 1;
addPaddingBytes(paddingAmount);
add_header(paddingAmount);
}

void writeMessageLength() {
add_header(info.length);
add_header(static_cast<uint16_t>((info.length - 4) / 8));
}

void addCryptoHeader(bool addChecksum, uint32_t checksum) {
Expand Down
11 changes: 6 additions & 5 deletions src/server/network/protocol/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ void Protocol::onSendMessage(const OutputMessage_ptr &msg) {
if (!rawMessages) {
const uint32_t sendMessageChecksum = msg->getLength() >= 128 && compression(*msg) ? (1U << 31) : 0;

msg->writeMessageLength();

if (!encryptionEnabled) {
msg->writeMessageLength();
return;
}

msg->writePaddingAmount();

XTEA_encrypt(*msg);
if (checksumMethod == CHECKSUM_METHOD_NONE) {
msg->addCryptoHeader(false, 0);
Expand Down Expand Up @@ -209,12 +210,12 @@ bool Protocol::XTEA_decrypt(NetworkMessage &msg) const {

XTEA_transform(buffer, messageLength, false);

uint16_t innerLength = msg.get<uint16_t>();
if (std::cmp_greater(innerLength, msgLength - 2)) {
uint8_t paddingSize = msg.getByte();
if (std::cmp_greater(paddingSize, msgLength - 1)) {
return false;
}

msg.setLength(innerLength);
msg.setLength(messageLength - paddingSize);
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/server/network/protocol/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Protocol : public std::enable_shared_from_this<Protocol> {
bool onRecvMessage(NetworkMessage &msg);
bool sendRecvMessageCallback(NetworkMessage &msg);
virtual void onRecvFirstMessage(NetworkMessage &msg) = 0;
virtual void onConnect() { }
virtual void sendLoginChallenge() { }

bool isConnectionExpired() const;

Expand Down
15 changes: 7 additions & 8 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) {
g_dispatcher().addEvent([self = getThis(), characterName, accountId, operatingSystem] { self->login(characterName, accountId, operatingSystem); }, __FUNCTION__);
}

void ProtocolGame::onConnect() {
void ProtocolGame::sendLoginChallenge() {
auto output = OutputMessagePool::getOutputMessage();
static std::random_device rd;
static std::ranlux24 generator(rd());
Expand All @@ -873,15 +873,15 @@ void ProtocolGame::onConnect() {
output->skipBytes(sizeof(uint32_t));

// Packet length & type
output->add<uint16_t>(0x0006);
output->addByte(0x01);
output->addByte(0x1F);

// Add timestamp & random number
challengeTimestamp = static_cast<uint32_t>(time(nullptr));
output->add<uint32_t>(challengeTimestamp);

challengeRandom = randNumber(generator);
output->addByte(challengeRandom);
output->addByte(0x71);

// Go back and write checksum
output->skipBytes(-12);
Expand Down Expand Up @@ -1612,7 +1612,7 @@ void ProtocolGame::parseOpenPrivateChannel(NetworkMessage &msg) {

void ProtocolGame::parseAutoWalk(NetworkMessage &msg) {
uint8_t numdirs = msg.getByte();
if (numdirs == 0 || (msg.getBufferPosition() + numdirs) != (msg.getLength() + 8)) {
if (numdirs == 0 || (msg.getBufferPosition() + numdirs) != (msg.getLength() + 6)) {
return;
}

Expand Down Expand Up @@ -4646,8 +4646,8 @@ void ProtocolGame::sendIcons(const std::unordered_set<PlayerIcon> &iconSet, cons
// Send as uint16_t in old protocol
msg.add<uint16_t>(static_cast<uint16_t>(icons));
} else {
// Send as uint32_t in new protocol
msg.add<uint32_t>(icons);
// Send as uint64_t in new protocol
msg.add<uint64_t>(icons);
msg.addByte(enumToValue(iconBakragore)); // Icons Bakragore
}

Expand All @@ -4657,7 +4657,7 @@ void ProtocolGame::sendIcons(const std::unordered_set<PlayerIcon> &iconSet, cons
void ProtocolGame::sendIconBakragore(const IconBakragore icon) {
NetworkMessage msg;
msg.addByte(0xA2);
msg.add<uint32_t>(0); // Send empty normal icons
msg.add<uint64_t>(0); // Send empty normal icons
msg.addByte(enumToValue(icon));
writeToOutputBuffer(msg);
}
Expand Down Expand Up @@ -8582,7 +8582,6 @@ void ProtocolGame::sendOpenStash() {
msg.add<uint16_t>(item.first);
msg.add<uint32_t>(item.second);
}
msg.add<uint16_t>(static_cast<uint16_t>(g_configManager().getNumber(STASH_ITEMS) - getStashSize(list)));
writeToOutputBuffer(msg);
}

Expand Down
2 changes: 1 addition & 1 deletion src/server/network/protocol/protocolgame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class ProtocolGame final : public Protocol {
void parsePacket(NetworkMessage &msg) override;
void parsePacketFromDispatcher(NetworkMessage &msg, uint8_t recvbyte);
void onRecvFirstMessage(NetworkMessage &msg) override;
void onConnect() override;
void sendLoginChallenge() override;

// Parse methods
void parseAutoWalk(NetworkMessage &msg);
Expand Down
Loading