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
Support for tibia 11 - only via protocol game. #2721
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,10 +67,10 @@ void Connection::close(bool force) | |
ConnectionManager::getInstance().releaseConnection(shared_from_this()); | ||
|
||
std::lock_guard<std::recursive_mutex> lockClass(connectionLock); | ||
if (connectionState != CONNECTION_STATE_OPEN) { | ||
if (connectionState == CONNECTION_STATE_DISCONNECTED) { | ||
return; | ||
} | ||
connectionState = CONNECTION_STATE_CLOSED; | ||
connectionState = CONNECTION_STATE_DISCONNECTED; | ||
|
||
if (protocol) { | ||
g_dispatcher.addTask( | ||
|
@@ -108,6 +108,7 @@ void Connection::accept(Protocol_ptr protocol) | |
{ | ||
this->protocol = protocol; | ||
g_dispatcher.addTask(createTask(std::bind(&Protocol::onConnect, protocol))); | ||
connectionState = CONNECTION_STATE_CONNECTING; | ||
|
||
accept(); | ||
} | ||
|
@@ -119,16 +120,53 @@ void Connection::accept() | |
readTimer.expires_from_now(boost::posix_time::seconds(CONNECTION_READ_TIMEOUT)); | ||
readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr<Connection>(shared_from_this()), std::placeholders::_1)); | ||
|
||
// Read size of the first packet | ||
boost::asio::async_read(socket, | ||
boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH), | ||
std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); | ||
if (connectionState == CONNECTION_STATE_CONNECTING) { | ||
// Read one-by-one ascii characters (new-line-terminated) to verify world name | ||
boost::asio::async_read(socket, | ||
boost::asio::buffer(msg.getBuffer(), 1), | ||
std::bind(&Connection::parseProxyWorldNameIdentification, shared_from_this(), std::placeholders::_1)); | ||
} else { | ||
// Read size of the first packet | ||
boost::asio::async_read(socket, | ||
boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH), | ||
std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer lambda instead of std::bind. std::bind can be hard to read and can result in larger object files and binaries due to type information that will not be produced by equivalent lambdas. |
||
} | ||
|
||
|
||
} catch (boost::system::system_error& e) { | ||
std::cout << "[Network error - Connection::accept] " << e.what() << std::endl; | ||
close(FORCE_CLOSE); | ||
} | ||
} | ||
|
||
void Connection::parseProxyWorldNameIdentification(const boost::system::error_code& error) | ||
{ | ||
std::lock_guard<std::recursive_mutex> lockClass(connectionLock); | ||
readTimer.cancel(); | ||
|
||
if (error) { | ||
close(FORCE_CLOSE); | ||
return; | ||
} else if (connectionState == CONNECTION_STATE_DISCONNECTED) { | ||
return; | ||
} | ||
|
||
char b = msg.getBuffer()[0]; | ||
if (b == 0x0A) { | ||
if (worldName != g_config.getString(ConfigManager::SERVER_NAME)) { | ||
std::cout << convertIPToString(getIP()) << " disconnected for sending invalid world name." << std::endl; | ||
close(); | ||
return; | ||
} | ||
|
||
connectionState = CONNECTION_STATE_CONNECTED; | ||
} else { | ||
worldName.push_back(b); | ||
This comment was marked as off-topic.
Sorry, something went wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for trivial type emplace_back ? :D There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BTW if you have no idea what you are doing always use push_back. |
||
} | ||
|
||
accept(); | ||
} | ||
|
||
void Connection::parseHeader(const boost::system::error_code& error) | ||
{ | ||
std::lock_guard<std::recursive_mutex> lockClass(connectionLock); | ||
|
@@ -137,7 +175,7 @@ void Connection::parseHeader(const boost::system::error_code& error) | |
if (error) { | ||
close(FORCE_CLOSE); | ||
return; | ||
} else if (connectionState != CONNECTION_STATE_OPEN) { | ||
} else if (connectionState == CONNECTION_STATE_DISCONNECTED) { | ||
return; | ||
} | ||
|
||
|
@@ -182,7 +220,7 @@ void Connection::parsePacket(const boost::system::error_code& error) | |
if (error) { | ||
close(FORCE_CLOSE); | ||
return; | ||
} else if (connectionState != CONNECTION_STATE_OPEN) { | ||
} else if (connectionState == CONNECTION_STATE_DISCONNECTED) { | ||
return; | ||
} | ||
|
||
|
@@ -195,10 +233,20 @@ void Connection::parsePacket(const boost::system::error_code& error) | |
checksum = 0; | ||
} | ||
|
||
uint32_t recvChecksum = msg.get<uint32_t>(); | ||
if (recvChecksum != checksum) { | ||
// it might not have been the checksum, step back | ||
msg.skipBytes(-NetworkMessage::CHECKSUM_LENGTH); | ||
bool checksummed = true; | ||
if (worldName.empty()) { | ||
checksummed = msg.get<uint32_t>() == checksum; | ||
if (!checksummed) { | ||
// it might not have been the checksum, step back | ||
msg.skipBytes(-NetworkMessage::CHECKSUM_LENGTH); | ||
} | ||
} else { | ||
uint32_t sequenceNumber = msg.get<uint32_t>(); | ||
if (!receivedFirst || lastSequenceNumber - sequenceNumber == 1) { | ||
lastSequenceNumber = sequenceNumber; | ||
} else { | ||
// the client has sent some data that was lost | ||
} | ||
} | ||
|
||
if (!receivedFirst) { | ||
|
@@ -207,7 +255,7 @@ void Connection::parsePacket(const boost::system::error_code& error) | |
|
||
if (!protocol) { | ||
// Game protocol has already been created at this point | ||
protocol = service_port->make_protocol(recvChecksum == checksum, msg, shared_from_this()); | ||
protocol = service_port->make_protocol(checksummed, msg, shared_from_this()); | ||
if (!protocol) { | ||
close(FORCE_CLOSE); | ||
return; | ||
|
@@ -239,7 +287,7 @@ void Connection::parsePacket(const boost::system::error_code& error) | |
void Connection::send(const OutputMessage_ptr& msg) | ||
{ | ||
std::lock_guard<std::recursive_mutex> lockClass(connectionLock); | ||
if (connectionState != CONNECTION_STATE_OPEN) { | ||
if (connectionState == CONNECTION_STATE_DISCONNECTED) { | ||
return; | ||
} | ||
|
||
|
@@ -295,7 +343,7 @@ void Connection::onWriteOperation(const boost::system::error_code& error) | |
|
||
if (!messageQueue.empty()) { | ||
internalSend(messageQueue.front()); | ||
} else if (connectionState == CONNECTION_STATE_CLOSED) { | ||
} else if (connectionState == CONNECTION_STATE_DISCONNECTED) { | ||
closeSocket(); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -244,6 +244,9 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg) | |
|
||
OperatingSystem_t operatingSystem = static_cast<OperatingSystem_t>(msg.get<uint16_t>()); | ||
version = msg.get<uint16_t>(); | ||
if (version >= 1111) { | ||
enableSequence(); | ||
} | ||
|
||
msg.skipBytes(7); // U32 client version, U8 client type, U16 dat revision | ||
|
||
|
@@ -1007,6 +1010,13 @@ void ProtocolGame::parseEditVip(NetworkMessage& msg) | |
const std::string description = msg.getString(); | ||
uint32_t icon = std::min<uint32_t>(10, msg.get<uint32_t>()); // 10 is max icon in 9.63 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is 10 still the max icon in client 11? |
||
bool notify = msg.getByte() != 0; | ||
if (version >= 1110) { | ||
int groupCount = msg.getByte(); | ||
for (int i = 0; i < groupCount; i++) { | ||
msg.getByte(); // group id | ||
} | ||
} | ||
|
||
addGameTask(&Game::playerRequestEditVip, player->getID(), guid, description, icon, notify); | ||
} | ||
|
||
|
@@ -1334,6 +1344,7 @@ void ProtocolGame::sendBasicData() | |
msg.add<uint32_t>(0); | ||
} | ||
msg.addByte(player->getVocation()->getClientId()); | ||
msg.addByte(player->getVocation()->getId() != VOCATION_NONE ? 0x01 : 0x00); | ||
msg.add<uint16_t>(0xFF); // number of known spells | ||
for (uint8_t spellId = 0x00; spellId < 0xFF; spellId++) { | ||
msg.addByte(spellId); | ||
|
@@ -1999,6 +2010,10 @@ void ProtocolGame::sendMarketDetail(uint16_t itemId) | |
msg.add<uint16_t>(0x00); | ||
} | ||
|
||
if (version >= 1101) { | ||
msg.add<uint16_t>(0x00); // imbuement slots | ||
} | ||
|
||
MarketStatistics* statistics = IOMarket::getInstance().getPurchaseStatistics(itemId); | ||
if (statistics) { | ||
msg.addByte(0x01); | ||
|
@@ -2732,6 +2747,9 @@ void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, const std::st | |
msg.add<uint32_t>(std::min<uint32_t>(10, icon)); | ||
msg.addByte(notify ? 0x01 : 0x00); | ||
msg.addByte(status); | ||
if (version >= 1110) { | ||
msg.addByte(0x00); // group count | ||
} | ||
writeToOutputBuffer(msg); | ||
} | ||
|
||
|
@@ -2862,6 +2880,10 @@ void ProtocolGame::AddCreature(NetworkMessage& msg, const Creature* creature, bo | |
msg.addByte(creature->getSpeechBubble()); | ||
msg.addByte(0xFF); // MARK_UNMARKED | ||
|
||
if (version >= 1110) { | ||
msg.addByte(0x00); // inspection state | ||
} | ||
|
||
if (otherPlayer) { | ||
msg.add<uint16_t>(otherPlayer->getHelpers()); | ||
} else { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer lambda instead of std::bind. std::bind can be hard to read and can result in larger object files and binaries due to type information that will not be produced by equivalent lambdas.