From f87b475f49cd6cdfab5b6f29f4b416943923d1b9 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Mon, 15 Aug 2011 21:30:31 -0300 Subject: [PATCH] revise network system --- CMakeLists.txt | 1 + src/framework/global.h | 3 + src/framework/luascript/luafunctions.cpp | 3 - src/framework/net/connection.cpp | 158 +++++++++++++---------- src/framework/net/connection.h | 35 +++-- src/framework/net/protocol.cpp | 47 +++---- src/framework/net/protocol.h | 5 +- src/otclient/core/const.h | 7 + src/otclient/core/datmanager.h | 8 +- src/otclient/core/game.cpp | 22 +++- src/otclient/core/game.h | 13 +- src/otclient/core/item.h | 4 +- src/otclient/core/map.h | 8 +- src/otclient/core/thing.cpp | 4 + src/otclient/core/thing.h | 2 +- src/otclient/core/tile.cpp | 6 +- src/otclient/core/tile.h | 2 +- src/otclient/net/protocolgame.cpp | 69 ++-------- src/otclient/net/protocolgame.h | 4 +- src/otclient/net/protocolgameparse.cpp | 6 +- src/otclient/net/protocolgamesend.cpp | 43 ++++++ src/otclient/net/protocollogin.cpp | 27 ++-- src/otclient/net/protocollogin.h | 2 +- src/otclient/otclient.cpp | 7 +- src/otclient/otclientluafunctions.cpp | 3 - src/otclient/util/position.h | 14 +- 26 files changed, 276 insertions(+), 227 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f41c782..324fa707 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ SET(SOURCES src/framework/thirdparty/apngloader.cpp # framework net + src/framework/net/networkmanager.cpp src/framework/net/connection.cpp src/framework/net/inputmessage.cpp src/framework/net/outputmessage.cpp diff --git a/src/framework/global.h b/src/framework/global.h index 4b63b9dc..d8b7bd9c 100644 --- a/src/framework/global.h +++ b/src/framework/global.h @@ -47,4 +47,7 @@ #include "util/rect.h" #include "util/size.h" +// easy typing for _1, _2, ... +using namespace std::placeholders; + #endif diff --git a/src/framework/luascript/luafunctions.cpp b/src/framework/luascript/luafunctions.cpp index 14b41973..aa12ceba 100644 --- a/src/framework/luascript/luafunctions.cpp +++ b/src/framework/luascript/luafunctions.cpp @@ -6,9 +6,6 @@ void LuaInterface::registerFunctions() { - // easy typing _1, _2, ... - using namespace std::placeholders; - // UIWidget g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIWidget::create); diff --git a/src/framework/net/connection.cpp b/src/framework/net/connection.cpp index 4ebbac7d..23a60cdd 100644 --- a/src/framework/net/connection.cpp +++ b/src/framework/net/connection.cpp @@ -1,125 +1,147 @@ #include "connection.h" +#include "networkmanager.h" #include +#include -static asio::io_service ioService; +asio::io_service g_ioService; Connection::Connection() : - m_timer(ioService), - m_resolver(ioService), - m_socket(ioService) + m_readTimer(g_ioService), + m_writeTimer(g_ioService), + m_resolver(g_ioService), + m_socket(g_ioService) { + m_connected = false; } -Connection::~Connection() +void Connection::poll() { - disconnect(); + g_ioService.poll(); + g_ioService.reset(); } -void Connection::poll() +void Connection::terminate() { - ioService.poll(); - ioService.reset(); + g_ioService.stop(); } -void Connection::connect(const std::string& host, uint16 port, const ConnectCallback& connectCallback) +void Connection::connect(const std::string& host, uint16 port, const SimpleCallback& connectCallback) { + m_connected = false; m_connectCallback = connectCallback; asio::ip::tcp::resolver::query query(host, fw::unsafe_cast(port)); - m_resolver.async_resolve(query, std::bind(&Connection::onResolve, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + m_resolver.async_resolve(query, std::bind(&Connection::onResolve, shared_from_this(), _1, _2)); - m_timer.expires_from_now(boost::posix_time::seconds(2)); - m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); + m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT)); + m_readTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), _1)); } -void Connection::disconnect() +void Connection::close() { - m_socket.close(); + if(!m_connected) + return; + + m_readTimer.cancel(); + m_writeTimer.cancel(); + + if(m_socket.is_open()) { + m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); + m_socket.close(); + } + + m_connected = false; } -void Connection::send(uint8* buffer, uint16 size) +void Connection::write(uint8* buffer, uint16 size) { + if(!m_connected) + return; + + m_writeTimer.cancel(); + asio::async_write(m_socket, - asio::buffer(buffer, size), - std::bind(&Connection::onSend, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + asio::buffer(buffer, size), + std::bind(&Connection::onWrite, shared_from_this(), _1, _2)); - m_timer.expires_from_now(boost::posix_time::seconds(2)); - m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); + m_writeTimer.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT)); + m_writeTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), _1)); } -void Connection::recv(uint16 bytes, uint32 timeout, const RecvCallback& callback) +void Connection::read(uint16 bytes, const RecvCallback& callback) { + m_readTimer.cancel(); + + if(!m_connected) + return; + m_recvCallback = callback; m_recvSize = bytes; asio::async_read(m_socket, - asio::buffer(m_recvBuffer, bytes), - std::bind(&Connection::onRecv, shared_from_this(), std::placeholders::_1)); - - if(timeout > 0) { - m_timer.expires_from_now(boost::posix_time::seconds(timeout)); - m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); - } -} + asio::buffer(m_recvBuffer, bytes), + std::bind(&Connection::onRecv, shared_from_this(), _1)); -void Connection::onTimeout(const boost::system::error_code& error) -{ - if(error != asio::error::operation_aborted) - g_dispatcher.addEvent(std::bind(m_errorCallback, error)); + m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT)); + m_readTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), _1)); } void Connection::onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator) { - m_timer.cancel(); + m_readTimer.cancel(); - if(error) { - if(m_errorCallback) - g_dispatcher.addEvent(std::bind(m_errorCallback, error)); - return; - } - - m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, shared_from_this(), std::placeholders::_1)); + if(!error) { + m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, shared_from_this(), _1)); - m_timer.expires_from_now(boost::posix_time::seconds(2)); - m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); + m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT)); + m_readTimer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), _1)); + } else + handleError(error); } void Connection::onConnect(const boost::system::error_code& error) { - m_timer.cancel(); - - if(error) { - if(m_errorCallback) - g_dispatcher.addEvent(std::bind(m_errorCallback, error)); - return; - } - - if(m_connectCallback) - g_dispatcher.addEvent(m_connectCallback); + m_readTimer.cancel(); + m_connected = true; + + if(!error) { + if(m_connectCallback) + g_dispatcher.addEvent(m_connectCallback); + } else + handleError(error); } -void Connection::onSend(const boost::system::error_code& error, size_t) +void Connection::onWrite(const boost::system::error_code& error, size_t) { - m_timer.cancel(); + m_writeTimer.cancel(); - if(error) { - if(m_errorCallback) - g_dispatcher.addEvent(std::bind(m_errorCallback, error)); - return; - } + if(error) + handleError(error); } void Connection::onRecv(const boost::system::error_code& error) { - m_timer.cancel(); + m_readTimer.cancel(); - if(error) { - if(m_errorCallback) - g_dispatcher.addEvent(std::bind(m_errorCallback, error)); - return; - } + if(!error) { + if(m_recvCallback) + g_dispatcher.addEvent(std::bind(m_recvCallback, m_recvBuffer, m_recvSize)); + } else + handleError(error); +} + +void Connection::onTimeout(const boost::system::error_code& error) +{ + if(error != asio::error::operation_aborted) + handleError(error); +} - if(m_recvCallback) - g_dispatcher.addEvent(std::bind(m_recvCallback, m_recvBuffer, m_recvSize)); +void Connection::handleError(const boost::system::error_code& error) +{ + logTraceDebug(error.message()); + close(); + if(m_errorCallback) + g_dispatcher.addEvent(std::bind(m_errorCallback, error)); } + diff --git a/src/framework/net/connection.h b/src/framework/net/connection.h index 69dd0677..c1fb1d54 100644 --- a/src/framework/net/connection.h +++ b/src/framework/net/connection.h @@ -8,40 +8,49 @@ class Connection : public std::enable_shared_from_this, boost::nonco { typedef std::function ErrorCallback; typedef std::function RecvCallback; - typedef std::function ConnectCallback; + + enum { + READ_TIMEOUT = 10, + WRITE_TIMEOUT = 10 + }; public: Connection(); - virtual ~Connection(); + static void init(); static void poll(); + static void terminate(); + + void connect(const std::string& host, uint16 port, const SimpleCallback& connectCallback); + void close(); - void connect(const std::string& host, uint16 port, const ConnectCallback& connectCallback); - void disconnect(); - void send(uint8* buffer, uint16 size); - void recv(uint16 bytes, uint32 timeout, const RecvCallback& callback); + void write(uint8* buffer, uint16 size); + void read(uint16 bytes, const RecvCallback& callback); void setErrorCallback(const ErrorCallback& errorCallback) { m_errorCallback = errorCallback; } - void setRecvCallback(const RecvCallback& recvCallback) { m_recvCallback = recvCallback; } + + bool isConnected() const { return m_connected; } private: - void onTimeout(const boost::system::error_code& error); void onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator); void onConnect(const boost::system::error_code& error); - void onSend(const boost::system::error_code& error, size_t); + void onWrite(const boost::system::error_code& error, size_t); void onRecv(const boost::system::error_code& error); + void onTimeout(const boost::system::error_code& error); + void handleError(const boost::system::error_code& error); - + SimpleCallback m_connectCallback; ErrorCallback m_errorCallback; - ConnectCallback m_connectCallback; + RecvCallback m_recvCallback; - asio::deadline_timer m_timer; + asio::deadline_timer m_readTimer; + asio::deadline_timer m_writeTimer; asio::ip::tcp::resolver m_resolver; asio::ip::tcp::socket m_socket; uint8 m_recvBuffer[65538]; uint16 m_recvSize; - RecvCallback m_recvCallback; + bool m_connected; }; #endif diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp index 75e5e887..f281aa82 100644 --- a/src/framework/net/protocol.cpp +++ b/src/framework/net/protocol.cpp @@ -1,10 +1,9 @@ #include "protocol.h" #include "connection.h" -Protocol::Protocol() : - m_connection(new Connection) +Protocol::Protocol() : m_connection(new Connection) { - m_connection->setErrorCallback(std::bind(&Protocol::onError, this, std::placeholders::_1)); + m_connection->setErrorCallback(std::bind(&Protocol::onError, this, _1)); m_xteaEncryptionEnabled = false; m_checksumEnabled = true; } @@ -14,41 +13,48 @@ void Protocol::connect(const std::string& host, uint16 port) m_connection->connect(host, port, std::bind(&Protocol::onConnect, asProtocol())); } +void Protocol::disconnect() +{ + m_connection->close(); +} + void Protocol::send(OutputMessage& outputMessage) { - // Encrypt + // encrypt if(m_xteaEncryptionEnabled) xteaEncrypt(outputMessage); - // Set checksum + // set checksum uint32 checksum = getAdlerChecksum(outputMessage.getBuffer() + OutputMessage::DATA_POS, outputMessage.getMessageSize()); outputMessage.setWritePos(OutputMessage::CHECKSUM_POS); outputMessage.addU32(checksum); - // Set size + // set size uint16 messageSize = outputMessage.getMessageSize(); outputMessage.setWritePos(OutputMessage::HEADER_POS); outputMessage.addU16(messageSize); - // Send - m_connection->send(outputMessage.getBuffer(), outputMessage.getMessageSize()); + // send + m_connection->write(outputMessage.getBuffer(), outputMessage.getMessageSize()); } void Protocol::recv() { m_inputMessage.reset(); - m_connection->recv(InputMessage::HEADER_LENGTH, 2, std::bind(&Protocol::internalRecvHeader, asProtocol(), std::placeholders::_1, std::placeholders::_2)); + m_connection->read(InputMessage::HEADER_LENGTH, std::bind(&Protocol::internalRecvHeader, asProtocol(), _1, _2)); } void Protocol::internalRecvHeader(uint8* buffer, uint16 size) { memcpy(m_inputMessage.getBuffer() + InputMessage::HEADER_POS, buffer, size); + // read message size uint16 dataSize = m_inputMessage.getU16(); m_inputMessage.setMessageSize(dataSize); - m_connection->recv(dataSize, 5, std::bind(&Protocol::internalRecvData, asProtocol(), std::placeholders::_1, std::placeholders::_2)); + // schedule read for message data + m_connection->read(dataSize, std::bind(&Protocol::internalRecvData, asProtocol(), _1, _2)); } void Protocol::internalRecvData(uint8* buffer, uint16 size) @@ -59,7 +65,7 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size) uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH); if(m_inputMessage.getU32() != checksum) { // error - logError("Checksum is invalid."); + logError("ERROR: got a network message with invalid checksum"); return; } } @@ -70,27 +76,12 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size) onRecv(m_inputMessage); } -void Protocol::onError(const boost::system::error_code& err) -{ - std::stringstream message; - - logError("PROTOCOL ERROR: ", err.message()); - message << "Boost error: " << err.message(); - - // invalid hostname - // connection timeouted - - // displays a dialog, finish protocol - - callLuaField("onError", message.str()); -} - bool Protocol::xteaDecrypt(InputMessage& inputMessage) { // FIXME: this function has not been tested yet uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH; if(messageSize % 8 != 0) { - logDebug("not valid encrypted message size"); + logError("ERROR: invalid encrypted network message"); return false; } @@ -113,7 +104,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage) int tmp = inputMessage.getU16(); if(tmp > inputMessage.getMessageSize() - 4) { - logDebug("not valid unencrypted message size"); + logDebug("ERROR: invalid decrypted a network message"); return false; } diff --git a/src/framework/net/protocol.h b/src/framework/net/protocol.h index f88a3350..7df0e383 100644 --- a/src/framework/net/protocol.h +++ b/src/framework/net/protocol.h @@ -13,14 +13,17 @@ public: Protocol(); void connect(const std::string& host, uint16 port); + void disconnect(); + void send(OutputMessage& outputMessage); void recv(); + void internalRecvHeader(uint8* buffer, uint16 size); void internalRecvData(uint8* buffer, uint16 size); virtual void onConnect() = 0; virtual void onRecv(InputMessage& inputMessage) = 0; - virtual void onError(const boost::system::error_code& err); + virtual void onError(const boost::system::error_code& err) = 0; ProtocolPtr asProtocol() { return std::static_pointer_cast(shared_from_this()); } diff --git a/src/otclient/core/const.h b/src/otclient/core/const.h index e51eed38..b85790b6 100644 --- a/src/otclient/core/const.h +++ b/src/otclient/core/const.h @@ -26,4 +26,11 @@ enum ThingType { THING_SHOT }; +enum Direction { + DIRECTION_NORTH, + DIRECTION_EAST, + DIRECTION_SOUTH, + DIRECTION_WEST +}; + #endif diff --git a/src/otclient/core/datmanager.h b/src/otclient/core/datmanager.h index 89f60301..2a0bac5e 100644 --- a/src/otclient/core/datmanager.h +++ b/src/otclient/core/datmanager.h @@ -13,10 +13,10 @@ public: void parseThingAttributes(std::stringstream& fin, ThingAttributes& thingAttributes); void parseThingAttributesOpt(std::stringstream& fin, ThingAttributes& thingAttributes, uint8 opt); - const ThingAttributes& getItemAttributes(uint16 id) { return m_itemsAttributes[id - 100]; } - const ThingAttributes& getCreatureAttributes(uint16 id) { return m_creaturesAttributes[id - 1]; } - const ThingAttributes& getEffectAttributes(uint16 id) { return m_effectsAttributes[id - 100]; } - const ThingAttributes& getShotAttributes(uint16 id) { return m_shotsAttributes[id - 1]; } + ThingAttributes& getItemAttributes(uint16 id) { return m_itemsAttributes[id - 100]; } + ThingAttributes& getCreatureAttributes(uint16 id) { return m_creaturesAttributes[id - 1]; } + ThingAttributes& getEffectAttributes(uint16 id) { return m_effectsAttributes[id - 100]; } + ThingAttributes& getShotAttributes(uint16 id) { return m_shotsAttributes[id - 1]; } uint32 getSignature() { return m_signature; } diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index 21c1245b..d7acc9b8 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -1,13 +1,32 @@ #include "game.h" #include "localplayer.h" +#include Game g_game; -Game::Game() +void Game::init() { m_online = false; } +void Game::terminate() +{ + if(m_online) + logout(); +} + +void Game::loginWorld(const std::string& account, const std::string& password, uint32 worldIp, uint16 worldPort, const std::string& characterName) +{ + m_protocolGame = ProtocolGamePtr(new ProtocolGame); + m_protocolGame->login(account, password, worldIp, worldPort, characterName); +} + +void Game::logout() +{ + m_protocolGame->sendLogout(); + onLogout(); +} + void Game::onLogin() { m_localPlayer = LocalPlayerPtr(new LocalPlayer); @@ -16,6 +35,7 @@ void Game::onLogin() void Game::onLogout() { + m_protocolGame.reset(); m_localPlayer.reset(); m_online = false; } diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index ffec50fe..ccd4a116 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -7,17 +7,22 @@ class Game { public: - Game(); + void init(); + void terminate(); + + void loginWorld(const std::string& account, + const std::string& password, + uint32 worldIp, uint16 worldPort, + const std::string& characterName); + void logout(); void onLogin(); void onLogout(); - void setProtocol(ProtocolGamePtr protocolGame) { m_protocolGame = protocolGame; } - bool isOnline() { return m_online; } - ProtocolGamePtr getProtocol() { return m_protocolGame; } LocalPlayerPtr getLocalPlayer() { return m_localPlayer; } + ProtocolGamePtr getProtocolGame() { return m_protocolGame; } private: LocalPlayerPtr m_localPlayer; diff --git a/src/otclient/core/item.h b/src/otclient/core/item.h index 70609925..d11ebc68 100644 --- a/src/otclient/core/item.h +++ b/src/otclient/core/item.h @@ -11,7 +11,7 @@ public: void draw(int x, int y); - void setCount(uint8 count) { m_count = count; } + void setCount(int count) { m_count = count; } int getCount() { return m_count; } const ThingAttributes& getAttributes(); @@ -19,7 +19,7 @@ public: ItemPtr asItem() { return std::static_pointer_cast(shared_from_this()); } private: - uint8 m_count; + int m_count; }; #endif diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index ece6fda0..ebd6a953 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -5,12 +5,6 @@ #include "effect.h" #include -struct MapPositionHasher : std::unary_function { - std::size_t operator()(const Position& pos) const { - return ((((pos.x * 65536) + pos.y) * 15) + pos.z) % 1000000; - } -}; - class Map { public: @@ -19,7 +13,7 @@ public: void draw(int x, int y); private: - std::unordered_map m_tiles; + std::unordered_map m_tiles; std::list m_effects; FrameBufferPtr m_framebuffer; diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index bb352ed5..ac03d069 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -2,6 +2,10 @@ #include "spritemanager.h" #include +Thing::Thing(ThingType type) : m_id(0), m_type(type) +{ +} + void Thing::internalDraw(int x, int y, int blendframes, int xdiv, int ydiv, int zdiv, int anim) { const ThingAttributes& attributes = getAttributes(); diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 33433ef0..b9f11e9c 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -8,7 +8,7 @@ class Thing : public LuaObject { public: - Thing(ThingType type) : m_id(0), m_type(type) { } + Thing(ThingType type); virtual ~Thing() { } virtual void draw(int x, int y) = 0; diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index ab7ee261..f03ded52 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -19,7 +19,7 @@ void Tile::addThing(ThingPtr thing, uint8 stackpos) if(thingAttributes.alwaysOnTop) m_itemsTop.push_back(thing); else - m_itemsBot.push_back(thing); + m_itemsBottom.push_back(thing); } } else if(thing->asCreature()) { m_creatures.push_back(thing); @@ -31,7 +31,7 @@ void Tile::draw(int x, int y) if(m_ground) m_ground->draw(x, y); - for(const ThingPtr& thing : m_itemsBot) + for(const ThingPtr& thing : m_itemsBottom) thing->draw(x, y); for(const ThingPtr& thing : m_creatures) @@ -46,7 +46,7 @@ int Tile::getStackSize() int ret = 0; if(m_ground) ret++; - ret += m_itemsBot.size(); + ret += m_itemsBottom.size(); ret += m_creatures.size(); ret += m_itemsTop.size(); return ret; diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index 6b4b5bbe..2d632aa2 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -19,7 +19,7 @@ public: private: ThingPtr m_ground; - std::deque m_itemsBot; + std::deque m_itemsBottom; std::deque m_creatures; std::deque m_itemsTop; }; diff --git a/src/otclient/net/protocolgame.cpp b/src/otclient/net/protocolgame.cpp index 6134842d..25b83e16 100644 --- a/src/otclient/net/protocolgame.cpp +++ b/src/otclient/net/protocolgame.cpp @@ -1,17 +1,10 @@ #include #include -#include ProtocolGame::ProtocolGame() { m_checksumEnabled = false; - g_game.setProtocol(ProtocolGamePtr(this)); -} - -ProtocolGame::~ProtocolGame() -{ - sendLogout(); - g_game.setProtocol(NULL); + m_waitingLoginPacket = false; } void ProtocolGame::login(const std::string& accountName, const std::string& accountPassword, uint32 ip, uint16 port, const std::string& characterName) @@ -21,6 +14,7 @@ void ProtocolGame::login(const std::string& accountName, const std::string& acco return; } + m_waitingLoginPacket = true; m_accountName = accountName; m_accountPassword = accountPassword; m_characterName = characterName; @@ -36,64 +30,27 @@ void ProtocolGame::onConnect() recv(); } -void ProtocolGame::sendLoginPacket(uint32 timestamp, uint8 unknown) -{ - OutputMessage oMsg; - - oMsg.addU8(0x0A); // Protocol id - oMsg.addU16(0x02); // OS - oMsg.addU16(862); // Client version - - oMsg.addU8(0); // First RSA byte must be 0x00 // 1 - - // Generete xtea key. - m_xteaKey[0] = 432324; - m_xteaKey[1] = 24324; - m_xteaKey[2] = 423432; - m_xteaKey[3] = 234324; - - // Add xtea key - oMsg.addU32(m_xteaKey[0]); // 5 - oMsg.addU32(m_xteaKey[1]); // 9 - oMsg.addU32(m_xteaKey[2]); // 13 - oMsg.addU32(m_xteaKey[3]); // 17 - - oMsg.addU8(0); // is gm set? - oMsg.addString(m_accountName); // Account Name // 20 - oMsg.addString(m_characterName); // Character Name // 22 - oMsg.addString(m_accountPassword); // Password // 24 - - oMsg.addU32(timestamp); // 28 - oMsg.addU8(unknown); // 29 - - // Packet data must have since byte 0, start, 128 bytes - oMsg.addPaddingBytes(128 - (29 + m_accountName.length() + m_characterName.length() + m_accountPassword.length())); - - // Encrypt msg with RSA - if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA)) - return; - - send(oMsg); - - m_xteaEncryptionEnabled = true; - - recv(); -} - void ProtocolGame::onRecv(InputMessage& inputMessage) { - static bool firstRecv = true; - if(firstRecv) { + if(m_waitingLoginPacket) { inputMessage.skipBytes(3); uint32 timestamp = inputMessage.getU32(); uint8 unknown = inputMessage.getU8(); + m_waitingLoginPacket = false; m_checksumEnabled = true; sendLoginPacket(timestamp, unknown); - - firstRecv = false; + recv(); } else { parseMessage(inputMessage); + recv(); } } + +void ProtocolGame::onError(const boost::system::error_code& error) +{ + // already disconnected, just send onLogout + g_game.onLogout(); +} + diff --git a/src/otclient/net/protocolgame.h b/src/otclient/net/protocolgame.h index 9bcd475e..ad03cfba 100644 --- a/src/otclient/net/protocolgame.h +++ b/src/otclient/net/protocolgame.h @@ -9,16 +9,15 @@ class ProtocolGame : public Protocol { - public: ProtocolGame(); - ~ProtocolGame(); public: void login(const std::string& accountName, const std::string& accountPassword, uint32 ip, uint16 port, const std::string& characterName); void onConnect(); void onRecv(InputMessage& inputMessage); + void onError(const boost::system::error_code& error); void sendLogout(); void sendPing(); @@ -115,6 +114,7 @@ private: Position parsePosition(InputMessage& msg); private: + bool m_waitingLoginPacket; std::string m_accountName; std::string m_accountPassword; std::string m_characterName; diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index 5a1ef210..53515c2a 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -226,7 +226,6 @@ void ProtocolGame::parseMessage(InputMessage& msg) break; } } - recv(); } void ProtocolGame::parsePlayerLogin(InputMessage& msg) @@ -629,7 +628,6 @@ void ProtocolGame::parseCreatureSpeak(InputMessage& msg) msg.getU32(); // time break; default: - //qDebug() << "Unknown speak type. opt: 0xAA, type: " << type; break; } @@ -691,7 +689,7 @@ void ProtocolGame::parseTextMessage(InputMessage& msg) { msg.getU8(); // messageType std::string message = msg.getString(); - logDebug(message); + //logDebug(message); } void ProtocolGame::parseCancelWalk(InputMessage& msg) @@ -813,8 +811,6 @@ void ProtocolGame::setMapDescription(InputMessage& msg, int32 x, int32 y, int32 zstep = -1; } - logDebug((int)startz); - for(int nz = startz; nz != endz + zstep; nz += zstep) setFloorDescription(msg, x, y, nz, width, height, z - nz, &skip); } diff --git a/src/otclient/net/protocolgamesend.cpp b/src/otclient/net/protocolgamesend.cpp index 696f794c..3af0e72b 100644 --- a/src/otclient/net/protocolgamesend.cpp +++ b/src/otclient/net/protocolgamesend.cpp @@ -1,4 +1,47 @@ #include "protocolgame.h" +#include + +void ProtocolGame::sendLoginPacket(uint32 timestamp, uint8 unknown) +{ + OutputMessage oMsg; + + oMsg.addU8(0x0A); // Protocol id + oMsg.addU16(0x02); // OS + oMsg.addU16(862); // Client version + + oMsg.addU8(0); // First RSA byte must be 0x00 // 1 + + // Generete xtea key. + m_xteaKey[0] = 432324; + m_xteaKey[1] = 24324; + m_xteaKey[2] = 423432; + m_xteaKey[3] = 234324; + + // Add xtea key + oMsg.addU32(m_xteaKey[0]); // 5 + oMsg.addU32(m_xteaKey[1]); // 9 + oMsg.addU32(m_xteaKey[2]); // 13 + oMsg.addU32(m_xteaKey[3]); // 17 + + oMsg.addU8(0); // is gm set? + oMsg.addString(m_accountName); // Account Name // 20 + oMsg.addString(m_characterName); // Character Name // 22 + oMsg.addString(m_accountPassword); // Password // 24 + + oMsg.addU32(timestamp); // 28 + oMsg.addU8(unknown); // 29 + + // Packet data must have since byte 0, start, 128 bytes + oMsg.addPaddingBytes(128 - (29 + m_accountName.length() + m_characterName.length() + m_accountPassword.length())); + + // Encrypt msg with RSA + if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA)) + return; + + send(oMsg); + + m_xteaEncryptionEnabled = true; +} void ProtocolGame::sendLogout() { diff --git a/src/otclient/net/protocollogin.cpp b/src/otclient/net/protocollogin.cpp index 30465732..d4fbce5f 100644 --- a/src/otclient/net/protocollogin.cpp +++ b/src/otclient/net/protocollogin.cpp @@ -6,15 +6,10 @@ // TODO just testing #include "protocolgame.h" +#include ProtocolLogin::ProtocolLogin() { - -} - -ProtocolLogin::~ProtocolLogin() -{ - } void ProtocolLogin::login(const std::string& accountName, const std::string& accountPassword) @@ -99,7 +94,6 @@ void ProtocolLogin::onRecv(InputMessage& inputMessage) { while(!inputMessage.end()) { uint8 opt = inputMessage.getU8(); - logDebug("opt:",(uint)opt); switch(opt) { case 0x0A: parseError(inputMessage); @@ -117,17 +111,22 @@ void ProtocolLogin::onRecv(InputMessage& inputMessage) } } +void ProtocolLogin::onError(const boost::system::error_code& error) +{ + // already disconnected, just send onLogout + callLuaField("onError", error.message()); +} + void ProtocolLogin::parseError(InputMessage& inputMessage) { std::string error = inputMessage.getString(); - logDebug(error); callLuaField("onError", error); + disconnect(); } void ProtocolLogin::parseMOTD(InputMessage& inputMessage) { std::string motd = inputMessage.getString(); - logDebug(motd); callLuaField("onMotd", motd); } @@ -140,14 +139,12 @@ void ProtocolLogin::parseCharacterList(InputMessage& inputMessage) uint32 ip = inputMessage.getU32(); uint16 port = inputMessage.getU16(); - logDebug("character: ", name.c_str(), world.c_str(), ip, " ", port); - // TODO just test if(i == 0) { - ProtocolGamePtr protocolGame = ProtocolGamePtr(new ProtocolGame); - protocolGame->login(m_accountName, m_accountPassword, ip, port, name); + g_game.loginWorld(m_accountName, m_accountPassword, ip, port, name); + break; } } - uint16 premiumDays = inputMessage.getU16(); - logDebug("prem days: ", premiumDays); + /*uint16 premiumDays =*/ inputMessage.getU16(); + disconnect(); } diff --git a/src/otclient/net/protocollogin.h b/src/otclient/net/protocollogin.h index 45548420..28ab43c9 100644 --- a/src/otclient/net/protocollogin.h +++ b/src/otclient/net/protocollogin.h @@ -11,7 +11,6 @@ class ProtocolLogin : public Protocol { public: ProtocolLogin(); - ~ProtocolLogin(); static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); } @@ -19,6 +18,7 @@ public: void onConnect(); void onRecv(InputMessage& inputMessage); + void onError(const boost::system::error_code& error); void cancel() { /* TODO: this func */ } diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp index 60d4bc9e..e931bf1f 100644 --- a/src/otclient/otclient.cpp +++ b/src/otclient/otclient.cpp @@ -62,6 +62,8 @@ void OTClient::init(std::vector args) // initialize the ui g_ui.init(); + g_game.init(); + // discover and load modules g_modules.discoverAndLoadModules(); @@ -146,6 +148,8 @@ void OTClient::terminate() // run modules unload event g_modules.unloadModules(); + g_game.terminate(); + // terminate ui g_ui.terminate(); @@ -156,6 +160,7 @@ void OTClient::terminate() poll(); // terminate network + Connection::terminate(); //g_network.terminate(); // terminate dispatcher @@ -263,7 +268,7 @@ void OTClient::onPlatformEvent(const PlatformEvent& event) { g_ui.inputEvent(event); - ProtocolGamePtr protocol = g_game.getProtocol(); + ProtocolGamePtr protocol = g_game.getProtocolGame(); if(protocol) { if(event.type == EventKeyDown) { if(event.keycode == KC_UP) diff --git a/src/otclient/otclientluafunctions.cpp b/src/otclient/otclientluafunctions.cpp index 29e98a96..32689e45 100644 --- a/src/otclient/otclientluafunctions.cpp +++ b/src/otclient/otclientluafunctions.cpp @@ -8,9 +8,6 @@ void OTClient::registerLuaFunctions() { - // easy typing _1, _2, ... - using namespace std::placeholders; - g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client)); g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1)); g_lua.bindGlobalFunction("importDat", std::bind(&DatManager::load, &g_dat, _1)); diff --git a/src/otclient/util/position.h b/src/otclient/util/position.h index 10969487..6efda8be 100644 --- a/src/otclient/util/position.h +++ b/src/otclient/util/position.h @@ -3,14 +3,6 @@ #include -enum Direction -{ - DIRECTION_NORTH, - DIRECTION_EAST, - DIRECTION_SOUTH, - DIRECTION_WEST -}; - class Position { public: @@ -33,6 +25,12 @@ public: int z; }; +struct PositionHasher : std::unary_function { + std::size_t operator()(const Position& pos) const { + return ((((pos.x * 65536) + pos.y) * 15) + pos.z) % 1000000; + } +}; + template std::ostream& operator<<(std::ostream& out, const Position& pos) {